1
0
mirror of synced 2024-12-05 03:06:05 +03:00

Merge branch 'hotfix/#1176-merging-entities-with-composite-association-identifier'

Close #1176
This commit is contained in:
Marco Pivetta 2015-01-22 12:11:16 +01:00
commit b889e18a9a
5 changed files with 92 additions and 14 deletions

View File

@ -40,8 +40,7 @@ class AssignedGenerator extends AbstractIdGenerator
*
* @throws \Doctrine\ORM\ORMException
*/
public function generate(
EntityManager $em, $entity)
public function generate(EntityManager $em, $entity)
{
$class = $em->getClassMetadata(get_class($entity));
$idFields = $class->getIdentifierFieldNames();
@ -55,12 +54,8 @@ class AssignedGenerator extends AbstractIdGenerator
}
if (isset($class->associationMappings[$idField])) {
if ( ! $em->getUnitOfWork()->isInIdentityMap($value)) {
throw ORMException::entityMissingForeignAssignedId($entity, $value);
}
// NOTE: Single Columns as associated identifiers only allowed - this constraint it is enforced.
$value = current($em->getUnitOfWork()->getEntityIdentifier($value));
$value = $em->getUnitOfWork()->getSingleIdentifierValue($value);
}
$identifier[$idField] = $value;

View File

@ -36,22 +36,22 @@ final class IdentifierFlattener
/**
* The UnitOfWork used to coordinate object-level transactions.
*
* @var \Doctrine\ORM\UnitOfWork
* @var UnitOfWork
*/
private $unitOfWork;
/**
* The metadata factory, used to retrieve the ORM metadata of entity classes.
*
* @var \Doctrine\Common\Persistence\Mapping\ClassMetadataFactory
* @var ClassMetadataFactory
*/
private $metadataFactory;
/**
* Initializes a new IdentifierFlattener instance, bound to the given EntityManager.
*
* @param \Doctrine\ORM\UnitOfWork $unitOfWork
* @param \Doctrine\Common\Persistence\Mapping\ClassMetadataFactory $metadataFactory
* @param UnitOfWork $unitOfWork
* @param ClassMetadataFactory $metadataFactory
*/
public function __construct(UnitOfWork $unitOfWork, ClassMetadataFactory $metadataFactory)
{
@ -62,8 +62,9 @@ final class IdentifierFlattener
/**
* convert foreign identifiers into scalar foreign key values to avoid object to string conversion failures.
*
* @param \Doctrine\ORM\Mapping\ClassMetadata $class
* @param array $id
* @param ClassMetadata $class
* @param array $id
*
* @return array
*/
public function flattenIdentifier(ClassMetadata $class, array $id)
@ -72,11 +73,14 @@ final class IdentifierFlattener
foreach ($id as $idField => $idValue) {
if (isset($class->associationMappings[$idField]) && is_object($idValue)) {
/* @var $targetClassMetadata ClassMetadata */
$targetClassMetadata = $this->metadataFactory->getMetadataFor(
$class->associationMappings[$idField]['targetEntity']
);
$associatedId = $this->unitOfWork->getEntityIdentifier($idValue);
$associatedId = $this->unitOfWork->isInIdentityMap($idValue)
? $this->unitOfWork->getEntityIdentifier($idValue)
: $targetClassMetadata->getIdentifierValues($idValue);
$flatId[$idField] = $associatedId[$targetClassMetadata->identifier[0]];
} else {

View File

@ -0,0 +1,23 @@
<?php
namespace Doctrine\Tests\Models\MixedToOneIdentity;
/** @Entity */
class CompositeToOneKeyState
{
const CLASSNAME = __CLASS__;
/**
* @Id
* @Column(type="string")
* @GeneratedValue(strategy="NONE")
*/
public $state;
/**
* @Id
* @ManyToOne(targetEntity="Country", cascade={"MERGE"})
* @JoinColumn(referencedColumnName="country")
*/
public $country;
}

View File

@ -0,0 +1,12 @@
<?php
namespace Doctrine\Tests\Models\MixedToOneIdentity;
/** @Entity */
class Country
{
const CLASSNAME = __CLASS__;
/** @Id @Column(type="string") @GeneratedValue(strategy="NONE") */
public $country;
}

View File

@ -0,0 +1,44 @@
<?php
namespace Doctrine\Tests\ORM\Functional;
use Doctrine\Tests\Models\MixedToOneIdentity\CompositeToOneKeyState;
use Doctrine\Tests\Models\MixedToOneIdentity\Country;
class MergeCompositeToOneKeyTest extends \Doctrine\Tests\OrmFunctionalTestCase
{
/**
* {@inheritDoc}
*/
protected function setUp()
{
parent::setUp();
$this->_schemaTool->createSchema(array(
$this->_em->getClassMetadata(Country::CLASSNAME),
$this->_em->getClassMetadata(CompositeToOneKeyState::CLASSNAME),
));
}
/**
* @group DDC-3378
* @group 1176
*/
public function testMergingOfEntityWithCompositeIdentifierContainingToOneAssociation()
{
$country = new Country();
$country->country = 'US';
$state = new CompositeToOneKeyState();
$state->state = 'CA';
$state->country = $country;
/* @var $merged CompositeToOneKeyState */
$merged = $this->_em->merge($state);
$this->assertInstanceOf(CompositeToOneKeyState::CLASSNAME, $state);
$this->assertNotSame($state, $merged);
$this->assertInstanceOf(Country::CLASSNAME, $merged->country);
$this->assertNotSame($country, $merged->country);
}
}