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

Commit 840d8eb

Browse files
committed
Merge pull request #168 from mmenozzi/1.0-generic-intermediate-nodes-fix
Convert non-managed intermediate nodes into AutoRoute documents
2 parents e721ebf + 2d194b4 commit 840d8eb

File tree

4 files changed

+147
-15
lines changed

4 files changed

+147
-15
lines changed

Adapter/PhpcrOdmAdapter.php

+72-10
Original file line numberDiff line numberDiff line change
@@ -115,33 +115,57 @@ public function removeAutoRoute(AutoRouteInterface $autoRoute)
115115
*/
116116
public function createAutoRoute($uri, $contentDocument, $autoRouteTag)
117117
{
118-
$path = $this->baseRoutePath;
119-
$document = $parentDocument = $this->dm->find(null, $path);
118+
$basePath = $this->baseRoutePath;
119+
$document = $parentDocument = $this->dm->find(null, $basePath);
120+
120121
if (null === $parentDocument) {
121122
throw new \RuntimeException(sprintf('The "route_basepath" configuration points to a non-existant path "%s".',
122-
$path
123+
$basePath
123124
));
124125
}
125126

126127
$segments = preg_split('#/#', $uri, null, PREG_SPLIT_NO_EMPTY);
127128
$headName = array_pop($segments);
128129
foreach ($segments as $segment) {
129-
$path .= '/' . $segment;
130-
$document = $this->dm->find(null, $path);
130+
$basePath .= '/' . $segment;
131+
$document = $this->dm->find(null, $basePath);
131132

132133
if (null === $document) {
133134
$document = new Generic();
134-
$document->setParent($parentDocument);
135+
$document->setParentDocument($parentDocument);
135136
$document->setNodeName($segment);
136137
$this->dm->persist($document);
137138
}
138139
$parentDocument = $document;
139140
}
140141

142+
$path = $basePath . '/' . $headName;
143+
$existingDocument = $this->dm->find(null, $path);
144+
145+
if ($existingDocument) {
146+
if ($existingDocument instanceof Generic) {
147+
return $this->migrateGenericToAutoRoute(
148+
$existingDocument,
149+
$contentDocument,
150+
$autoRouteTag,
151+
AutoRouteInterface::TYPE_PRIMARY
152+
);
153+
}
154+
155+
throw new \RuntimeException(
156+
sprintf(
157+
'Encountered existing PHPCR-ODM document at path "%s" of class "%s", the route tree should ' .
158+
'contain only instances of AutoRouteInterface.',
159+
$path,
160+
get_class($existingDocument)
161+
)
162+
);
163+
}
164+
141165
$headRoute = new $this->autoRouteFqcn();
142166
$headRoute->setContent($contentDocument);
143167
$headRoute->setName($headName);
144-
$headRoute->setParent($document);
168+
$headRoute->setParentDocument($document);
145169
$headRoute->setAutoRouteTag($autoRouteTag);
146170
$headRoute->setType(AutoRouteInterface::TYPE_PRIMARY);
147171

@@ -190,13 +214,51 @@ public function getReferringAutoRoutes($contentDocument)
190214
*/
191215
public function findRouteForUri($uri)
192216
{
193-
$path = $this->getPathFromUri($uri);
194-
195-
return $this->dm->find(null, $path);
217+
return $this->dm->find(
218+
'Symfony\Cmf\Component\RoutingAuto\Model\AutoRouteInterface',
219+
$this->getPathFromUri($uri)
220+
);
196221
}
197222

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

CHANGELOG.md

+11
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,17 @@
11
Changelog
22
=========
33

4+
1.0.2
5+
----------
6+
7+
* Convert non-managed intermediate nodes into AutoRoute documents #165
8+
9+
1.0.0
10+
-----
11+
12+
* Enabled new `container` token provider - retrieve URL elements
13+
from container parameters.
14+
415
1.0.0-RC1
516
---------
617

Tests/Functional/EventListener/AutoRouteListenerTest.php

+33
Original file line numberDiff line numberDiff line change
@@ -521,4 +521,37 @@ public function testConflictResolverDefaultThrowException()
521521
$this->getDm()->persist($blog);
522522
$this->getDm()->flush();
523523
}
524+
525+
public function testGenericNodeShouldBeConvertedInAnAutoRouteNode()
526+
{
527+
$blog = new Blog;
528+
$blog->path = '/test/my-post';
529+
$blog->title = 'My Post';
530+
$this->getDm()->persist($blog);
531+
$this->getDm()->flush();
532+
533+
$this->assertInstanceOf(
534+
'Doctrine\ODM\PHPCR\Document\Generic',
535+
$this->getDm()->find(null, '/test/auto-route/blog')
536+
);
537+
$blogRoute = $this->getDm()->find(null, '/test/auto-route/blog/my-post');
538+
$this->assertInstanceOf('Symfony\Cmf\Component\RoutingAuto\Model\AutoRouteInterface', $blogRoute);
539+
$this->assertSame($blog, $blogRoute->getContent());
540+
541+
$page = new Page;
542+
$page->path = '/test/blog';
543+
$page->title = 'Blog';
544+
545+
$this->getDm()->persist($page);
546+
$this->getDm()->flush();
547+
548+
$this->assertInstanceOf(
549+
'Symfony\Cmf\Component\RoutingAuto\Model\AutoRouteInterface',
550+
$this->getDm()->find(null, '/test/auto-route/blog')
551+
);
552+
$this->assertInstanceOf(
553+
'Symfony\Cmf\Component\RoutingAuto\Model\AutoRouteInterface',
554+
$this->getDm()->find(null, '/test/auto-route/blog/my-post')
555+
);
556+
}
524557
}

Tests/Unit/Adapter/PhpcrOdmAdapterTest.php

+31-5
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);
@@ -119,10 +121,34 @@ public function testCreateAutoRoute($path, $expectedParentPath, $expectedName, $
119121
$this->assertInstanceOf('Symfony\Cmf\Bundle\RoutingAutoBundle\Model\AutoRoute', $res);
120122
$this->assertEquals($expectedName, $res->getName());
121123

122-
$this->assertSame($this->parentRoute, $res->getParent());
124+
$this->assertSame($this->parentRoute, $res->getParentDocument());
123125
$this->assertSame($this->contentDocument, $res->getContent());
124126
}
125127

128+
/**
129+
* @expectedException \RuntimeException
130+
* @expectedExceptionMessageRegExp /Failed to migrate existing.*? at "\/test\/generic" .*? It is an instance of "stdClass"\./
131+
*/
132+
public function testCreateAutoRouteThrowsExceptionIfItCannotMigrateExistingGenericDocumentToAutoRoute()
133+
{
134+
$uri = '/generic';
135+
$genericDocument = $this->prophesize('Doctrine\ODM\PHPCR\Document\Generic');
136+
$genericDocument->getNode()->willReturn($this->prophesize('PHPCR\NodeInterface')->reveal());
137+
$genericDocument->getId()->willReturn($this->baseRoutePath . $uri);
138+
$documentClassMapper = $this->prophesize('Doctrine\ODM\PHPCR\DocumentClassMapperInterface');
139+
$configuration = $this->prophesize('Doctrine\ODM\PHPCR\Configuration');
140+
$configuration->getDocumentClassMapper()->willReturn($documentClassMapper->reveal());
141+
$this->dm->getConfiguration()->willReturn($configuration->reveal());
142+
$this->dm->getPhpcrSession()->willReturn($this->phpcrSession);
143+
$this->dm->detach($genericDocument)->willReturn(null);
144+
$this->dm->find(null, $this->baseRoutePath)->willReturn($this->baseNode);
145+
$this->dm->find(null, $this->baseRoutePath . $uri)->willReturn(
146+
$genericDocument->reveal(),
147+
new \stdClass()
148+
);
149+
$this->adapter->createAutoRoute($uri, $this->contentDocument, 'it');
150+
}
151+
126152
/**
127153
* @expectedException \RuntimeException
128154
* @expectedExceptionMessage configuration points to a non-existant path
@@ -155,7 +181,7 @@ public function provideCompareRouteContent()
155181
public function testCompareRouteContent($isMatch)
156182
{
157183
$this->route->getContent()->willReturn($this->contentDocument);
158-
$content = $isMatch ? $this->contentDocument : $this->contentDocument2;
184+
$isMatch ? $this->contentDocument : $this->contentDocument2;
159185

160186
$this->adapter->compareAutoRouteContent($this->route->reveal(), $this->contentDocument);
161187
}
@@ -172,11 +198,11 @@ public function testGetReferringRoutes()
172198
public function testFindRouteForUri()
173199
{
174200
$uri = '/this/is/uri';
175-
$expectedRoutes = array($this->route->reveal());
201+
$expectedRoute = $this->route->reveal();
176202

177-
$this->dm->find(null, $this->baseRoutePath . $uri)->willReturn($expectedRoutes);
203+
$this->dm->find('Symfony\Cmf\Component\RoutingAuto\Model\AutoRouteInterface', $this->baseRoutePath . $uri)->willReturn($expectedRoute);
178204

179205
$res = $this->adapter->findRouteForUri($uri);
180-
$this->assertSame($expectedRoutes, $res);
206+
$this->assertSame($expectedRoute, $res);
181207
}
182208
}

0 commit comments

Comments
 (0)