diff --git a/_exts/sensio/sphinx/configurationblock.py b/_exts/sensio/sphinx/configurationblock.py index 7269f192..e0077c02 100644 --- a/_exts/sensio/sphinx/configurationblock.py +++ b/_exts/sensio/sphinx/configurationblock.py @@ -6,7 +6,6 @@ from docutils.parsers.rst import Directive, directives from docutils import nodes -from string import upper class configurationblock(nodes.General, nodes.Element): pass diff --git a/_exts/sensio/sphinx/phpcode.py b/_exts/sensio/sphinx/phpcode.py index c9230a3f..8379129b 100644 --- a/_exts/sensio/sphinx/phpcode.py +++ b/_exts/sensio/sphinx/phpcode.py @@ -7,7 +7,7 @@ from docutils import nodes, utils from sphinx.util.nodes import split_explicit_title -from string import lower +import sys def php_namespace_role(typ, rawtext, text, lineno, inliner, options={}, content=[]): text = utils.unescape(text) @@ -82,7 +82,7 @@ def php_phpclass_role(typ, rawtext, text, lineno, inliner, options={}, content=[ text = utils.unescape(text) has_explicit_title, title, full_class = split_explicit_title(text) - full_url = 'http://php.net/manual/en/class.%s.php' % lower(full_class) + full_url = 'http://php.net/manual/en/class.%s.php' % full_class.lower() if not has_explicit_title: title = full_class @@ -94,7 +94,7 @@ def php_phpfunction_role(typ, rawtext, text, lineno, inliner, options={}, conten text = utils.unescape(text) has_explicit_title, title, full_function = split_explicit_title(text) - full_url = 'http://php.net/manual/en/function.%s.php' % lower(full_function.replace('_', '-')) + full_url = 'http://php.net/manual/en/function.%s.php' % full_function.replace('_', '-').lower() if not has_explicit_title: title = full_function diff --git a/bundles/map.rst.inc b/bundles/map.rst.inc index a8e67e34..af8c003e 100644 --- a/bundles/map.rst.inc +++ b/bundles/map.rst.inc @@ -50,9 +50,9 @@ library or they introduce a complete new concept. * :doc:`routing_auto/index` * :doc:`routing_auto/introduction` - * :doc:`routing_auto/providers` - * :doc:`routing_auto/exists_actions` - * :doc:`routing_auto/not_exists_actions` + * :doc:`routing_auto/token_providers` + * :doc:`routing_auto/conflict_resolvers` + * :doc:`routing_auto/defunct_route_handlers` * :doc:`routing_auto/customization` * :doc:`search/index` diff --git a/bundles/routing_auto/conflict_resolvers.rst b/bundles/routing_auto/conflict_resolvers.rst new file mode 100644 index 00000000..eec96aba --- /dev/null +++ b/bundles/routing_auto/conflict_resolvers.rst @@ -0,0 +1,56 @@ +.. index:: + single: Conflict Resolvers; RoutingAutoBundle + +Conflict Resolvers +------------------ + +Conflict resolvers are invoked when the system detects that a newly generated +route would conflict with an route already existing in the route repository. + +This section details the conflict resolvers which are provided by default. + +auto_increment +~~~~~~~~~~~~~~ + +The ``auto_increment`` conflict resolver will add a numerical suffix to the path, for +example if ``my/path`` already exists, it would first become ``my/path-1`` and if that path *also* +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: + uri_schema: /cmf/blog + conflict_resolver: auto_increment + + .. code-block:: xml + + + + + + + +throw_exception +~~~~~~~~~~~~~~~ + +The ``throw_exception`` efficiently "resolves" conflicts by throwing exceptions. +This is the default action. + +.. configuration-block:: + + .. code-block:: yaml + + stdClass: + uri_schema: /cmf/blog + conflict_resolver: throw_exception + + .. code-block:: xml + + + + + + diff --git a/bundles/routing_auto/customization.rst b/bundles/routing_auto/customization.rst index b293ebfe..cd3d123c 100644 --- a/bundles/routing_auto/customization.rst +++ b/bundles/routing_auto/customization.rst @@ -4,53 +4,65 @@ Customization ------------- -.. _routingauto_customization_pathproviders: +.. _routingauto_customization_tokenproviders: -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 +URI 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\UriContext; + + class FoobarTokenProvider implements TokenProviderInterface { - public function providePath(RouteStack $routeStack) + /** + * {@inheritDoc} + */ + public function provideValue(UriContext $uriContext, $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 - + @@ -58,54 +70,110 @@ To use the path provider you must register it in the container and add the 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 URI to resolve a +conflict:: + + namespace Symfony\Cmf\Component\RoutingAuto\ConflictResolver; + + use Symfony\Cmf\Component\RoutingAuto\ConflictResolverInterface; + use Symfony\Cmf\Component\RoutingAuto\UriContext; + use Symfony\Cmf\Component\RoutingAuto\Adapter\AdapterInterface; + + class UniqidConflictResolver implements ConflictResolverInterface + { + public function resolveConflict(UriContext $uriContext) + { + $uri = $uriContext->getUri(); + 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"} + + .. code-block:: xml + + + + + + + + + .. 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 URI 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\UriContextCollection; + 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(UriContextCollection $uriContextCollection) { - throw new CouldNotFindRouteException('/'.$routeStack->getFullPath()); + $referringAutoRouteCollection = $this->adapter->getReferringAutoRoutes($uriContextCollection->getSubjectObject()); + + foreach ($referringAutoRouteCollection as $referringAutoRoute) { + if (false === $uriContextCollection->containsAutoRoute($referringAutoRoute)) { + $newRoute = $uriContextCollection->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:: @@ -113,22 +181,20 @@ It is registered in the DI configuration as follows: .. 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 - + id="acme_cms.defunct_route_handler.foobar" + class="Acme\CmsBundle\RoutingAuto\DefunctRouteHandler\RemoveConflictResolver" + > + @@ -136,22 +202,7 @@ It is registered in the DI configuration as follows: 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); diff --git a/bundles/routing_auto/defunct_route_handlers.rst b/bundles/routing_auto/defunct_route_handlers.rst new file mode 100644 index 00000000..caced977 --- /dev/null +++ b/bundles/routing_auto/defunct_route_handlers.rst @@ -0,0 +1,103 @@ +.. index:: + single: Customization; RoutingAutoBundle + +Defunct Route Handlers +---------------------- + +.. _routingauto_customization_defunctroutehandlers: + +When an already-persisted document is updated and the URI generated by the +RoutingAuto system is changed, a *new* route is always created. Defunct route +handlers decide what to do with the *old* routes. + +remove +~~~~~~ + +The remove handler will simply delete any old routes. This is the **default** +action. + +.. configuration-block:: + + .. code-block:: yaml + + stdClass: + uri_schema: /cmf/blog + defunct_route_handler: remove + + .. code-block:: xml + + + + + + + +.. note:: + + The above example is illustrative only. Removing old routes is the default + action, so it is not necessary to explicitly configure this handler. + +leave_redirect +~~~~~~~~~~~~~~ + +The ``LeaveRedirectDefunctRouteHandler`` will automatically update old routes +to redirect the browser to the route which has replaced it. This effectively +means you can rename your objects without worrying about users recieving HTTP +404 responses. + +The handler will replace the old route with a ``RedirectRoute`` at the same +path. + +.. configuration-block:: + + .. code-block:: yaml + + stdClass: + uri_schema: /cmf/blog + defunct_route_handler: leave_redirect + + .. code-block:: xml + + + + + + + +For the redirect to work you will also need to configure a redirect controller +in the ``cmf_routing`` configuration:: + +.. configuration-block:: + + .. code-block:: yaml + + cmf_routing: + dynamic: + controllers_by_class: + Symfony\Cmf\Bundle\RoutingBundle\Doctrine\Phpcr\RedirectRoute: cmf_routing.redirect_controller:redirectAction + + .. code-block:: xml + + + + + + + + cmf_routing.redirect_controller:redirectAction + + + + + + + .. code-block:: php + + $container->loadFromExtension('cmf_routing', array( + 'dynamic' => array( + 'controllers_by_class' => array( + 'Symfony\Cmf\Bundle\RoutingBundle\Doctrine\Phpcr\RedirectRoute' => 'cmf_routing.redirect_controller:redirectAction', + ), + ), + )); diff --git a/bundles/routing_auto/exists_actions.rst b/bundles/routing_auto/exists_actions.rst deleted file mode 100644 index 476ce4f8..00000000 --- a/bundles/routing_auto/exists_actions.rst +++ /dev/null @@ -1,67 +0,0 @@ -.. index:: - single: Exists Actions; RoutingAutoBundle - -Path Exists Actions -------------------- - -These are the default actions available to take if the path provided by a -``path_provider`` already exists and so creating a new path would create a -conflict. - -auto_increment -~~~~~~~~~~~~~~ - -The ``auto_increment`` action will add a numerical suffix to the path, for -example ``my/path`` would first become ``my/path-1`` and if that path *also* -exists it will try ``my/path-2``, ``my/path-3`` and so on into infinity until -it finds a path which *doesn't* exist. - -This action should typically be used in the ``content_name`` builder unit to -resolve conflicts. Using it in the ``content_path`` builder chain would not -make much sense. - -.. configuration-block:: - - .. code-block:: yaml - - exists_action: auto_increment - - .. code-block:: xml - - - - .. code-block:: php - - array( - // ... - 'exists_action' => 'auto_increment', - ); - -use -~~~ - -The ``use`` action will simply take the existing path and use it. For example, -in a forum the builder unit must first determine the category path, ``/my-category``, -if this path exists (and it should) then it will be *used* in the stack. - -This action should typically be used in one of the content path builder units -to specify that it should use the existing route. On the other hand, using -this as the content name builder action should cause the old route to be -overwritten. - -.. configuration-block:: - - .. code-block:: yaml - - exists_action: use - - .. code-block:: xml - - - - .. code-block:: php - - array( - // ... - 'exists_action' => 'use', - ); diff --git a/bundles/routing_auto/index.rst b/bundles/routing_auto/index.rst index 1ddaf6b6..0f82770f 100644 --- a/bundles/routing_auto/index.rst +++ b/bundles/routing_auto/index.rst @@ -5,7 +5,8 @@ RoutingAutoBundle :maxdepth: 2 introduction - providers - exists_actions - not_exists_actions + token_providers + conflict_resolvers + defunct_route_handlers customization + diff --git a/bundles/routing_auto/introduction.rst b/bundles/routing_auto/introduction.rst index a8e4c61c..98b31a34 100644 --- a/bundles/routing_auto/introduction.rst +++ b/bundles/routing_auto/introduction.rst @@ -5,10 +5,8 @@ RoutingAutoBundle ================= - The RoutingAutoBundle allows you to define automatically created routes for - documents. - -.. include:: ../_not-stable-caution.rst.inc +The RoutingAutoBundle allows you to automatically persist routes when +documents are persisted based on URI schemas and contextual information. This implies a separation of the ``Route`` and ``Content`` documents. If your needs are simple this bundle may not be for you and you should have a look at @@ -30,7 +28,7 @@ content documents - a category and the topics. These documents are called If you create a new category with the title "My New Category", the RoutingAutoBundle will automatically create the route ``/forum/my-new-cateogry``. For each new ``Topic`` it could create a route -like ``/forum/my-new-category/my-new-topic``. This URL resolves to a special +like ``/forum/my-new-category/my-new-topic``. This URI resolves to a special type of route that is called an *auto route*. By default, when you update a content document that has an auto route, the @@ -51,13 +49,13 @@ pattern ``/forum/my-new-forum/{topic}``, which could be handled by a controller. Why not just do that? #. By having a route for each page in the system, the application has a - knowledge of which URLs are accessible. This can be very useful, for + knowledge of which URIs are accessible. This can be very useful, for example, when specifying endpoints for menu items that are used when generating a site map; #. By separating the route from the content you allow the route to be customized independently of the content, for example, a topic may have - the same title as another topic but might need a different URL; -#. Separate route documents are translateable - this means you can have a URL + the same title as another topic but might need a different URI; +#. Separate route documents are translateable - this means you can have a URI for *each language*, "/welcome" and "/bienvenue" would each reference the same document in English and French respectively. This would be difficult if the slug was embedded in the content document; @@ -68,142 +66,58 @@ Why not just do that? Usage ----- -The diagram below shows a fictional URL for a forum topic. The first 6 elements -of the URL are called the *content path*. The last element is called the *content name*. +Imagine you have a fictional forum application and that you want to access the +forum topic with the following fictional URI: -.. image:: ../../_images/bundles/routing_auto_post_schema.png +- ``https://mywebsite.com/my-forum/drinks/coffee`` -The content path is further broken down into *path units* and *path elements*. A -path unit is a group of path elements and path elements are simply documents -in the PHPCR tree. +The RoutingAutoBundle uses a URI schema to define how routes are generated. A +schema for the above URI would look like this (the bundle does not care about +the host or protocol): -.. note:: +- ``/my-forum/{category}/{title}`` - Although path elements can be of any document class in this case, only - objects which extend the :class:`Symfony\\Component\\Routing\\Route` - object will be considered when matching a URL. +You can see that ``my-forum`` is static (it will not change) but that +``drinks`` has been replaced with ``{category}`` and ``coffee`` with +``{title}``. The replacements are called *tokens*. - The default behavior is to use ``Generic`` documents when generating a content - path, and these documents will result in a 404 when accessed directly. +The value for tokens are provided by *token providers*. -Internally, each path unit is built up by a *builder unit*. Builder units -contain one *path provider* class and two actions classes - one action to take -if the provided path exists in the PHPCR tree, the other if it does not. The -goal of each builder unit is to generate a path and then provide a route -object for each element in that path. +The schema, token providers, and other configurations (more on this later) are +contained within ``routing_auto.format`` files (currently ``xml`` and ``yaml`` are +supported). These files are contained either in your bundles +``Resources/config`` directory or in a custom location specified in +the bundle configuration. -The configuration for the example above could be as follows: +The configuration files for the above schema as applied to a ``Topic`` +document could be defined as follows: .. configuration-block:: .. code-block:: yaml - # app/config/config.yml - cmf_routing_auto: - mappings: - - Acme\ForumBundle\Document\Topic - content_path: - # corresponds first path unit in diagram: my-forum - forum_path: - provider: [specified, { path: my-form }] - exists_action: use - not_exists_action: create - - # corresponds second path unit in diagram: my-category - category_path: - provider: [content_object, { method: getCategory }] - exists_action: use - not_exists_action: throw_exception - - # corresponds to the content name: my-new-topic - content_name: - provider: [content_method, { method: getTitle }] - exists_action: [auto_increment, { pattern: -%d }] - not_exists_action: create - - .. code-block:: xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - .. code-block:: php - - // app/config/config.php - $container->loadFromExtension('cmf_routing_auto', array( - 'mappings' => array( - 'Acme\ForumBundle\Document\Topic' => array( - 'content_path' => array( - // corresponds first path unit in diagram: my-forum - 'forum_path' => array( - 'provider' => array('specified', array( - 'path' => 'my-forum', - )), - 'exists_action' => 'use', - 'not_exists_action' => 'create', - ), - - // corresponds second path unit in diagram: my-category - 'category_path' => array( - 'provider' => array('content_object', array( - 'method' => 'getCategory', - )), - 'exists_action' => 'use', - 'not_exists_action' => 'throw_exception', - ), - ), - - // corresponds to the content name: my-new-topic - 'content_name' => array( - 'provider' => array('content_method', array( - 'method' => 'getTitle', - )), - 'exists_action' => array('auto_increment', array( - 'pattern' => '-%d', - )), - 'not_exists_action' => 'create', - ), - ), - ), - )); + # src/Acme/ForumBundle/Resources/config/routing_auto.yml + Acme\ForumBundle\Document\Topic: + uri_schema: /my-forum/{category}/{title} + token_providers: + category: [content_method, {method: getCategoryTitle, slugify: true} ] + title: [content_method, {method: getTitle} ] # slugify is true by default + + .. code-block: xml + + + + + + + + + + + + + + The ``Topic`` document would then need to implement the methods named above as follows:: @@ -216,41 +130,41 @@ follows:: /** * Returns the category object associated with the topic. */ - public function getCategory() - { - return $this->category; - } - - public function getPublishedDate() + public function getCategoryName() { - return new \DateTime('2013/04/06'); + return 'Drinks'; } public function getTitle() { - return "My Topic Title"; + return 'Coffee'; } } -After persisting this object, the route will be created. Of course, you need to make -the properties editable and then you have a fully working routing system. +After persisting this object, the route will be created. You will of course +be wanting to return property values and not static strings, but you get the +idea. .. note:: Any mapping applied to an object will also apply to subclasses of that object. Imagine you have 2 documents, ``ContactPage`` and ``Page``, which both extend ``AbstractPage``. When you map the ``AbstractPage`` class, it - will be applied to both documents. + will be applied to both documents. You can also use the ``extend`` keyword + to achieve the same thing with objects which are not related. + +This is just a basic example. You can also configure what should happen when +a route already exists (confict resolution) and what to do with old routes +when the generated URI is changed (defunct route handling). -Provided Providers and Action ------------------------------ +Read more +--------- -The RoutingAutoBundle comes with a couple path providers and actions by -default. Read more about them in the other sections: +* :doc:`token_providers` +* :doc:`conflict_resolvers` +* :doc:`defunct_route_handlers` +* :doc:`customization` -* :doc:`providers` -* :doc:`exists_actions` -* :doc:`not_exists_actions` Customization ------------- diff --git a/bundles/routing_auto/not_exists_actions.rst b/bundles/routing_auto/not_exists_actions.rst deleted file mode 100644 index 3ce12694..00000000 --- a/bundles/routing_auto/not_exists_actions.rst +++ /dev/null @@ -1,60 +0,0 @@ -.. index:: - single: Not Exists Actions; RoutingAutoBundle - -Path not Exists Actions ------------------------ - -These are the default actions available to take if the path provided by a -``path_provider`` does not exist. - -create -~~~~~~ - -The ``create`` action will create the path. - -.. configuration-block:: - - .. code-block:: yaml - - not_exists_action: create - - .. code-block:: xml - - - - .. code-block:: php - - array( - // ... - 'not_exists_action' => 'create', - ); - -.. note:: - - **Currently** all routes provided by the content path builder units will be - created as ``Generic`` documents, whilst the content name route will be - created as an ``AutoRoute`` document. - -throw_exception -~~~~~~~~~~~~~~~ - -This action will throw an exception if the route provided by the path provider -does not exist. You should take this action if you are sure that the route -*should* exist. - -.. configuration-block:: - - .. code-block:: yaml - - not_exists_action: throw_exception - - .. code-block:: xml - - - - .. code-block:: php - - array( - // ... - 'not_exists_action' => 'throw_exception', - ); diff --git a/bundles/routing_auto/providers.rst b/bundles/routing_auto/providers.rst deleted file mode 100644 index fb4fead3..00000000 --- a/bundles/routing_auto/providers.rst +++ /dev/null @@ -1,200 +0,0 @@ -.. index:: - single: Path Providers; RoutingAutoBundle - -Path Providers --------------- - -Path providers specify a target path which is used by the subsequent path -actions to provide the actual route documents. - -**Base** providers must be the first configured as the first builder in the -content path chain. This is because the paths that they provide correspond -directly to an existing path, i.e. they have an absolute reference. - -specified (base provider) -~~~~~~~~~~~~~~~~~~~~~~~~~ - -This is the most basic path provider and allows you to specify an exact -(fixed) path. - -Options -....... - -* ``path`` - **required** The path to provide. - -.. configuration-block:: - - .. code-block:: yaml - - provider: [specified, { path: this/is/a/path }] - - .. code-block:: xml - - - - - .. code-block:: php - - array( - // ... - 'provider' => array('specified', array('path' => 'this/is/a/path')), - ); - -.. caution:: - - You should never specifiy absolute paths in the auto route system. If the - builder unit is the first content path chain it is understood that it is - the base of an absolute path. - -content_object (base provider) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The content object provider will try and provide a path from an object -implementing ``RouteReferrersInterface`` provided by a designated method on the -content document. For example, if you have a ``Topic`` class, which has a -``getCategory`` method, using this provider you can tell the ``Topic`` auto route -to use the route of the category as a base. - -So basically, if your category document has a path of ``/this/is/my/category``, -you can use this path as the base of your ``Category`` auto-route. - -Options -....... - - - ``method``: **required** Method used to return the document whose route path you wish to use. - -.. configuration-block:: - - .. code-block:: yaml - - provider: [content_object, { method: getCategory }] - - .. code-block:: xml - - - - - .. code-block:: php - - array( - // ... - 'provider' => array('content_object', array('method' => 'getCategory')), - ); - -.. note:: - - At the time of writing translated objects are not supported. But a patch - is already created for this feature. - -content_method -~~~~~~~~~~~~~~ - -The ``content_method`` provider allows the content object (e.g. a forum -``Topic``) to specify a path using one of its methods. This is quite a powerful -method as it allows the content document to do whatever it can to produce the -route, the disadvantage is that your content document will have extra code in -it. - -Options -....... - -* ``method``: **required** Method used to return the route name/path/path elements. -* ``slugify``: If the return value should be slugified, default is ``true``. - -.. configuration-block:: - - .. code-block:: yaml - - provider: [content_method, { method: getTitle }] - - .. code-block:: xml - - - - - .. code-block:: php - - array( - // ... - 'provider' => array('content_method', array('method' => 'getTitle')), - ); - -This example will use the existing method "getTitle" of the ``Topic`` document -to retrieve the title. By default all strings are *slugified*. - -The method can return the path either as a single string, an array of path -elements or an object which can be converted into a string, as shown in the -following example:: - - class Topic - { - /* Using a string */ - public function getTitle() - { - return "This is a topic"; - } - - /* Using an array */ - public function getPathElements() - { - return array('this', 'is', 'a', 'path'); - } - - /* Using an object */ - public function getStringObject() - { - $object = ...; // an object which has a __toString() method - - return $object; - } - } - -content_datetime -~~~~~~~~~~~~~~~~ - -The ``content_datettime`` provider will provide a path from a ``DateTime`` -object provided by a designated method on the content document. - -.. configuration-block:: - - .. code-block:: yaml - - provider: [content_datetime, { method: getDate, date_format: Y/m/d }] - - .. code-block:: xml - - - - - .. code-block:: php - - array( - // ... - 'provider' => array('content_datetime', array( - 'method' => 'getDate', - 'date_format' => 'Y/m/d', - )), - ); - -.. note:: - - This method extends `content_method`_ and inherits the slugify feature. - Internally, it returns a string using the `DateTime->format()` method. This - means that you can specify your date in anyway you like and it will be - automatically slugified. Also, by adding path separators in the - ``date_format`` you are effectively creating routes for each date component - as slugify applies to **each element** of the path. - -Options -....... - -* ``method``: **required** Method used to return the route name/path/path - elements. -* ``slugify``: If the return value should be slugified, default is ``true``. -* ``date_format``: Any date format accepted by the `DateTime` class, default - ``Y-m-d``. diff --git a/bundles/routing_auto/token_providers.rst b/bundles/routing_auto/token_providers.rst new file mode 100644 index 00000000..809c3f38 --- /dev/null +++ b/bundles/routing_auto/token_providers.rst @@ -0,0 +1,127 @@ +.. index:: + single: Path Providers; RoutingAutoBundle + +Token Providers +--------------- + +Token providers provide values for the tokens specified in the URI schemas. + +content_method +~~~~~~~~~~~~~~ + +The ``content_method`` provider allows the content object (e.g. a forum +``Topic``) to specify a path using one of its methods. This is quite a powerful +method as it allows the content document to do whatever it can to produce the +route. + +Options +....... + +* ``method``: **required** Method used to return the route name/path/path elements. +* ``slugify``: If the return value should be slugified, default is ``true``. + +.. configuration-block:: + + .. code-block:: yaml + + # src/Acme/ForumBundle/Resources/config/routing_auto.yml + Acme\ForumBundle\Document\Topic: + uri_schema: /my-forum/{title} + token_providers: + title: [content_method, {method: getTitle} ] + + .. code-block: xml + + + + + + + + + + + +This example will use the existing method "getTitle" of the ``Topic`` document +to retrieve the title. By default all strings are *slugified*. + +Options +....... + +* ``method``: **required** Method used to return the route name/path/path + elements. +* ``slugify``: If the return value should be slugified, default is ``true``. + +content_datetime +~~~~~~~~~~~~~~~~ + +The ``content_datetime`` provider will provide a path from a ``DateTime`` +object provided by a designated method on the content document. + +.. configuration-block:: + + .. code-block:: yaml + + # src/Acme/ForumBundle/Resources/config/routing_auto.yml + Acme\ForumBundle\Document\Topic: + uri_schema: /blog/{date}/my-post + token_providers: + date: [content_datetime, {method: getDate} ] + + .. code-block: xml + + + + + + + + + + + +Options +....... + +* ``method``: **required** Method used to return the route name/path/path + elements. +* ``slugify``: If the return value should be slugified, default is ``true``. +* ``date_format``: Any date format accepted by the `DateTime` class, default + ``Y-m-d``. + +content_locale +~~~~~~~~~~~~~~ + +The ``content_locale`` provider will provide the locale (e.g. ``fr``, ``de``, +etc) from the subject object. It ultimately it determines the locale from the +storage specific adapter - so it is dependent upon the adapter supporting this +feature. + +.. configuration-block:: + + .. code-block:: yaml + + # src/Acme/ForumBundle/Resources/config/routing_auto.yml + Acme\ForumBundle\Document\Topic: + uri_schema: /blog/{locale}/my-post + token_providers: + locale: [content_locale ] + + .. code-block: xml + + + + + + + + + +Options +....... + +* ``method``: **required** Method used to return the route name/path/path + elements. +* ``slugify``: If the return value should be slugified, default is ``true``. +* ``locale_format``: Any locale format accepted by the `DateTime` class, default + ``Y-m-d``.