Skip to content

Commit

Permalink
Allow to directly override properties, without using @Orm\AttributeOv…
Browse files Browse the repository at this point in the history
…errides
  • Loading branch information
joschi127 committed Mar 26, 2018
1 parent 272be2d commit 82af596
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 12 deletions.
54 changes: 44 additions & 10 deletions EventListener/LoadORMMetadataSubscriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs)
} else {
$this->unsetAssociationMappings($metadata);
$this->unsetFieldMappings($metadata, $wasMappedSuperclass);
$this->unsetOverriddenFieldMappings($metadata, $eventArgs->getEntityManager()->getConfiguration());
}

$this->updateAssociationMappingsToMappedSuperclasses($metadata);
Expand Down Expand Up @@ -213,16 +214,14 @@ protected function setFieldMappings(ClassMetadataInfo $metadata, $configuration,
// ... add field mapping of the parent class to the the actually used class - it was removed
// from the parent class in unsetFieldMappings()
foreach ($parentMetadata->fieldMappings as $name => $mapping) {
// remove existing mapping for these fields
unset($metadata->fieldMappings[$mapping['fieldName']]);
unset($metadata->columnNames[$mapping['fieldName']]);
unset($metadata->fieldNames[$mapping['columnName']]);

// re-add mapping for these fields (as if it were fields of the class itself, not
// inherited fields)
unset($mapping['declared']);
unset($mapping['inherited']);
$metadata->mapField($mapping);
// only inherit mapping if class does not have an own mapping for this field itself
// (this makes it possible to just override mappings, without having to use
// @ORM\AttributeOverrides)
if (!isset($metadata->fieldMappings[$mapping['fieldName']])) {
unset($mapping['declared']);
unset($mapping['inherited']);
$metadata->mapField($mapping);
}
}
foreach ($parentMetadata->reflFields as $name => $field) {
if (!isset($metadata->reflFields[$name])) {
Expand Down Expand Up @@ -323,6 +322,26 @@ protected function unsetFieldMappings(ClassMetadataInfo $metadata, $wasMappedSup
return;
}

protected function unsetOverriddenFieldMappings(ClassMetadataInfo $metadata, $configuration)
{
if ($this->classIsOverridden($metadata->getName())) {
$allOverridingClasses = $this->getAllOverridingClasses($metadata->getName());

foreach($allOverridingClasses as $overridingClass) {
$overridingMetadata = $this->getClassMetadata($overridingClass, $configuration);
if (in_array($overridingClass, $configuration->getMetadataDriverImpl()->getAllClassNames())) {
$configuration->getMetadataDriverImpl()->loadMetadataForClass($overridingClass, $overridingMetadata);

foreach ($metadata->fieldMappings as $name => $mapping) {
if ($overridingMetadata->hasField($name) && !$overridingMetadata->isInheritedField($name)) {
unset($metadata->fieldMappings[$name]);
}
}
}
}
}
}

protected function updateAssociationMappingsToMappedSuperclasses(ClassMetadataInfo $metadata)
{
// update association mappings of other classes, which are pointing to a class which is overridden
Expand Down Expand Up @@ -377,6 +396,21 @@ protected function getOverridingClass($className)
return null;
}

protected function getAllOverridingClasses($className)
{
$overridingClass = $this->getOverridingClass($className);
$allOverridingClasses = [ $overridingClass ];
foreach($this->parentClassesByClass[$overridingClass] as $parentClass) {
if ($parentClass == $className) {
break;
}

array_unshift($allOverridingClasses, $parentClass);
}

return $allOverridingClasses;
}

protected function typeIsRelation($type)
{
return in_array(
Expand Down
7 changes: 6 additions & 1 deletion Tests/EntityOverride/CustomizedExamplePlainTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@

class CustomizedExamplePlainTest extends TestBase
{
public function testCustimizedEntity()
public function testCustomizedEntity()
{
$this->drop();

$e = new CustomizedExamplePlain();
$e->setDefaultFieldProtected('test_value_1');
$e->setDefaultFieldPrivate('test_value_2');
$e->setAdditionalCustomField('test_value_3');
$e->setOverriddenField('test_value_4_with_more_than_20_characters'); // override will allow 50 instead of only 20 characters
$this->em->persist($e);
$this->em->flush();
$this->em->clear();
Expand All @@ -29,6 +30,9 @@ public function testCustimizedEntity()

$this->fetchAndCheckCustomizedEntityBy(['additionalCustomField' => 'test_value_3']);
$this->em->clear();

$this->fetchAndCheckCustomizedEntityBy(['overriddenField' => 'test_value_4_with_more_than_20_characters']);
$this->em->clear();
}

protected function fetchAndCheckCustomizedEntityBy(array $criteria)
Expand All @@ -45,6 +49,7 @@ protected function fetchAndCheckCustomizedEntityBy(array $criteria)
$this->assertEquals('test_value_1', $e->getDefaultFieldProtected());
$this->assertEquals('test_value_2', $e->getDefaultFieldPrivate());
$this->assertEquals('test_value_3', $e->getAdditionalCustomField());
$this->assertEquals('test_value_4_with_more_than_20_characters', $e->getOverriddenField());
}

protected function drop()
Expand Down
6 changes: 6 additions & 0 deletions Tests/Functional/src/Entity/CustomizedExamplePlain.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ class CustomizedExamplePlain extends ExamplePlain
*/
protected $additionalCustomField;

/**
* @var string
* @ORM\Column(type="string", length=50, nullable=true)
*/
protected $overriddenField;

/**
* @return string
*/
Expand Down
17 changes: 17 additions & 0 deletions Tests/Functional/src/Entity/CustomizedUser.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
/**
* @ORM\Entity
* @ORM\Table(name="test_user")
*
*/
class CustomizedUser extends User
{
Expand All @@ -18,6 +19,22 @@ class CustomizedUser extends User
*/
protected $phoneNumber;

/**
* Overridden property from FOS\UserBundle\Model\User and Joschi127\DoctrineEntityOverrideBundle\Tests\Functional\src\Entity\User.
*
* @var string
* @ORM\Column(type="string", length=220, nullable=false)
*/
protected $email;

/**
* Overridden property from FOS\UserBundle\Model\User.
*
* @var string
* @ORM\Column(type="string", length=230, nullable=true)
*/
protected $password;

public function __construct()
{
parent::__construct();
Expand Down
24 changes: 23 additions & 1 deletion Tests/Functional/src/Entity/ExamplePlain.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,13 @@ class ExamplePlain
* @ORM\Column(type="string", length=255, nullable=true)
*/
private $defaultFieldPrivate; // special handling for private inherited properties required, so let us
// check both, protected and private properties, in our test
// check both, protected and private properties, in our test

/**
* @var string
* @ORM\Column(type="string", length=20, nullable=false)
*/
protected $overriddenField;

/**
* @return int
Expand Down Expand Up @@ -72,4 +78,20 @@ public function setDefaultFieldPrivate($defaultFieldPrivate)
{
$this->defaultFieldPrivate = $defaultFieldPrivate;
}

/**
* @return string
*/
public function getOverriddenField()
{
return $this->overriddenField;
}

/**
* @param string $overriddenField
*/
public function setOverriddenField($overriddenField)
{
$this->overriddenField = $overriddenField;
}
}
16 changes: 16 additions & 0 deletions Tests/Functional/src/Entity/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,22 @@ class User extends BaseUser
*/
protected $lastName;

/**
* Overridden property from FOS\UserBundle\Model\User.
*
* @var string
* @ORM\Column(type="string", length=110, nullable=false)
*/
protected $username;

/**
* Overridden property from FOS\UserBundle\Model\User.
*
* @var string
* @ORM\Column(type="string", length=120, nullable=true)
*/
protected $email;

/**
* @var ArrayCollection
* @ORM\ManyToMany(targetEntity="Joschi127\DoctrineEntityOverrideBundle\Tests\Functional\src\Entity\Group", cascade={"persist"})
Expand Down

0 comments on commit 82af596

Please sign in to comment.