Skip to content

Commit

Permalink
Transform manyToMany from yaml to attributes (#308)
Browse files Browse the repository at this point in the history
  • Loading branch information
uncaught committed Apr 21, 2024
1 parent 9e0a97b commit ea7e844
Show file tree
Hide file tree
Showing 9 changed files with 236 additions and 5 deletions.
6 changes: 6 additions & 0 deletions config/yaml-to-annotations.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@
use Rector\Doctrine\CodeQuality\AttributeTransformer\PropertyAttributeTransformer\IdAttributeTransformer;
use Rector\Doctrine\CodeQuality\AttributeTransformer\PropertyAttributeTransformer\IdColumnAttributeTransformer;
use Rector\Doctrine\CodeQuality\AttributeTransformer\PropertyAttributeTransformer\IdGeneratorAttributeTransformer;
use Rector\Doctrine\CodeQuality\AttributeTransformer\PropertyAttributeTransformer\InverseJoinColumnAttributeTransformer;
use Rector\Doctrine\CodeQuality\AttributeTransformer\PropertyAttributeTransformer\JoinColumnAttributeTransformer;
use Rector\Doctrine\CodeQuality\AttributeTransformer\PropertyAttributeTransformer\JoinTableAttributeTransformer;
use Rector\Doctrine\CodeQuality\AttributeTransformer\PropertyAttributeTransformer\ManyToManyAttributeTransformer;
use Rector\Doctrine\CodeQuality\AttributeTransformer\PropertyAttributeTransformer\ManyToOneAttributeTransformer;
use Rector\Doctrine\CodeQuality\AttributeTransformer\PropertyAttributeTransformer\OneToManyAttributeTransformer;
use Rector\Doctrine\CodeQuality\AttributeTransformer\PropertyAttributeTransformer\OrderByAttributeTransformer;
Expand All @@ -40,9 +43,12 @@
$rectorConfig->singleton(IdAttributeTransformer::class);
$rectorConfig->singleton(IdColumnAttributeTransformer::class);
$rectorConfig->singleton(IdGeneratorAttributeTransformer::class);
$rectorConfig->singleton(ManyToManyAttributeTransformer::class);
$rectorConfig->singleton(ManyToOneAttributeTransformer::class);
$rectorConfig->singleton(OneToManyAttributeTransformer::class);
$rectorConfig->singleton(JoinTableAttributeTransformer::class);
$rectorConfig->singleton(JoinColumnAttributeTransformer::class);
$rectorConfig->singleton(InverseJoinColumnAttributeTransformer::class);
$rectorConfig->singleton(OrderByAttributeTransformer::class);

$rectorConfig->when(YamlToAttributeTransformer::class)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

namespace Rector\Doctrine\Tests\CodeQuality\Rector\Class_\YamlToAttributeDoctrineMappingRector\Fixture;

final class ManyToMany
{
public $myObjects;

public $theirObjects;
}

?>
-----
<?php

namespace Rector\Doctrine\Tests\CodeQuality\Rector\Class_\YamlToAttributeDoctrineMappingRector\Fixture;

#[\Doctrine\ORM\Mapping\Table]
final class ManyToMany
{
#[\Doctrine\ORM\Mapping\ManyToMany(targetEntity: \App\SomeTargetEntity::class, inversedBy: 'theirObjects')]
#[\Doctrine\ORM\Mapping\JoinTable(name: 'owned_objects')]
#[\Doctrine\ORM\Mapping\JoinColumn(name: 'owner_id', referencedColumnName: 'some_id', onDelete: 'cascade')]
#[\Doctrine\ORM\Mapping\InverseJoinColumn(name: 'object_id', referencedColumnName: 'some_id', onDelete: 'cascade')]
public $myObjects;

#[\Doctrine\ORM\Mapping\ManyToMany(targetEntity: \App\SomeTargetEntity::class, mappedBy: 'myObjects')]
public $theirObjects;
}

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
Rector\Doctrine\Tests\CodeQuality\Rector\Class_\YamlToAttributeDoctrineMappingRector\Fixture\ManyToMany:
manyToMany:
myObjects:
targetEntity: App\SomeTargetEntity
inversedBy: theirObjects
joinTable:
name: owned_objects
joinColumns:
owner_id:
referencedColumnName: some_id
onDelete: cascade
inverseJoinColumns:
object_id:
referencedColumnName: some_id
onDelete: cascade

theirObjects:
targetEntity: App\SomeTargetEntity
mappedBy: myObjects
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

declare(strict_types=1);

namespace Rector\Doctrine\CodeQuality\AttributeTransformer\PropertyAttributeTransformer;

use PhpParser\Node\AttributeGroup;
use PhpParser\Node\Param;
use PhpParser\Node\Stmt\Property;
use Rector\Doctrine\CodeQuality\Contract\PropertyAttributeTransformerInterface;
use Rector\Doctrine\CodeQuality\NodeFactory\AttributeFactory;
use Rector\Doctrine\CodeQuality\ValueObject\EntityMapping;
use Rector\Doctrine\Enum\MappingClass;
use Rector\PhpParser\Node\NodeFactory;

final readonly class InverseJoinColumnAttributeTransformer implements PropertyAttributeTransformerInterface
{
public function __construct(
private NodeFactory $nodeFactory
) {
}

public function transform(EntityMapping $entityMapping, Property|Param $property): void
{
$joinTableMapping = $entityMapping->matchManyToManyPropertyMapping($property)['joinTable'] ?? null;
if (! is_array($joinTableMapping)) {
return;
}

$joinColumns = $joinTableMapping['inverseJoinColumns'] ?? null;
if (! is_array($joinColumns)) {
return;
}

foreach ($joinColumns as $columnName => $joinColumn) {
$property->attrGroups[] = $this->createInverseJoinColumnAttrGroup($columnName, $joinColumn);
}
}

public function getClassName(): string
{
return MappingClass::INVERSE_JOIN_COLUMN;
}

private function createInverseJoinColumnAttrGroup(int|string $columnName, mixed $joinColumn): AttributeGroup
{
$joinColumn = array_merge([
'name' => $columnName,
], $joinColumn);

$args = $this->nodeFactory->createArgs($joinColumn);

return AttributeFactory::createGroup($this->getClassName(), $args);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,27 @@ public function __construct(

public function transform(EntityMapping $entityMapping, Property|Param $property): void
{
$manyToOnePropertyMapping = $entityMapping->matchManyToOnePropertyMapping($property);
if (! is_array($manyToOnePropertyMapping)) {
$this->transformMapping($property, $entityMapping->matchManyToManyPropertyMapping($property)['joinTable'] ?? null);
$this->transformMapping($property, $entityMapping->matchManyToOnePropertyMapping($property));
}

/**
* @param array<string, array<string, mixed>>|null $mapping
*/
private function transformMapping(Property|Param $property, ?array $mapping): void
{
if (! is_array($mapping)) {
return;
}

$singleJoinColumn = $manyToOnePropertyMapping['joinColumn'] ?? null;
$singleJoinColumn = $mapping['joinColumn'] ?? null;
if (is_array($singleJoinColumn)) {
$name = $singleJoinColumn['name'];
unset($singleJoinColumn['name']);
$manyToOnePropertyMapping['joinColumns'][$name] = $singleJoinColumn;
$mapping['joinColumns'][$name] = $singleJoinColumn;
}

$joinColumns = $manyToOnePropertyMapping['joinColumns'] ?? null;
$joinColumns = $mapping['joinColumns'] ?? null;
if (! is_array($joinColumns)) {
return;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

declare(strict_types=1);

namespace Rector\Doctrine\CodeQuality\AttributeTransformer\PropertyAttributeTransformer;

use PhpParser\Node\Param;
use PhpParser\Node\Stmt\Property;
use Rector\Doctrine\CodeQuality\Contract\PropertyAttributeTransformerInterface;
use Rector\Doctrine\CodeQuality\Enum\EntityMappingKey;
use Rector\Doctrine\CodeQuality\Helper\NodeValueNormalizer;
use Rector\Doctrine\CodeQuality\NodeFactory\AttributeFactory;
use Rector\Doctrine\CodeQuality\ValueObject\EntityMapping;
use Rector\Doctrine\Enum\MappingClass;
use Rector\PhpParser\Node\NodeFactory;

final readonly class JoinTableAttributeTransformer implements PropertyAttributeTransformerInterface
{
public function __construct(
private NodeFactory $nodeFactory
) {
}

public function transform(EntityMapping $entityMapping, Property|Param $property): void
{
$joinTableMapping = $entityMapping->matchManyToManyPropertyMapping($property)['joinTable'] ?? null;
if (! is_array($joinTableMapping)) {
return;
}

// handled by another mapper
unset($joinTableMapping['joinColumns'], $joinTableMapping['inverseJoinColumns']);

$args = $this->nodeFactory->createArgs($joinTableMapping);
$property->attrGroups[] = AttributeFactory::createGroup($this->getClassName(), $args);

NodeValueNormalizer::ensureKeyIsClassConstFetch($args, EntityMappingKey::TARGET_ENTITY);
}

public function getClassName(): string
{
return MappingClass::JOIN_TABLE;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

declare(strict_types=1);

namespace Rector\Doctrine\CodeQuality\AttributeTransformer\PropertyAttributeTransformer;

use PhpParser\Node\Param;
use PhpParser\Node\Stmt\Property;
use Rector\Doctrine\CodeQuality\Contract\PropertyAttributeTransformerInterface;
use Rector\Doctrine\CodeQuality\Enum\EntityMappingKey;
use Rector\Doctrine\CodeQuality\Helper\NodeValueNormalizer;
use Rector\Doctrine\CodeQuality\NodeFactory\AttributeFactory;
use Rector\Doctrine\CodeQuality\ValueObject\EntityMapping;
use Rector\Doctrine\Enum\MappingClass;
use Rector\PhpParser\Node\NodeFactory;

final readonly class ManyToManyAttributeTransformer implements PropertyAttributeTransformerInterface
{
public function __construct(
private NodeFactory $nodeFactory
) {
}

public function transform(EntityMapping $entityMapping, Property|Param $property): void
{
$manyToManyMapping = $entityMapping->matchManyToManyPropertyMapping($property);
if (! is_array($manyToManyMapping)) {
return;
}

// handled by another mapper
unset($manyToManyMapping['joinTable']);

$args = $this->nodeFactory->createArgs($manyToManyMapping);
$property->attrGroups[] = AttributeFactory::createGroup($this->getClassName(), $args);

NodeValueNormalizer::ensureKeyIsClassConstFetch($args, EntityMappingKey::TARGET_ENTITY);
}

public function getClassName(): string
{
return MappingClass::MANY_TO_MANY;
}
}
9 changes: 9 additions & 0 deletions rules/CodeQuality/ValueObject/EntityMapping.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,15 @@ public function matchEmbeddedPropertyMapping(Property|Param $property): ?array
return $this->entityMapping['embedded'][$propertyName] ?? null;
}

/**
* @return array<string, mixed>|null
*/
public function matchManyToManyPropertyMapping(Property|Param $property): ?array
{
$propertyName = $this->getPropertyName($property);
return $this->entityMapping['manyToMany'][$propertyName] ?? null;
}

/**
* @return array<string, mixed>|null
*/
Expand Down
15 changes: 15 additions & 0 deletions src/Enum/MappingClass.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,21 @@ final class MappingClass
*/
public const INDEX = 'Doctrine\ORM\Mapping\Index';

/**
* @var string
*/
public const INVERSE_JOIN_COLUMN = 'Doctrine\ORM\Mapping\InverseJoinColumn';

/**
* @var string
*/
public const JOIN_TABLE = 'Doctrine\ORM\Mapping\JoinTable';

/**
* @var string
*/
public const MANY_TO_MANY = 'Doctrine\ORM\Mapping\ManyToMany';

/**
* @var string
*/
Expand Down

0 comments on commit ea7e844

Please sign in to comment.