Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions src/Doctrine/EntityRegenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ public function regenerateEntities(string $classOrNamespace)
$classPath = $this->getPathOfClass($classMetadata->name);
}

$mappedFields = $this->getMappedFieldsInEntity($classMetadata);

if ($classMetadata->customRepositoryClassName) {
$this->generateRepository($classMetadata);
}
Expand Down Expand Up @@ -93,6 +95,10 @@ public function regenerateEntities(string $classOrNamespace)
continue;
}

if (!in_array($fieldName, $mappedFields)) {
continue;
}

$manipulator->addEntityField($fieldName, $mapping);
}

Expand All @@ -106,6 +112,10 @@ public function regenerateEntities(string $classOrNamespace)
};

foreach ($classMetadata->associationMappings as $fieldName => $mapping) {
if (!in_array($fieldName, $mappedFields)) {
continue;
}

switch ($mapping['type']) {
case ClassMetadata::MANY_TO_ONE:
$relation = (new RelationManyToOne())
Expand Down Expand Up @@ -225,4 +235,36 @@ private function generateRepository(ClassMetadata $metadata)

$this->generator->writeChanges();
}

private function getMappedFieldsInEntity(ClassMetadata $classMetadata)
{
/* @var $classReflection \ReflectionClass */
$classReflection = $classMetadata->reflClass;

$targetFields = array_merge(
array_keys($classMetadata->fieldMappings),
array_keys($classMetadata->associationMappings)
);

if ($classReflection) {
// exclude traits
$traitProperties = [];

foreach ($classReflection->getTraits() as $trait) {
foreach ($trait->getProperties() as $property) {
$traitProperties[] = $property->getName();
}
}

$targetFields = array_diff($targetFields, $traitProperties);

// exclude inherited properties
$targetFields = array_filter($targetFields, function ($field) use ($classReflection) {
return $classReflection->hasProperty($field) &&
$classReflection->getProperty($field)->getDeclaringClass()->getName() == $classReflection->getName();
});
}

return $targetFields;
}
}
13 changes: 13 additions & 0 deletions src/Util/ClassSourceManipulator.php
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,19 @@ private function addStatementToConstructor(Node\Stmt $stmt)
{
if (!$this->getConstructorNode()) {
$constructorNode = (new Builder\Method('__construct'))->makePublic()->getNode();

// add call to parent::__construct() if there is a need to
try {
$ref = new \ReflectionClass($this->getThisFullClassName());

if ($ref->getParentClass() && $ref->getParentClass()->getConstructor()) {
$constructorNode->stmts[] = new Node\Stmt\Expression(
new Node\Expr\StaticCall(new Node\Name('parent'), new Node\Identifier('__construct'))
);
}
} catch (\ReflectionException $e) {
}

$this->addNodeAfterProperties($constructorNode);
}

Expand Down
20 changes: 18 additions & 2 deletions tests/Doctrine/EntityRegeneratorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,9 @@ private function doTestRegeneration(string $sourceDir, Kernel $kernel, string $n
$fs = new Filesystem();
$tmpDir = __DIR__.'/../tmp/current_project';
$fs->remove($tmpDir);
$fs->mirror($sourceDir, $tmpDir);

// if traits (Timestampable, Teamable) gets copied into new project, tests will fail because of double exclusion
$fs->mirror($sourceDir, $tmpDir, $this->createAllButTraitsIterator($sourceDir));

$kernel->boot();
$container = $kernel->getContainer();
Expand Down Expand Up @@ -114,6 +116,13 @@ private function doTestRegeneration(string $sourceDir, Kernel $kernel, string $n
$this->assertEquals($expectedContents, $actualContents, sprintf('File "%s" does not match: %s', $file->getFilename(), $actualContents));
}
}

private function createAllButTraitsIterator(string $sourceDir): \Iterator
{
$directoryIterator = new \RecursiveDirectoryIterator($sourceDir, \FilesystemIterator::SKIP_DOTS);
$filter = new AllButTraitsIterator($directoryIterator);
return new \RecursiveIteratorIterator($filter, \RecursiveIteratorIterator::SELF_FIRST);
}
}

class TestEntityRegeneratorKernel extends Kernel
Expand Down Expand Up @@ -203,4 +212,11 @@ public function getRootDir()
{
return __DIR__.'/../tmp/current_project';
}
}
}

class AllButTraitsIterator extends \RecursiveFilterIterator
{
public function accept() {
return !in_array($this->current()->getFilename(), ['TeamTrait.php', 'TimestampableTrait.php']);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<?php

namespace Symfony\Bundle\MakerBundle\Tests\Doctrine\fixtures\source_project\src\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
* @ORM\MappedSuperclass()
*/
class BaseClient
{
use TeamTrait;

/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;

/**
* @ORM\Column(type="string")
*/
private $name;

/**
* @ORM\ManyToOne(targetEntity="User")
*/
private $creator;

/**
* @ORM\Column(type="integer")
*/
private $magic;

public function __construct()
{
$this->magic = 42;
}

public function getId()
{
return $this->id;
}

public function getName(): ?string
{
return $this->name;
}

public function setName(string $name): self
{
$this->name = $name;

return $this;
}

public function getMagic(): ?int
{
return $this->magic;
}

public function setMagic(int $magic): self
{
$this->magic = $magic;

return $this;
}

public function getCreator(): ?User
{
return $this->creator;
}

public function setCreator(?User $creator): self
{
$this->creator = $creator;

return $this;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<?php

namespace Symfony\Bundle\MakerBundle\Tests\Doctrine\fixtures\source_project\src\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;

/**
* @ORM\Entity()
*/
class Client extends BaseClient
{
use TimestampableTrait;

/**
* @ORM\Column(type="string")
* @var string
*/
private $apiKey;

/**
* @ORM\ManyToMany(targetEntity="Tag")
*/
private $tags;

/**
* @ORM\Embedded(class="Embed")
*/
private $embed;

public function __construct()
{
parent::__construct();
$this->embed = new Embed();
$this->tags = new ArrayCollection();
}

public function getEmbed(): Embed
{
return $this->embed;
}

public function setEmbed(Embed $embed): self
{
$this->embed = $embed;

return $this;
}

public function getApiKey(): ?string
{
return $this->apiKey;
}

public function setApiKey(string $apiKey): self
{
$this->apiKey = $apiKey;

return $this;
}

/**
* @return Collection|Tag[]
*/
public function getTags(): Collection
{
return $this->tags;
}

public function addTag(Tag $tag): self
{
if (!$this->tags->contains($tag)) {
$this->tags[] = $tag;
}

return $this;
}

public function removeTag(Tag $tag): self
{
if ($this->tags->contains($tag)) {
$this->tags->removeElement($tag);
}

return $this;
}
}
28 changes: 28 additions & 0 deletions tests/Doctrine/fixtures/expected_no_overwrite/src/Entity/Embed.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace Symfony\Bundle\MakerBundle\Tests\Doctrine\fixtures\source_project\src\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
* @ORM\Embeddable()
*/
class Embed
{
/**
* @ORM\Column(type="integer")
*/
private $val;

public function getVal(): ?int
{
return $this->val;
}

public function setVal(int $val): self
{
$this->val = $val;

return $this;
}
}
Loading