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

Massive refactoring #73

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all 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
75 changes: 75 additions & 0 deletions AutoRoute/Adapter/AdapterInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<?php

/*
* This file is part of the Symfony CMF package.
*
* (c) 2011-2013 Symfony CMF
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Cmf\Bundle\RoutingAutoBundle\AutoRoute\Adapter;

use Symfony\Cmf\Component\Routing\RouteObjectInterface;

/**
* Adapters will (eventually) abstract all database operations
* with the aim of enabling other providers such as ORM.
*
* @author Daniel Leech <[email protected]>
*/
interface AdapterInterface
{
/**
* Return locales for object
*
* @return array
*/
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.
*/
public function translateObject($object, $locale);

/**
* Create a new auto route at the given path
* with the given document as the content.
*
* @param string $path
* @param object $document
*
* @return Route new route document
*/
public function createRoute($path, $document);

/**
* 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
* and the given content object are the same.
*
* @param RouteObjectInterface
* @param object
*/
public function compareRouteContent(RouteObjectInterface $route, $contentObject);

/**
* Attempt to find a route with the given URL
*
* @param string $url
*
* @return null|Symfony\Cmf\Component\Routing\RouteObjectInterface
*/
public function findRouteForUrl($url);
}
108 changes: 108 additions & 0 deletions AutoRoute/Adapter/PhpcrOdmAdapter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
<?php

/*
* This file is part of the Symfony CMF package.
*
* (c) 2011-2013 Symfony CMF
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Cmf\Bundle\RoutingAutoBundle\AutoRoute\Adapter;

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;

/**
* Abstraction adapter for PHPCR-ODM
*
* This class will eventually encapsulate all of the PHPCR-ODM
* specific logic to enable support for multiple backends.
*/
class PhpcrOdmAdapter implements AdapterInterface
{
protected $dm;
protected $baseRoutePath;

public function __construct(DocumentManager $dm, $routeBasePath)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wouterj we will need to add the route base path to the configuration -- but it would only apply to PHPCR-ODM.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, let's add it :)

{
$this->dm = $dm;
$this->baseRoutePath = $routeBasePath;
}

public function getLocales($contentDocument)
{
if ($this->dm->isDocumentTranslatable($contentDocument)) {
return $this->dm->getLocalesFor($contentDocument);
}

return array();
}

public function translateObject($contentDocument, $locale)
{
$meta = $this->dm->getMetadataFactory()->getMetadataFor(get_class($contentDocument));
$contentDocument = $this->dm->findTranslation($meta->getName(), $meta->getIdentifierValue($contentDocument), $locale);

return $contentDocument;
}

public function createRoute($path, $contentDocument)
{
$pathElements = explode('/', $path);
$headName = array_pop($pathElements);
$parentPath = implode('/', $pathElements);

// bypass the ODM ... but changes will still only be
// persisted when the PHPCR session is saved in the ODMs flush().
NodeHelper::createPath($this->dm->getPhpcrSession(), $parentPath);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This static call is a pain because I have to mock both a PHPCR SessionInterface and also an associated expectation to return a NodeInterface. @dbu do you think there is any scope for adding an instantiable version of this class in PHPCR utils? would make testing easier :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, whenever you try to cheat you get caught sooner or later :-(
i was too lazy to pass those helper all around the place. we can't even make the SessionInterface provide this, as its only in phpcr util. if we had built this as a class with methods, we could allow to set the helper and have a getter that creates the instance if its not set. but this would be a major BC break to change that now. we could introduce a new class in parallel but the best name is already taken. and whatever we do, it won't be phpcr-utils 1.1 but 1.2 so i fear right now we do need to mock. but open an issue on phpcr-utils that we should fix this there, and in jackalope and phpcr-odm.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


$autoRouteParent = $this->dm->find(null, $parentPath);

if (!$autoRouteParent) {
throw new \RuntimeException(sprintf(
'Hmph, could not find parent path "%s", this really should not have happened.',
$parentPath
));
}

$headRoute = new AutoRoute();
$headRoute->setContent($contentDocument);
$headRoute->setName($headName);
$headRoute->setParent($autoRouteParent);

return $headRoute;
}

public function getRealClassName($className)
{
return ClassUtils::getRealClass($className);
}

public function compareRouteContent(RouteObjectInterface $route, $contentDocument)
{
if ($route->getContent() === $contentDocument) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if this method would be needed or not -- it depends on if the method to get the routes associated content would differ from one adapter to another.

return true;
}

return false;
}

public function getReferringRoutes($contentDocument)
{
return $this->dm->getReferrers($contentDocument, null, null, null, 'Symfony\Cmf\Component\Routing\RouteObjectInterface');
}

/**
* {@inheritDoc}
*/
public function findRouteForUrl($url)
{
return $this->dm->find(null, $this->baseRoutePath . $url);
}
}
101 changes: 44 additions & 57 deletions AutoRoute/AutoRouteManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@

namespace Symfony\Cmf\Bundle\RoutingAutoBundle\AutoRoute;

use Symfony\Cmf\Bundle\RoutingAutoBundle\AutoRoute\RouteStack\Builder;
use Doctrine\Common\Util\ClassUtils;
use Symfony\Cmf\Bundle\RoutingAutoBundle\AutoRoute\Driver\DriverInterface;
use Metadata\MetadataFactoryInterface;

/**
* This class is concerned with the automatic creation of route objects.
Expand All @@ -22,81 +22,68 @@
*/
class AutoRouteManager
{
protected $factory;
protected $driver;
protected $urlGenerator;
protected $defunctRouteHandler;

public function __construct(DriverInterface $driver, Factory $factory, Builder $builder)
/**
* @param DriverInterface $driver Database driver
* @param UrlGeneratorInterface $urlGenerator Routing auto URL generator
* @param DefunctRouteHandlerInterface $defunctRouteHandler Handler for defunct routes
*/
public function __construct(
DriverInterface $driver,
UrlGeneratorInterface $urlGenerator,
DefunctRouteHandlerInterface $defunctRouteHandler
)
{
$this->factory = $factory;
$this->builder = $builder;
$this->driver = $driver;
$this->urlGenerator = $urlGenerator;
$this->defunctRouteHandler = $defunctRouteHandler;
}

/**
* Create or update the automatically generated route for
* the given document.
*
* When this is finished it will support multiple locales.
*
* @param object Mapped document for which to generate the AutoRoute
*
* @return BuilderContext[]
* @param object $document
*/
public function updateAutoRouteForDocument($document)
public function buildOperationStack(OperationStack $operationStack, $document)
{
$classFqn = ClassUtils::getClass($document);
$locales = $this->driver->getLocales($document) ? : array(null);

$contexts = array();

foreach ($locales as $locale) {
if (null !== $locale) {
$document = $this->driver->translateObject($document, $locale);
}
$urls = $this->getUrlsForDocument($document);

$context = new BuilderContext;
foreach ($urls as $url) {
$existingRoute = $this->driver->findRouteForUrl($url);

$context->setContent($document);
$context->setLocale($locale);
if ($existingRoute) {
$isSameContent = $this->driver->compareRouteContent($existingRoute, $document);

// build path elements
$builderUnitChain = $this->factory->getRouteStackBuilderUnitChain($classFqn);
$builderUnitChain->executeChain($context);
if ($isSameContent) {
continue;
}

// persist the content name element (the autoroute)
$autoRouteStack = new AutoRouteStack($context);
$builderUnit = $this->factory->getContentNameBuilderUnit($classFqn);
$this->builder->build($autoRouteStack, $builderUnit);
$url = $this->urlGenerator->resolveConflict($document, $url);
}

$contexts[] = $context;
$newRoute = $this->driver->createRoute($url, $document);
$operationStack->pushNewRoute($newRoute);
}

return $contexts;
}
$this->defunctRouteHandler->handleDefunctRoutes($document, $operationStack);

/**
* Remove all auto routes associated with the given document.
*
* @param object $document Mapped document
*
* @todo: Test me
*
* @return array Array of removed routes
*/
public function removeAutoRoutesForDocument($document)
{
throw new \Exception('Implement me??');
return $operationStack;
}

/**
* Return true if the given document is mapped with AutoRoute
*
* @param object $document Document
*
* @return boolean
*/
public function isAutoRouteable($document)
private function getUrlsForDocument($document)
{
return $this->factory->hasMapping(ClassUtils::getClass($document));
$urls = array();
$locales = $this->driver->getLocales($document) ? : array(null);

foreach ($locales as $locale) {
if (null !== $locale) {
$this->driver->translateObject($document, $locale);
}

$urls[] = $this->urlGenerator->generateUrl($document);
}

return $urls;
}
}
45 changes: 0 additions & 45 deletions AutoRoute/AutoRouteStack.php

This file was deleted.

Loading