Skip to content
This repository has been archived by the owner on Sep 16, 2021. It is now read-only.

Commit

Permalink
Merge pull request #168 from mmenozzi/1.0-generic-intermediate-nodes-fix
Browse files Browse the repository at this point in the history
Convert non-managed intermediate nodes into AutoRoute documents
  • Loading branch information
dantleech committed Nov 10, 2015
2 parents e721ebf + 2d194b4 commit 840d8eb
Show file tree
Hide file tree
Showing 4 changed files with 147 additions and 15 deletions.
82 changes: 72 additions & 10 deletions Adapter/PhpcrOdmAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -115,33 +115,57 @@ 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();
$document->setParent($parentDocument);
$document->setParentDocument($parentDocument);
$document->setNodeName($segment);
$this->dm->persist($document);
}
$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);
$headRoute->setParent($document);
$headRoute->setParentDocument($document);
$headRoute->setAutoRouteTag($autoRouteTag);
$headRoute->setType(AutoRouteInterface::TYPE_PRIMARY);

Expand Down Expand Up @@ -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;
}
}
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
---------

Expand Down
33 changes: 33 additions & 0 deletions Tests/Functional/EventListener/AutoRouteListenerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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')
);
}
}
36 changes: 31 additions & 5 deletions Tests/Unit/Adapter/PhpcrOdmAdapterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -119,10 +121,34 @@ 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());
}

/**
* @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
Expand Down Expand Up @@ -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);
}
Expand All @@ -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);
}
}

0 comments on commit 840d8eb

Please sign in to comment.