From eb077c9bf575237be14562e508ddaa019fd45745 Mon Sep 17 00:00:00 2001 From: Manuele Menozzi Date: Wed, 28 Oct 2015 19:00:26 +0100 Subject: [PATCH 1/2] Convert non-managed intermediate nodes into AutoRoute documents This is a backport on 1.0 branch of the feature/bugfix for the Generic intermediates nodes which now will be converted in AutoRoute if needed. --- Adapter/PhpcrOdmAdapter.php | 78 +++++++++++++++++-- CHANGELOG.md | 11 +++ .../EventListener/AutoRouteListenerTest.php | 33 ++++++++ Tests/Unit/Adapter/PhpcrOdmAdapterTest.php | 34 +++++++- 4 files changed, 144 insertions(+), 12 deletions(-) diff --git a/Adapter/PhpcrOdmAdapter.php b/Adapter/PhpcrOdmAdapter.php index 47ca677..84e1599 100644 --- a/Adapter/PhpcrOdmAdapter.php +++ b/Adapter/PhpcrOdmAdapter.php @@ -115,19 +115,20 @@ public function removeAutoRoute(AutoRouteInterface $autoRoute) */ public function createAutoRoute($uri, $contentDocument, $autoRouteTag) { - $path = $this->baseRoutePath; - $document = $parentDocument = $this->dm->find(null, $path); + $basePath = $this->baseRoutePath; + $document = $parentDocument = $this->dm->find(null, $basePath); + if (null === $parentDocument) { throw new \RuntimeException(sprintf('The "route_basepath" configuration points to a non-existant path "%s".', - $path + $basePath )); } $segments = preg_split('#/#', $uri, null, PREG_SPLIT_NO_EMPTY); $headName = array_pop($segments); foreach ($segments as $segment) { - $path .= '/' . $segment; - $document = $this->dm->find(null, $path); + $basePath .= '/' . $segment; + $document = $this->dm->find(null, $basePath); if (null === $document) { $document = new Generic(); @@ -138,6 +139,29 @@ public function createAutoRoute($uri, $contentDocument, $autoRouteTag) $parentDocument = $document; } + $path = $basePath . '/' . $headName; + $existingDocument = $this->dm->find(null, $path); + + if ($existingDocument) { + if ($existingDocument instanceof Generic) { + return $this->migrateGenericToAutoRoute( + $existingDocument, + $contentDocument, + $autoRouteTag, + AutoRouteInterface::TYPE_PRIMARY + ); + } + + throw new \RuntimeException( + sprintf( + 'Encountered existing PHPCR-ODM document at path "%s" of class "%s", the route tree should ' . + 'contain only instances of AutoRouteInterface.', + $path, + get_class($existingDocument) + ) + ); + } + $headRoute = new $this->autoRouteFqcn(); $headRoute->setContent($contentDocument); $headRoute->setName($headName); @@ -190,13 +214,51 @@ public function getReferringAutoRoutes($contentDocument) */ public function findRouteForUri($uri) { - $path = $this->getPathFromUri($uri); - - return $this->dm->find(null, $path); + return $this->dm->find( + 'Symfony\Cmf\Component\RoutingAuto\Model\AutoRouteInterface', + $this->getPathFromUri($uri) + ); } private function getPathFromUri($uri) { return $this->baseRoutePath . $uri; } + + /** + * Convert the given generic document to an auto route document. + * + * @param Generic $document + * @param object $contentDocument + * @param string $autoRouteTag + * @param string $routeType + * @return AutoRouteInterface + */ + private function migrateGenericToAutoRoute(Generic $document, $contentDocument, $autoRouteTag, $routeType) + { + $autoRouteClassName = $this->autoRouteFqcn; + $mapper = $this->dm->getConfiguration()->getDocumentClassMapper(); + $mapper->writeMetadata($this->dm, $document->getNode(), $autoRouteClassName); + $this->dm->getPhpcrSession()->save(); + // Detach is needed to force Doctrine to re-load the node + $this->dm->detach($document); + $autoRoute = $this->dm->find(null, $document->getId()); + + if (!$autoRoute instanceof $autoRouteClassName) { + throw new \RuntimeException( + sprintf( + 'Failed to migrate existing, non-managed, PHPCR node at "%s" to a managed document implementing ' . + 'the AutoRouteInterface. It is an instance of "%s".', + $document->getId(), + get_class($autoRoute) + ) + ); + } + + $autoRoute->setContent($contentDocument); + $autoRoute->setAutoRouteTag($autoRouteTag); + $autoRoute->setType($routeType); + + return $autoRoute; + } } diff --git a/CHANGELOG.md b/CHANGELOG.md index d4c9e94..fb00294 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,17 @@ Changelog ========= +1.0.2 +---------- + +* Convert non-managed intermediate nodes into AutoRoute documents #165 + +1.0.0 +----- + +* Enabled new `container` token provider - retrieve URL elements + from container parameters. + 1.0.0-RC1 --------- diff --git a/Tests/Functional/EventListener/AutoRouteListenerTest.php b/Tests/Functional/EventListener/AutoRouteListenerTest.php index 8d5c74b..34ec358 100644 --- a/Tests/Functional/EventListener/AutoRouteListenerTest.php +++ b/Tests/Functional/EventListener/AutoRouteListenerTest.php @@ -521,4 +521,37 @@ public function testConflictResolverDefaultThrowException() $this->getDm()->persist($blog); $this->getDm()->flush(); } + + public function testGenericNodeShouldBeConvertedInAnAutoRouteNode() + { + $blog = new Blog; + $blog->path = '/test/my-post'; + $blog->title = 'My Post'; + $this->getDm()->persist($blog); + $this->getDm()->flush(); + + $this->assertInstanceOf( + 'Doctrine\ODM\PHPCR\Document\Generic', + $this->getDm()->find(null, '/test/auto-route/blog') + ); + $blogRoute = $this->getDm()->find(null, '/test/auto-route/blog/my-post'); + $this->assertInstanceOf('Symfony\Cmf\Component\RoutingAuto\Model\AutoRouteInterface', $blogRoute); + $this->assertSame($blog, $blogRoute->getContent()); + + $page = new Page; + $page->path = '/test/blog'; + $page->title = 'Blog'; + + $this->getDm()->persist($page); + $this->getDm()->flush(); + + $this->assertInstanceOf( + 'Symfony\Cmf\Component\RoutingAuto\Model\AutoRouteInterface', + $this->getDm()->find(null, '/test/auto-route/blog') + ); + $this->assertInstanceOf( + 'Symfony\Cmf\Component\RoutingAuto\Model\AutoRouteInterface', + $this->getDm()->find(null, '/test/auto-route/blog/my-post') + ); + } } diff --git a/Tests/Unit/Adapter/PhpcrOdmAdapterTest.php b/Tests/Unit/Adapter/PhpcrOdmAdapterTest.php index 9a967cd..bda317c 100644 --- a/Tests/Unit/Adapter/PhpcrOdmAdapterTest.php +++ b/Tests/Unit/Adapter/PhpcrOdmAdapterTest.php @@ -109,6 +109,8 @@ public function testCreateAutoRoute($path, $expectedParentPath, $expectedName, $ if ($parentPathExists) { $this->dm->find(null, $expectedParentPath) ->willReturn($this->parentRoute); + $this->dm->find(null, $expectedParentPath . '/' . $expectedName) + ->willReturn(null); } else { $this->dm->find(null, $expectedParentPath) ->willReturn(null); @@ -123,6 +125,30 @@ public function testCreateAutoRoute($path, $expectedParentPath, $expectedName, $ $this->assertSame($this->contentDocument, $res->getContent()); } + /** + * @expectedException \RuntimeException + * @expectedExceptionMessageRegExp /Failed to migrate existing.*? at "\/test\/generic" .*? It is an instance of "stdClass"\./ + */ + public function testCreateAutoRouteThrowsExceptionIfItCannotMigrateExistingGenericDocumentToAutoRoute() + { + $uri = '/generic'; + $genericDocument = $this->prophesize('Doctrine\ODM\PHPCR\Document\Generic'); + $genericDocument->getNode()->willReturn($this->prophesize('PHPCR\NodeInterface')->reveal()); + $genericDocument->getId()->willReturn($this->baseRoutePath . $uri); + $documentClassMapper = $this->prophesize('Doctrine\ODM\PHPCR\DocumentClassMapperInterface'); + $configuration = $this->prophesize('Doctrine\ODM\PHPCR\Configuration'); + $configuration->getDocumentClassMapper()->willReturn($documentClassMapper->reveal()); + $this->dm->getConfiguration()->willReturn($configuration->reveal()); + $this->dm->getPhpcrSession()->willReturn($this->phpcrSession); + $this->dm->detach($genericDocument)->willReturn(null); + $this->dm->find(null, $this->baseRoutePath)->willReturn($this->baseNode); + $this->dm->find(null, $this->baseRoutePath . $uri)->willReturn( + $genericDocument->reveal(), + new \stdClass() + ); + $this->adapter->createAutoRoute($uri, $this->contentDocument, 'it'); + } + /** * @expectedException \RuntimeException * @expectedExceptionMessage configuration points to a non-existant path @@ -155,7 +181,7 @@ public function provideCompareRouteContent() public function testCompareRouteContent($isMatch) { $this->route->getContent()->willReturn($this->contentDocument); - $content = $isMatch ? $this->contentDocument : $this->contentDocument2; + $isMatch ? $this->contentDocument : $this->contentDocument2; $this->adapter->compareAutoRouteContent($this->route->reveal(), $this->contentDocument); } @@ -172,11 +198,11 @@ public function testGetReferringRoutes() public function testFindRouteForUri() { $uri = '/this/is/uri'; - $expectedRoutes = array($this->route->reveal()); + $expectedRoute = $this->route->reveal(); - $this->dm->find(null, $this->baseRoutePath . $uri)->willReturn($expectedRoutes); + $this->dm->find('Symfony\Cmf\Component\RoutingAuto\Model\AutoRouteInterface', $this->baseRoutePath . $uri)->willReturn($expectedRoute); $res = $this->adapter->findRouteForUri($uri); - $this->assertSame($expectedRoutes, $res); + $this->assertSame($expectedRoute, $res); } } From 2d194b43d32f0bf1350d8aa04aa981b902a5392a Mon Sep 17 00:00:00 2001 From: Manuele Menozzi Date: Mon, 9 Nov 2015 23:22:57 +0100 Subject: [PATCH 2/2] Fixes deprecated Ruote#getParent() and Route#setParent() calls --- Adapter/PhpcrOdmAdapter.php | 4 ++-- Tests/Unit/Adapter/PhpcrOdmAdapterTest.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Adapter/PhpcrOdmAdapter.php b/Adapter/PhpcrOdmAdapter.php index 84e1599..2eaf0a9 100644 --- a/Adapter/PhpcrOdmAdapter.php +++ b/Adapter/PhpcrOdmAdapter.php @@ -132,7 +132,7 @@ public function createAutoRoute($uri, $contentDocument, $autoRouteTag) if (null === $document) { $document = new Generic(); - $document->setParent($parentDocument); + $document->setParentDocument($parentDocument); $document->setNodeName($segment); $this->dm->persist($document); } @@ -165,7 +165,7 @@ public function createAutoRoute($uri, $contentDocument, $autoRouteTag) $headRoute = new $this->autoRouteFqcn(); $headRoute->setContent($contentDocument); $headRoute->setName($headName); - $headRoute->setParent($document); + $headRoute->setParentDocument($document); $headRoute->setAutoRouteTag($autoRouteTag); $headRoute->setType(AutoRouteInterface::TYPE_PRIMARY); diff --git a/Tests/Unit/Adapter/PhpcrOdmAdapterTest.php b/Tests/Unit/Adapter/PhpcrOdmAdapterTest.php index bda317c..1e063eb 100644 --- a/Tests/Unit/Adapter/PhpcrOdmAdapterTest.php +++ b/Tests/Unit/Adapter/PhpcrOdmAdapterTest.php @@ -121,7 +121,7 @@ public function testCreateAutoRoute($path, $expectedParentPath, $expectedName, $ $this->assertInstanceOf('Symfony\Cmf\Bundle\RoutingAutoBundle\Model\AutoRoute', $res); $this->assertEquals($expectedName, $res->getName()); - $this->assertSame($this->parentRoute, $res->getParent()); + $this->assertSame($this->parentRoute, $res->getParentDocument()); $this->assertSame($this->contentDocument, $res->getContent()); }