From 2a2497ccbacaea02ee39fa599b506f8bdb98a3d1 Mon Sep 17 00:00:00 2001 From: ElectricMaxxx Date: Tue, 20 May 2014 22:58:49 +0200 Subject: [PATCH 01/13] allow to add uuid as id to proxies --- lib/Doctrine/ODM/PHPCR/UnitOfWork.php | 7 ++- .../Tests/ODM/PHPCR/UnitOfWorkTest.php | 52 +++++++++++++++++-- 2 files changed, 55 insertions(+), 4 deletions(-) diff --git a/lib/Doctrine/ODM/PHPCR/UnitOfWork.php b/lib/Doctrine/ODM/PHPCR/UnitOfWork.php index 57c7aa3fc..e7ff9e714 100644 --- a/lib/Doctrine/ODM/PHPCR/UnitOfWork.php +++ b/lib/Doctrine/ODM/PHPCR/UnitOfWork.php @@ -566,7 +566,12 @@ public function getOrCreateProxy($targetId, $className, $locale = null) */ public function refreshDocumentForProxy($className, Proxy $document) { - $node = $this->session->getNode($this->determineDocumentId($document)); + $id = $this->determineDocumentId($document); + if (UUIDHelper::isUUID($id)) { + $node = $this->session->getNodeByIdentifier($id); + } else { + $node = $this->session->getNode($id); + } $hints = array('refresh' => true, 'fallback' => true); diff --git a/tests/Doctrine/Tests/ODM/PHPCR/UnitOfWorkTest.php b/tests/Doctrine/Tests/ODM/PHPCR/UnitOfWorkTest.php index cba2e966b..5c4b4e8a3 100644 --- a/tests/Doctrine/Tests/ODM/PHPCR/UnitOfWorkTest.php +++ b/tests/Doctrine/Tests/ODM/PHPCR/UnitOfWorkTest.php @@ -9,6 +9,7 @@ use Jackalope\Factory; use Jackalope\Node; +use PHPCR\Util\UUIDHelper; /** * TODO: remove Jackalope dependency @@ -39,7 +40,6 @@ public function setUp() $this->factory = new Factory; $this->session = $this->getMock('Jackalope\Session', array(), array($this->factory), '', false); $this->objectManager = $this->getMock('Jackalope\ObjectManager', array(), array($this->factory), '', false); - $this->type = 'Doctrine\Tests\ODM\PHPCR\UoWUser'; $this->dm = DocumentManager::create($this->session); $this->uow = new UnitOfWork($this->dm); @@ -53,19 +53,22 @@ public function setUp() $cmf->setMetadataFor($this->type, $metadata); } - protected function createNode($id, $username) + protected function createNode($id, $username, $uuid = null) { $repository = $this->getMockBuilder('Jackalope\Repository')->disableOriginalConstructor()->getMock(); $this->session->expects($this->any()) ->method('getRepository') ->with() ->will($this->returnValue($repository)); - $nodeData = array( "jcr:primaryType" => "rep:root", "jcr:system" => array(), 'username' => $username, ); + + if (null !== $uuid) { + $nodeData['jcr:uuid'] = $uuid; + } return new Node($this->factory, $nodeData, $id, $this->session, $this->objectManager); } @@ -161,6 +164,49 @@ public function testUuid() $uow = new UnitOfWork($dm); $this->assertEquals('like-a-uuid', $method->invoke($uow)); } + + 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)); + + $this->session + ->expects($this->any()) + ->method('getNode') + ->will($this->returnValue($this->createNode('/somepath', 'persisted-username'))); + + $userAsReference->username = 'updatedName'; + $this->uow->scheduleInsert($userAsReference); + + $this->assertCount(0, $this->uow->getScheduledInserts()); + $this->assertCount(0, $this->uow->getScheduledRemovals()); + } + + public function testGetOrCreateProxyWithUuid() + { + $uuid = UUIDHelper::generateUUID(); + $user = $this->uow->getOrCreateDocument($this->type, $this->createNode('/somepath', 'foo', $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($userAsReference->id)); + + $this->session + ->expects($this->any()) + ->method('getNodeByIdentifier') + ->will($this->returnValue($this->createNode('/somepath', 'persisted-username'))); + + $userAsReference->username = 'updatedName'; + $this->uow->scheduleInsert($userAsReference); + + $this->assertCount(0, $this->uow->getScheduledInserts()); + $this->assertCount(0, $this->uow->getScheduledRemovals()); + } } class UoWUser From 7b5ef44f6165fd3316fef7c27dbd9e217bb6b632 Mon Sep 17 00:00:00 2001 From: ElectricMaxxx Date: Wed, 21 May 2014 10:05:05 +0200 Subject: [PATCH 02/13] bring it back on the line --- lib/Doctrine/ODM/PHPCR/UnitOfWork.php | 11 +++++++---- tests/Doctrine/Tests/ODM/PHPCR/UnitOfWorkTest.php | 14 ++------------ 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/lib/Doctrine/ODM/PHPCR/UnitOfWork.php b/lib/Doctrine/ODM/PHPCR/UnitOfWork.php index e7ff9e714..7020a2009 100644 --- a/lib/Doctrine/ODM/PHPCR/UnitOfWork.php +++ b/lib/Doctrine/ODM/PHPCR/UnitOfWork.php @@ -566,11 +566,14 @@ public function getOrCreateProxy($targetId, $className, $locale = null) */ public function refreshDocumentForProxy($className, Proxy $document) { - $id = $this->determineDocumentId($document); - if (UUIDHelper::isUUID($id)) { - $node = $this->session->getNodeByIdentifier($id); + $identifier = $this->determineDocumentId($document); + if (UUIDHelper::isUUID($identifier)) { + $node = $this->session->getNodeByIdentifier($identifier); + // switch the registration to come back on the line + $this->unregisterDocument($document); + $this->registerDocument($document, $node->getPath()); } else { - $node = $this->session->getNode($id); + $node = $this->session->getNode($identifier); } $hints = array('refresh' => true, 'fallback' => true); diff --git a/tests/Doctrine/Tests/ODM/PHPCR/UnitOfWorkTest.php b/tests/Doctrine/Tests/ODM/PHPCR/UnitOfWorkTest.php index 5c4b4e8a3..d180953b0 100644 --- a/tests/Doctrine/Tests/ODM/PHPCR/UnitOfWorkTest.php +++ b/tests/Doctrine/Tests/ODM/PHPCR/UnitOfWorkTest.php @@ -177,13 +177,8 @@ public function testGetOrCreateProxy() $this->session ->expects($this->any()) ->method('getNode') + ->with($this->equalTo('/somepath')) ->will($this->returnValue($this->createNode('/somepath', 'persisted-username'))); - - $userAsReference->username = 'updatedName'; - $this->uow->scheduleInsert($userAsReference); - - $this->assertCount(0, $this->uow->getScheduledInserts()); - $this->assertCount(0, $this->uow->getScheduledRemovals()); } public function testGetOrCreateProxyWithUuid() @@ -199,13 +194,8 @@ public function testGetOrCreateProxyWithUuid() $this->session ->expects($this->any()) ->method('getNodeByIdentifier') + ->with($this->equalTo($uuid)) ->will($this->returnValue($this->createNode('/somepath', 'persisted-username'))); - - $userAsReference->username = 'updatedName'; - $this->uow->scheduleInsert($userAsReference); - - $this->assertCount(0, $this->uow->getScheduledInserts()); - $this->assertCount(0, $this->uow->getScheduledRemovals()); } } From d52bfd06ddd4406b8e1fbac9efd8623208a4fb0c Mon Sep 17 00:00:00 2001 From: ElectricMaxxx Date: Wed, 21 May 2014 10:28:12 +0200 Subject: [PATCH 03/13] refactor tests --- tests/Doctrine/Tests/ODM/PHPCR/UnitOfWorkTest.php | 14 +------------- tests/phpunit_doctrine_dbal.xml.dist | 3 ++- 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/tests/Doctrine/Tests/ODM/PHPCR/UnitOfWorkTest.php b/tests/Doctrine/Tests/ODM/PHPCR/UnitOfWorkTest.php index d180953b0..99d57b14e 100644 --- a/tests/Doctrine/Tests/ODM/PHPCR/UnitOfWorkTest.php +++ b/tests/Doctrine/Tests/ODM/PHPCR/UnitOfWorkTest.php @@ -173,12 +173,6 @@ public function testGetOrCreateProxy() $this->assertEquals(2, $this->uow->getDocumentState($userAsReference)); $this->assertEquals($userAsReference, $this->uow->getDocumentById($userAsReference->id)); - - $this->session - ->expects($this->any()) - ->method('getNode') - ->with($this->equalTo('/somepath')) - ->will($this->returnValue($this->createNode('/somepath', 'persisted-username'))); } public function testGetOrCreateProxyWithUuid() @@ -189,13 +183,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($userAsReference->id)); - - $this->session - ->expects($this->any()) - ->method('getNodeByIdentifier') - ->with($this->equalTo($uuid)) - ->will($this->returnValue($this->createNode('/somepath', 'persisted-username'))); + $this->assertEquals($userAsReference, $this->uow->getDocumentById($uuid)); } } diff --git a/tests/phpunit_doctrine_dbal.xml.dist b/tests/phpunit_doctrine_dbal.xml.dist index ae3513fb0..d0374f384 100644 --- a/tests/phpunit_doctrine_dbal.xml.dist +++ b/tests/phpunit_doctrine_dbal.xml.dist @@ -16,7 +16,8 @@ - ./ + /home/maximilian/websites/Cmf/phpcr-odm/tests/Doctrine/Tests/ODM/PHPCR/UnitOfWorkTest.php + From b9ccfa91e790612a1d990716190ffe04cc85b277 Mon Sep 17 00:00:00 2001 From: ElectricMaxxx Date: Wed, 21 May 2014 10:29:08 +0200 Subject: [PATCH 04/13] redo test cheat --- tests/phpunit_doctrine_dbal.xml.dist | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/phpunit_doctrine_dbal.xml.dist b/tests/phpunit_doctrine_dbal.xml.dist index d0374f384..ae3513fb0 100644 --- a/tests/phpunit_doctrine_dbal.xml.dist +++ b/tests/phpunit_doctrine_dbal.xml.dist @@ -16,8 +16,7 @@ - /home/maximilian/websites/Cmf/phpcr-odm/tests/Doctrine/Tests/ODM/PHPCR/UnitOfWorkTest.php - + ./ From c9d6f80792c77b0eb71a5f95d1a03e9cfec335ff Mon Sep 17 00:00:00 2001 From: ElectricMaxxx Date: Thu, 22 May 2014 23:14:14 +0200 Subject: [PATCH 05/13] refactor node fetching stuff in DM --- lib/Doctrine/ODM/PHPCR/DocumentManager.php | 93 +++++++++++++------ .../Tests/ODM/PHPCR/DocumentManagerTest.php | 66 ++++++++----- 2 files changed, 109 insertions(+), 50 deletions(-) diff --git a/lib/Doctrine/ODM/PHPCR/DocumentManager.php b/lib/Doctrine/ODM/PHPCR/DocumentManager.php index ce20b3d1e..ebec06ed7 100644 --- a/lib/Doctrine/ODM/PHPCR/DocumentManager.php +++ b/lib/Doctrine/ODM/PHPCR/DocumentManager.php @@ -313,28 +313,30 @@ 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; - } + // when there is a document return that on, when it is valid + $document = $this->unitOfWork->getDocumentById($id); + if ($document) { + return $this->documentHasValidClassName($document, $className) ? $document : null; + } - $document = $this->unitOfWork->getDocumentById($id); - if ($document) { - try { - $this->unitOfWork->validateClassName($document, $className); + // id can either be an path or an uuid, so we can have a look if one of both does have an entry + if (UUIDHelper::isUUID($id)) { + try { + $id = $this->session->getNodeByIdentifier($id)->getPath(); + } catch (ItemNotFoundException $e) { + return null; + } + } elseif (strpos($id, '/') !== 0) { + $id = '/'.$id; + } - return $document; - } catch(ClassMismatchException $e) { - return null; - } + $document = $this->unitOfWork->getDocumentById($id); + if ($document) { + return $this->documentHasValidClassName($document, $className) ? $document : null; + } - } + // next try: when it is an absolute path, then fetch it from the session, create a new document for it + try { $node = $this->session->getNode($id); } catch (PathNotFoundException $e) { return null; @@ -349,6 +351,25 @@ public function find($className, $id) } } + /** + * Just a little helper to validate the documents class name with a + * boolean answer. + * + * @param object $document + * @param string $className + * @return bool + */ + public function documentHasValidClassName($document, $className) + { + try { + $this->unitOfWork->validateClassName($document, $className); + + return true; + } catch(ClassMismatchException $e) { + return false; + } + } + /** * Finds many documents by id. * @@ -388,13 +409,8 @@ public function findMany($className, array $ids) foreach ($ids as $id) { $document = $this->unitOfWork->getDocumentById($id); - if ($document) { - try { - $this->unitOfWork->validateClassName($document, $className); + if ($document && $this->documentHasValidClassName($document, $className)) { $documents[$id] = $document; - } catch (ClassMismatchException $e) { - // ignore on class mismatch - } } elseif (isset($nodes[$id])) { try { $documents[$id] = $this->unitOfWork->getOrCreateDocument($className, $nodes[$id], $hints); @@ -1203,7 +1219,9 @@ public function initializeObject($document) } /** - * Return the node of the given object + * Return the node of the given object. + * + * This node is fetched by the objects uuid or its id meants the absolute path. * * @param object $document * @@ -1218,8 +1236,27 @@ public function getNodeForDocument($document) throw new InvalidArgumentException('Parameter $document needs to be an object, '.gettype($document).' given'); } - $path = $this->unitOfWork->getDocumentId($document); + $identifier = $this->unitOfWork->getDocumentId($document); + if (null === $identifier) { + return null; + } + + if (UUIDHelper::isUUID($identifier)) { + try { + $node = $this->session->getNodeByIdentifier($identifier); - return $this->session->getNode($path); + return $node; + } catch (ItemNotFoundException $e) { + return null; + } + } else { + try { + $node = $this->session->getNode($identifier); + + return $node; + } catch (PathNotFoundException $e) { + return null; + } + } } } diff --git a/tests/Doctrine/Tests/ODM/PHPCR/DocumentManagerTest.php b/tests/Doctrine/Tests/ODM/PHPCR/DocumentManagerTest.php index 5a2766c6d..bda2f8192 100644 --- a/tests/Doctrine/Tests/ODM/PHPCR/DocumentManagerTest.php +++ b/tests/Doctrine/Tests/ODM/PHPCR/DocumentManagerTest.php @@ -2,8 +2,12 @@ namespace Doctrine\Tests\ODM\PHPCR; +use Doctrine\ODM\PHPCR\Configuration; use Doctrine\ODM\PHPCR\DocumentManager; use Doctrine\ODM\PHPCR\Mapping\ClassMetadata; +use PHPCR\ItemNotFoundException; +use PHPCR\Util\UUIDHelper; +use PHPCR\PathNotFoundException; /** * @group unit @@ -11,38 +15,56 @@ class DocumentManagerTest extends PHPCRTestCase { /** - * @covers Doctrine\ODM\PHPCR\DocumentManager::find - */ - public function testFind() - { - $fakeUuid = \PHPCR\Util\UUIDHelper::generateUUID(); - $session = $this->getMockForAbstractClass('PHPCR\SessionInterface', array('getNodeByIdentifier')); - $session->expects($this->once())->method('getNodeByIdentifier')->will($this->throwException(new \PHPCR\ItemNotFoundException(sprintf('403: %s', $fakeUuid)))); - $config = new \Doctrine\ODM\PHPCR\Configuration(); - - $dm = DocumentManager::create($session, $config); - $nonExistent = $dm->find(null, $fakeUuid); - - $this->assertNull($nonExistent); - } + * @covers Doctrine\ODM\PHPCR\DocumentManager::find + */ + public function testFindExceptionWhenUuidNotFound() + { + $fakeUuid = UUIDHelper::generateUUID(); + $session = $this->getMockForAbstractClass('PHPCR\SessionInterface', array('getNodeByIdentifier')); + $session->expects($this->once())->method('getNodeByIdentifier')->will($this->throwException(new ItemNotFoundException(sprintf('403: %s', $fakeUuid)))); + $config = new Configuration(); + + $dm = DocumentManager::create($session, $config); + + $nonExistent = $dm->find(null, $fakeUuid); + + $this->assertNull($nonExistent); + } /** - * @covers Doctrine\ODM\PHPCR\DocumentManager::findTranslation + * @covers Doctrine\ODM\PHPCR\DocumentManager::find */ - public function testFindTranslation() + public function testFindExceptionWhenIdNotFound() { - $fakeUuid = \PHPCR\Util\UUIDHelper::generateUUID(); - $session = $this->getMockForAbstractClass('PHPCR\SessionInterface', array('getNodeByIdentifier')); - $session->expects($this->once())->method('getNodeByIdentifier')->will($this->throwException(new \PHPCR\ItemNotFoundException(sprintf('403: %s', $fakeUuid)))); - $config = new \Doctrine\ODM\PHPCR\Configuration(); + $fakeId = 'fakeId'; + $session = $this->getMockForAbstractClass('PHPCR\SessionInterface', array('getNode')); + $session->expects($this->once())->method('getNode')->will($this->throwException(new PathNotFoundException(sprintf('403: %s', $fakeId)))); + $config = new Configuration(); $dm = DocumentManager::create($session, $config); - $nonExistent = $dm->findTranslation(null, $fakeUuid, 'en'); + $nonExistent = $dm->find(null, $fakeId); $this->assertNull($nonExistent); } + + /** + * @covers Doctrine\ODM\PHPCR\DocumentManager::findTranslation + */ + public function testFindTranslation() + { + $fakeUuid = UUIDHelper::generateUUID(); + $session = $this->getMockForAbstractClass('PHPCR\SessionInterface', array('getNodeByIdentifier')); + $session->expects($this->once())->method('getNodeByIdentifier')->will($this->throwException(new ItemNotFoundException(sprintf('403: %s', $fakeUuid)))); + $config = new Configuration(); + + $dm = DocumentManager::create($session, $config); + + $nonExistent = $dm->findTranslation(null, $fakeUuid, 'en'); + + $this->assertNull($nonExistent); + } /** * @covers Doctrine\ODM\PHPCR\DocumentManager::create @@ -51,7 +73,7 @@ public function testFindTranslation() public function testNewInstanceFromConfiguration() { $session = $this->getMock('PHPCR\SessionInterface'); - $config = new \Doctrine\ODM\PHPCR\Configuration(); + $config = new Configuration(); $dm = DocumentManager::create($session, $config); From 71f4a5898f48740308264c5e2dc69be71474bbfa Mon Sep 17 00:00:00 2001 From: ElectricMaxxx Date: Thu, 22 May 2014 23:58:08 +0200 Subject: [PATCH 06/13] replace getNode on session by method in DM --- lib/Doctrine/ODM/PHPCR/DocumentManager.php | 37 ++++++++-------------- lib/Doctrine/ODM/PHPCR/UnitOfWork.php | 37 +++++++--------------- 2 files changed, 25 insertions(+), 49 deletions(-) diff --git a/lib/Doctrine/ODM/PHPCR/DocumentManager.php b/lib/Doctrine/ODM/PHPCR/DocumentManager.php index ebec06ed7..d977eb6fc 100644 --- a/lib/Doctrine/ODM/PHPCR/DocumentManager.php +++ b/lib/Doctrine/ODM/PHPCR/DocumentManager.php @@ -1219,44 +1219,33 @@ public function initializeObject($document) } /** - * Return the node of the given object. + * Return the node of the given object or its hash. * - * This node is fetched by the objects uuid or its id meants the absolute path. + * This node is fetched by the objects uuid or its id means the absolute path. * - * @param object $document + * @param object|string $document * * @return \PHPCR\NodeInterface * - * @throws InvalidArgumentException if $document is not an object. + * @throws InvalidArgumentException if $document isn't mapped in UoW. * @throws PHPCRException if $document is not managed */ public function getNodeForDocument($document) { - if (!is_object($document)) { - throw new InvalidArgumentException('Parameter $document needs to be an object, '.gettype($document).' given'); - } - - $identifier = $this->unitOfWork->getDocumentId($document); - if (null === $identifier) { - return null; + if (!$identifier = $this->unitOfWork->getDocumentId($document)) { + throw new InvalidArgumentException('Parameter document should have an entry in identityMap.'); } if (UUIDHelper::isUUID($identifier)) { - try { - $node = $this->session->getNodeByIdentifier($identifier); + $node = $this->session->getNodeByIdentifier($identifier); - return $node; - } catch (ItemNotFoundException $e) { - return null; - } + // switch uuid mapping to identifier mapping for identityMap + $this->unitOfWork->unregisterDocument($document); + $this->unitOfWork->registerDocument($document, $node->getPath()); } else { - try { - $node = $this->session->getNode($identifier); - - return $node; - } catch (PathNotFoundException $e) { - return null; - } + $node = $this->session->getNode($identifier); } + + return $node; } } diff --git a/lib/Doctrine/ODM/PHPCR/UnitOfWork.php b/lib/Doctrine/ODM/PHPCR/UnitOfWork.php index 7020a2009..b85701688 100644 --- a/lib/Doctrine/ODM/PHPCR/UnitOfWork.php +++ b/lib/Doctrine/ODM/PHPCR/UnitOfWork.php @@ -562,20 +562,10 @@ public function getOrCreateProxy($targetId, $className, $locale = null) * Populate the proxy with actual data * * @param string $className - * @param Proxy $document + * @param Proxy $document */ public function refreshDocumentForProxy($className, Proxy $document) { - $identifier = $this->determineDocumentId($document); - if (UUIDHelper::isUUID($identifier)) { - $node = $this->session->getNodeByIdentifier($identifier); - // switch the registration to come back on the line - $this->unregisterDocument($document); - $this->registerDocument($document, $node->getPath()); - } else { - $node = $this->session->getNode($identifier); - } - $hints = array('refresh' => true, 'fallback' => true); $oid = spl_object_hash($document); @@ -583,7 +573,7 @@ public function refreshDocumentForProxy($className, Proxy $document) $hints['locale'] = $this->documentLocales[$oid]['current']; } - $this->getOrCreateDocument($className, $node, $hints); + $this->getOrCreateDocument($className, $this->dm->getNodeForDocument($document), $hints); } /** @@ -1647,13 +1637,11 @@ private function doRefresh($document, &$visited) throw new InvalidArgumentException('Document has to be managed to be refreshed '.self::objToStr($document, $this->dm)); } - $node = $this->session->getNode($this->getDocumentId($document)); - $class = $this->dm->getClassMetadata(get_class($document)); $this->cascadeRefresh($class, $document, $visited); $hints = array('refresh' => true); - $this->getOrCreateDocument(ClassUtils::getClass($document), $node, $hints); + $this->getOrCreateDocument(ClassUtils::getClass($document), $this->dm->getNodeForDocument($document), $hints); } public function merge($document) @@ -2308,7 +2296,7 @@ private function executeUpdates($documents, $dispatchEvents = true) } $class = $this->dm->getClassMetadata(get_class($document)); - $node = $this->session->getNode($this->getDocumentId($document)); + $node = $this->dm->getNodeForDocument($document); if ($this->writeMetadata) { $this->documentClassMapper->writeMetadata($this->dm, $node, $class->name); @@ -2397,7 +2385,7 @@ private function executeUpdates($documents, $dispatchEvents = true) continue; } - $associatedNode = $this->session->getNode($this->getDocumentId($fv)); + $associatedNode = $this->dm->getNodeForDocument($fv); if ($strategy === PropertyType::PATH) { $refNodesIds[] = $associatedNode->getPath(); } else { @@ -2415,7 +2403,7 @@ private function executeUpdates($documents, $dispatchEvents = true) } } elseif ($mapping['type'] === $class::MANY_TO_ONE) { if (isset($fieldValue)) { - $associatedNode = $this->session->getNode($this->getDocumentId($fieldValue)); + $associatedNode = $this->dm->getNodeForDocument($fieldValue); if ($strategy === PropertyType::PATH) { $node->setProperty($fieldName, $associatedNode->getPath(), $strategy); @@ -2447,7 +2435,7 @@ private function executeUpdates($documents, $dispatchEvents = true) throw new PHPCRException(sprintf("%s is not an instance of %s for document %s field %s", self::objToStr($fv, $this->dm), $mapping['referencedBy'], self::objToStr($document, $this->dm), $mapping['fieldName'])); } - $referencingNode = $this->session->getNode($this->getDocumentId($fv)); + $referencingNode = $this->dm->getNodeForDocument($fv); $referencingMeta = $this->dm->getClassMetadata($mapping['referringDocument']); $referencingField = $referencingMeta->getAssociation($mapping['referencedBy']); @@ -2630,7 +2618,7 @@ private function executeReorders($documents) } foreach ($list as $value) { list($parent, $src, $target, $before) = $value; - $parentNode = $this->session->getNode($this->getDocumentId($parent)); + $parentNode = $this->dm->getNodeForDocument($parent); // check for src and target ... $dest = $target; @@ -2859,7 +2847,7 @@ public function removeVersion($documentVersion) * * @param object $document */ - private function unregisterDocument($document) + public function unregisterDocument($document) { $oid = spl_object_hash($document); @@ -3044,7 +3032,7 @@ public function getLocalesFor($document) $oid = spl_object_hash($document); if ($this->contains($oid)) { try { - $node = $this->session->getNode($this->getDocumentId($document)); + $node = $this->dm->getNodeForDocument($document); $locales = $this->dm->getTranslationStrategy($metadata->translator)->getLocalesFor($document, $node, $metadata); } catch (PathNotFoundException $e) { $locales = array(); @@ -3170,7 +3158,7 @@ protected function doLoadDatabaseTranslation($document, ClassMetadata $metadata, $strategy = $this->dm->getTranslationStrategy($metadata->translator); try { - $node = $this->session->getNode($this->getDocumentId($oid)); + $node = $this->dm->getNodeForDocument($oid); if ($strategy->loadTranslation($document, $node, $metadata, $locale)) { return $locale; } @@ -3370,9 +3358,8 @@ private function doRemoveAllTranslations($document, ClassMetadata $metadata) return; } - $node = $this->session->getNode($this->getDocumentId($document)); $strategy = $this->dm->getTranslationStrategy($metadata->translator); - $strategy->removeAllTranslations($document, $node, $metadata); + $strategy->removeAllTranslations($document, $this->dm->getNodeForDocument($document), $metadata); } private function setLocale($document, ClassMetadata $metadata, $locale) From ca55003456d4bd42934bbaf62e7084bef9bb850b Mon Sep 17 00:00:00 2001 From: ElectricMaxxx Date: Fri, 23 May 2014 00:13:28 +0200 Subject: [PATCH 07/13] more replaces --- lib/Doctrine/ODM/PHPCR/UnitOfWork.php | 32 ++++++++++++--------------- 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/lib/Doctrine/ODM/PHPCR/UnitOfWork.php b/lib/Doctrine/ODM/PHPCR/UnitOfWork.php index b85701688..cc7368b94 100644 --- a/lib/Doctrine/ODM/PHPCR/UnitOfWork.php +++ b/lib/Doctrine/ODM/PHPCR/UnitOfWork.php @@ -2666,7 +2666,11 @@ private function executeRemovals($documents) $id = $this->getDocumentId($document); try { - $node = $this->session->getNode($id); + if (UUIDHelper::isUUID($id)) { + $node = $this->session->getNodeByIdentifier($id); + } else { + $node = $this->session->getNode($id); + } $this->doRemoveAllTranslations($document, $class); $node->remove(); } catch (PathNotFoundException $e) { @@ -3466,28 +3470,20 @@ private static function objToStr($obj, DocumentManager $dm = null) private function getVersionedNodePath($document) { - $path = $this->getDocumentId($document); + $id = $this->getDocumentId($document); $metadata = $this->dm->getClassMetadata(get_class($document)); - - if (!$metadata->versionable) { - throw new InvalidArgumentException(sprintf( - "The document at path '%s' is not versionable", - $path - )); + if ($metadata->versionable !== 'full') { + throw new InvalidArgumentException(sprintf("The document at '%s' is not full versionable", $id)); } - $node = $this->session->getNode($path); - - $mixin = $metadata->versionable === 'simple' ? - 'mix:simpleVersionable' : - 'mix:versionable'; - - if (!$node->isNodeType($mixin)) { - $node->addMixin($mixin); + if (UUIDHelper::isUUID($id)) { + $node = $this->session->getNodeByIdentifier($id); + } else { + $node = $this->session->getNode($id); } + $node->addMixin('mix:versionable'); - - return $path; + return $id; } /** From 860eb22e53e159e733f5438a9ca8ba08f95d5589 Mon Sep 17 00:00:00 2001 From: ElectricMaxxx Date: Fri, 23 May 2014 08:29:38 +0200 Subject: [PATCH 08/13] CS stuff and refactoring --- lib/Doctrine/ODM/PHPCR/DocumentManager.php | 32 ++++++++++++++-------- lib/Doctrine/ODM/PHPCR/UnitOfWork.php | 12 ++------ 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/lib/Doctrine/ODM/PHPCR/DocumentManager.php b/lib/Doctrine/ODM/PHPCR/DocumentManager.php index d977eb6fc..20a64cf6a 100644 --- a/lib/Doctrine/ODM/PHPCR/DocumentManager.php +++ b/lib/Doctrine/ODM/PHPCR/DocumentManager.php @@ -313,10 +313,11 @@ public function getClassMetadata($className) */ public function find($className, $id) { - // when there is a document return that on, when it is valid + // document still mapped -> return that when class name is valid $document = $this->unitOfWork->getDocumentById($id); if ($document) { - return $this->documentHasValidClassName($document, $className) ? $document : null; + $document = $this->documentHasValidClassName($document, $className) ? $document : null; + return $document; } // id can either be an path or an uuid, so we can have a look if one of both does have an entry @@ -330,12 +331,14 @@ public function find($className, $id) $id = '/'.$id; } + // document mapped by id = absolute Path -> return that when class name is valid $document = $this->unitOfWork->getDocumentById($id); if ($document) { - return $this->documentHasValidClassName($document, $className) ? $document : null; + $document = $this->documentHasValidClassName($document, $className) ? $document : null; + return $document; } - // next try: when it is an absolute path, then fetch it from the session, create a new document for it + // no document mapped, then try to fetch it from session and create a new one try { $node = $this->session->getNode($id); } catch (PathNotFoundException $e) { @@ -359,7 +362,7 @@ public function find($className, $id) * @param string $className * @return bool */ - public function documentHasValidClassName($document, $className) + private function documentHasValidClassName($document, $className) { try { $this->unitOfWork->validateClassName($document, $className); @@ -1236,14 +1239,21 @@ public function getNodeForDocument($document) throw new InvalidArgumentException('Parameter document should have an entry in identityMap.'); } - if (UUIDHelper::isUUID($identifier)) { - $node = $this->session->getNodeByIdentifier($identifier); + return $this->getNodeByPathOrUuid($identifier); + } - // switch uuid mapping to identifier mapping for identityMap - $this->unitOfWork->unregisterDocument($document); - $this->unitOfWork->registerDocument($document, $node->getPath()); + /** + * Creates a node from a given path or an uuid + * + * @param $pathOrUuid + * @return \PHPCR\NodeInterface + */ + public function getNodeByPathOrUuid($pathOrUuid) + { + if (UUIDHelper::isUUID($pathOrUuid)) { + $node = $this->session->getNodeByIdentifier($pathOrUuid); } else { - $node = $this->session->getNode($identifier); + $node = $this->session->getNode($pathOrUuid); } return $node; diff --git a/lib/Doctrine/ODM/PHPCR/UnitOfWork.php b/lib/Doctrine/ODM/PHPCR/UnitOfWork.php index cc7368b94..9b156b809 100644 --- a/lib/Doctrine/ODM/PHPCR/UnitOfWork.php +++ b/lib/Doctrine/ODM/PHPCR/UnitOfWork.php @@ -2666,11 +2666,7 @@ private function executeRemovals($documents) $id = $this->getDocumentId($document); try { - if (UUIDHelper::isUUID($id)) { - $node = $this->session->getNodeByIdentifier($id); - } else { - $node = $this->session->getNode($id); - } + $this->dm->getNodeByPathOrUuid($id); $this->doRemoveAllTranslations($document, $class); $node->remove(); } catch (PathNotFoundException $e) { @@ -3476,11 +3472,7 @@ private function getVersionedNodePath($document) throw new InvalidArgumentException(sprintf("The document at '%s' is not full versionable", $id)); } - if (UUIDHelper::isUUID($id)) { - $node = $this->session->getNodeByIdentifier($id); - } else { - $node = $this->session->getNode($id); - } + $node = $this->dm->getNodeByPathOrUuid($id); $node->addMixin('mix:versionable'); return $id; From d53fc67d1375a5f8d18113da340a042d2620f5be Mon Sep 17 00:00:00 2001 From: ElectricMaxxx Date: Fri, 23 May 2014 08:39:53 +0200 Subject: [PATCH 09/13] fix test --- lib/Doctrine/ODM/PHPCR/UnitOfWork.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Doctrine/ODM/PHPCR/UnitOfWork.php b/lib/Doctrine/ODM/PHPCR/UnitOfWork.php index 9b156b809..094c7af0f 100644 --- a/lib/Doctrine/ODM/PHPCR/UnitOfWork.php +++ b/lib/Doctrine/ODM/PHPCR/UnitOfWork.php @@ -2666,7 +2666,7 @@ private function executeRemovals($documents) $id = $this->getDocumentId($document); try { - $this->dm->getNodeByPathOrUuid($id); + $node = $this->dm->getNodeByPathOrUuid($id); $this->doRemoveAllTranslations($document, $class); $node->remove(); } catch (PathNotFoundException $e) { From 9841f74b477d9c9fddbac26c96ce75440e3f179b Mon Sep 17 00:00:00 2001 From: ElectricMaxxx Date: Fri, 23 May 2014 08:54:15 +0200 Subject: [PATCH 10/13] roll back determineDocumentId() for documents --- lib/Doctrine/ODM/PHPCR/UnitOfWork.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/Doctrine/ODM/PHPCR/UnitOfWork.php b/lib/Doctrine/ODM/PHPCR/UnitOfWork.php index 094c7af0f..8a05feb64 100644 --- a/lib/Doctrine/ODM/PHPCR/UnitOfWork.php +++ b/lib/Doctrine/ODM/PHPCR/UnitOfWork.php @@ -566,6 +566,14 @@ public function getOrCreateProxy($targetId, $className, $locale = null) */ public function refreshDocumentForProxy($className, Proxy $document) { + $identifier = $this->determineDocumentId($document); + $node = $this->dm->getNodeByPathOrUuid($identifier); + if (UUIDHelper::isUUID($identifier)) { + // switch document registration to path as usual + $this->unregisterDocument($document); + $this->registerDocument($document, $node->getPath()); + } + $hints = array('refresh' => true, 'fallback' => true); $oid = spl_object_hash($document); @@ -573,7 +581,7 @@ public function refreshDocumentForProxy($className, Proxy $document) $hints['locale'] = $this->documentLocales[$oid]['current']; } - $this->getOrCreateDocument($className, $this->dm->getNodeForDocument($document), $hints); + $this->getOrCreateDocument($className, $node, $hints); } /** From 8fc96b8e34aae60c7a5dd248e53d954fc5d50372 Mon Sep 17 00:00:00 2001 From: ElectricMaxxx Date: Fri, 25 Jul 2014 16:55:23 +0200 Subject: [PATCH 11/13] use changes of the org. system --- lib/Doctrine/ODM/PHPCR/Mapping/ClassMetadata.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/Doctrine/ODM/PHPCR/Mapping/ClassMetadata.php b/lib/Doctrine/ODM/PHPCR/Mapping/ClassMetadata.php index b83db5bd0..cfbad5f46 100644 --- a/lib/Doctrine/ODM/PHPCR/Mapping/ClassMetadata.php +++ b/lib/Doctrine/ODM/PHPCR/Mapping/ClassMetadata.php @@ -1464,8 +1464,12 @@ public function __sleep() */ public function newInstance() { - if (!$this->instantiator instanceof InstantiatorInterface) { - $this->instantiator = new Instantiator(); + if ($this->prototype === null) { + if (PHP_VERSION_ID === 50429 || PHP_VERSION_ID === 50513) { + $this->_prototype = $this->reflClass->newInstanceWithoutConstructor(); + } else { + $this->_prototype = unserialize(sprintf('O:%d:"%s":0:{}', strlen($this->name), $this->name)); + } } return $this->instantiator->instantiate($this->name); From f77edd6953a69b754af800548b8f39dc6e2b93d3 Mon Sep 17 00:00:00 2001 From: ElectricMaxxx Date: Fri, 25 Jul 2014 17:01:40 +0200 Subject: [PATCH 12/13] fix serialization bug --- lib/Doctrine/ODM/PHPCR/Mapping/ClassMetadata.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Doctrine/ODM/PHPCR/Mapping/ClassMetadata.php b/lib/Doctrine/ODM/PHPCR/Mapping/ClassMetadata.php index cfbad5f46..e41af80f7 100644 --- a/lib/Doctrine/ODM/PHPCR/Mapping/ClassMetadata.php +++ b/lib/Doctrine/ODM/PHPCR/Mapping/ClassMetadata.php @@ -1466,9 +1466,9 @@ public function newInstance() { if ($this->prototype === null) { if (PHP_VERSION_ID === 50429 || PHP_VERSION_ID === 50513) { - $this->_prototype = $this->reflClass->newInstanceWithoutConstructor(); + $this->prototype = $this->reflClass->newInstanceWithoutConstructor(); } else { - $this->_prototype = unserialize(sprintf('O:%d:"%s":0:{}', strlen($this->name), $this->name)); + $this->prototype = unserialize(sprintf('O:%d:"%s":0:{}', strlen($this->name), $this->name)); } } From 6bc14501d9d34d7ce20b00519ecb808f95251b96 Mon Sep 17 00:00:00 2001 From: ElectricMaxxx Date: Mon, 18 Aug 2014 13:17:38 +0200 Subject: [PATCH 13/13] remove onknown change --- lib/Doctrine/ODM/PHPCR/Mapping/ClassMetadata.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/Doctrine/ODM/PHPCR/Mapping/ClassMetadata.php b/lib/Doctrine/ODM/PHPCR/Mapping/ClassMetadata.php index e41af80f7..fc14bba05 100644 --- a/lib/Doctrine/ODM/PHPCR/Mapping/ClassMetadata.php +++ b/lib/Doctrine/ODM/PHPCR/Mapping/ClassMetadata.php @@ -29,8 +29,6 @@ use Doctrine\Common\Persistence\Mapping\ReflectionService; use Doctrine\Common\Persistence\Mapping\ClassMetadata as ClassMetadataInterface; use Doctrine\Common\ClassLoader; -use Doctrine\Instantiator\Instantiator; -use Doctrine\Instantiator\InstantiatorInterface; /** * Metadata class @@ -97,6 +95,13 @@ class ClassMetadata implements ClassMetadataInterface */ public $reflFields = array(); + /** + * The prototype from which new instances of the mapped class are created. + * + * @var object + */ + private $prototype; + /** * READ-ONLY: The ID generator used for generating IDs for this class. * @@ -1114,7 +1119,6 @@ public function hasField($fieldName) return false; } return in_array($fieldName, $this->fieldMappings) - || isset($this->inheritedFields[$fieldName]) || $this->identifier === $fieldName || $this->localeMapping === $fieldName || $this->node === $fieldName @@ -1472,7 +1476,7 @@ public function newInstance() } } - return $this->instantiator->instantiate($this->name); + return clone $this->prototype; } /**