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

[WIP] Support for handling defunct routes #81

Merged
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ before_script:
- composer require symfony/framework-bundle:${SYMFONY_VERSION} --prefer-source
- vendor/symfony-cmf/testing/bin/travis/phpcr_odm_doctrine_dbal.sh

script: phpunit --coverage-text
script:
- phpunit --coverage-text
- ./vendor/bin/phpspec run

notifications:
irc: "irc.freenode.org#symfony-cmf"
Expand Down
61 changes: 55 additions & 6 deletions AutoRoute/Adapter/AdapterInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
namespace Symfony\Cmf\Bundle\RoutingAutoBundle\AutoRoute\Adapter;

use Symfony\Cmf\Component\Routing\RouteObjectInterface;
use Symfony\Cmf\Bundle\RoutingAutoBundle\Model\AutoRouteInterface;
use Symfony\Cmf\Bundle\RoutingAutoBundle\AutoRoute\UrlContext;

/**
* Adapters will (eventually) abstract all database operations
Expand All @@ -32,7 +34,7 @@ public function getLocales($object);
* Translate the given object into the given locale
*
* @param object $object
* @param string $locale e.g. fr, en, de, be, etc.
* @param string $locale e.g. fr, en, de, be, etc.
*/
public function translateObject($object, $locale);

Expand All @@ -42,27 +44,28 @@ public function translateObject($object, $locale);
*
* @param string $path
* @param object $document
* @param string $tag
*
* @return Route new route document
* @return AutoRouteInterface new route document
*/
public function createRoute($path, $document);
public function createAutoRoute($path, $document, $tag);

/**
* Return the canonical name for the given class, this is
* Return the canonical name for the given class, this is
* required as somethimes an ORM may return a proxy class.
*
* @return string
*/
public function getRealClassName($className);

/**
* Return true if the content associated with the route
* Return true if the content associated with the auto route
* and the given content object are the same.
*
* @param RouteObjectInterface
* @param object
*/
public function compareRouteContent(RouteObjectInterface $route, $contentObject);
public function compareAutoRouteContent(AutoRouteInterface $autoRoute, $contentObject);

/**
* Attempt to find a route with the given URL
Expand All @@ -72,4 +75,50 @@ public function compareRouteContent(RouteObjectInterface $route, $contentObject)
* @return null|Symfony\Cmf\Component\Routing\RouteObjectInterface
*/
public function findRouteForUrl($url);

/**
* Generate a tag which can be used to identify this route from
* other routes as required.
*
* @param UrlContext $urlContext
*/
public function generateAutoRouteTag(UrlContext $urlContext);

/**
* Migrate the descendant path elements from one route to another.
*
* e.g. in an RDBMS with a routes:
*
* /my-blog
* /my-blog/posts/post1
* /my-blog/posts/post2
* /my-new-blog
*
* We want to migrate the children of "my-blog" to "my-new-blog" so that
* we have:
*
* /my-blog
* /my-new-blog
* /my-new-blog/posts/post1
* /my-new-blog/posts/post2
*
* @param AutoRouteInterface $srcAutoRoute
* @param AutoRouteInterface $destAutoRoute
*/
public function migrateAutoRouteChildren(AutoRouteInterface $srcAutoRoute, AutoRouteInterface $destAutoRoute);

/**
* Remove the given auto route
*
* @param AutoRouteInterface $autoRoute
*/
public function removeAutoRoute(AutoRouteInterface $autoRoute);

/**
* Return auto routes which refer to the given content
* object.
*
* @param object $contentDocument
*/
public function getReferringAutoRoutes($contentDocument);
}
115 changes: 95 additions & 20 deletions AutoRoute/Adapter/PhpcrOdmAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,28 +14,37 @@
use Doctrine\ODM\PHPCR\DocumentManager;
use Doctrine\ODM\PHPCR\Document\Generic;
use Doctrine\Common\Util\ClassUtils;
use Symfony\Cmf\Component\Routing\RouteObjectInterface;
use PHPCR\Util\NodeHelper;
use Symfony\Cmf\Bundle\RoutingAutoBundle\Model\AutoRoute;
use PHPCR\InvalidItemStateException;
use Symfony\Cmf\Bundle\RoutingAutoBundle\Model\AutoRouteInterface;
use Symfony\Cmf\Bundle\RoutingAutoBundle\AutoRoute\UrlContext;
use Symfony\Cmf\Bundle\RoutingBundle\Doctrine\Phpcr\RedirectRoute;

/**
* Abstraction adapter for PHPCR-ODM
* Adapter for PHPCR-ODM
*
* This class will eventually encapsulate all of the PHPCR-ODM
* specific logic to enable support for multiple backends.
* @author Daniel Leech <[email protected]>
*/
class PhpcrOdmAdapter implements AdapterInterface
{
const TAG_NO_MULTILANG = 'no-multilang';

protected $dm;
protected $baseRoutePath;

/**
* @param DocumentManager $dm
* @param string $routeBasePath Route path for all routes
*/
public function __construct(DocumentManager $dm, $routeBasePath)
{
$this->dm = $dm;
$this->baseRoutePath = $routeBasePath;
}

/**
* {@inheritDoc}
*/
public function getLocales($contentDocument)
{
if ($this->dm->isDocumentTranslatable($contentDocument)) {
Expand All @@ -45,6 +54,9 @@ public function getLocales($contentDocument)
return array();
}

/**
* {@inheritDoc}
*/
public function translateObject($contentDocument, $locale)
{
$meta = $this->dm->getMetadataFactory()->getMetadataFor(get_class($contentDocument));
Expand All @@ -53,29 +65,64 @@ public function translateObject($contentDocument, $locale)
return $contentDocument;
}

public function removeDefunctRoute($route, $canonicalRoute)
/**
* {@inheritDoc}
*/
public function generateAutoRouteTag(UrlContext $urlContext)
{
return $urlContext->getLocale() ? : self::TAG_NO_MULTILANG;
}

/**
* {@inheritDoc}
*/
public function removeDefunctRoute(AutoRouteInterface $autoRoute, $newRoute)
{
$session = $this->dm->getPhpcrSession();
try {
$node = $this->dm->getNodeForDocument($route);
$canonicalNode = $this->dm->getNodeForDocument($canonicalRoute);
$nodeChildren = $node->getNodes();
foreach ($nodeChildren as $nodeChild) {
$session->move($nodeChild->getPath(), $canonicalNode->getPath() . '/' . $nodeChild->getName());
}
$session->removeItem($node->getPath());
$node = $this->dm->getNodeForDocument($autoRoute);
$newNode = $this->dm->getNodeForDocument($newRoute);
} catch (InvalidItemStateException $e) {
// nothing ..
}

$session->save();
}

public function createRoute($url, $contentDocument)
/**
* {@inheritDoc}
*/
public function migrateAutoRouteChildren(AutoRouteInterface $srcAutoRoute, AutoRouteInterface $destAutoRoute)
{
$session = $this->dm->getPhpcrSession();
$srcAutoRouteNode = $this->dm->getNodeForDocument($srcAutoRoute);
$destAutoRouteNode = $this->dm->getNodeForDocument($destAutoRoute);

$srcAutoRouteChildren = $srcAutoRouteNode->getNodes();

foreach ($srcAutoRouteChildren as $srcAutoRouteChild) {
$session->move($srcAutoRouteChild->getPath(), $destAutoRouteNode->getPath() . '/' . $srcAutoRouteChild->getName());
}
}

/**
* {@inheritDoc}
*/
public function removeAutoRoute(AutoRouteInterface $autoRoute)
{
$session = $this->dm->getPhpcrSession();
$node = $this->dm->getNodeForDocument($autoRoute);
$session->removeItem($node->getPath());
$session->save();
}

/**
* {@inheritDoc}
*/
public function createAutoRoute($url, $contentDocument, $autoRouteTag)
{
$path = $this->baseRoutePath;
$parentDocument = $this->dm->find(null, $path);

$segments = preg_split('#/#', $url, null, PREG_SPLIT_NO_EMPTY);
$headName = array_pop($segments);
foreach ($segments as $segment) {
Expand All @@ -95,27 +142,55 @@ public function createRoute($url, $contentDocument)
$headRoute->setContent($contentDocument);
$headRoute->setName($headName);
$headRoute->setParent($document);
$headRoute->setAutoRouteTag($autoRouteTag);

return $headRoute;
}

private function buildParentPathForUrl($url)
{

return $document;
}

public function createRedirectRoute($referringAutoRoute, $newRoute)
{
$parentDocument = $referringAutoRoute->getParent();

$redirectRoute = new RedirectRoute();
$redirectRoute->setName($referringAutoRoute->getName());
$redirectRoute->setRouteTarget($newRoute);
$redirectRoute->setParent($parentDocument);

$this->dm->persist($redirectRoute);
}

/**
* {@inheritDoc}
*/
public function getRealClassName($className)
{
return ClassUtils::getRealClass($className);
}

public function compareRouteContent(RouteObjectInterface $route, $contentDocument)
/**
* {@inheritDoc}
*/
public function compareAutoRouteContent(AutoRouteInterface $autoRoute, $contentDocument)
{
if ($route->getContent() === $contentDocument) {
if ($autoRoute->getContent() === $contentDocument) {
return true;
}

return false;
}

public function getReferringRoutes($contentDocument)
/**
* {@inheritDoc}
*/
public function getReferringAutoRoutes($contentDocument)
{
return $this->dm->getReferrers($contentDocument, null, null, null, 'Symfony\Cmf\Component\Routing\RouteObjectInterface');
return $this->dm->getReferrers($contentDocument, null, null, null, 'Symfony\Cmf\Bundle\RoutingAutoBundle\Model\AutoRouteInterface');
}

/**
Expand All @@ -124,6 +199,7 @@ public function getReferringRoutes($contentDocument)
public function findRouteForUrl($url)
{
$path = $this->getPathFromUrl($url);

return $this->dm->find(null, $path);
}

Expand All @@ -132,4 +208,3 @@ private function getPathFromUrl($url)
return $this->baseRoutePath . $url;
}
}

Loading