From 256f9af5b3c5809d7624945b69d3f0cb94dbfed2 Mon Sep 17 00:00:00 2001 From: ElectricMaxxx Date: Tue, 17 Jan 2017 22:34:12 +0100 Subject: [PATCH 1/5] use uuid build reference and register document by uuid --- composer.json | 3 +- lib/Doctrine/ODM/PHPCR/DocumentManager.php | 8 ++- lib/Doctrine/ODM/PHPCR/UnitOfWork.php | 41 +++++++++++--- .../Tests/ODM/PHPCR/UnitOfWorkTest.php | 54 +++++++++++++++---- 4 files changed, 83 insertions(+), 23 deletions(-) diff --git a/composer.json b/composer.json index cc0febc01..a4ffe5c14 100644 --- a/composer.json +++ b/composer.json @@ -21,7 +21,8 @@ "phpcr/phpcr-implementation": "^2.1.0", "phpcr/phpcr-utils": "^1.2.8", "doctrine/instantiator": "^1.0.1", - "symfony/console": "^2.3|^3.0" + "symfony/console": "^2.3|^3.0", + "jackalope/jackalope-doctrine-dbal": "~1.0" }, "require-dev": { "symfony/yaml": "^2.3|^3.0", diff --git a/lib/Doctrine/ODM/PHPCR/DocumentManager.php b/lib/Doctrine/ODM/PHPCR/DocumentManager.php index 0d46ec039..f40549ad2 100644 --- a/lib/Doctrine/ODM/PHPCR/DocumentManager.php +++ b/lib/Doctrine/ODM/PHPCR/DocumentManager.php @@ -917,13 +917,11 @@ public function initializeObject($document) */ public function getNodeForDocument($document) { - if (!is_object($document)) { - throw new InvalidArgumentException('Parameter $document needs to be an object, '.gettype($document).' given'); + if (!$identifier = $this->unitOfWork->getDocumentId($document)) { + throw new InvalidArgumentException('This document is not managed by this manager.'); } - $path = $this->unitOfWork->getDocumentId($document); - - return $this->session->getNode($path); + return $this->unitOfWork->getNodeByPathOrUuid($identifier); } /** diff --git a/lib/Doctrine/ODM/PHPCR/UnitOfWork.php b/lib/Doctrine/ODM/PHPCR/UnitOfWork.php index 4a0f9691c..b1b4da7e6 100644 --- a/lib/Doctrine/ODM/PHPCR/UnitOfWork.php +++ b/lib/Doctrine/ODM/PHPCR/UnitOfWork.php @@ -34,6 +34,7 @@ use Doctrine\ODM\PHPCR\Exception\RuntimeException; use Doctrine\ODM\PHPCR\Id\AssignedIdGenerator; use Doctrine\ODM\PHPCR\Id\IdException; +use Doctrine\ODM\PHPCR\Mapping\Annotations\Id; use Doctrine\ODM\PHPCR\Mapping\ClassMetadata; use Doctrine\ODM\PHPCR\Mapping\MappingException; use Doctrine\ODM\PHPCR\Id\IdGenerator; @@ -674,7 +675,7 @@ public function getOrCreateProxy($targetId, $className, $locale = null) $metadata = $this->dm->getClassMetadata($className); $proxyDocument = $this->dm->getProxyFactory()->getProxy($className, array($metadata->identifier => $targetId)); - // register the document under its own id + // register the document under its own id/uuid $this->registerDocument($proxyDocument, $targetId); if ($locale) { @@ -692,7 +693,12 @@ public function getOrCreateProxy($targetId, $className, $locale = null) */ public function refreshDocumentForProxy($className, Proxy $document) { - $node = $this->session->getNode($this->determineDocumentId($document)); + $pathOrUuid = $this->determineDocumentId($document); + $node = $this->getNodeByPathOrUuid($pathOrUuid); + if (UUIDHelper::isUUID($pathOrUuid)) { + $this->unregisterDocument($document); + $this->registerDocument($document, $node->getPath()); + } $hints = array('refresh' => true, 'fallback' => true); @@ -3063,18 +3069,25 @@ private function unregisterDocument($document) /** * @param object $document - * @param string $id The document id to look for. + * @param string $pathOrUuid The document id to look for. * * @return string generated object hash */ - public function registerDocument($document, $id) + public function registerDocument($document, $pathOrUuid) { $oid = spl_object_hash($document); - $this->documentIds[$oid] = $id; - $this->identityMap[$id] = $document; + $this->documentIds[$oid] = $pathOrUuid; + $this->identityMap[$pathOrUuid] = $document; // frozen nodes need another state so they are managed but not included for updates - $frozen = $this->session->nodeExists($id) && $this->session->getNode($id)->isNodeType('nt:frozenNode'); + try { + $node = $this->getNodeByPathOrUuid($pathOrUuid); + $frozen = $node instanceof NodeInterface ? $node->isNodeType('nt:frozenNode') : false; + } catch (ItemNotFoundException $e) { + $frozen = false; + } catch (PathNotFoundException $e) { + $frozen = false; + } $this->setDocumentState($oid, $frozen ? self::STATE_FROZEN : self::STATE_MANAGED); @@ -3112,6 +3125,20 @@ public function getDocumentById($id) return false; } + /** + * Creates a node from a given path or an uuid + * + * @param $pathOrUuid + * + * @return NodeInterface + */ + public function getNodeByPathOrUuid($pathOrUuid) + { + return UUIDHelper::isUUID($pathOrUuid) + ? $this->session->getNodeByIdentifier($pathOrUuid) + : $this->session->getNode($pathOrUuid); + } + /** * Get the object ID for the given document * diff --git a/tests/Doctrine/Tests/ODM/PHPCR/UnitOfWorkTest.php b/tests/Doctrine/Tests/ODM/PHPCR/UnitOfWorkTest.php index f8b5f2eed..ced4670c9 100644 --- a/tests/Doctrine/Tests/ODM/PHPCR/UnitOfWorkTest.php +++ b/tests/Doctrine/Tests/ODM/PHPCR/UnitOfWorkTest.php @@ -8,6 +8,7 @@ use Doctrine\ODM\PHPCR\Mapping\ClassMetadata; use Jackalope\Factory; use Jackalope\Node; +use PHPCR\Util\UUIDHelper; /** * TODO: remove Jackalope dependency @@ -56,7 +57,7 @@ public function setUp() $this->session = $this->getMockBuilder('Jackalope\Session') ->disableOriginalConstructor() ->getMock(); - + $this->objectManager = $this->getMockBuilder('Jackalope\ObjectManager') ->disableOriginalConstructor() ->getMock(); @@ -74,54 +75,66 @@ public function setUp() $cmf->setMetadataFor($this->type, $metadata); } - protected function createNode($id, $username, $primaryType = 'rep:root') + protected function createNode($id, $username, $primaryType = 'rep:root', $uuid = null) { $repository = $this->getMockBuilder('Jackalope\Repository')->disableOriginalConstructor()->getMock(); $this->session->expects($this->any()) ->method('getRepository') ->with() ->will($this->returnValue($repository)); - + $type = $this->getMockBuilder('Jackalope\NodeType\NodeType')->disableOriginalConstructor()->getMock(); $type->expects($this->any()) ->method('getName') ->with() ->will($this->returnValue($primaryType)); - + $ntm = $this->getMockBuilder('Jackalope\NodeType\NodeTypeManager')->disableOriginalConstructor()->getMock(); $ntm->expects($this->any()) ->method('getNodeType') ->with() ->will($this->returnValue($type)); - + $workspace = $this->getMockBuilder('Jackalope\Workspace')->disableOriginalConstructor()->getMock(); $workspace->expects($this->any()) ->method('getNodeTypeManager') ->with() ->will($this->returnValue($ntm)); - + $this->session->expects($this->any()) ->method('getWorkspace') ->with() ->will($this->returnValue($workspace)); - + $this->session->expects($this->any()) ->method('nodeExists') ->with($id) ->will($this->returnValue(true)); - + $nodeData = array( "jcr:primaryType" => $primaryType, "jcr:system" => array(), 'username' => $username, ); + if (null !== $uuid) { + $nodeData['jcr:uuid'] = $uuid; + } + $node = new Node($this->factory, $nodeData, $id, $this->session, $this->objectManager); - + $this->session->expects($this->any()) ->method('getNode') ->with($id) ->will($this->returnValue($node)); - + + if (null !== $uuid) { + $this->session->expects($this->any()) + ->method('getNodeByIdentifier') + ->with($uuid) + ->will($this->returnValue($node)); + } + + return $node; } @@ -247,6 +260,27 @@ public function testComputeSingleDocumentChangeSetForRemovedDocument() // Should not throw "InvalidArgumentException: Document has to be managed for single computation" $this->uow->computeSingleDocumentChangeSet($object); } + + public function testGetOrCreateProxy() + { + $user = $this->uow->getOrCreateDocument($this->type, $this->createNode('/somepath', 'foo')); + $this->uow->clear(); + $userAsReference = $this->uow->getOrCreateProxy($user->id, get_class($user)); + + $this->assertEquals(2, $this->uow->getDocumentState($userAsReference)); + $this->assertEquals($userAsReference, $this->uow->getDocumentById($userAsReference->id)); + } + + public function testGetOrCreateProxyWithUuid() + { + $uuid = UUIDHelper::generateUUID(); + $user = $this->uow->getOrCreateDocument($this->type, $this->createNode('/somepath', 'foo', 'rep:root', $uuid)); + $this->uow->clear(); + $userAsReference = $this->uow->getOrCreateProxy($uuid, get_class($user)); + + $this->assertEquals(2, $this->uow->getDocumentState($userAsReference)); + $this->assertEquals($userAsReference, $this->uow->getDocumentById($uuid)); + } } class UoWUser From b6853e739f95462cd3315135b8442a68795d6094 Mon Sep 17 00:00:00 2001 From: ElectricMaxxx Date: Wed, 18 Jan 2017 00:03:40 +0100 Subject: [PATCH 2/5] try to introduce uuid -> path mapping with documents managed by uuid --- composer.json | 3 +- lib/Doctrine/ODM/PHPCR/DocumentManager.php | 41 ++-- lib/Doctrine/ODM/PHPCR/UnitOfWork.php | 184 +++++++++++------- .../Tests/ODM/PHPCR/UnitOfWorkTest.php | 8 +- 4 files changed, 142 insertions(+), 94 deletions(-) diff --git a/composer.json b/composer.json index a4ffe5c14..cc0febc01 100644 --- a/composer.json +++ b/composer.json @@ -21,8 +21,7 @@ "phpcr/phpcr-implementation": "^2.1.0", "phpcr/phpcr-utils": "^1.2.8", "doctrine/instantiator": "^1.0.1", - "symfony/console": "^2.3|^3.0", - "jackalope/jackalope-doctrine-dbal": "~1.0" + "symfony/console": "^2.3|^3.0" }, "require-dev": { "symfony/yaml": "^2.3|^3.0", diff --git a/lib/Doctrine/ODM/PHPCR/DocumentManager.php b/lib/Doctrine/ODM/PHPCR/DocumentManager.php index f40549ad2..fde511ca6 100644 --- a/lib/Doctrine/ODM/PHPCR/DocumentManager.php +++ b/lib/Doctrine/ODM/PHPCR/DocumentManager.php @@ -280,30 +280,29 @@ public function getClassMetadata($className) */ public function find($className, $id) { - try { - if (UUIDHelper::isUUID($id)) { - try { - $id = $this->session->getNodeByIdentifier($id)->getPath(); - } catch (ItemNotFoundException $e) { - return null; - } - } elseif (strpos($id, '/') !== 0) { - $id = '/'.$id; - } + if (!UUIDHelper::isUUID($id) && strpos($id, '/') !== 0) { + $id = '/'.$id; + } - $document = $this->unitOfWork->getDocumentById($id); - if ($document) { - try { - $this->unitOfWork->validateClassName($document, $className); + // try to get a manage document + $document = $this->unitOfWork->getDocumentByPathOrUuid($id); + if ($document) { + try { + $this->unitOfWork->validateClassName($document, $className); - return $document; - } catch (ClassMismatchException $e) { - return null; - } + return $document; + } catch (ClassMismatchException $e) { + return null; } - $node = $this->session->getNode($id); + } + + // get the node + try { + $node = $this->unitOfWork->getNodeByPathOrUuid($id); } catch (PathNotFoundException $e) { return null; + } catch (ItemNotFoundException $e) { + return null; } $hints = array('fallback' => true); @@ -368,7 +367,7 @@ public function findTranslation($className, $id, $locale, $fallback = true) $id = '/'.$id; } - $document = $this->unitOfWork->getDocumentById($id); + $document = $this->unitOfWork->getDocumentByPathOrUuid($id); if ($document) { $this->unitOfWork->validateClassName($document, $className); @@ -917,7 +916,7 @@ public function initializeObject($document) */ public function getNodeForDocument($document) { - if (!$identifier = $this->unitOfWork->getDocumentId($document)) { + if (null === $identifier = $this->unitOfWork->getDocumentId($document)) { throw new InvalidArgumentException('This document is not managed by this manager.'); } diff --git a/lib/Doctrine/ODM/PHPCR/UnitOfWork.php b/lib/Doctrine/ODM/PHPCR/UnitOfWork.php index b1b4da7e6..afa43ba48 100644 --- a/lib/Doctrine/ODM/PHPCR/UnitOfWork.php +++ b/lib/Doctrine/ODM/PHPCR/UnitOfWork.php @@ -100,6 +100,18 @@ class UnitOfWork */ private $documentIds = array(); + /** + * @var array + */ + private $documentUuids = array(); + + /** + * Mapping to find ids (abs. path) of document managed by its uuid. + * + * @var array + */ + private $uuidIdMapping = array(); + /** * Track version history of the version documents we create, indexed by spl_object_hash * @var \PHPCR\Version\VersionHistoryInterface[] @@ -388,14 +400,14 @@ public function getOrCreateDocuments($className, $nodes, array &$hints = array() $class = $this->dm->getClassMetadata($actualClassName); // prepare first, add later when fine - $document = $this->getDocumentById($id); + $document = $this->getDocumentByPathOrUuid($id); if ($document) { if (!$refresh) { ++$existingDocuments; $documents[$id] = $document; } else { - $overrideLocalValuesOids[$id] = spl_object_hash($document); + $overrideLocalValuesOids[$id] = $this->getObjectId($document); } try { @@ -444,7 +456,7 @@ public function getOrCreateDocuments($className, $nodes, array &$hints = array() foreach ($nodes as $node) { $id = $node->getPath(); - $document = $this->getDocumentById($id) ?: (isset($documents[$id]) ? $documents[$id] : null); + $document = $this->getDocumentByPathOrUuid($id) ?: (isset($documents[$id]) ? $documents[$id] : null); if (! $document) { continue; @@ -660,7 +672,7 @@ public function getOrCreateProxyFromNode(NodeInterface $node, $locale = null) */ public function getOrCreateProxy($targetId, $className, $locale = null) { - $document = $this->getDocumentById($targetId); + $document = $this->getDocumentByPathOrUuid($targetId); // check if referenced document already exists if ($document) { @@ -675,7 +687,7 @@ public function getOrCreateProxy($targetId, $className, $locale = null) $metadata = $this->dm->getClassMetadata($className); $proxyDocument = $this->dm->getProxyFactory()->getProxy($className, array($metadata->identifier => $targetId)); - // register the document under its own id/uuid + // register the document under its own path/uuid $this->registerDocument($proxyDocument, $targetId); if ($locale) { @@ -695,6 +707,7 @@ public function refreshDocumentForProxy($className, Proxy $document) { $pathOrUuid = $this->determineDocumentId($document); $node = $this->getNodeByPathOrUuid($pathOrUuid); + if (UUIDHelper::isUUID($pathOrUuid)) { $this->unregisterDocument($document); $this->registerDocument($document, $node->getPath()); @@ -702,7 +715,7 @@ public function refreshDocumentForProxy($className, Proxy $document) $hints = array('refresh' => true, 'fallback' => true); - $oid = spl_object_hash($document); + $oid = $this->getObjectId($document); if (isset($this->documentLocales[$oid]['current'])) { $hints['locale'] = $this->documentLocales[$oid]['current']; } @@ -752,7 +765,7 @@ public function bindTranslation($document, $locale) */ private function doBindTranslation($document, $locale, ClassMetadata $class) { - $oid = spl_object_hash($document); + $oid = $this->getObjectId($document); // only trigger the events if we bind a new translation if (empty($this->documentTranslations[$oid][$locale]) @@ -802,7 +815,7 @@ private function doScheduleInsert($document, &$visited, $overrideIdGenerator = n )); } - $oid = spl_object_hash($document); + $oid = $this->getObjectId($document); // To avoid recursion loops (over children and parents) if (isset($visited[$oid])) { return; @@ -933,7 +946,7 @@ private function getIdGenerator($type) public function scheduleMove($document, $targetPath) { - $oid = spl_object_hash($document); + $oid = $this->getObjectId($document); $state = $this->getDocumentState($document); @@ -954,7 +967,7 @@ public function scheduleMove($document, $targetPath) public function scheduleReorder($document, $srcName, $targetName, $before) { - $oid = spl_object_hash($document); + $oid = $this->getObjectId($document); $state = $this->getDocumentState($document); switch ($state) { @@ -978,7 +991,7 @@ public function scheduleRemove($document) private function doRemove($document, &$visited) { - $oid = spl_object_hash($document); + $oid = $this->getObjectId($document); if (isset($visited[$oid])) { return; } @@ -1067,7 +1080,7 @@ private function purgeChildren($document) */ private function setDocumentState($document, $state) { - $oid = is_object($document) ? spl_object_hash($document) : $document; + $oid = $this->getObjectId($document); $this->documentState[$oid] = $state; } @@ -1085,7 +1098,7 @@ private function setDocumentState($document, $state) */ public function getDocumentState($document) { - $oid = spl_object_hash($document); + $oid = $this->getObjectId($document); if (!isset($this->documentState[$oid])) { // this will only use the metadata if id is mapped $id = $this->determineDocumentId($document); @@ -1094,7 +1107,7 @@ public function getDocumentState($document) return self::STATE_NEW; } - if ($this->getDocumentById($id)) { + if ($this->getDocumentByPathOrUuid($id)) { return self::STATE_DETACHED; } @@ -1114,7 +1127,7 @@ public function getDocumentState($document) */ public function isScheduledForInsert($document) { - return isset($this->scheduledInserts[spl_object_hash($document)]); + return isset($this->scheduledInserts[$this->getObjectId($document)]); } /** @@ -1140,7 +1153,7 @@ public function computeSingleDocumentChangeSet($document) return; } - $oid = spl_object_hash($document); + $oid = $this->getObjectId($document); if (!isset($this->scheduledInserts[$oid])) { $class = $this->dm->getClassMetadata(get_class($document)); $this->computeChangeSet($class, $document); @@ -1325,7 +1338,7 @@ private function computeAssociationChanges($document, $class, $oid, $isNew, $cha $associations = $this->originalData[$oid][$fieldName]->getOriginalPaths(); foreach ($associations as $association) { - $association = $this->getDocumentById($association); + $association = $this->getDocumentByPathOrUuid($association); if ($association && !$this->originalData[$oid][$fieldName]->contains($association)) { $this->scheduleRemove($association); } @@ -1421,7 +1434,7 @@ private function computeChildrenChanges($document, $class, $oid, $isNew, $change foreach ($originalNames as $key => $childName) { // check moved children to not accidentally remove a child that simply moved away. if (!(in_array($childName, $childNames) || in_array($childName, $movedChildNames))) { - $child = $this->getDocumentById($id.'/'.$childName); + $child = $this->getDocumentByPathOrUuid($id.'/'.$childName); $this->scheduleRemove($child); unset($originalNames[$key]); } @@ -1462,7 +1475,7 @@ public function computeChangeSet(ClassMetadata $class, $document) return; } - $oid = spl_object_hash($document); + $oid = $this->getObjectId($document); if (in_array($oid, $this->changesetComputed)) { return; } @@ -1598,7 +1611,7 @@ public function computeChangeSet(ClassMetadata $class, $document) $translationChanges = false; if ($this->isDocumentTranslatable($class)) { - $oid = spl_object_hash($document); + $oid = $this->getObjectId($document); if (isset($this->documentTranslations[$oid])) { foreach ($this->documentTranslations[$oid] as $localeToCheck => $data) { // a translation was removed @@ -1692,7 +1705,7 @@ private function computeChildChanges($mapping, $child, $parentId, $nodename, $pa $childId = $parentId.'/'.$nodename; $targetClass->setIdentifierValue($child, $childId); - if ($this->getDocumentById($childId)) { + if ($this->getDocumentByPathOrUuid($childId)) { $child = $this->merge($child); } else { $this->persistNew($targetClass, $child, ClassMetadata::GENERATOR_TYPE_ASSIGNED, $parent); @@ -1809,7 +1822,7 @@ public function refresh($document) private function doRefresh($document, &$visited) { - $oid = spl_object_hash($document); + $oid = $this->getObjectId($document); if (isset($visited[$oid])) { return; } @@ -1869,7 +1882,7 @@ private function cascadeMergeCollection($managedCol, array $mapping) private function doMerge($document, array &$visited, $prevManagedCopy = null, $assoc = null) { - $oid = spl_object_hash($document); + $oid = $this->getObjectId($document); if (isset($visited[$oid])) { return $document; // Prevent infinite recursion } @@ -1894,7 +1907,7 @@ private function doMerge($document, array &$visited, $prevManagedCopy = null, $a $managedCopy = $class->newInstance(); $persist = true; } else { - $managedCopy = $this->getDocumentById($id); + $managedCopy = $this->getDocumentByPathOrUuid($id); if ($managedCopy) { // We have the document in-memory already, just make sure its not removed. if ($this->getDocumentState($managedCopy) == self::STATE_REMOVED) { @@ -2091,7 +2104,7 @@ public function detach($document) */ private function doDetach($document, array &$visited) { - $oid = spl_object_hash($document); + $oid = $this->getObjectId($document); if (isset($visited[$oid])) { return; // Prevent infinite recursion } @@ -2768,7 +2781,7 @@ private function executeMoves($documents) $newId = $targetPath.substr($id, strlen($sourcePath)); $this->documentIds[$childOid] = $newId; - $child = $this->getDocumentById($id); + $child = $this->getDocumentByPathOrUuid($id); if (!$child) { continue; } @@ -2849,8 +2862,8 @@ private function executeReorders($documents) */ private function executeRemovals($documents) { - foreach ($documents as $oid => $document) { - if (empty($this->documentIds[$oid])) { + foreach ($documents as $document) { + if (!$this->documentIsManaged($document)) { continue; } @@ -3041,8 +3054,7 @@ public function removeVersion($documentVersion) */ private function unregisterDocument($document) { - $oid = spl_object_hash($document); - + $oid = $this->getObjectId($document); if (isset($this->documentIds[$oid])) { unset($this->identityMap[$this->documentIds[$oid]]); } @@ -3064,6 +3076,10 @@ private function unregisterDocument($document) $this->documentVersion[$oid] ); + if (!empty($this->documentUuids[$oid]) && array_key_exists($this->documentUuids[$oid], $this->uuidIdMapping)) { + unset($this->uuidIdMapping[$this->documentUuids[$oid]], $this->documentUuids[$oid]); + } + $this->changesetComputed = array_diff($this->changesetComputed, array($oid)); } @@ -3075,20 +3091,22 @@ private function unregisterDocument($document) */ public function registerDocument($document, $pathOrUuid) { - $oid = spl_object_hash($document); - $this->documentIds[$oid] = $pathOrUuid; - $this->identityMap[$pathOrUuid] = $document; + $oid = $this->getObjectId($document); + // we shouldn't register document which can not be found, so we don't catch exception here + $node = $this->getNodeByPathOrUuid($pathOrUuid); - // frozen nodes need another state so they are managed but not included for updates - try { - $node = $this->getNodeByPathOrUuid($pathOrUuid); - $frozen = $node instanceof NodeInterface ? $node->isNodeType('nt:frozenNode') : false; - } catch (ItemNotFoundException $e) { - $frozen = false; - } catch (PathNotFoundException $e) { - $frozen = false; + if (UUIDHelper::isUUID($pathOrUuid)) { + $this->documentUuids[$oid] = $pathOrUuid; + $id = $node->getPath(); + $this->uuidIdMapping[$pathOrUuid] = $id; + $this->identityMap[$id] = $document; + } else { + $this->documentIds[$oid] = $pathOrUuid; + $this->identityMap[$pathOrUuid] = $document; } + // frozen nodes need another state so they are managed but not included for updates + $frozen = $node->isNodeType('nt:frozenNode'); $this->setDocumentState($oid, $frozen ? self::STATE_FROZEN : self::STATE_MANAGED); return $oid; @@ -3101,23 +3119,24 @@ public function registerDocument($document, $pathOrUuid) */ public function contains($document) { - $oid = is_object($document) ? spl_object_hash($document) : $document; - - return isset($this->documentIds[$oid]) && !isset($this->scheduledRemovals[$oid]); + return ($this->documentIsManaged($document) && !isset($this->scheduledRemovals[$this->getObjectId($document)])); } /** - * Tries to find a document with the given id in the identity map of - * this UnitOfWork. + * Tries to find a document with the id, which can be a path or an id found in uuid-id mapping, + * in the identity map of this UnitOfWork. * - * @param string $id The document id to look for. - * @param string $rootClassName The name of the root class of the mapped document hierarchy. + * @param string $pathOrUuid The document id to look for. * * @return object|false Returns the document with the specified id if it exists in * this UnitOfWork, FALSE otherwise. */ - public function getDocumentById($id) + public function getDocumentByPathOrUuid($pathOrUuid) { + $id = UUIDHelper::isUUID($pathOrUuid) && array_key_exists($pathOrUuid, $this->uuidIdMapping) + ? $this->uuidIdMapping[$pathOrUuid] + : $pathOrUuid; + if (isset($this->identityMap[$id])) { return $this->identityMap[$id]; } @@ -3143,18 +3162,16 @@ public function getNodeByPathOrUuid($pathOrUuid) * Get the object ID for the given document * * @param object|string $document document instance or document object hash + * @param bool $throw * - * @return string|null + * @return null|string * * @throws PHPCRException */ public function getDocumentId($document, $throw = true) { - $oid = is_object($document) ? spl_object_hash($document) : $document; - if (empty($this->documentIds[$oid])) { - if (!$throw) { - return null; - } + if ($throw && !$this->documentIsManaged($document)) { + $msg = 'Document is not managed and has no id'; if (is_object($document)) { $msg.= ': '.self::objToStr($document); @@ -3162,7 +3179,14 @@ public function getDocumentId($document, $throw = true) throw new PHPCRException($msg); } - return $this->documentIds[$oid]; + $oid = $this->getObjectId($document); + if (!empty($this->documentUuids[$oid]) && array_key_exists($this->documentUuids[$oid], $this->uuidIdMapping)) { + return $this->uuidIdMapping[$this->documentUuids[$oid]]; + } elseif (!empty($this->documentIds[$oid])) { + return $this->documentIds[$oid]; + } + + return null; } /** @@ -3225,7 +3249,9 @@ public function clear() $this->scheduledRemovals = $this->visitedCollections = $this->documentHistory = - $this->documentVersion = array(); + $this->documentVersion = + $this->documentUuids = + $this->uuidIdMapping = array(); $this->invokeGlobalEvent(Event::onClear, new OnClearEventArgs($this->dm)); @@ -3248,7 +3274,7 @@ public function getLocalesFor($document) throw new MissingTranslationException('This document is not translatable: : '.self::objToStr($document, $this->dm)); } - $oid = spl_object_hash($document); + $oid = $this->getObjectId($document); if ($this->contains($oid)) { try { $node = $this->session->getNode($this->getDocumentId($document)); @@ -3284,7 +3310,7 @@ private function doSaveTranslation($document, NodeInterface $node, $metadata) return; } - $oid = spl_object_hash($document); + $oid = $this->getObjectId($document); if (!empty($this->documentTranslations[$oid])) { $strategy = $this->dm->getTranslationStrategy($metadata->translator); foreach ($this->documentTranslations[$oid] as $locale => $data) { @@ -3327,7 +3353,7 @@ private function doSaveTranslation($document, NodeInterface $node, $metadata) */ protected function doLoadPendingTranslation($document, ClassMetadata $metadata, $locale) { - $oid = spl_object_hash($document); + $oid = $this->getObjectId($document); if (!isset($this->documentTranslations[$oid][$locale])) { return false; @@ -3365,7 +3391,7 @@ protected function doLoadPendingTranslation($document, ClassMetadata $metadata, */ protected function doLoadDatabaseTranslation($document, ClassMetadata $metadata, $locale, $fallback, $refresh) { - $oid = spl_object_hash($document); + $oid = $this->getObjectId($document); $strategy = $this->dm->getTranslationStrategy($metadata->translator); try { @@ -3437,7 +3463,7 @@ public function doLoadTranslation($document, ClassMetadata $metadata, $locale = $currentLocale = $this->getCurrentLocale($document, $metadata); - $oid = spl_object_hash($document); + $oid = $this->getObjectId($document); if (null === $locale || $locale === $currentLocale) { // current locale is already loaded and not removed if (!$refresh && isset($this->documentTranslations[$oid][$currentLocale])) { @@ -3585,7 +3611,7 @@ public function removeTranslation($document, $locale) $document->__load(); } - $oid = spl_object_hash($document); + $oid = $this->getObjectId($document); $this->documentTranslations[$oid][$locale] = null; $this->setLocale($document, $metadata, null); } @@ -3603,7 +3629,7 @@ public function removeTranslation($document, $locale) */ private function isTranslationRemoved($document, $locale) { - $oid = spl_object_hash($document); + $oid = $this->getObjectId($document); return isset($this->documentTranslations[$oid]) && empty($this->documentTranslations[$oid][$locale]) @@ -3638,7 +3664,7 @@ private function setLocale($document, ClassMetadata $metadata, $locale) return; } - $oid = spl_object_hash($document); + $oid = $this->getObjectId($document); if (empty($this->documentLocales[$oid])) { $this->documentLocales[$oid] = array('original' => $locale); } @@ -3687,7 +3713,7 @@ public function getCurrentLocale($document, ClassMetadata $metadata = null) } } - $oid = spl_object_hash($document); + $oid = $this->getObjectId($document); if (isset($this->documentLocales[$oid]['current'])) { return $this->documentLocales[$oid]['current']; } @@ -4007,7 +4033,7 @@ public function invokeGlobalEvent($eventName, EventArgs $event) * class name is within them. * * @param NodeInterface $parentNode - * @param string $classFqn + * @param ClassMetadata $class */ private function validateChildClass(NodeInterface $parentNode, ClassMetadata $class) { @@ -4020,4 +4046,28 @@ private function validateChildClass(NodeInterface $parentNode, ClassMetadata $cl $metadata = $this->dm->getClassMetadata($parentClass); $metadata->assertValidChildClass($class); } + + /** + * @param $document + * @return string + */ + private function getObjectId($document) + { + $oid = is_object($document) ? spl_object_hash($document) : $document; + return $oid; + } + + /** + * Decides whether a document is managed by its uuid or id. + * + * @param $document + * + * @return bool + */ + private function documentIsManaged($document) + { + $oid = $this->getObjectId($document); + + return isset($this->documentIds[$oid]) || isset($this->documentUuids[$oid]); + } } diff --git a/tests/Doctrine/Tests/ODM/PHPCR/UnitOfWorkTest.php b/tests/Doctrine/Tests/ODM/PHPCR/UnitOfWorkTest.php index ced4670c9..b952f82db 100644 --- a/tests/Doctrine/Tests/ODM/PHPCR/UnitOfWorkTest.php +++ b/tests/Doctrine/Tests/ODM/PHPCR/UnitOfWorkTest.php @@ -116,6 +116,7 @@ protected function createNode($id, $username, $primaryType = 'rep:root', $uuid = "jcr:system" => array(), 'username' => $username, ); + if (null !== $uuid) { $nodeData['jcr:uuid'] = $uuid; } @@ -134,7 +135,6 @@ protected function createNode($id, $username, $primaryType = 'rep:root', $uuid = ->will($this->returnValue($node)); } - return $node; } @@ -165,7 +165,7 @@ public function testGetDocumentById() { $user1 = $this->uow->getOrCreateDocument($this->type, $this->createNode('/somepath', 'foo')); - $user2 = $this->uow->getDocumentById('/somepath', $this->type); + $user2 = $this->uow->getDocumentByPathOrUuid('/somepath', $this->type); $this->assertSame($user1, $user2); } @@ -268,7 +268,7 @@ public function testGetOrCreateProxy() $userAsReference = $this->uow->getOrCreateProxy($user->id, get_class($user)); $this->assertEquals(2, $this->uow->getDocumentState($userAsReference)); - $this->assertEquals($userAsReference, $this->uow->getDocumentById($userAsReference->id)); + $this->assertEquals($userAsReference, $this->uow->getDocumentByPathOrUuid($userAsReference->id)); } public function testGetOrCreateProxyWithUuid() @@ -279,7 +279,7 @@ public function testGetOrCreateProxyWithUuid() $userAsReference = $this->uow->getOrCreateProxy($uuid, get_class($user)); $this->assertEquals(2, $this->uow->getDocumentState($userAsReference)); - $this->assertEquals($userAsReference, $this->uow->getDocumentById($uuid)); + $this->assertEquals($userAsReference, $this->uow->getDocumentByPathOrUuid($uuid)); } } From 4b612d6b2ac14947e694842d40f4408dd49f037f Mon Sep 17 00:00:00 2001 From: ElectricMaxxx Date: Wed, 18 Jan 2017 00:15:19 +0100 Subject: [PATCH 3/5] change method name --- lib/Doctrine/ODM/PHPCR/UnitOfWork.php | 64 +++++++++++++-------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/lib/Doctrine/ODM/PHPCR/UnitOfWork.php b/lib/Doctrine/ODM/PHPCR/UnitOfWork.php index afa43ba48..7a84d5c33 100644 --- a/lib/Doctrine/ODM/PHPCR/UnitOfWork.php +++ b/lib/Doctrine/ODM/PHPCR/UnitOfWork.php @@ -407,7 +407,7 @@ public function getOrCreateDocuments($className, $nodes, array &$hints = array() ++$existingDocuments; $documents[$id] = $document; } else { - $overrideLocalValuesOids[$id] = $this->getObjectId($document); + $overrideLocalValuesOids[$id] = $this->getObjectHash($document); } try { @@ -715,7 +715,7 @@ public function refreshDocumentForProxy($className, Proxy $document) $hints = array('refresh' => true, 'fallback' => true); - $oid = $this->getObjectId($document); + $oid = $this->getObjectHash($document); if (isset($this->documentLocales[$oid]['current'])) { $hints['locale'] = $this->documentLocales[$oid]['current']; } @@ -765,7 +765,7 @@ public function bindTranslation($document, $locale) */ private function doBindTranslation($document, $locale, ClassMetadata $class) { - $oid = $this->getObjectId($document); + $oid = $this->getObjectHash($document); // only trigger the events if we bind a new translation if (empty($this->documentTranslations[$oid][$locale]) @@ -815,7 +815,7 @@ private function doScheduleInsert($document, &$visited, $overrideIdGenerator = n )); } - $oid = $this->getObjectId($document); + $oid = $this->getObjectHash($document); // To avoid recursion loops (over children and parents) if (isset($visited[$oid])) { return; @@ -946,7 +946,7 @@ private function getIdGenerator($type) public function scheduleMove($document, $targetPath) { - $oid = $this->getObjectId($document); + $oid = $this->getObjectHash($document); $state = $this->getDocumentState($document); @@ -967,7 +967,7 @@ public function scheduleMove($document, $targetPath) public function scheduleReorder($document, $srcName, $targetName, $before) { - $oid = $this->getObjectId($document); + $oid = $this->getObjectHash($document); $state = $this->getDocumentState($document); switch ($state) { @@ -991,7 +991,7 @@ public function scheduleRemove($document) private function doRemove($document, &$visited) { - $oid = $this->getObjectId($document); + $oid = $this->getObjectHash($document); if (isset($visited[$oid])) { return; } @@ -1080,7 +1080,7 @@ private function purgeChildren($document) */ private function setDocumentState($document, $state) { - $oid = $this->getObjectId($document); + $oid = $this->getObjectHash($document); $this->documentState[$oid] = $state; } @@ -1098,7 +1098,7 @@ private function setDocumentState($document, $state) */ public function getDocumentState($document) { - $oid = $this->getObjectId($document); + $oid = $this->getObjectHash($document); if (!isset($this->documentState[$oid])) { // this will only use the metadata if id is mapped $id = $this->determineDocumentId($document); @@ -1127,7 +1127,7 @@ public function getDocumentState($document) */ public function isScheduledForInsert($document) { - return isset($this->scheduledInserts[$this->getObjectId($document)]); + return isset($this->scheduledInserts[$this->getObjectHash($document)]); } /** @@ -1153,7 +1153,7 @@ public function computeSingleDocumentChangeSet($document) return; } - $oid = $this->getObjectId($document); + $oid = $this->getObjectHash($document); if (!isset($this->scheduledInserts[$oid])) { $class = $this->dm->getClassMetadata(get_class($document)); $this->computeChangeSet($class, $document); @@ -1475,7 +1475,7 @@ public function computeChangeSet(ClassMetadata $class, $document) return; } - $oid = $this->getObjectId($document); + $oid = $this->getObjectHash($document); if (in_array($oid, $this->changesetComputed)) { return; } @@ -1611,7 +1611,7 @@ public function computeChangeSet(ClassMetadata $class, $document) $translationChanges = false; if ($this->isDocumentTranslatable($class)) { - $oid = $this->getObjectId($document); + $oid = $this->getObjectHash($document); if (isset($this->documentTranslations[$oid])) { foreach ($this->documentTranslations[$oid] as $localeToCheck => $data) { // a translation was removed @@ -1822,7 +1822,7 @@ public function refresh($document) private function doRefresh($document, &$visited) { - $oid = $this->getObjectId($document); + $oid = $this->getObjectHash($document); if (isset($visited[$oid])) { return; } @@ -1882,7 +1882,7 @@ private function cascadeMergeCollection($managedCol, array $mapping) private function doMerge($document, array &$visited, $prevManagedCopy = null, $assoc = null) { - $oid = $this->getObjectId($document); + $oid = $this->getObjectHash($document); if (isset($visited[$oid])) { return $document; // Prevent infinite recursion } @@ -2104,7 +2104,7 @@ public function detach($document) */ private function doDetach($document, array &$visited) { - $oid = $this->getObjectId($document); + $oid = $this->getObjectHash($document); if (isset($visited[$oid])) { return; // Prevent infinite recursion } @@ -3054,7 +3054,7 @@ public function removeVersion($documentVersion) */ private function unregisterDocument($document) { - $oid = $this->getObjectId($document); + $oid = $this->getObjectHash($document); if (isset($this->documentIds[$oid])) { unset($this->identityMap[$this->documentIds[$oid]]); } @@ -3091,7 +3091,7 @@ private function unregisterDocument($document) */ public function registerDocument($document, $pathOrUuid) { - $oid = $this->getObjectId($document); + $oid = $this->getObjectHash($document); // we shouldn't register document which can not be found, so we don't catch exception here $node = $this->getNodeByPathOrUuid($pathOrUuid); @@ -3119,7 +3119,7 @@ public function registerDocument($document, $pathOrUuid) */ public function contains($document) { - return ($this->documentIsManaged($document) && !isset($this->scheduledRemovals[$this->getObjectId($document)])); + return ($this->documentIsManaged($document) && !isset($this->scheduledRemovals[$this->getObjectHash($document)])); } /** @@ -3145,7 +3145,7 @@ public function getDocumentByPathOrUuid($pathOrUuid) } /** - * Creates a node from a given path or an uuid + * Creates a node from a given path or an UUID * * @param $pathOrUuid * @@ -3179,7 +3179,7 @@ public function getDocumentId($document, $throw = true) throw new PHPCRException($msg); } - $oid = $this->getObjectId($document); + $oid = $this->getObjectHash($document); if (!empty($this->documentUuids[$oid]) && array_key_exists($this->documentUuids[$oid], $this->uuidIdMapping)) { return $this->uuidIdMapping[$this->documentUuids[$oid]]; } elseif (!empty($this->documentIds[$oid])) { @@ -3274,7 +3274,7 @@ public function getLocalesFor($document) throw new MissingTranslationException('This document is not translatable: : '.self::objToStr($document, $this->dm)); } - $oid = $this->getObjectId($document); + $oid = $this->getObjectHash($document); if ($this->contains($oid)) { try { $node = $this->session->getNode($this->getDocumentId($document)); @@ -3310,7 +3310,7 @@ private function doSaveTranslation($document, NodeInterface $node, $metadata) return; } - $oid = $this->getObjectId($document); + $oid = $this->getObjectHash($document); if (!empty($this->documentTranslations[$oid])) { $strategy = $this->dm->getTranslationStrategy($metadata->translator); foreach ($this->documentTranslations[$oid] as $locale => $data) { @@ -3353,7 +3353,7 @@ private function doSaveTranslation($document, NodeInterface $node, $metadata) */ protected function doLoadPendingTranslation($document, ClassMetadata $metadata, $locale) { - $oid = $this->getObjectId($document); + $oid = $this->getObjectHash($document); if (!isset($this->documentTranslations[$oid][$locale])) { return false; @@ -3391,7 +3391,7 @@ protected function doLoadPendingTranslation($document, ClassMetadata $metadata, */ protected function doLoadDatabaseTranslation($document, ClassMetadata $metadata, $locale, $fallback, $refresh) { - $oid = $this->getObjectId($document); + $oid = $this->getObjectHash($document); $strategy = $this->dm->getTranslationStrategy($metadata->translator); try { @@ -3463,7 +3463,7 @@ public function doLoadTranslation($document, ClassMetadata $metadata, $locale = $currentLocale = $this->getCurrentLocale($document, $metadata); - $oid = $this->getObjectId($document); + $oid = $this->getObjectHash($document); if (null === $locale || $locale === $currentLocale) { // current locale is already loaded and not removed if (!$refresh && isset($this->documentTranslations[$oid][$currentLocale])) { @@ -3611,7 +3611,7 @@ public function removeTranslation($document, $locale) $document->__load(); } - $oid = $this->getObjectId($document); + $oid = $this->getObjectHash($document); $this->documentTranslations[$oid][$locale] = null; $this->setLocale($document, $metadata, null); } @@ -3629,7 +3629,7 @@ public function removeTranslation($document, $locale) */ private function isTranslationRemoved($document, $locale) { - $oid = $this->getObjectId($document); + $oid = $this->getObjectHash($document); return isset($this->documentTranslations[$oid]) && empty($this->documentTranslations[$oid][$locale]) @@ -3664,7 +3664,7 @@ private function setLocale($document, ClassMetadata $metadata, $locale) return; } - $oid = $this->getObjectId($document); + $oid = $this->getObjectHash($document); if (empty($this->documentLocales[$oid])) { $this->documentLocales[$oid] = array('original' => $locale); } @@ -3713,7 +3713,7 @@ public function getCurrentLocale($document, ClassMetadata $metadata = null) } } - $oid = $this->getObjectId($document); + $oid = $this->getObjectHash($document); if (isset($this->documentLocales[$oid]['current'])) { return $this->documentLocales[$oid]['current']; } @@ -4051,7 +4051,7 @@ private function validateChildClass(NodeInterface $parentNode, ClassMetadata $cl * @param $document * @return string */ - private function getObjectId($document) + private function getObjectHash($document) { $oid = is_object($document) ? spl_object_hash($document) : $document; return $oid; @@ -4066,7 +4066,7 @@ private function getObjectId($document) */ private function documentIsManaged($document) { - $oid = $this->getObjectId($document); + $oid = $this->getObjectHash($document); return isset($this->documentIds[$oid]) || isset($this->documentUuids[$oid]); } From 461fee3623597e320af60c8848681ac55e7cbca8 Mon Sep 17 00:00:00 2001 From: ElectricMaxxx Date: Wed, 18 Jan 2017 07:39:47 +0100 Subject: [PATCH 4/5] fix test driven node existence --- lib/Doctrine/ODM/PHPCR/UnitOfWork.php | 15 +++++++++++---- .../Tests/ODM/PHPCR/DocumentManagerTest.php | 14 +++++++++++--- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/lib/Doctrine/ODM/PHPCR/UnitOfWork.php b/lib/Doctrine/ODM/PHPCR/UnitOfWork.php index 7a84d5c33..d36bb9e9d 100644 --- a/lib/Doctrine/ODM/PHPCR/UnitOfWork.php +++ b/lib/Doctrine/ODM/PHPCR/UnitOfWork.php @@ -3092,21 +3092,28 @@ private function unregisterDocument($document) public function registerDocument($document, $pathOrUuid) { $oid = $this->getObjectHash($document); - // we shouldn't register document which can not be found, so we don't catch exception here - $node = $this->getNodeByPathOrUuid($pathOrUuid); + $node = null; + // frozen nodes need another state so they are managed but not included for updates + $frozen = false; if (UUIDHelper::isUUID($pathOrUuid)) { + // we shouldn't register document which can not be found, so we don't catch exception here + $node = $this->getNodeByPathOrUuid($pathOrUuid); $this->documentUuids[$oid] = $pathOrUuid; $id = $node->getPath(); $this->uuidIdMapping[$pathOrUuid] = $id; $this->identityMap[$id] = $document; + + if (null !== $node && $node->isNodeType('nt:frozenNode')) { + $frozen = true; + } } else { $this->documentIds[$oid] = $pathOrUuid; $this->identityMap[$pathOrUuid] = $document; + + $frozen = $this->session->nodeExists($pathOrUuid) && $this->session->getNode($pathOrUuid)->isNodeType('nt:frozenNode'); } - // frozen nodes need another state so they are managed but not included for updates - $frozen = $node->isNodeType('nt:frozenNode'); $this->setDocumentState($oid, $frozen ? self::STATE_FROZEN : self::STATE_MANAGED); return $oid; diff --git a/tests/Doctrine/Tests/ODM/PHPCR/DocumentManagerTest.php b/tests/Doctrine/Tests/ODM/PHPCR/DocumentManagerTest.php index efae4ab4a..fc2927323 100644 --- a/tests/Doctrine/Tests/ODM/PHPCR/DocumentManagerTest.php +++ b/tests/Doctrine/Tests/ODM/PHPCR/DocumentManagerTest.php @@ -15,6 +15,16 @@ */ class DocumentManagerTest extends PHPCRTestCase { + /** + * @var SessionInterface + */ + protected $session; + + public function setUp() + { + $this->session = $this->getMockBuilder('PHPCR\SessionInterface')->getMock(); + } + /** * @covers Doctrine\ODM\PHPCR\DocumentManager::find */ @@ -96,9 +106,7 @@ public function testGetClassMetadataFor() */ public function testContains() { - $session = $this->getMockBuilder('PHPCR\SessionInterface')->getMock(); - - $dm = DocumentManager::create($session); + $dm = DocumentManager::create($this->session); $obj = new \stdClass; $uow = $dm->getUnitOfWork(); From ea7923ca63ab0c375dd030c01e2768ee27cc287f Mon Sep 17 00:00:00 2001 From: ElectricMaxxx Date: Thu, 19 Jan 2017 08:05:51 +0100 Subject: [PATCH 5/5] add one test to the crud tests --- lib/Doctrine/ODM/PHPCR/UnitOfWork.php | 20 ++++++----- .../ODM/PHPCR/Functional/BasicCrudTest.php | 35 +++++++++++++++++++ 2 files changed, 46 insertions(+), 9 deletions(-) diff --git a/lib/Doctrine/ODM/PHPCR/UnitOfWork.php b/lib/Doctrine/ODM/PHPCR/UnitOfWork.php index d36bb9e9d..f2a1ffbc6 100644 --- a/lib/Doctrine/ODM/PHPCR/UnitOfWork.php +++ b/lib/Doctrine/ODM/PHPCR/UnitOfWork.php @@ -101,6 +101,8 @@ class UnitOfWork private $documentIds = array(); /** + * A map to of oid to uuid. + * * @var array */ private $documentUuids = array(); @@ -110,7 +112,7 @@ class UnitOfWork * * @var array */ - private $uuidIdMapping = array(); + private $uuidToPathMap = array(); /** * Track version history of the version documents we create, indexed by spl_object_hash @@ -3076,8 +3078,8 @@ private function unregisterDocument($document) $this->documentVersion[$oid] ); - if (!empty($this->documentUuids[$oid]) && array_key_exists($this->documentUuids[$oid], $this->uuidIdMapping)) { - unset($this->uuidIdMapping[$this->documentUuids[$oid]], $this->documentUuids[$oid]); + if (isset($this->documentUuids[$oid]) && array_key_exists($this->documentUuids[$oid], $this->uuidToPathMap)) { + unset($this->uuidToPathMap[$this->documentUuids[$oid]], $this->documentUuids[$oid]); } $this->changesetComputed = array_diff($this->changesetComputed, array($oid)); @@ -3101,7 +3103,7 @@ public function registerDocument($document, $pathOrUuid) $node = $this->getNodeByPathOrUuid($pathOrUuid); $this->documentUuids[$oid] = $pathOrUuid; $id = $node->getPath(); - $this->uuidIdMapping[$pathOrUuid] = $id; + $this->uuidToPathMap[$pathOrUuid] = $id; $this->identityMap[$id] = $document; if (null !== $node && $node->isNodeType('nt:frozenNode')) { @@ -3140,8 +3142,8 @@ public function contains($document) */ public function getDocumentByPathOrUuid($pathOrUuid) { - $id = UUIDHelper::isUUID($pathOrUuid) && array_key_exists($pathOrUuid, $this->uuidIdMapping) - ? $this->uuidIdMapping[$pathOrUuid] + $id = UUIDHelper::isUUID($pathOrUuid) && array_key_exists($pathOrUuid, $this->uuidToPathMap) + ? $this->uuidToPathMap[$pathOrUuid] : $pathOrUuid; if (isset($this->identityMap[$id])) { @@ -3187,8 +3189,8 @@ public function getDocumentId($document, $throw = true) } $oid = $this->getObjectHash($document); - if (!empty($this->documentUuids[$oid]) && array_key_exists($this->documentUuids[$oid], $this->uuidIdMapping)) { - return $this->uuidIdMapping[$this->documentUuids[$oid]]; + if (!empty($this->documentUuids[$oid]) && array_key_exists($this->documentUuids[$oid], $this->uuidToPathMap)) { + return $this->uuidToPathMap[$this->documentUuids[$oid]]; } elseif (!empty($this->documentIds[$oid])) { return $this->documentIds[$oid]; } @@ -3258,7 +3260,7 @@ public function clear() $this->documentHistory = $this->documentVersion = $this->documentUuids = - $this->uuidIdMapping = array(); + $this->uuidToPathMap = array(); $this->invokeGlobalEvent(Event::onClear, new OnClearEventArgs($this->dm)); diff --git a/tests/Doctrine/Tests/ODM/PHPCR/Functional/BasicCrudTest.php b/tests/Doctrine/Tests/ODM/PHPCR/Functional/BasicCrudTest.php index 9699ff4e3..75043f3ab 100644 --- a/tests/Doctrine/Tests/ODM/PHPCR/Functional/BasicCrudTest.php +++ b/tests/Doctrine/Tests/ODM/PHPCR/Functional/BasicCrudTest.php @@ -656,6 +656,30 @@ public function testChangeset() // nothing should happen, we did not alter any value $this->dm->flush(); } + + public function testGetReferenceProxyByUuidAndFindByPathShouldNotRegisterTwice() + { + $user = new User7(); + $user->username = 'referenced-one'; + $user->id = '/functional/referenced-one'; + + $this->dm->persist($user); + $this->dm->flush(); + + $user = $this->dm->find(null, '/functional/referenced-one'); + $uuid = $user->uuid; + $this->dm->clear(); + + $proxy = $this->dm->getReference(get_class(new User7()), $uuid); + $this->assertEquals($uuid, $proxy->id); + $document = $this->dm->find(get_class($user), '/functional/referenced-one'); + + $this->assertNotNull($document); + + // when calling the uuid the proxy will be awake too + $this->assertEquals($uuid, $document->uuid); + $this->assertEquals($document->id, $proxy->id); + } } /** @@ -716,6 +740,7 @@ class User5 public $numbers; } + /** * @PHPCRODM\Document() */ @@ -725,6 +750,16 @@ class User6 extends User5 public $id; } +/** + * + * @PHPCRODM\Document(referenceable=true) + */ +class User7 extends User +{ + /** @var @PHPCRODM\Uuid */ + public $uuid; +} + class User3Repository extends DocumentRepository implements RepositoryIdInterface { /**