diff --git a/lib/Doctrine/ODM/PHPCR/DocumentManager.php b/lib/Doctrine/ODM/PHPCR/DocumentManager.php index 0d46ec039..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,13 +916,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 (null === $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..f2a1ffbc6 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; @@ -99,6 +100,20 @@ class UnitOfWork */ private $documentIds = array(); + /** + * A map to of oid to uuid. + * + * @var array + */ + private $documentUuids = array(); + + /** + * Mapping to find ids (abs. path) of document managed by its uuid. + * + * @var array + */ + private $uuidToPathMap = array(); + /** * Track version history of the version documents we create, indexed by spl_object_hash * @var \PHPCR\Version\VersionHistoryInterface[] @@ -387,14 +402,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->getObjectHash($document); } try { @@ -443,7 +458,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; @@ -659,7 +674,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) { @@ -674,7 +689,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 path/uuid $this->registerDocument($proxyDocument, $targetId); if ($locale) { @@ -692,11 +707,17 @@ 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); - $oid = spl_object_hash($document); + $oid = $this->getObjectHash($document); if (isset($this->documentLocales[$oid]['current'])) { $hints['locale'] = $this->documentLocales[$oid]['current']; } @@ -746,7 +767,7 @@ public function bindTranslation($document, $locale) */ private function doBindTranslation($document, $locale, ClassMetadata $class) { - $oid = spl_object_hash($document); + $oid = $this->getObjectHash($document); // only trigger the events if we bind a new translation if (empty($this->documentTranslations[$oid][$locale]) @@ -796,7 +817,7 @@ private function doScheduleInsert($document, &$visited, $overrideIdGenerator = n )); } - $oid = spl_object_hash($document); + $oid = $this->getObjectHash($document); // To avoid recursion loops (over children and parents) if (isset($visited[$oid])) { return; @@ -927,7 +948,7 @@ private function getIdGenerator($type) public function scheduleMove($document, $targetPath) { - $oid = spl_object_hash($document); + $oid = $this->getObjectHash($document); $state = $this->getDocumentState($document); @@ -948,7 +969,7 @@ public function scheduleMove($document, $targetPath) public function scheduleReorder($document, $srcName, $targetName, $before) { - $oid = spl_object_hash($document); + $oid = $this->getObjectHash($document); $state = $this->getDocumentState($document); switch ($state) { @@ -972,7 +993,7 @@ public function scheduleRemove($document) private function doRemove($document, &$visited) { - $oid = spl_object_hash($document); + $oid = $this->getObjectHash($document); if (isset($visited[$oid])) { return; } @@ -1061,7 +1082,7 @@ private function purgeChildren($document) */ private function setDocumentState($document, $state) { - $oid = is_object($document) ? spl_object_hash($document) : $document; + $oid = $this->getObjectHash($document); $this->documentState[$oid] = $state; } @@ -1079,7 +1100,7 @@ private function setDocumentState($document, $state) */ public function getDocumentState($document) { - $oid = spl_object_hash($document); + $oid = $this->getObjectHash($document); if (!isset($this->documentState[$oid])) { // this will only use the metadata if id is mapped $id = $this->determineDocumentId($document); @@ -1088,7 +1109,7 @@ public function getDocumentState($document) return self::STATE_NEW; } - if ($this->getDocumentById($id)) { + if ($this->getDocumentByPathOrUuid($id)) { return self::STATE_DETACHED; } @@ -1108,7 +1129,7 @@ public function getDocumentState($document) */ public function isScheduledForInsert($document) { - return isset($this->scheduledInserts[spl_object_hash($document)]); + return isset($this->scheduledInserts[$this->getObjectHash($document)]); } /** @@ -1134,7 +1155,7 @@ public function computeSingleDocumentChangeSet($document) return; } - $oid = spl_object_hash($document); + $oid = $this->getObjectHash($document); if (!isset($this->scheduledInserts[$oid])) { $class = $this->dm->getClassMetadata(get_class($document)); $this->computeChangeSet($class, $document); @@ -1319,7 +1340,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); } @@ -1415,7 +1436,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]); } @@ -1456,7 +1477,7 @@ public function computeChangeSet(ClassMetadata $class, $document) return; } - $oid = spl_object_hash($document); + $oid = $this->getObjectHash($document); if (in_array($oid, $this->changesetComputed)) { return; } @@ -1592,7 +1613,7 @@ public function computeChangeSet(ClassMetadata $class, $document) $translationChanges = false; if ($this->isDocumentTranslatable($class)) { - $oid = spl_object_hash($document); + $oid = $this->getObjectHash($document); if (isset($this->documentTranslations[$oid])) { foreach ($this->documentTranslations[$oid] as $localeToCheck => $data) { // a translation was removed @@ -1686,7 +1707,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); @@ -1803,7 +1824,7 @@ public function refresh($document) private function doRefresh($document, &$visited) { - $oid = spl_object_hash($document); + $oid = $this->getObjectHash($document); if (isset($visited[$oid])) { return; } @@ -1863,7 +1884,7 @@ private function cascadeMergeCollection($managedCol, array $mapping) private function doMerge($document, array &$visited, $prevManagedCopy = null, $assoc = null) { - $oid = spl_object_hash($document); + $oid = $this->getObjectHash($document); if (isset($visited[$oid])) { return $document; // Prevent infinite recursion } @@ -1888,7 +1909,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) { @@ -2085,7 +2106,7 @@ public function detach($document) */ private function doDetach($document, array &$visited) { - $oid = spl_object_hash($document); + $oid = $this->getObjectHash($document); if (isset($visited[$oid])) { return; // Prevent infinite recursion } @@ -2762,7 +2783,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; } @@ -2843,8 +2864,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; } @@ -3035,8 +3056,7 @@ public function removeVersion($documentVersion) */ private function unregisterDocument($document) { - $oid = spl_object_hash($document); - + $oid = $this->getObjectHash($document); if (isset($this->documentIds[$oid])) { unset($this->identityMap[$this->documentIds[$oid]]); } @@ -3058,23 +3078,43 @@ private function unregisterDocument($document) $this->documentVersion[$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)); } /** * @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; + $oid = $this->getObjectHash($document); + $node = null; // 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'); + $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->uuidToPathMap[$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'); + } $this->setDocumentState($oid, $frozen ? self::STATE_FROZEN : self::STATE_MANAGED); @@ -3088,23 +3128,24 @@ public function registerDocument($document, $id) */ 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->getObjectHash($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->uuidToPathMap) + ? $this->uuidToPathMap[$pathOrUuid] + : $pathOrUuid; + if (isset($this->identityMap[$id])) { return $this->identityMap[$id]; } @@ -3112,22 +3153,34 @@ 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 * * @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); @@ -3135,7 +3188,14 @@ public function getDocumentId($document, $throw = true) throw new PHPCRException($msg); } - return $this->documentIds[$oid]; + $oid = $this->getObjectHash($document); + 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]; + } + + return null; } /** @@ -3198,7 +3258,9 @@ public function clear() $this->scheduledRemovals = $this->visitedCollections = $this->documentHistory = - $this->documentVersion = array(); + $this->documentVersion = + $this->documentUuids = + $this->uuidToPathMap = array(); $this->invokeGlobalEvent(Event::onClear, new OnClearEventArgs($this->dm)); @@ -3221,7 +3283,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->getObjectHash($document); if ($this->contains($oid)) { try { $node = $this->session->getNode($this->getDocumentId($document)); @@ -3257,7 +3319,7 @@ private function doSaveTranslation($document, NodeInterface $node, $metadata) return; } - $oid = spl_object_hash($document); + $oid = $this->getObjectHash($document); if (!empty($this->documentTranslations[$oid])) { $strategy = $this->dm->getTranslationStrategy($metadata->translator); foreach ($this->documentTranslations[$oid] as $locale => $data) { @@ -3300,7 +3362,7 @@ private function doSaveTranslation($document, NodeInterface $node, $metadata) */ protected function doLoadPendingTranslation($document, ClassMetadata $metadata, $locale) { - $oid = spl_object_hash($document); + $oid = $this->getObjectHash($document); if (!isset($this->documentTranslations[$oid][$locale])) { return false; @@ -3338,7 +3400,7 @@ protected function doLoadPendingTranslation($document, ClassMetadata $metadata, */ protected function doLoadDatabaseTranslation($document, ClassMetadata $metadata, $locale, $fallback, $refresh) { - $oid = spl_object_hash($document); + $oid = $this->getObjectHash($document); $strategy = $this->dm->getTranslationStrategy($metadata->translator); try { @@ -3410,7 +3472,7 @@ public function doLoadTranslation($document, ClassMetadata $metadata, $locale = $currentLocale = $this->getCurrentLocale($document, $metadata); - $oid = spl_object_hash($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])) { @@ -3558,7 +3620,7 @@ public function removeTranslation($document, $locale) $document->__load(); } - $oid = spl_object_hash($document); + $oid = $this->getObjectHash($document); $this->documentTranslations[$oid][$locale] = null; $this->setLocale($document, $metadata, null); } @@ -3576,7 +3638,7 @@ public function removeTranslation($document, $locale) */ private function isTranslationRemoved($document, $locale) { - $oid = spl_object_hash($document); + $oid = $this->getObjectHash($document); return isset($this->documentTranslations[$oid]) && empty($this->documentTranslations[$oid][$locale]) @@ -3611,7 +3673,7 @@ private function setLocale($document, ClassMetadata $metadata, $locale) return; } - $oid = spl_object_hash($document); + $oid = $this->getObjectHash($document); if (empty($this->documentLocales[$oid])) { $this->documentLocales[$oid] = array('original' => $locale); } @@ -3660,7 +3722,7 @@ public function getCurrentLocale($document, ClassMetadata $metadata = null) } } - $oid = spl_object_hash($document); + $oid = $this->getObjectHash($document); if (isset($this->documentLocales[$oid]['current'])) { return $this->documentLocales[$oid]['current']; } @@ -3980,7 +4042,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) { @@ -3993,4 +4055,28 @@ private function validateChildClass(NodeInterface $parentNode, ClassMetadata $cl $metadata = $this->dm->getClassMetadata($parentClass); $metadata->assertValidChildClass($class); } + + /** + * @param $document + * @return string + */ + private function getObjectHash($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->getObjectHash($document); + + return isset($this->documentIds[$oid]) || isset($this->documentUuids[$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(); 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 { /** diff --git a/tests/Doctrine/Tests/ODM/PHPCR/UnitOfWorkTest.php b/tests/Doctrine/Tests/ODM/PHPCR/UnitOfWorkTest.php index f8b5f2eed..b952f82db 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; } @@ -152,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); } @@ -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->getDocumentByPathOrUuid($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->getDocumentByPathOrUuid($uuid)); + } } class UoWUser