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

Commit 7b86bac

Browse files
committed
Merge pull request #165 from mmenozzi/generic-intermediate-nodes-fix
Generic intermediate nodes fix
2 parents ee71ce9 + 732680d commit 7b86bac

File tree

3 files changed

+143
-9
lines changed

3 files changed

+143
-9
lines changed

Adapter/PhpcrOdmAdapter.php

Lines changed: 72 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -114,19 +114,20 @@ public function removeAutoRoute(AutoRouteInterface $autoRoute)
114114
*/
115115
public function createAutoRoute(UriContext $uriContext, $contentDocument, $autoRouteTag)
116116
{
117-
$path = $this->baseRoutePath;
118-
$document = $parentDocument = $this->dm->find(null, $path);
117+
$basePath = $this->baseRoutePath;
118+
$document = $parentDocument = $this->dm->find(null, $basePath);
119+
119120
if (null === $parentDocument) {
120121
throw new \RuntimeException(sprintf('The "route_basepath" configuration points to a non-existant path "%s".',
121-
$path
122+
$basePath
122123
));
123124
}
124125

125126
$segments = preg_split('#/#', $uriContext->getUri(), null, PREG_SPLIT_NO_EMPTY);
126127
$headName = array_pop($segments);
127128
foreach ($segments as $segment) {
128-
$path .= '/' . $segment;
129-
$document = $this->dm->find(null, $path);
129+
$basePath .= '/' . $segment;
130+
$document = $this->dm->find(null, $basePath);
130131

131132
if (null === $document) {
132133
$document = new Generic();
@@ -137,6 +138,29 @@ public function createAutoRoute(UriContext $uriContext, $contentDocument, $autoR
137138
$parentDocument = $document;
138139
}
139140

141+
$path = $basePath . '/' . $headName;
142+
$existingDocument = $this->dm->find(null, $path);
143+
144+
if ($existingDocument) {
145+
if ($existingDocument instanceof Generic) {
146+
return $this->migrateGenericToAutoRoute(
147+
$existingDocument,
148+
$contentDocument,
149+
$autoRouteTag,
150+
AutoRouteInterface::TYPE_PRIMARY
151+
);
152+
}
153+
154+
throw new \RuntimeException(
155+
sprintf(
156+
'Encountered existing PHPCR-ODM document at path "%s" of class "%s", the route tree should ' .
157+
'contain only instances of AutoRouteInterface.',
158+
$path,
159+
get_class($existingDocument)
160+
)
161+
);
162+
}
163+
140164
$headRoute = new $this->autoRouteFqcn();
141165
$headRoute->setContent($contentDocument);
142166
$headRoute->setName($headName);
@@ -190,12 +214,54 @@ public function getReferringAutoRoutes($contentDocument)
190214
public function findRouteForUri($uri, UriContext $uriContext)
191215
{
192216
$path = $this->getPathFromUri($uri);
217+
$document = $this->dm->find(null, $path);
218+
219+
if ($document instanceof AutoRouteInterface) {
220+
return $document;
221+
}
193222

194-
return $this->dm->find(null, $path);
223+
return null;
195224
}
196225

197226
private function getPathFromUri($uri)
198227
{
199228
return $this->baseRoutePath . $uri;
200229
}
230+
231+
/**
232+
* Convert the given generic document to an auto route document.
233+
*
234+
* @param Generic $document
235+
* @param object $contentDocument
236+
* @param string $autoRouteTag
237+
* @param string $routeType
238+
* @return AutoRouteInterface
239+
*/
240+
private function migrateGenericToAutoRoute(Generic $document, $contentDocument, $autoRouteTag, $routeType)
241+
{
242+
$autoRouteClassName = $this->autoRouteFqcn;
243+
$mapper = $this->dm->getConfiguration()->getDocumentClassMapper();
244+
$mapper->writeMetadata($this->dm, $document->getNode(), $autoRouteClassName);
245+
$this->dm->getPhpcrSession()->save();
246+
// Detach is needed to force Doctrine to re-load the node
247+
$this->dm->detach($document);
248+
$autoRoute = $this->dm->find(null, $document->getId());
249+
250+
if (!$autoRoute instanceof $autoRouteClassName) {
251+
throw new \RuntimeException(
252+
sprintf(
253+
'Failed to migrate existing, non-managed, PHPCR node at "%s" to a managed document implementing ' .
254+
'the AutoRouteInterface. It is an instance of "%s".',
255+
$document->getId(),
256+
get_class($autoRoute)
257+
)
258+
);
259+
}
260+
261+
$autoRoute->setContent($contentDocument);
262+
$autoRoute->setAutoRouteTag($autoRouteTag);
263+
$autoRoute->setType($routeType);
264+
265+
return $autoRoute;
266+
}
201267
}

Tests/Functional/EventListener/AutoRouteListenerTest.php

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -552,4 +552,37 @@ public function testConflictResolverDefaultThrowException()
552552
$this->getDm()->persist($blog);
553553
$this->getDm()->flush();
554554
}
555+
556+
public function testGenericNodeShouldBeConvertedInAnAutoRouteNode()
557+
{
558+
$blog = new Blog;
559+
$blog->path = '/test/my-post';
560+
$blog->title = 'My Post';
561+
$this->getDm()->persist($blog);
562+
$this->getDm()->flush();
563+
564+
$this->assertInstanceOf(
565+
'Doctrine\ODM\PHPCR\Document\Generic',
566+
$this->getDm()->find(null, '/test/auto-route/blog')
567+
);
568+
$blogRoute = $this->getDm()->find(null, '/test/auto-route/blog/my-post');
569+
$this->assertInstanceOf('Symfony\Cmf\Component\RoutingAuto\Model\AutoRouteInterface', $blogRoute);
570+
$this->assertSame($blog, $blogRoute->getContent());
571+
572+
$page = new Page;
573+
$page->path = '/test/blog';
574+
$page->title = 'Blog';
575+
576+
$this->getDm()->persist($page);
577+
$this->getDm()->flush();
578+
579+
$this->assertInstanceOf(
580+
'Symfony\Cmf\Component\RoutingAuto\Model\AutoRouteInterface',
581+
$this->getDm()->find(null, '/test/auto-route/blog')
582+
);
583+
$this->assertInstanceOf(
584+
'Symfony\Cmf\Component\RoutingAuto\Model\AutoRouteInterface',
585+
$this->getDm()->find(null, '/test/auto-route/blog/my-post')
586+
);
587+
}
555588
}

Tests/Unit/Adapter/PhpcrOdmAdapterTest.php

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ public function testCreateAutoRoute($path, $expectedParentPath, $expectedName, $
109109
if ($parentPathExists) {
110110
$this->dm->find(null, $expectedParentPath)
111111
->willReturn($this->parentRoute);
112+
$this->dm->find(null, $expectedParentPath . '/' . $expectedName)
113+
->willReturn(null);
112114
} else {
113115
$this->dm->find(null, $expectedParentPath)
114116
->willReturn(null);
@@ -124,6 +126,31 @@ public function testCreateAutoRoute($path, $expectedParentPath, $expectedName, $
124126
$this->assertSame($this->contentDocument, $res->getContent());
125127
}
126128

129+
/**
130+
* @expectedException \RuntimeException
131+
* @expectedExceptionMessageRegExp /Failed to migrate existing.*? at "\/test\/generic" .*? It is an instance of "stdClass"\./
132+
*/
133+
public function testCreateAutoRouteThrowsExceptionIfItCannotMigrateExistingGenericDocumentToAutoRoute()
134+
{
135+
$uri = '/generic';
136+
$genericDocument = $this->prophesize('Doctrine\ODM\PHPCR\Document\Generic');
137+
$genericDocument->getNode()->willReturn($this->prophesize('PHPCR\NodeInterface')->reveal());
138+
$genericDocument->getId()->willReturn($this->baseRoutePath . $uri);
139+
$documentClassMapper = $this->prophesize('Doctrine\ODM\PHPCR\DocumentClassMapperInterface');
140+
$configuration = $this->prophesize('Doctrine\ODM\PHPCR\Configuration');
141+
$configuration->getDocumentClassMapper()->willReturn($documentClassMapper->reveal());
142+
$this->dm->getConfiguration()->willReturn($configuration->reveal());
143+
$this->dm->getPhpcrSession()->willReturn($this->phpcrSession);
144+
$this->dm->detach($genericDocument)->willReturn(null);
145+
$this->dm->find(null, $this->baseRoutePath)->willReturn($this->baseNode);
146+
$this->dm->find(null, $this->baseRoutePath . $uri)->willReturn(
147+
$genericDocument->reveal(),
148+
new \stdClass()
149+
);
150+
$this->uriContext->getUri()->willReturn($uri);
151+
$this->adapter->createAutoRoute($this->uriContext->reveal(), $this->contentDocument, 'it');
152+
}
153+
127154
/**
128155
* @expectedException \RuntimeException
129156
* @expectedExceptionMessage configuration points to a non-existant path
@@ -174,11 +201,19 @@ public function testGetReferringRoutes()
174201
public function testFindRouteForUri()
175202
{
176203
$uri = '/this/is/uri';
177-
$expectedRoutes = array($this->route->reveal());
204+
$expectedRoute = $this->route->reveal();
178205

179-
$this->dm->find(null, $this->baseRoutePath . $uri)->willReturn($expectedRoutes);
206+
$this->dm->find(null, $this->baseRoutePath . $uri)->willReturn($expectedRoute);
180207

181208
$res = $this->adapter->findRouteForUri($uri, $this->uriContext->reveal());
182-
$this->assertSame($expectedRoutes, $res);
209+
$this->assertSame($expectedRoute, $res);
210+
}
211+
212+
public function testFindRouteForUriShouldReturnNullWhenNodeAtGivenPathIsNotAnAutoRoute()
213+
{
214+
$uri = '/this/is/uri';
215+
$genericNode = $this->prophesize('Doctrine\ODM\PHPCR\Document\Generic');
216+
$this->dm->find(null, $this->baseRoutePath . $uri)->willReturn($genericNode);
217+
$this->assertNull($this->adapter->findRouteForUri($uri, $this->uriContext->reveal()));
183218
}
184219
}

0 commit comments

Comments
 (0)