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

Updated routing auto documentation for 1.0 #511

Merged
merged 4 commits into from
Aug 11, 2014
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
54 changes: 54 additions & 0 deletions bundles/routing_auto/conflict_resolvers.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
.. index::
single: Conflict Resolvers; RoutingAutoBundle

Conflict Resolvers
-------------------
Copy link
Member

Choose a reason for hiding this comment

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

one dash to much


These are the conflict resolvers which are provided by default by the
Copy link
Member

Choose a reason for hiding this comment

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

I would like to have a short description about what conflict resolvers are in the first place

RoutingAutoBundle.

auto_increment
~~~~~~~~~~~~~~

The ``auto_increment`` conflict resolver will add a numerical suffix to the path, for
example ``my/path`` would first become ``my/path-1`` and if that path *also*
Copy link
Member

Choose a reason for hiding this comment

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

"for example if my/path already exists, it'll first become my/path-1 and if that [...]"

exists it will try ``my/path-2``, ``my/path-3`` and so on into infinity until
it finds a path which *doesn't* exist.

.. configuration-block::

.. code-block:: yaml

stdClass:
url_schema: /cmf/blog
conflict_resolver: auto_increment

.. code-block:: xml

<auto-mapping xmlns="http://cmf.symfony.com/schema/routing_auto">
<mapping class="stdClass" url-schema="/cmf/blog">
<conflict-resolver name="auto_increment" />
</mapping>
</auto-mapping>
Copy link
Member

Choose a reason for hiding this comment

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

we no longer have a format option?

Copy link
Member Author

Choose a reason for hiding this comment

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

no. not at the moment.


throw_exception
~~~~~~~~~~~~~~~

The ``throw_exception`` efficiently resolves conflicts by throwing exceptions.
Copy link
Member

Choose a reason for hiding this comment

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

it doesn't resolve conflicts, it just avoid it by aborting the process before it happends

Copy link
Member Author

Choose a reason for hiding this comment

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

yeah, kindof a joke, "resolves" is meant to be in quotation marks.

This is the default action.

.. configuration-block::

.. code-block:: yaml

stdClass:
url_schema: /cmf/blog
conflict_resolver: throw_exception

.. code-block:: xml

<auto-mapping xmlns="http://cmf.symfony.com/schema/routing_auto">
<mapping class="stdClass" url-schema="/cmf/blog">
<conflict-resolver name="throw_exception" />
</mapping>
</auto-mapping>
203 changes: 127 additions & 76 deletions bundles/routing_auto/customization.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,152 +6,203 @@ Customization

.. _routingauto_customization_pathproviders:

Adding Path Providers
~~~~~~~~~~~~~~~~~~~~~
Token Providers
~~~~~~~~~~~~~~~

The goal of a ``PathProvider`` class is to add one or several path elements to
the route stack. For example, the following provider will add the path
``foo/bar`` to the route stack::
The goal of a ``TokenProvider`` class is to provide values for tokens in the
URL schema. Such values can be derived form the object for which the route
is being generated, or from the environment (e.g. the you could use the
current locale in the route).

// src/Acme/CmsBundle/RoutingAuto/PathProvider/FoobarProvider.php
namespace Acme\CmsBundle\RoutingAuto\PathProvider;
The following token provider will simply provide the value "foobar"::

use Symfony\Cmf\Bundle\RoutingAutoBundle\AutoRoute\PathProviderInterface;
use Symfony\Cmf\Bundle\RoutingAutoBundle\AutoRoute\RouteStack;
// src/Acme/CmsBundle/RoutingAuto/PathProvider/FoobarTokenProvider.php
namespace Symfony\Cmf\Component\RoutingAuto\TokenProvider;

class FoobarProvider implements PathProviderInterface
use Symfony\Cmf\Component\RoutingAuto\TokenProviderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Cmf\Component\RoutingAuto\UrlContext;

class FoobarTokenProvider implements TokenProviderInterface
{
public function providePath(RouteStack $routeStack)
/**
* {@inheritDoc}
*/
public function provideValue(UrlContext $urlContext, $options)
{
return 'foobar';
}

/**
* {@inheritDoc}
*/
public function configureOptions(OptionsResolverInterface $optionsResolver)
{
$routeStack->addPathElements(array('foo', 'bar'));
}
}

To use the path provider you must register it in the container and add the
``cmf_routing_auto.provider`` tag and set the **alias** accordingly:
``cmf_routing_auto.token_provider`` tag and set the **alias** accordingly:

.. configuration-block::

.. code-block:: yaml

services:
acme_cms.path_provider.foobar:
class: Acme\CmsBundle\RoutingAuto\PathProvider\FoobarProvider
scope: prototype
acme_cms.token_provider.foobar:
class: Acme\CmsBundle\RoutingAuto\PathProvider\FoobarTokenProvider
tags:
- { name: cmf_routing_auto.provider, alias: "foobar"}
- { name: cmf_routing_auto.token_provider, alias: "foobar"}

.. code-block:: xml

<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services">
<service
id="acme_cms.path_provider.foobar"
class="Acme\CmsBundle\RoutingAuto\PathProvider\FoobarProvider"
scope="prototype"
id="acme_cms.token_provider.foobar"
class="Acme\CmsBundle\RoutingAuto\PathProvider\FoobarTokenProvider"
>
<tag name="cmf_routing_auto.provider" alias="foobar"/>
<tag name="cmf_routing_auto.token_provider" alias="foobar"/>
</service>
</container>

.. code-block:: php

use Symfony\Component\DependencyInjection\Definition;

$definition = new Definition('Acme\CmsBundle\RoutingAuto\PathProvider\FoobarProvider');
$definition->addTag('cmf_routing_auto.provider', array('alias' => 'foobar'));
$definition->setScope('prototype');
$definition = new Definition('Acme\CmsBundle\RoutingAuto\PathProvider\FoobarTokenProvider');
$definition->addTag('cmf_routing_auto.token_provider', array('alias' => 'foobar'));

$container->setDefinition('acme_cms.path_provider.foobar', $definition);
$container->setDefinition('acme_cms.token_provider.foobar', $definition);

The ``FoobarProvider`` is now available as **foobar** in the routing auto
The ``FoobarTokenProvider`` is now available as **foobar** in the routing auto
configuration.

.. caution::
Conflict Resolvers
~~~~~~~~~~~~~~~~~~

Conflict resolvers decide what happens if a generated route already exists in
the route repository and is not related to the context object.

The following example will append an unique string to the URL to resolve a
conflict::

namespace Symfony\Cmf\Component\RoutingAuto\ConflictResolver;

use Symfony\Cmf\Component\RoutingAuto\ConflictResolverInterface;
use Symfony\Cmf\Component\RoutingAuto\UrlContext;
use Symfony\Cmf\Component\RoutingAuto\Adapter\AdapterInterface;

class UniqidConflictResolver implements ConflictResolverInterface
{
public function resolveConflict(UrlContext $urlContext)
{
$url = $urlContext->getUrl();
return sprintf('%s-%s', uniqid());
}
}

It is registered in the DI configuration as follows:

.. configuration-block::

.. code-block:: yaml

services:
acme_cms.conflict_resolver.foobar:
class: Acme\CmsBundle\RoutingAuto\ConflictResolver\UniqidConflictResolver
tags:
- { name: cmf_routing_auto.conflict_resolver, alias: "uniqid"}
Copy link
Member

Choose a reason for hiding this comment

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

add a space before }


.. code-block:: xml

<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services">
<service
id="acme_cms.conflict_resolver.foobar"
class="Acme\CmsBundle\RoutingAuto\ConflictResolver\UniqidConflictResolver"
>
<tag name="cmf_routing_auto.conflict_resolver" alias="uniqid"/>
</service>
</container>

.. code-block:: php

use Symfony\Component\DependencyInjection\Definition;

Both path providers and path actions need to be defined with a scope of
"prototype". This ensures that each time the auto routing system requests
the class a new one is given and you do not have any state problems.
$definition = new Definition('Acme\CmsBundle\RoutingAuto\ConflictResolver\UniqidConflictResolver');
$definition->addTag('cmf_routing_auto.conflict_resolver', array('alias' => 'foobar'));

Adding Path Actions
~~~~~~~~~~~~~~~~~~~
$container->setDefinition('acme_cms.conflict_resolver.uniqid', $definition);

In the auto routing system, a "path action" is an action to take if the path
provided by the "path provider" exists or not.
Defunct Route Handlers
~~~~~~~~~~~~~~~~~~~~~~

You can add a path action by extending the ``PathActionInterface`` and
registering your new class correctly in the DI configuration.
Defunct Route Handlers decide what happens to old routes when an object is
updated and its generated URL changes.

This is a very simple implementation from the bundle - it is used to throw an
exception when a path already exists::
They are not all-together trivial - the following handler removes old routes and is
the default handler::

namespace Symfony\Cmf\Bundle\RoutingAutoBundle\RoutingAuto\PathNotExists;
namespace Symfony\Cmf\Component\RoutingAuto\DefunctRouteHandler;

use Symfony\Cmf\Bundle\RoutingAutoBundle\AutoRoute\PathActionInterface;
use Symfony\Cmf\Bundle\RoutingAutoBundle\AutoRoute\Exception\CouldNotFindRouteException;
use Symfony\Cmf\Bundle\RoutingAutoBundle\AutoRoute\RouteStack;
use Symfony\Cmf\Component\RoutingAuto\DefunctRouteHandlerInterface;
use Symfony\Cmf\Component\RoutingAuto\UrlContextCollection;
use Symfony\Cmf\Component\RoutingAuto\Adapter\AdapterInterface;

class ThrowException implements PathActionInterface
class RemoveDefunctRouteHandler implements DefunctRouteHandlerInterface
{
public function init(array $options)
protected $adapter;

public function __construct(AdapterInterface $adapter)
{
$this->adapter = $adapter;
}

public function execute(RouteStack $routeStack)
public function handleDefunctRoutes(UrlContextCollection $urlContextCollection)
{
throw new CouldNotFindRouteException('/'.$routeStack->getFullPath());
$referringAutoRouteCollection = $this->adapter->getReferringAutoRoutes($urlContextCollection->getSubjectObject());

foreach ($referringAutoRouteCollection as $referringAutoRoute) {
if (false === $urlContextCollection->containsAutoRoute($referringAutoRoute)) {
$newRoute = $urlContextCollection->getAutoRouteByTag($referringAutoRoute->getAutoRouteTag());

$this->adapter->migrateAutoRouteChildren($referringAutoRoute, $newRoute);
$this->adapter->removeAutoRoute($referringAutoRoute);
}
}
}
}

The ``init()`` method configures the provider (throwing errors when required
options do not exists) and the ``execute()`` method executes the action.

It is registered in the DI configuration as follows:

.. configuration-block::

.. code-block:: yaml

services:
cmf_routing_auto.not_exists_action.throw_exception:
class: Symfony\Cmf\Bundle\RoutingAutoBundle\RoutingAuto\PathNotExists\ThrowException
scope: prototype
acme_cms.defunct_route_handler.foobar:
class: Acme\CmsBundle\RoutingAuto\DefunctRouteHandler\RemoveConflictResolver
tags:
- { name: cmf_routing_auto.not_exists_action, alias: "throw_exception"}
- { name: cmf_routing_auto.defunct_route_handler, alias: "remove"}

.. code-block:: xml

<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services">
<service
id="cmf_routing_auto.not_exists_action.throw_exception"
class="Symfony\Cmf\Bundle\RoutingAutoBundle\RoutingAuto\PathNotExists\ThrowException"
scope="prototype"
>
<tag name="cmf_routing_auto.not_exists_action" alias="throw_exception"/>
id="acme_cms.defunct_route_handler.foobar"
class="Acme\CmsBundle\RoutingAuto\DefunctRouteHandler\RemoveConflictResolver"
>
<tag name="cmf_routing_auto.defunct_route_handler" alias="remove"/>
</service>
</container>

.. code-block:: php

use Symfony\Component\DependencyInjection\Definition;

$definition = new Definition('Symfony\Cmf\Bundle\RoutingAutoBundle\RoutingAuto\PathNotExists\ThrowException');
$definition->addTag('cmf_routing_auto.provider', array('alias' => 'throw_exception'));
$definition->setScope('prototype');

$container->setDefinition('cmf_routing_auto.not_exists_action.throw_exception', $definition);

Note the following:

* **Scope**: Must *always* be set to *prototype*;
* **Tag**: The tag registers the service with the auto routing system, it can
be one of the following:

* ``cmf_routing_auto.exists.action`` - if the action is to be used when a
path exists;
* ``cmf_routing_auto.not_exists.action`` - if the action is to be used when
a path does not exist;
$definition = new Definition('Acme\CmsBundle\RoutingAuto\DefunctRouteHandler\RemoveConflictResolver');
$definition->addTag('cmf_routing_auto.defunct_route_handler', array('alias' => 'foobar'));

* **Alias**: The alias of the tag is the name by which you will reference this
action in the auto routing configuration.
$container->setDefinition('acme_cms.defunct_route_handler.remove', $definition);
Loading