Skip to content

Commit

Permalink
add wip recipe for custom action
Browse files Browse the repository at this point in the history
  • Loading branch information
koyaan committed Aug 27, 2013
1 parent d341639 commit 5ee2c01
Showing 1 changed file with 226 additions and 0 deletions.
226 changes: 226 additions & 0 deletions Resources/doc/reference/recipe_custom_action.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
Creating a Custom Admin Action
==============================

This is a full working example of creating a custom list action for SonataAdmin.
The Example is based on an existing ``CarAdmin`` in an ``AcmeDemoBundle``. It is
assumed you already have and admin service up and running.

The recipe
----------

SonataAdmin provides a very straight-forward way of adding your own custom actions.

To do this we need to:

- extend the ``SonataAdmin:CRUD`` Controller and tell our admin class to use it
- create the custom action in our Controller
- create a template to show the action in list view
- add the route and the new action in the Admin class

Extending the Admin Controller
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

First we need to create or own Controller extending the one from SonataAdmin


.. code-block:: php
<?php // src/Acme/DemoBundle/Controller/CRUDController.php
namespace Acme\DemoBundle\Controller;
use Sonata\AdminBundle\Controller\CRUDController as Controller;
class CRUDController extends Controller
{
// ...
}
Admin classes by default use ``SonataAdmin:CRUD`` controller , this is the third parameter
of an admin service defintion, we need to change it to our own.

Either by using XML:

.. code-block:: xml
<!-- src/Acme/DemoBundle/Resources/config/admin.xml -->
...
<service id="acme.demo.admin.car" class="Acme\DemoBundle\Admin\CarAdmin">
<tag name="sonata.admin" manager_type="orm" group="Demo" label="Car" />
<argument />
<argument>Acme\DemoBundle\Entity\Car</argument>
<argument>AcmeDemoBundle:CRUD</argument
...
</service>
...
Or by overwriting the configuration in your ``config.yml``


.. code-block:: yaml
# app/config/config.yml
services:
acme.demo.admin.car:
class: Acme\DemoBundle\Admin\CarAdmin
tags:
- { name: sonata.admin, manager_type: orm, group: Demo, label: Car }
arguments:
- null
- Acme\DemoBundle\Entity\Car
- AcmeDemoBundle:CRUD
For more information about service configuration please refer to

TODO: link


Create the custom action in our Controller
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Now it's time to actually create your custom action here, for this example i chose
to implement a ``clone`` action.

.. code-block:: php
<?php // src/Acme/DemoBundle/Controller/CRUDController.php
namespace Acme\DemoBundle\Controller;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Sonata\AdminBundle\Controller\CRUDController as Controller;
use Symfony\Component\HttpFoundation\RedirectResponse;
class CRUDController extends Controller
{
public function cloneAction()
{
$id = $this->get('request')->get($this->admin->getIdParameter());
$object = $this->admin->getObject($id);
if (!$object) {
throw new NotFoundHttpException(sprintf('unable to find the object with id : %s', $id));
}
$clonedObject = clone $object;
$clonedObject->setName($object->getName()." (Clone)");
$this->admin->create($clonedObject);
$this->addFlash('sonata_flash_success', 'Cloned successfully');
return new RedirectResponse($this->admin->generateUrl('list'));
}
}
Here we first get the id of the object, see if it exists then clone it and insert the clone
as new object. Finally we set a flash message indicating success and redirect to the list view.

TODO: talk about other options or just refer to https://github.com/sonata-project/SonataAdminBundle/blob/master/Controller/CRUDController.php for reference?

Create a template for the new action
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


We need to tell SonataAdmin how to render our new action we do that by creating a ``list__action_clone.html.twig`` in the
namespace of our custom Admin Controller.


.. code-block:: twig
{# src/Acme/DemoBundle/Resources/views/CRUD/list__action_clone.html.twig #}
<a href="{{ admin.generateObjectUrl('clone', object) }}">clone</a>
Right now ``clone`` is not a known route, we define it in the next step.


Bringing it all together
^^^^^^^^^^^^^^^^^^^^^^^


What's left now is actually adding our custom action to the admin class

We have to add the new route in ``configureRoutes``

.. code-block:: php
protected function configureRoutes(RouteCollection $collection)
{
$collection->add('clone', $this->getRouterIdParameter().'/clone');
}
Which gives us a route like ``../admin/sonata/demo/car/1/clone``.
You could also just do ``$collection->add('clone');`` to get a route like ``../admin/sonata/demo/car/clone?id=1``

Next we have to add the action in ``configureListFields`` specifying the template we created.


.. code-block:: php
protected function configureListFields(ListMapper $listMapper)
{
$listMapper
// other fields...
->add('_action', 'actions', array( 'actions' => array(
'Clone' => array('template' =>
'AcmeDemoBundle:CRUD:list__action_clone.html.twig'))))
;
}
The full example ``CarAdmin.php`` looks like this:

.. code-block:: php
<?php // src/Acme/DemoBundle/Admin/CarAdmin.php
namespace Acme\DemoBundle\Admin;
// ...
use Sonata\AdminBundle\Route\RouteCollection;
class CarAdmin extends Admin
{
// ...
protected function configureListFields(ListMapper $listMapper)
{
$listMapper
->addIdentifier('name')
->add('engine')
->add('rescueEngine')
->add('createdAt')
->add('_action', 'actions', array( 'actions' => array(
'Clone' => array('template' =>
'AcmeDemoBundle:CRUD:list__action_clone.html.twig'))))
;
}
protected function configureRoutes(RouteCollection $collection)
{
$collection->add('clone', $this->getRouterIdParameter().'/clone');
}
}
Final result looks like this:

TODO: screenshot

An example of this for ``CarAdmin`` in the AcmeDemoBundle of sonata-sandbox can be found here:
https://github.com/koyaan/sandbox/commit/5bdbc3528ec095f697a9deec32a4bc8ca8d13321

0 comments on commit 5ee2c01

Please sign in to comment.