Skip to content

[WIP] ORM based dynamic routing #95

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
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
3 changes: 3 additions & 0 deletions DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ public function getConfigTreeBuilder()
->fixXmlConfig('locale')
->children()
->scalarNode('enabled')->defaultNull()->end()
->arrayNode('instances')
->prototype('scalar')->end()
->end()
Copy link
Member

Choose a reason for hiding this comment

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

from the code below i understand you moved the route enhancer configuration under this node. what exactly for? to allow more than one dynamic router being configured at the same time? we could do that, but then we should move the information if its to be an orm or phpcr-odm router in there as well. how do you decide that right now? or do you have the extension load and enhance a dynamic router service defined by your application?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

i think you know better how to handle this...

i added those lines as child of 'dynamic' field of 'symfony_cmf_routing' (or 'cmf_..') into app/config/config.yml

    instances:
        - symfony_cmf_routing.orm.dynamic_router
        - symfony_cmf_routing.dynamic_router

the chain -> routers_by_id tells which router and priority, they are not all dynamic one but the dynamic should be setup by the extension if i understood correct.
should another field (say 'dynamic') be added to 'routers_by_id' to mark a router as dynamic? the provider info are into xml services config and this tells which repository should the router fetch from.

Copy link
Member

Choose a reason for hiding this comment

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

as solution for this issue, #112 is separating the route provider from the rest of the dynamic router. the configuration does not expect that you would want to run more than one dynamic router. i think that makes sense, people in most cases won't need both orm and phpcr routes at the same time. if they really do, they can still define their own dynamic router service in their application.

->scalarNode('generic_controller')->defaultValue('symfony_cmf_content.controller:indexAction')->end()
->arrayNode('controllers_by_type')
->useAttributeAsKey('type')
Expand Down
41 changes: 22 additions & 19 deletions DependencyInjection/SymfonyCmfRoutingExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ private function setupDynamicRouter(array $config, ContainerBuilder $container,
$container->setParameter($this->getAlias() . '.uri_filter_regexp', $config['uri_filter_regexp']);

$loader->load('cmf_routing.xml');
$loader->load('cmf_orm_routing.xml');
$container->setParameter($this->getAlias() . '.routing_repositoryroot', $config['routing_repositoryroot']);
if (isset($config['locales']) && $config['locales']) {
$container->setParameter($this->getAlias() . '.locales', $config['locales']);
Expand All @@ -108,26 +109,28 @@ private function setupDynamicRouter(array $config, ContainerBuilder $container,
$managerRegistry->setFactoryService(new Reference($config['manager_registry']));
$managerRegistry->replaceArgument(0, $config['manager_name']);

$dynamic = $container->getDefinition($this->getAlias().'.dynamic_router');
foreach ($config['instances'] as $dynRouterServiceId) {

// if any mappings are defined, set the respective route enhancer
if (!empty($config['generic_controller'])) {
$dynamic->addMethodCall('addRouteEnhancer', array(new Reference($this->getAlias() . '.enhancer_explicit_template')));
}
if (!empty($config['controllers_by_type'])) {
$dynamic->addMethodCall('addRouteEnhancer', array(new Reference($this->getAlias() . '.enhancer_controllers_by_type')));
}
if (!empty($config['controllers_by_class'])) {
$dynamic->addMethodCall('addRouteEnhancer', array(new Reference($this->getAlias() . '.enhancer_controllers_by_class')));
}
if (!empty($config['generic_controller']) && !empty($config['templates_by_class'])) {
$dynamic->addMethodCall('addRouteEnhancer', array(new Reference($this->getAlias() . '.enhancer_controller_for_templates_by_class')));
$dynamic->addMethodCall('addRouteEnhancer', array(new Reference($this->getAlias() . '.enhancer_templates_by_class')));
}
if (!empty($config['route_filters_by_id'])) {
$matcher = $container->getDefinition('symfony_cmf_routing.nested_matcher');
foreach ($config['route_filters_by_id'] as $id => $priority) {
$matcher->addMethodCall('addRouteFilter', array(new Reference($id), $priority));
$dynamic = $container->getDefinition($dynRouterServiceId);
// if any mappings are defined, set the respective route enhancer
if (!empty($config['generic_controller'])) {
$dynamic->addMethodCall('addRouteEnhancer', array(new Reference($this->getAlias() . '.enhancer_explicit_template')));
}
if (!empty($config['controllers_by_type'])) {
$dynamic->addMethodCall('addRouteEnhancer', array(new Reference($this->getAlias() . '.enhancer_controllers_by_type')));
}
if (!empty($config['controllers_by_class'])) {
$dynamic->addMethodCall('addRouteEnhancer', array(new Reference($this->getAlias() . '.enhancer_controllers_by_class')));
}
if (!empty($config['generic_controller']) && !empty($config['templates_by_class'])) {
$dynamic->addMethodCall('addRouteEnhancer', array(new Reference($this->getAlias() . '.enhancer_controller_for_templates_by_class')));
$dynamic->addMethodCall('addRouteEnhancer', array(new Reference($this->getAlias() . '.enhancer_templates_by_class')));
}
if (!empty($config['route_filters_by_id'])) {
$matcher = $container->getDefinition('symfony_cmf_routing.nested_matcher');
foreach ($config['route_filters_by_id'] as $id => $priority) {
$matcher->addMethodCall('addRouteFilter', array(new Reference($id), $priority));
}
}
}
}
Expand Down
56 changes: 56 additions & 0 deletions Entity/ContentRepository.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php

namespace Symfony\Cmf\Bundle\RoutingBundle\Entity;

use Symfony\Cmf\Component\Routing\ContentRepositoryInterface;

/**
* Description of ContentRepository
*
* @author teito
*/
class ContentRepository implements ContentRepositoryInterface
{
public function __construct($orm)
{
$this->orm = $orm;
}

/**
* {@inheritDoc}
*/
public function findById($id)
{
$identifier = $id;

list($model, $id) = $this->getModelAndId($identifier);

return $this->orm->getRepository($model)->find($id);
}

/**
* {@inheritDoc}
*/
public function getContentId($content)
{
if (! is_object($content)) {
return null;
}
try {
return implode(':', array(
get_class($content),
$content->getId()
));
} catch (\Exception $e) {
return null;
}
}

public function getModelAndId($identifier)
{
$model = substr($identifier, 0, strpos($identifier, ':'));
$id = substr($identifier, strpos($identifier, ':'));

return array($model, $id);
}
}
141 changes: 141 additions & 0 deletions Entity/ExternalRoute.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
<?php

namespace Symfony\Cmf\Bundle\RoutingBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Cmf\Component\Routing\RedirectRouteInterface;

/**
* ExternalRoute
* @ORM\Entity(repositoryClass="Raindrop\RoutingBundle\Entity\ExternalRouteRepository")
* @ORM\HasLifecycleCallbacks()
* @ORM\Table(name="external_routes")
*/
class ExternalRoute implements RedirectRouteInterface
Copy link
Member

Choose a reason for hiding this comment

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

could we call this RedirectRoute instead of ExternalRoute? it does not need to be an external redirect, could also be internal...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes ofc.
I didn't know how to handle this too: does this require to be compatible with redirection controllers of cmf?

{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;

/**
* @ORM\Column(type="string", length=255)
*/
private $uri;

/**
* @ORM\Column(type="boolean", nullable=true)
*/
protected $permanent;

/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}

/**
* Set uri
*
* @param string $uri
* @return ExternalRoute
*/
public function setUri($uri)
{
$this->uri = $uri;

return $this;
}

/**
* Get url
*
* @return string
*/
public function getUri()
{
return $this->uri;
}

/**
* May come handy
* @return type
*/
public function getUrl()
{
return $this->getUri();
}

/**
* Set permanent
*
* @param boolean $permanent
* @return ExternalRoute
*/
public function setPermanent($permanent = true)
{
$this->permanent = $permanent;

return $this;
}

/**
* Get permanent
*
* @return boolean
*/
public function getPermanent()
{
return $this->permanent;
}

public function isPermanent()
{
return $this->getPermanent();
}

/**
* @TODO
*/
public function getParameters()
{
return null;
}

/**
* @TODO
*/
public function getRouteTarget()
{
throw new LogicException('There is no route target for an external route, ask for uri instead');
}

/**
* @TODO
*/
public function getRouteName()
{
throw new LogicException('There is no name for an external route, ask for id or uri');
}

/**
* The external route points to self ??
*
* @return \Raindrop\RoutingBundle\Entity\ExternalRoute
*/
public function getRouteContent()
{
return $this;
}

public function getRouteKey()
{
return null;
}
}
125 changes: 125 additions & 0 deletions Entity/Route.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
<?php

namespace Symfony\Cmf\Bundle\RoutingBundle\Entity;

use Symfony\Cmf\Bundle\RoutingBundle\Document\Route as BaseRoute;

/**
* ORM route version.
* @author matteo caberlotto [email protected]
*/
class Route extends BaseRoute
{
/**
* {@inheritDoc}
*/
protected $id_prefix = '';

/**
* {@inheritDoc}
*/
protected $id;

/**
* {@inheritDoc}
*/
protected $name;

/**
* {@inheritDoc}
*/
protected $path;

/**
* {@inheritDoc}
*/
protected $position;

/**
* {@inheritDoc}
*/
protected $variablePattern;

/**
* {@inheritDoc}
*/
protected $addFormatPattern;

/**
* {@inheritDoc}
*/
protected $addTrailingSlash;

/**
* {@inheritDoc}
*/
protected $host;

/**
* {@inheritDoc}
*/
protected $defaults;

/**
* {@inheritDoc}
*/
protected $requirements;

/**
* {@inheritDoc}
*/
protected $options;

/**
* This property is used to order routes during ORM query and thus
* matching order.
* (Higher position wins. i.e.: ORDER BY - DESC)
*/
protected $priority;

/**
* Set priority
*
* @param int $priority
*/
public function setPriority($priority)
{
$this->priority = $priority;

return $priority;
}

/**
* Returns the route priority
*/
public function getPriority()
{
return $this->priority;
}

/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}

/**
* {@inheritDoc}
*/
public function getDefaults()
{
return $this->defaults;
}

/**
* {@inheritDoc}
*/
public function getStaticPrefix()
{
return $this->path;
}
}
Loading