Browse Source

Cleaned up and expanded batch_actions.rst:
* added note about two options when adding a new batch_action
* added note about what the merge example is trying to do and when it's available
* edited code blocks to prevent line wraps on sonata website
* updated list__batch.html.twig example to reflect latest contents
* added link to Symfony bundle extension docs

Christian Morgan 11 years ago
parent
commit
b17e7eb387
1 changed files with 66 additions and 45 deletions
  1. 66 45
      Resources/doc/reference/batch_actions.rst

+ 66 - 45
Resources/doc/reference/batch_actions.rst

@@ -1,16 +1,25 @@
 Batch actions
 =============
 
-Batch actions are actions triggered on a set of selected models (all of them or only a specific subset).
+Batch actions are actions triggered on a set of selected objects. By default 
+Admins have a ``delete`` action which allows you to remove several entries at once.
 
 Defining new actions
 --------------------
 
-You can easily add some custom batch action in the list view. By default the ``delete`` action
-allows you to remove several entries at once.
+To create a new custom batch action which appears in the list view follow these steps:
 
-Override the ``getBatchActions`` from your ``Admin`` class to define custom batch actions.
-For example, we define here a new ``merge`` action.
+Override ``getBatchActions()`` in your ``Admin`` class to define the new batch actions
+by adding them to the $actions array. Each entry has two settings:
+
+- **label**: The name to use when offering this option to users, should be passed through the translator
+- **ask_confirmation**: defaults to true and means that the user will be asked for confirmation before the batch action is processed
+
+For example, lets define a new ``merge`` action which takes a number of source items and 
+merges them onto a single target item. It should only be available when two conditions are met:
+
+- the EDIT and DELETE routes exist for this Admin (have not been disabled)
+- the logged in administrator has EDIT and DELETE permissions
 
 .. code-block:: php
 
@@ -20,15 +29,17 @@ For example, we define here a new ``merge`` action.
 
     public function getBatchActions()
     {
-        // retrieve the default (currently only the delete action) actions
+        // retrieve the default batch actions (currently only delete)
         $actions = parent::getBatchActions();
 
-        // check user permissions
-        if($this->hasRoute('edit') && $this->isGranted('EDIT') && $this->hasRoute('delete') && $this->isGranted('DELETE')){
-            $actions['merge']=[
-                'label'            => $this->trans('action_merge', array(), 'SonataAdminBundle'),
-                'ask_confirmation' => true // If true, a confirmation will be asked before performing the action
-            ];
+        if (
+          $this->hasRoute('edit') && $this->isGranted('EDIT') && 
+          $this->hasRoute('delete') && $this->isGranted('DELETE')
+        ) {
+            $actions['merge'] = array(
+                'label' => $this->trans('action_merge', array(), 'SonataAdminBundle'),
+                'ask_confirmation' => true
+            );
 
         }
 
@@ -39,24 +50,24 @@ For example, we define here a new ``merge`` action.
 (Optional) Overriding the batch selection template
 --------------------------------------------------
 
-Obviously, a merge action requires two kind of selection : a set of source model to merge
-into one target model. By default, this bundle only enable the user to select some model,
-but there is only one selection kind. Thus you will need to override the ``list__batch.html.twig``
-template to display both a checkbox (source selection) and a radio (target selection) for each
-model row. See Symfony bundle overriding mechanism for further explanation.
+A merge action requires two kind of selection: a set of source objects to merge from
+and a target object to merge into. By default, batch_actions only let you select one set
+of objects to manipulate. We can override this behavior by changing our list template 
+(``list__batch.html.twig``) and adding a radio button to choose the target object. 
 
 .. code-block:: html+jinja
 
     {# in Acme/ProjectBundle/Resources/views/CRUD/list__batch.html.twig #}
+    {# See SonataAdminBundle:CRUD:list__batch.html.twig for the current default template #}
 
+    {% extends admin.getTemplate('base_list_field') %}
 
-    {# See SonataAdminBundle:CRUD:list__batch.html.twig for the current default template #}
-    <td class="sonata-ba-list-field sonata-ba-list-field-batch">
+    {% block field %}
         <input type="checkbox" name="idx[]" value="{{ admin.id(object) }}" />
 
         {# the new radio #}
         <input type="radio" name="targetId" value="{{ admin.id(object) }}" />
-    </td>
+    {% endblock %}
 
 
 And add this:
@@ -64,35 +75,39 @@ And add this:
 .. code-block:: php
 
     <?php
-
-    // In Acme/ProjectBundle/AcmeProjectBundle.php
+    // Acme/ProjectBundle/AcmeProjectBundle.php
 
     public function getParent()
     {
         return 'SonataAdminBundle';
     }
 
+See the [Symfony bundle overriding mechanism](http://symfony.com/doc/current/cookbook/bundles/inheritance.html) 
+for further explanation of overriding bundle templates.
+
 
 (Optional) Overriding the default relevancy check function
 ----------------------------------------------------------
 
-By default, batch actions are not executed if no model was selected, and the user is notified of
-this lack of selection. If your custom batch action need some more complex logic to determine if
-an action can be performed or not, just define the ``batchActionMyActionIsRelevant`` method in
-your ``CRUDController`` class. This check is performed before any confirmation, to make sure there
-is actually something to confirm. This method may return three different values :
+By default, batch actions are not executed if no object was selected, and the user is notified of
+this lack of selection. If your custom batch action needs more complex logic to determine if
+an action can be performed or not, just define a ``batchAction<MyAction>IsRelevant`` method 
+(e.g. ``batchActionMergeIsRelevant``) in your ``CRUDController`` class. This check is performed 
+before the user is asked for confirmation, to make sure there is actually something to confirm. 
+
+This method may return three different values:
 
  - ``true``: The batch action is relevant and can be applied.
- - a string: The batch action is not relevant given the current request parameters (for example the ``target`` is missing for a ``merge`` action). The returned string is the message that inform the user why the action is aborted.
  - ``false``: Same as above, with the default "action aborted, no model selected" notification message.
+ - a string: The batch action is not relevant given the current request parameters (for example the ``target`` is missing for a ``merge`` action). The returned string is a message displayed to the user.
 
 .. code-block:: php
 
     <?php
 
-    // In Acme/Controller/CRUDController.php
+    // In Acme/ProjectBundle/Controller/CRUDController.php
 
-    public function batchActionMergeIsRelevant(array $normalizedSelectedIds, $allEntitiesSelected)
+    public function batchActionMergeIsRelevant(array $selectedIds, $allEntitiesSelected)
     {
         // here you have access to all POST parameters, if you use some custom ones
         // POST parameters are kept even after the confirmation page.
@@ -103,7 +118,7 @@ is actually something to confirm. This method may return three different values
             return 'flash_batch_merge_no_target';
         }
 
-        $normalizedTargetId = $parameterBag->get('targetId');
+        $targetId = $parameterBag->get('targetId');
 
         // if all entities are selected, a merge can be done
         if ($allEntitiesSelected) {
@@ -111,35 +126,35 @@ is actually something to confirm. This method may return three different values
         }
 
         // filter out the target from the selected models
-        $normalizedSelectedIds = array_filter($normalizedSelectedIds,
-            function($normalizedSelectedId) use($normalizedTargetId){
-                return $normalizedSelectedId !== $normalizedTargetId;
+        $selectedIds = array_filter($selectedIds,
+            function($selectedId) use($targetId){
+                return $selectedId !== $targetId;
             }
         );
 
         // if at least one but not the target model is selected, a merge can be done.
-        return count($normalizedSelectedIds) > 0;
+        return count($selectedIds) > 0;
     }
 
 
 Define the core action logic
 ----------------------------
 
-The method ``batchActionMyAction`` will be executed to achieve the core logic. The selected
-models are passed to the method through a query argument retrieving them. If for some reason
-it makes sense to perform your batch action without the default selection method (for example
-you defined another way, at template level, to select model at a lower granularity), the
-passed query is ``null``.
+The method ``batchAction<MyAction>`` will be executed to process your batch. The selected
+objects are passed to this method through a query argument which can be used to retrieve them. 
+If for some reason it makes sense to perform your batch action without the default selection 
+method (for example you defined another way, at template level, to select model at a lower 
+granularity), the passed query is ``null``.
 
 .. code-block:: php
 
     <?php
 
-    // In Acme/Controller/CRUDController.php
+    // In Acme/ProjectBundle/Controller/CRUDController.php
 
     public function batchActionMerge(ProxyQueryInterface $selectedModelQuery)
     {
-        if ($this->admin->isGranted('EDIT') === false || $this->admin->isGranted('DELETE') === false)
+        if (!$this->admin->isGranted('EDIT') || !$this->admin->isGranted('DELETE'))
         {
             throw new AccessDeniedException();
         }
@@ -152,7 +167,9 @@ passed query is ``null``.
         if( $target === null){
             $this->addFlash('sonata_flash_info', 'flash_batch_merge_no_target');
 
-            return new RedirectResponse($this->admin->generateUrl('list',$this->admin->getFilterParameters()));
+            return new RedirectResponse(
+              $this->admin->generateUrl('list',$this->admin->getFilterParameters())
+            );
         }
 
         $selectedModels = $selectedModelQuery->execute();
@@ -168,10 +185,14 @@ passed query is ``null``.
         } catch (\Exception $e) {
             $this->addFlash('sonata_flash_error', 'flash_batch_merge_error');
 
-            return new RedirectResponse($this->admin->generateUrl('list',$this->admin->getFilterParameters()));
+            return new RedirectResponse(
+              $this->admin->generateUrl('list',$this->admin->getFilterParameters())
+            );
         }
 
         $this->addFlash('sonata_flash_success', 'flash_batch_merge_success');
 
-        return new RedirectResponse($this->admin->generateUrl('list',$this->admin->getFilterParameters()));
+        return new RedirectResponse(
+          $this->admin->generateUrl('list',$this->admin->getFilterParameters())
+        );
     }