1
0
mirror of synced 2025-03-06 21:06:16 +03:00

Merge branch 'fix/#5935-#5684-#6020-#6152-id-generator-convert-to-custom-dbal-id-type'

Close #5935
Close #5684
Close #6020
Close #6152
This commit is contained in:
Marco Pivetta 2016-11-27 17:49:54 +01:00
commit 77a338e0fd
2 changed files with 158 additions and 27 deletions

View File

@ -19,36 +19,33 @@
namespace Doctrine\ORM; namespace Doctrine\ORM;
use Doctrine\Common\Persistence\Mapping\RuntimeReflectionService;
use Doctrine\DBAL\LockMode;
use Doctrine\ORM\Internal\HydrationCompleteHandler;
use Doctrine\ORM\Mapping\Reflection\ReflectionPropertiesGetter;
use Exception;
use InvalidArgumentException;
use UnexpectedValueException;
use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection; use Doctrine\Common\Collections\Collection;
use Doctrine\Common\NotifyPropertyChanged; use Doctrine\Common\NotifyPropertyChanged;
use Doctrine\Common\PropertyChangedListener; use Doctrine\Common\Persistence\Mapping\RuntimeReflectionService;
use Doctrine\Common\Persistence\ObjectManagerAware; use Doctrine\Common\Persistence\ObjectManagerAware;
use Doctrine\ORM\Mapping\ClassMetadata; use Doctrine\Common\PropertyChangedListener;
use Doctrine\ORM\Proxy\Proxy; use Doctrine\DBAL\LockMode;
use Doctrine\ORM\Cache\Persister\CachedPersister;
use Doctrine\ORM\Event\LifecycleEventArgs; use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\ORM\Event\PreUpdateEventArgs; use Doctrine\ORM\Event\ListenersInvoker;
use Doctrine\ORM\Event\PreFlushEventArgs;
use Doctrine\ORM\Event\OnFlushEventArgs; use Doctrine\ORM\Event\OnFlushEventArgs;
use Doctrine\ORM\Event\PostFlushEventArgs; use Doctrine\ORM\Event\PostFlushEventArgs;
use Doctrine\ORM\Event\ListenersInvoker; use Doctrine\ORM\Event\PreFlushEventArgs;
use Doctrine\ORM\Event\PreUpdateEventArgs;
use Doctrine\ORM\Cache\Persister\CachedPersister; use Doctrine\ORM\Internal\HydrationCompleteHandler;
use Doctrine\ORM\Persisters\Entity\BasicEntityPersister; use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Persisters\Entity\SingleTablePersister; use Doctrine\ORM\Mapping\Reflection\ReflectionPropertiesGetter;
use Doctrine\ORM\Persisters\Entity\JoinedSubclassPersister;
use Doctrine\ORM\Persisters\Collection\OneToManyPersister;
use Doctrine\ORM\Persisters\Collection\ManyToManyPersister; use Doctrine\ORM\Persisters\Collection\ManyToManyPersister;
use Doctrine\ORM\Persisters\Collection\OneToManyPersister;
use Doctrine\ORM\Persisters\Entity\BasicEntityPersister;
use Doctrine\ORM\Persisters\Entity\JoinedSubclassPersister;
use Doctrine\ORM\Persisters\Entity\SingleTablePersister;
use Doctrine\ORM\Proxy\Proxy;
use Doctrine\ORM\Utility\IdentifierFlattener; use Doctrine\ORM\Utility\IdentifierFlattener;
use Exception;
use InvalidArgumentException;
use UnexpectedValueException;
/** /**
* The UnitOfWork is responsible for tracking changes to objects during an * The UnitOfWork is responsible for tracking changes to objects during an
@ -890,7 +887,7 @@ class UnitOfWork implements PropertyChangedListener
$idValue = $idGen->generate($this->em, $entity); $idValue = $idGen->generate($this->em, $entity);
if ( ! $idGen instanceof \Doctrine\ORM\Id\AssignedGenerator) { if ( ! $idGen instanceof \Doctrine\ORM\Id\AssignedGenerator) {
$idValue = array($class->identifier[0] => $idValue); $idValue = [$class->getSingleIdentifierFieldName() => $this->convertSingleFieldIdentifierToPHPValue($class, $idValue)];
$class->setIdentifierValues($entity, $idValue); $class->setIdentifierValues($entity, $idValue);
} }
@ -1008,16 +1005,17 @@ class UnitOfWork implements PropertyChangedListener
if ($postInsertIds) { if ($postInsertIds) {
// Persister returned post-insert IDs // Persister returned post-insert IDs
foreach ($postInsertIds as $postInsertId) { foreach ($postInsertIds as $postInsertId) {
$id = $postInsertId['generatedId']; $idField = $class->getSingleIdentifierFieldName();
$idValue = $this->convertSingleFieldIdentifierToPHPValue($class, $postInsertId['generatedId']);
$entity = $postInsertId['entity']; $entity = $postInsertId['entity'];
$oid = spl_object_hash($entity); $oid = spl_object_hash($entity);
$idField = $class->identifier[0];
$class->reflFields[$idField]->setValue($entity, $id); $class->reflFields[$idField]->setValue($entity, $idValue);
$this->entityIdentifiers[$oid] = array($idField => $id); $this->entityIdentifiers[$oid] = array($idField => $idValue);
$this->entityStates[$oid] = self::STATE_MANAGED; $this->entityStates[$oid] = self::STATE_MANAGED;
$this->originalEntityData[$oid][$idField] = $id; $this->originalEntityData[$oid][$idField] = $idValue;
$this->addToIdentityMap($entity); $this->addToIdentityMap($entity);
} }
@ -3467,4 +3465,20 @@ class UnitOfWork implements PropertyChangedListener
} }
} }
} }
/**
* @param ClassMetadata $class
* @param mixed $identifierValue
*
* @return mixed the identifier after type conversion
*
* @throws \Doctrine\ORM\Mapping\MappingException if the entity has more than a single identifier
*/
private function convertSingleFieldIdentifierToPHPValue(ClassMetadata $class, $identifierValue)
{
return $this->em->getConnection()->convertToPHPValue(
$identifierValue,
$class->getTypeOfField($class->getSingleIdentifierFieldName())
);
}
} }

View File

@ -0,0 +1,117 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Types as DBALTypes;
/**
* This test verifies that custom post-insert identifiers respect type conversion semantics.
* The generated identifier must be converted via DBAL types before populating the entity
* identifier field.
*
* @group 5935 5684 6020 6152
*/
class DDC5684Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
protected function setUp()
{
parent::setUp();
if (DBALTypes\Type::hasType(DDC5684ObjectIdType::CLASSNAME)) {
DBALTypes\Type::overrideType(DDC5684ObjectIdType::CLASSNAME, DDC5684ObjectIdType::CLASSNAME);
} else {
DBALTypes\Type::addType(DDC5684ObjectIdType::CLASSNAME, DDC5684ObjectIdType::CLASSNAME);
}
$this->_schemaTool->createSchema([$this->_em->getClassMetadata(DDC5684Object::CLASSNAME)]);
}
protected function tearDown()
{
$this->_schemaTool->dropSchema([$this->_em->getClassMetadata(DDC5684Object::CLASSNAME)]);
parent::tearDown();
}
public function testAutoIncrementIdWithCustomType()
{
$object = new DDC5684Object();
$this->_em->persist($object);
$this->_em->flush();
$this->assertInstanceOf(DDC5684ObjectId::CLASSNAME, $object->id);
}
public function testFetchObjectWithAutoIncrementedCustomType()
{
$object = new DDC5684Object();
$this->_em->persist($object);
$this->_em->flush();
$this->_em->clear();
$rawId = $object->id->value;
$object = $this->_em->find(DDC5684Object::CLASSNAME, new DDC5684ObjectId($rawId));
$this->assertInstanceOf(DDC5684ObjectId::CLASSNAME, $object->id);
$this->assertEquals($rawId, $object->id->value);
}
}
class DDC5684ObjectIdType extends DBALTypes\IntegerType
{
const CLASSNAME = __CLASS__;
public function convertToPHPValue($value, AbstractPlatform $platform)
{
return new DDC5684ObjectId($value);
}
public function convertToDatabaseValue($value, AbstractPlatform $platform)
{
return $value->value;
}
public function getName()
{
return self::CLASSNAME;
}
public function requiresSQLCommentHint(AbstractPlatform $platform)
{
return true;
}
}
class DDC5684ObjectId
{
const CLASSNAME = __CLASS__;
public $value;
public function __construct($value)
{
$this->value = $value;
}
public function __toString()
{
return (string) $this->value;
}
}
/**
* @Entity
* @Table(name="ticket_5684_objects")
*/
class DDC5684Object
{
const CLASSNAME = __CLASS__;
/**
* @Id
* @Column(type=Doctrine\Tests\ORM\Functional\Ticket\DDC5684ObjectIdType::class)
* @GeneratedValue(strategy="AUTO")
*/
public $id;
}