Prechádzať zdrojové kódy

fix regression introduced with the datagrid, simplify the CRUDController, update some phpdocs

Thomas Rabaix 14 rokov pred
rodič
commit
2d2c8d88c0

+ 127 - 114
Admin/Admin.php

@@ -139,7 +139,9 @@ abstract class Admin implements AdminInterface
      *
      * @var array
      */
-    protected $formOptions = array();
+    protected $formOptions = array(
+        'validation_groups' => 'Default'
+    );
 
     /**
      * The code related to the admin
@@ -264,6 +266,13 @@ abstract class Admin implements AdminInterface
      */
     protected $datagridBuilder;
 
+    /**
+     * The datagrid instance
+     *
+     * @var \Sonata\AdminBundle\Datagrid\DatagridInterface
+     */
+    protected $datagrid;
+
     /**
      * The router intance
      *
@@ -334,7 +343,7 @@ abstract class Admin implements AdminInterface
 
     }
 
-    public function configureSideMenu(Menu $menu, $action, Admin $childAdmin = null)
+    public function configureSideMenu(MenuItem $menu, $action, Admin $childAdmin = null)
     {
 
     }
@@ -476,7 +485,7 @@ abstract class Admin implements AdminInterface
     }
 
     /**
-     * return the name of the parent related field, so the field can be use to set the default
+     * Returns the name of the parent related field, so the field can be use to set the default
      * value (ie the parent object) or to filter the object
      *
      * @return string the name of the parent related field
@@ -539,7 +548,7 @@ abstract class Admin implements AdminInterface
     }
 
     /**
-     * return the baseRoutePattern used to generate the routing information
+     * Returns the baseRoutePattern used to generate the routing information
      *
      * @throws RuntimeException
      * @return string the baseRoutePattern used to generate the routing information
@@ -572,7 +581,7 @@ abstract class Admin implements AdminInterface
     }
 
     /**
-     * return the baseRouteName used to generate the routing information
+     * Returns the baseRouteName used to generate the routing information
      *
      * @throws RuntimeException
      * @return string the baseRouteName used to generate the routing information
@@ -609,6 +618,8 @@ abstract class Admin implements AdminInterface
      *
      * @param string $word
      * @param string $sep the separator
+     *
+     * @return string
      */
     public function urlize($word, $sep = '_')
     {
@@ -616,7 +627,7 @@ abstract class Admin implements AdminInterface
     }
 
     /**
-     * return the class name handled by the Admin instance
+     * Returns the class name handled by the Admin instance
      *
      * @return string the class name handled by the Admin instance
      */
@@ -627,7 +638,7 @@ abstract class Admin implements AdminInterface
 
 
     /**
-     * return the list of batchs actions
+     * Returns the list of batchs actions
      *
      * @return array the list of batchs actions
      */
@@ -639,19 +650,19 @@ abstract class Admin implements AdminInterface
     }
 
     /**
-     * return the list of available urls
+     * Returns the list of available urls
      *
      * @return \Sonata\AdminBundle\Route\RouteCollection the list of available urls
      */
-    public function getRoutes($prefix = '')
+    public function getRoutes()
     {
-        $this->buildRoutes($prefix);
+        $this->buildRoutes();
 
         return $this->routes;
     }
 
     /**
-     * return the parameter representing router id, ie: {id} or {childId}
+     * Returns the parameter representing router id, ie: {id} or {childId}
      *
      * @return string
      */
@@ -661,7 +672,7 @@ abstract class Admin implements AdminInterface
     }
 
     /**
-     * return the parameter representing request id, ie: id or childId
+     * Returns the parameter representing request id, ie: id or childId
      *
      * @return string
      */
@@ -675,7 +686,7 @@ abstract class Admin implements AdminInterface
      *
      * @return void
      */
-    public function buildRoutes($prefix = '')
+    public function buildRoutes()
     {
         if ($this->loaded['routes']) {
             return;
@@ -693,7 +704,6 @@ abstract class Admin implements AdminInterface
         $collection->add('list');
         $collection->add('create');
         $collection->add('update');
-        $collection->add('create');
         $collection->add('batch');
         $collection->add('edit', $this->getRouterIdParameter().'/edit');
         $collection->add('delete', $this->getRouterIdParameter().'/delete');
@@ -709,7 +719,7 @@ abstract class Admin implements AdminInterface
     }
 
     /**
-     * return the url defined by the $name
+     * Returns the url defined by the $name
      *
      * @param strinf $name
      * @return Route
@@ -736,7 +746,6 @@ abstract class Admin implements AdminInterface
      */
     public function generateUrl($name, array $parameters = array())
     {
-
         if (!$this->isChild()) {
             if (strpos($name, '.')) {
                 $name = $this->getCode().'|'.$name;
@@ -789,7 +798,7 @@ abstract class Admin implements AdminInterface
     }
 
     /**
-     * return the list template
+     * Returns the list template
      *
      * @return string the list template
      */
@@ -799,7 +808,7 @@ abstract class Admin implements AdminInterface
     }
 
     /**
-     * return the edit template
+     * Returns the edit template
      *
      * @return string the edit template
      */
@@ -809,7 +818,7 @@ abstract class Admin implements AdminInterface
     }
 
     /**
-     * return an instance of the related classname
+     * Returns an instance of the related classname
      *
      * @return Object An instance of the related classname
      */
@@ -849,10 +858,10 @@ abstract class Admin implements AdminInterface
     }
 
     /**
-     * return the target object
+     * Returns the target object
      *
      * @param integer $id
-     * @return
+     * @return object
      */
     public function getObject($id)
     {
@@ -887,14 +896,17 @@ abstract class Admin implements AdminInterface
     }
 
     /**
-     * return a form depend on the given $object
+     * Returns a form depend on the given $object
      *
      * @param object $object
      * @param array $options the form options
      * @return \Symfony\Component\Form\Form
      */
-    public function getForm($object, array $options = array())
+    public function getForm($object = null, array $options = array())
     {
+        if (!$object) {
+            $object = $this->getNewInstance();
+        }
 
         // append parent object if any
         // todo : clean the way the Admin class can retrieve set the object
@@ -927,14 +939,13 @@ abstract class Admin implements AdminInterface
     }
 
     /**
-     * return a list depend on the given $object
+     * Returns a list depend on the given $object
      *
-     * @param  $object
-     * @return \Symfony\Component\Datagrid\ListCollection
+     * @param array $options
+     * @return \Sonata\AdminBundle\Datagrid\ListCollection
      */
     public function getList(array $options = array())
     {
-
         $list = $this->getListBuilder()->getBaseList($options);
 
         $mapper = new ListMapper($this->getListBuilder(), $list, $this);
@@ -957,43 +968,45 @@ abstract class Admin implements AdminInterface
     }
 
     /**
-     * return a list depend on the given $object
+     * Returns a list depend on the given $object
      *
-     * @param  $object
-     * @return Symfony\Component\Datagrid\Datagrid
+     * @return \Sonata\AdminBundle\Datagrid\DatagridInterface
      */
     public function getDatagrid()
     {
-        // retrieve the parameters
-        $parameters = $this->request->query->all();
+        if (!$this->datagrid) {
+            // retrieve the parameters
+            $parameters = $this->request->query->all();
 
-        if ($this->isChild() && $this->getParentAssociationMapping()) {
-            $mapping = $this->getParentAssociationMapping();
-            $parameters[$mapping['fieldName']] = $this->request->get($this->getParent()->getIdParameter());
-        }
+            if ($this->isChild() && $this->getParentAssociationMapping()) {
+                $parameters[$this->getParentAssociationMapping()] = $this->request->get($this->getParent()->getIdParameter());
+            }
 
-        // build the datagrid filter
-        $datagrid = $this->getDatagridBuilder()->getBaseDatagrid($this, $parameters);
-        $datagrid->getPager()->setMaxPerPage($this->maxPerPage);
+            // build the datagrid filter
+            $this->datagrid = $this->getDatagridBuilder()->getBaseDatagrid($this, $parameters);
+            $this->datagrid->getPager()->setMaxPerPage($this->maxPerPage);
 
-        $mapper = new DatagridMapper($this->getDatagridBuilder(), $datagrid, $this);
+            $mapper = new DatagridMapper($this->getDatagridBuilder(), $this->datagrid, $this);
 
-        $this->buildFilterFieldDescriptions();
-        $this->configureDatagridFilters($mapper);
+            $this->buildFilterFieldDescriptions();
+            $this->configureDatagridFilters($mapper);
 
-        foreach ($this->getFilterFieldDescriptions() as $fieldDescription) {
-            $mapper->add($fieldDescription);
+            foreach ($this->getFilterFieldDescriptions() as $fieldDescription) {
+                $mapper->add($fieldDescription);
+            }
         }
 
-        return $datagrid;
+        return $this->datagrid;
     }
 
     /**
      * Build the side menu related to the current action
      *
+     * @param string $action
+     * @param \Sonata\AdminBundle\Admin\AdminInterface $childAdmin
      * @return MenuItem|false
      */
-    public function buildSideMenu($action, Admin $childAdmin = null)
+    public function buildSideMenu($action, AdminInterface $childAdmin = null)
     {
         if ($this->loaded['side_menu']) {
             return;
@@ -1010,9 +1023,10 @@ abstract class Admin implements AdminInterface
 
     /**
      * @param string $action
-     * @return Knplabs\MenuBundle\Menu
+     * @param \Sonata\AdminBundle\Admin\AdminInterface $childAdmin
+     * @return \Knplabs\MenuBundle\Menu
      */
-    public function getSideMenu($action, Admin $childAdmin = null)
+    public function getSideMenu($action, AdminInterface $childAdmin = null)
     {
         if ($this->isChild()) {
             return $this->getParent()->getSideMenu($action, $this);
@@ -1024,7 +1038,7 @@ abstract class Admin implements AdminInterface
     }
 
     /**
-     * return the root code
+     * Returns the root code
      *
      * @return string the root code
      */
@@ -1034,13 +1048,12 @@ abstract class Admin implements AdminInterface
     }
 
     /**
-     * return the master admin
+     * Returns the master admin
      *
      * @return \Sonata\AdminBundle\Admin\Admin the root admin class
      */
     public function getRoot()
     {
-
         $parentFieldDescription = $this->getParentFieldDescription();
 
         if (!$parentFieldDescription) {
@@ -1114,7 +1127,7 @@ abstract class Admin implements AdminInterface
     }
 
     /**
-     * return true if the Admin is linked to a parent FieldDescription
+     * Returns true if the Admin is linked to a parent FieldDescription
      *
      * @return bool
      */
@@ -1135,7 +1148,7 @@ abstract class Admin implements AdminInterface
     }
 
     /**
-     * return the subject, if none is set try to load one from the request
+     * Returns the subject, if none is set try to load one from the request
      *
      * @return $object the subject
      */
@@ -1170,7 +1183,7 @@ abstract class Admin implements AdminInterface
     }
 
     /**
-     * return the form FieldDescription with the given $name
+     * Returns the form FieldDescription with the given $name
      *
      * @param string $name
      * @return \Sonata\AdminBundle\Admin\FieldDescriptionInterface
@@ -1181,7 +1194,7 @@ abstract class Admin implements AdminInterface
     }
 
     /**
-     * return true if the admin has a FieldDescription with the given $name
+     * Returns true if the admin has a FieldDescription with the given $name
      *
      * @param string $name
      * @return bool
@@ -1217,7 +1230,7 @@ abstract class Admin implements AdminInterface
     }
 
     /**
-     * return the collection of list FieldDescriptions
+     * Returns the collection of list FieldDescriptions
      *
      * @return array
      */
@@ -1230,18 +1243,19 @@ abstract class Admin implements AdminInterface
     }
 
     /**
-     * return a list FieldDescription
+     * Returns a list FieldDescription
      *
      * @param string $name
      * @return \Sonata\AdminBundle\Admin\FieldDescriptionInterface
      */
-    public function getListFieldDescription($name) {
+    public function getListFieldDescription($name)
+    {
 
         return $this->hasListFieldDescription($name) ? $this->listFieldDescriptions[$name] : null;
     }
 
     /**
-     * return true if the list FieldDescription exists
+     * Returns true if the list FieldDescription exists
      *
      * @param string $name
      * @return bool
@@ -1277,18 +1291,19 @@ abstract class Admin implements AdminInterface
     }
 
     /**
-     * return a filter FieldDescription
+     * Returns a filter FieldDescription
      *
      * @param string $name
      * @return array|null
      */
-    public function getFilterFieldDescription($name) {
+    public function getFilterFieldDescription($name)
+    {
 
         return $this->hasFilterFieldDescription($name) ? $this->filterFieldDescriptions[$name] : null;
     }
 
     /**
-     * return true if the filter FieldDescription exists
+     * Returns true if the filter FieldDescription exists
      *
      * @param string $name
      * @return bool
@@ -1323,7 +1338,7 @@ abstract class Admin implements AdminInterface
     }
 
     /**
-     * return the filter FieldDescription collection
+     * Returns the filter FieldDescription collection
      *
      * @param array filter FieldDescription collection
      */
@@ -1361,7 +1376,7 @@ abstract class Admin implements AdminInterface
     }
 
     /**
-     * return an collection of admin children
+     * Returns an collection of admin children
      *
      * @return array list of Admin children
      */
@@ -1371,7 +1386,7 @@ abstract class Admin implements AdminInterface
     }
 
     /**
-     * return an admin child with the given $code
+     * Returns an admin child with the given $code
      *
      * @param string $code
      * @return array|null
@@ -1384,7 +1399,7 @@ abstract class Admin implements AdminInterface
     /**
      * set the Parent Admin
      *
-     * @param \Sonata\AdminBundle\Admin\Admin $parent
+     * @param \Sonata\AdminBundle\Admin\AdminInterface $parent
      * @return void
      */
     public function setParent(AdminInterface $parent)
@@ -1403,7 +1418,7 @@ abstract class Admin implements AdminInterface
     }
 
     /**
-     * return true if the Admin class has an Parent Admin defined
+     * Returns true if the Admin class has an Parent Admin defined
      *
      * @return boolean
      */
@@ -1413,7 +1428,7 @@ abstract class Admin implements AdminInterface
     }
 
     /**
-     * return true if the admin has children, false otherwise
+     * Returns true if the admin has children, false otherwise
      *
      * @return bool if the admin has children
      */
@@ -1434,7 +1449,7 @@ abstract class Admin implements AdminInterface
     }
 
     /**
-     * return the uniqid
+     * Returns the uniqid
      *
      * @return integer
      */
@@ -1444,7 +1459,7 @@ abstract class Admin implements AdminInterface
     }
 
     /**
-     * return the classname label
+     * Returns the classname label
      *
      * @return string the classname label
      */
@@ -1454,7 +1469,7 @@ abstract class Admin implements AdminInterface
     }
 
     /**
-     * return an array of persistent parameters
+     * Returns an array of persistent parameters
      *
      * @return array
      */
@@ -1469,7 +1484,6 @@ abstract class Admin implements AdminInterface
      */
     public function getBreadcrumbs($action)
     {
-
         if ($this->isChild()) {
             return $this->getParent()->getBreadcrumbs($action);
         }
@@ -1478,65 +1492,65 @@ abstract class Admin implements AdminInterface
     }
 
     /**
-     * generate the breadcrumbs array
+     * Generates the breadcrumbs array
      *
-     * @param  $action
+     * @param string $action
      * @param \Knplabs\MenuBundle\MenuItem|null $menu
      * @return array the breadcrumbs
      */
     public function buildBreadcrumbs($action, MenuItem $menu = null)
     {
-        if (!isset($this->breadcrumbs[$action])) {
-            $menu = $menu ?: new Menu;
+        if (isset($this->breadcrumbs[$action])) {
+            return $this->breadcrumbs[$action];
+        }
 
-            $child = $menu->addChild(
-                $this->trans(sprintf('link_%s_list', $this->getClassnameLabel())),
-                $this->generateUrl('list')
-            );
+        $menu = $menu ?: new Menu;
 
-            $childAdmin = $this->getCurrentChildAdmin();
+        $child = $menu->addChild(
+            $this->trans(sprintf('link_%s_list', $this->getClassnameLabel())),
+            $this->generateUrl('list')
+        );
 
-            if ($childAdmin) {
-                $id = $this->request->get($this->getIdParameter());
+        $childAdmin = $this->getCurrentChildAdmin();
 
-                $child = $child->addChild(
-                    (string) $this->getSubject(),
-                    $this->generateUrl('edit', array('id' => $id))
-                );
+        if ($childAdmin) {
+            $id = $this->request->get($this->getIdParameter());
 
-                return $childAdmin->buildBreadcrumbs($action, $child);
+            $child = $child->addChild(
+                (string) $this->getSubject(),
+                $this->generateUrl('edit', array('id' => $id))
+            );
 
-            } elseif ($this->isChild()) {
+            return $childAdmin->buildBreadcrumbs($action, $child);
 
-                if ($action != 'list') {
-                    $menu = $menu->addChild(
-                        $this->trans(sprintf('link_%s_list', $this->getClassnameLabel())),
-                        $this->generateUrl('list')
-                    );
-                }
+        } elseif ($this->isChild()) {
 
-                $breadcrumbs = $menu->getBreadcrumbsArray(
-                    $this->trans(sprintf('link_%s_%s', $this->getClassnameLabel(), $action))
+            if ($action != 'list') {
+                $menu = $menu->addChild(
+                    $this->trans(sprintf('link_%s_list', $this->getClassnameLabel())),
+                    $this->generateUrl('list')
                 );
+            }
 
-            } else if ($action != 'list') {
-
-                $breadcrumbs = $child->getBreadcrumbsArray(
-                    $this->trans(sprintf('link_%s_%s', $this->getClassnameLabel(), $action))
-                );
+            $breadcrumbs = $menu->getBreadcrumbsArray(
+                $this->trans(sprintf('link_%s_%s', $this->getClassnameLabel(), $action))
+            );
 
-            } else {
+        } else if ($action != 'list') {
 
-                $breadcrumbs = $child->getBreadcrumbsArray();
-            }
+            $breadcrumbs = $child->getBreadcrumbsArray(
+                $this->trans(sprintf('link_%s_%s', $this->getClassnameLabel(), $action))
+            );
 
-            // the generated $breadcrumbs contains an empty element
-            array_shift($breadcrumbs);
+        } else {
 
-            $this->breadcrumbs[$action] = $breadcrumbs;
+            $breadcrumbs = $child->getBreadcrumbsArray();
         }
 
-        return $this->breadcrumbs[$action];
+        // the generated $breadcrumbs contains an empty element
+        array_shift($breadcrumbs);
+
+        return $this->breadcrumbs[$action] = $breadcrumbs;
     }
 
     /**
@@ -1551,7 +1565,7 @@ abstract class Admin implements AdminInterface
     }
 
     /**
-     * return the current child status
+     * Returns the current child status
      *
      * @return bool
      */
@@ -1561,9 +1575,9 @@ abstract class Admin implements AdminInterface
     }
 
     /**
-     * return the current child admin instance
+     * Returns the current child admin instance
      *
-     * @return \Sonata\AdminBundle\Admin\Admin|null the current child admin instance
+     * @return \Sonata\AdminBundle\Admin\AdminInterface|null the current child admin instance
      */
     public function getCurrentChildAdmin()
     {
@@ -1587,7 +1601,6 @@ abstract class Admin implements AdminInterface
      */
     public function trans($id, array $parameters = array(), $domain = null, $locale = null)
     {
-
         $domain = $domain ?: $this->translationDomain;
 
         if (!$this->translator) {
@@ -1609,7 +1622,7 @@ abstract class Admin implements AdminInterface
     }
 
     /**
-     * return the translation domain
+     * Returns the translation domain
      *
      * @return string the translation domain
      */

+ 5 - 10
Builder/ORM/DatagridBuilder.php

@@ -149,27 +149,25 @@ class DatagridBuilder implements DatagridBuilderInterface
     }
 
     /**
-     * @param \Sonata\AdminBundle\Datagrid\ORM\Datagrid $datagrid
-     * @param \Sonata\AdminBundle\Admin\FieldDescription $fieldDescription
+     * @param \Sonata\AdminBundle\Datagrid\DatagridInterface $datagrid
+     * @param \Sonata\AdminBundle\Admin\FieldDescriptionInterface $fieldDescription
      * @return bool
      */
     public function addFilter(DatagridInterface $datagrid, FieldDescriptionInterface $fieldDescription)
     {
-
         if (!$fieldDescription->getType()) {
 
             return false;
         }
 
         switch($fieldDescription->getType()) {
-
             case ClassMetadataInfo::MANY_TO_ONE:
                 $options = $fieldDescription->getOption('filter_field_options');
                 $filter = new \Sonata\AdminBundle\Filter\ORM\IntegerFilter($fieldDescription);
 
                 break;
-            case ClassMetadataInfo::MANY_TO_MANY:
 
+            case ClassMetadataInfo::MANY_TO_MANY:
                 $options = $fieldDescription->getOption('filter_field_options');
                 $options['choices'] = $this->getChoices($fieldDescription);
 
@@ -180,20 +178,17 @@ class DatagridBuilder implements DatagridBuilderInterface
                 break;
 
             default:
-
                 $class = $this->getFilterFieldClass($fieldDescription);
-
                 $filter = new $class($fieldDescription);
-
         }
 
-        $datagrid->addFilter($filter);
+        return $datagrid->addFilter($filter);
     }
 
     /**
      * @param \Sonata\AdminBundle\Admin\AdminInterface $admin
      * @param array $values
-     * @return \Sonata\AdminBundle\Datagrid\ORM\Datagrid
+     * @return \Sonata\AdminBundle\Datagrid\DatagridInterface
      */
     public function getBaseDatagrid(AdminInterface $admin, array $values = array())
     {

+ 16 - 18
Builder/ORM/FormBuilder.php

@@ -70,7 +70,7 @@ class FormBuilder implements FormBuilderInterface
     }
 
     /**
-     * return the field associated to a FieldDescription
+     * Returns the field associated to a FieldDescription
      *   ie : build the embedded form from the related AdminInterface instance
      *
      * @throws RuntimeException
@@ -126,7 +126,7 @@ class FormBuilder implements FormBuilderInterface
 
 
     /**
-     * return the class associated to a FieldDescriptionInterface if any defined
+     * Returns the class associated to a FieldDescriptionInterface if any defined
      *
      * @throws RuntimeException
      * @param \Sonata\AdminBundle\Admin\FieldDescriptionInterface $fieldDescription
@@ -153,7 +153,7 @@ class FormBuilder implements FormBuilderInterface
     /**
      * Add a new instance to the related FieldDescriptionInterface value
      *
-     * @param  $object
+     * @param object $object
      * @param \Sonata\AdminBundle\Admin\FieldDescriptionInterface $fieldDescription
      * @return void
      */
@@ -168,9 +168,9 @@ class FormBuilder implements FormBuilderInterface
     }
 
     /**
-     * return an OneToOne associated field
+     * Returns an OneToOne associated field
      *
-     * @param  $object
+     * @param object $object
      * @param \Sonata\AdminBundle\Admin\FieldDescriptionInterface $fieldDescription
      * @return ChoiceField
      */
@@ -212,7 +212,7 @@ class FormBuilder implements FormBuilderInterface
     }
 
     /**
-     * return the OneToMany associated field
+     * Returns the OneToMany associated field
      *
      * @param  $object
      * @param \Sonata\AdminBundle\Admin\FieldDescriptionInterface $fieldDescription
@@ -242,6 +242,11 @@ class FormBuilder implements FormBuilderInterface
         return $this->getManyToManyField($object, $fieldDescription);
     }
 
+    /**
+     * @param object $object
+     * @param \Sonata\AdminBundle\Admin\FieldDescriptionInterface $fieldDescription
+     * @return \Symfony\Component\Form\FieldFactory\FieldInterface
+     */
     protected function getManyToManyField($object, FieldDescriptionInterface $fieldDescription)
     {
 
@@ -264,6 +269,11 @@ class FormBuilder implements FormBuilderInterface
         return $instance;
     }
 
+    /**
+     * @param object $object
+     * @param \Sonata\AdminBundle\Admin\FieldDescriptionInterface $fieldDescription
+     * @return FieldGroup|\Symfony\Component\Form\FieldFactory\FieldInterface|\Symfony\Component\Form\TextField
+     */
     protected function getManyToOneField($object, FieldDescriptionInterface $fieldDescription)
     {
 
@@ -303,18 +313,6 @@ class FormBuilder implements FormBuilderInterface
     }
 
     /**
-     * The method add a new field to the provided Form, there are 4 ways to add new field :
-     *
-     *   - if $name is a string with no related FieldDescription, then the form will use the FieldFactory
-     *     to instantiate a new Field
-     *   - if $name is a FormDescription, the method uses information defined in the FormDescription to
-     *     instantiate a new Field
-     *   - if $name is a FieldInterface, then a FieldDescriptionInterface is created, the FieldInterface is added to
-     *     the form
-     *   - if $name is a string with a related FieldDescription, then the method uses information defined in the
-     *     FormDescription to instantiate a new Field
-     *
-     *
      * @param Form $form
      * @param \Sonata\AdminBundle\Admin\FieldDescriptionInterface $name
      * @param array $options

+ 4 - 0
Command/ExplainAdminCommand.php

@@ -66,6 +66,10 @@ class ExplainAdminCommand extends Command
         }
 
         $output->writeln('');
+        $output->writeln('<info>Form Options</info>');
+        $output->writeln(sprintf('  -  % -25s % -15s', 'validation_groups', implode('|', $admin->getForm()->getOption('validation_groups'))));
+        $output->writeln('');
+
         $output->writeln('<info>Form Fields</info>');
         foreach ($admin->getFormFieldDescriptions() as $name => $fieldDescription) {
             $output->writeln(sprintf('  - % -25s  % -15s % -15s', $name, $fieldDescription->getType(), $fieldDescription->getTemplate()));

+ 3 - 14
Controller/CRUDController.php

@@ -125,12 +125,9 @@ class CRUDController extends Controller
     public function listAction()
     {
         return $this->render($this->admin->getListTemplate(), array(
-            'datagrid'          => $this->admin->getDatagrid(),
-            'list'              => $this->admin->getList(),
+            'action'            => 'list',
             'admin'             => $this->admin,
             'base_template'     => $this->getBaseTemplate(),
-            'side_menu'         => $this->admin->getSideMenu('list'),
-            'breadcrumbs'       => $this->admin->getBreadcrumbs('list'),
         ));
     }
 
@@ -198,14 +195,10 @@ class CRUDController extends Controller
         }
 
         return $this->render($this->admin->getEditTemplate(), array(
+            'action'         => 'edit',
             'form'           => $form,
-            'object'         => $object,
-            'fields'         => $this->admin->getFormFieldDescriptions(),
-            'form_groups'    => $this->admin->getFormGroups(),
             'admin'          => $this->admin,
             'base_template'  => $this->getBaseTemplate(),
-            'side_menu'      => $this->admin->getSideMenu('edit'),
-            'breadcrumbs'    => $this->admin->getBreadcrumbs('edit'),
         ));
     }
 
@@ -292,14 +285,10 @@ class CRUDController extends Controller
         }
 
         return $this->render($this->admin->getEditTemplate(), array(
+            'action'        => 'create',
             'form'          => $form,
-            'object'        => $object,
-            'fields'        => $this->admin->getFormFieldDescriptions(),
-            'form_groups'   => $this->admin->getFormGroups(),
             'admin'         => $this->admin,
             'base_template' => $this->getBaseTemplate(),
-            'side_menu'     => $this->admin->getSideMenu('create'),
-            'breadcrumbs'   => $this->admin->getBreadcrumbs('create'),
         ));
     }
 }

+ 4 - 4
Datagrid/Datagrid.php

@@ -12,10 +12,10 @@
 namespace Sonata\AdminBundle\Datagrid;
 
 use Sonata\AdminBundle\Datagrid\PagerInterface;
+use Sonata\AdminBundle\Filter\FilterInterface;
 
 class Datagrid implements DatagridInterface
 {
-
     /**
      *
      * The filter instances
@@ -60,7 +60,7 @@ class Datagrid implements DatagridInterface
         foreach ($this->getFilters() as $name => $filter) {
             $filter->apply(
                 $this->query,
-                isset($values[$name]) ? $this->values[$name] : null
+                isset($this->values[$name]) ? $this->values[$name] : null
             );
         }
 
@@ -71,9 +71,9 @@ class Datagrid implements DatagridInterface
         $this->bound = true;
     }
 
-    public function addFilter($filter)
+    public function addFilter(FilterInterface $filter)
     {
-        $this->filters[$filter->getName()] = $filter;
+        return $this->filters[$filter->getName()] = $filter;
     }
 
     public function getFilters()

+ 3 - 1
Datagrid/DatagridInterface.php

@@ -10,6 +10,8 @@
  */
 namespace Sonata\AdminBundle\Datagrid;
 
+use Sonata\AdminBundle\Filter\FilterInterface;
+
 interface DatagridInterface
 {
 
@@ -19,7 +21,7 @@ interface DatagridInterface
 
     function buildPager();
 
-    function addFilter($filter);
+    function addFilter(FilterInterface $filter);
 
     function getFilters();
 

+ 5 - 5
Datagrid/DatagridMapper.php

@@ -39,7 +39,7 @@ class DatagridMapper
      * @throws \RuntimeException
      * @param string $name
      * @param array $fieldDescriptionOptions
-     * @return
+     * @return \Sonata\AdminBundle\Datagrid\FilterInterface
      */
     public function add($name, array $fieldDescriptionOptions = array())
     {
@@ -52,7 +52,7 @@ class DatagridMapper
 
             $fieldDescription = $this->admin->getModelManager()->getNewFieldDescriptionInstance(
                 $this->admin->getClass(),
-                $field->getKey(),
+                $name,
                 $fieldDescriptionOptions
             );
 
@@ -85,8 +85,8 @@ class DatagridMapper
     }
 
     /**
-     * @param  $key
-     * @return
+     * @param string $key
+     * @return boolean
      */
     public function has($key)
     {
@@ -94,7 +94,7 @@ class DatagridMapper
     }
 
     /**
-     * @param  $key
+     * @param string $key
      * @return void
      */
     public function remove($key)

+ 11 - 8
Datagrid/ORM/Pager.php

@@ -27,15 +27,17 @@ class Pager extends BasePager
     /**
      * Returns a query for counting the total results.
      *
-     * @return Doctrine\ORM\Query
+     * @return integer
      */
     public function computeNbResult()
     {
         $countQuery = clone $this->getQuery();
 
-        $countQuery->setParameters($this->getParameters());
+        if(count($this->getParameters()) > 0) {
+            $countQuery->setParameters($this->getParameters());
+        }
 
-        $countQuery->select(sprintf('count(%s.%s) as nb', $countQuery->getRootAlias(), $this->getCountColumn()));
+        $countQuery->select(sprintf('count(%s.%s) as cnt', $countQuery->getRootAlias(), $this->getCountColumn()));
 
         return $countQuery->getQuery()->getSingleScalarResult();
     }
@@ -44,8 +46,7 @@ class Pager extends BasePager
      * Get all the results for the pager instance
      *
      * @param mixed $hydrationMode A hydration mode identifier
-     *
-     * @return  array
+     * @return array
      */
     public function getResults($hydrationMode = Query::HYDRATE_OBJECT)
     {
@@ -71,16 +72,18 @@ class Pager extends BasePager
     {
         $this->resetIterator();
 
-        $count = $this->computeNbResult();
-        $this->setNbResults($count);
+        $this->setNbResults($this->computeNbResult());
 
         $query = $this->getQuery();
 
         $query
-            ->setParameters($this->getParameters())
             ->setFirstResult(0)
             ->setMaxResults(0);
 
+        if (count($this->getParameters()) > 0) {
+            $query->setParameters($this->getParameters());
+        }
+
         if (0 == $this->getPage() || 0 == $this->getMaxPerPage() || 0 == $this->getNbResults()) {
             $this->setLastPage(0);
         } else {

+ 0 - 3
Filter/ORM/Filter.php

@@ -11,10 +11,7 @@
 
 namespace Sonata\AdminBundle\Filter\ORM;
 
-use Sonata\AdminBundle\Admin\FieldDescription;
 use Sonata\AdminBundle\Filter\Filter as BaseFilter;
-use Symfony\Component\Form\Configurable;
-use Doctrine\ORM\QueryBuilder;
 use Doctrine\ORM\Mapping\ClassMetadataInfo;
 
 abstract class Filter extends BaseFilter

+ 2 - 5
Filter/ORM/IntegerFilter.php

@@ -11,15 +11,12 @@
 
 namespace Sonata\AdminBundle\Filter\ORM;
 
-use Sonata\AdminBundle\Admin\FieldDescription;
 use Doctrine\ORM\QueryBuilder;
 
 class IntegerFilter extends Filter
 {
-
-   public function filter($queryBuilder, $alias, $field, $value)
+    public function filter($queryBuilder, $alias, $field, $value)
     {
-
         if ($value == null) {
             return;
         }
@@ -34,7 +31,7 @@ class IntegerFilter extends Filter
             $this->getName()
         ));
 
-        $queryBuilder->setParameter($this->getName(), $value);
+        $queryBuilder->setParameter($this->getName(), (int)$value);
     }
 
     protected function configure()

+ 30 - 0
Form/FormMapper.php

@@ -40,6 +40,24 @@ class FormMapper
         $this->admin = $admin;
     }
 
+    /**
+     * The method add a new field to the provided Form, there are 4 ways to add new field :
+     *
+     *   - if $name is a string with no related FieldDescription, then the form will use the FieldFactory
+     *     to instantiate a new Field
+     *   - if $name is a FormDescription, the method uses information defined in the FormDescription to
+     *     instantiate a new Field
+     *   - if $name is a FieldInterface, then a FieldDescriptionInterface is created, the FieldInterface is added to
+     *     the form
+     *   - if $name is a string with a related FieldDescription, then the method uses information defined in the
+     *     FormDescription to instantiate a new Field
+     *
+     * @throws \RuntimeException
+     * @param string $name
+     * @param array $fieldOptions
+     * @param array $fieldDescriptionOptions
+     * @return \Symfony\Component\Form\FieldInterface|void
+     */
     public function add($name, array $fieldOptions = array(), array $fieldDescriptionOptions = array())
     {
 
@@ -102,16 +120,28 @@ class FormMapper
         );
     }
 
+    /**
+     * @param string $name
+     * @return \Symfony\Component\Form\FieldInterface
+     */
     public function get($name)
     {
         return $this->form->get($name);
     }
 
+    /**
+     *
+     * @return boolean
+     */
     public function has($key)
     {
         return $this->form->has($key);
     }
 
+    /**
+     *
+     * @return void
+     */
     public function remove($key)
     {
         $this->admin->removeFormFieldDescription($key);

+ 1 - 1
Resources/views/CRUD/action.html.twig

@@ -20,7 +20,7 @@ file that was distributed with this source code.
     </div>
 {% endblock %}
 
-{% block side_menu %}{% if side_menu %}{{ side_menu.render|raw }}{% endif %}{% endblock %}
+{% block side_menu %}{% if action is defined %}{{ admin.sidemenu(action).render|raw }}{% endif %}{% endblock %}
 
 {% block content %}
 

+ 11 - 11
Resources/views/CRUD/base_edit.html.twig

@@ -20,27 +20,27 @@ file that was distributed with this source code.
     </div>
 {% endblock %}
 
-{% block side_menu %}{% if side_menu %}{{ side_menu.render|raw }}{% endif %}{% endblock %}
+{% block side_menu %}{{ admin.sidemenu(action).render|raw }}{% endblock %}
 
 {% block form %}
 
-    {% if object.id > 0 %}
+    {% if form.data.id > 0 %}
         {% set url = 'edit' %}
     {% else %}
         {% set url = 'create' %}
     {% endif %}
 
-    <form action="{{ admin.generateUrl(url, {'id': object.id, 'uniqid': admin.uniqid}) }}"{% if form.isMultipart %} enctype="multipart/form-data"{% endif %} method="POST">
+    <form action="{{ admin.generateUrl(url, {'id': form.data.id, 'uniqid': admin.uniqid}) }}"{% if form.isMultipart %} enctype="multipart/form-data"{% endif %} method="POST">
 
         {{ form_hidden(form) }}
-        
+
         {% if form.errors %}
             <div class="sonata-ba-form-error">
                 {{ form_errors(form) }}
             </div>
         {% endif %}
-        
-        {% for name, form_group in form_groups %}
+
+        {% for name, form_group in admin.formgroups %}
             {% if name %}
                 <fieldset>
                     <legend>
@@ -49,14 +49,14 @@ file that was distributed with this source code.
                             <a href="" class="sonata-ba-collapsed">{% trans 'link_expand' from 'AdminBundle' %}</a>
                         {% endif %}
                     </legend>
-                    
+
                     <div class="sonata-ba-collapsed-fields">
             {% endif %}
 
 
             {% for field_name in form_group.fields %}
-                {% if fields[field_name] is defined %}
-                    {{ fields[field_name]|render_form_element(form, object) }}
+                {% if admin.formfielddescriptions[field_name] is defined %}
+                    {{ admin.formfielddescriptions[field_name]|render_form_element(form, form.data) }}
                 {% endif %}
             {% endfor %}
 
@@ -67,13 +67,13 @@ file that was distributed with this source code.
         {% endfor %}
 
         {% if app.request.isxmlhttprequest %}
-            {% if object.id %}
+            {% if form.data.id %}
                 <input type="submit" name="btn_update" value="{% trans "btn_update" from admin.translationdomain %}"/>
             {% else %}
                 <input type="submit" name="btn_create" value="{% trans "btn_create" from admin.translationdomain %}"/>
             {% endif %}
         {% else %}
-            {% if object.id %}
+            {% if form.data.id %}
                 <input type="submit" name="btn_update_and_edit" value="{% trans "btn_update_and_edit_again" from admin.translationdomain %}"/>
                 <input type="submit" name="btn_update_and_list" value="{% trans "btn_update_and_return_to_list" from admin.translationdomain %}"/>
             {% else %}

+ 17 - 17
Resources/views/CRUD/base_list.html.twig

@@ -19,15 +19,15 @@ file that was distributed with this source code.
     </div>
 {% endblock %}
 
-{% block side_menu %}{% if side_menu %}{{ side_menu.render|raw }}{% endif %}{% endblock %}
+{% block side_menu %}{{ admin.sidemenu(action).render|raw }}{% endblock %}
 
 {% block list_table %}
-    {% if datagrid.results|length > 0 %}
+    {% if admin.datagrid.results|length > 0 %}
         <form action="{{ admin.generateUrl('batch') }}" method="POST" >
             <table>
                 {% block table_header %}
                     <tr>
-                        {% for field_description in list.elements %}
+                        {% for field_description in admin.list.elements %}
                             {% if field_description.getOption('code') == '_batch' %}
                                 <th class="sonata-ba-list-field-header sonata-ba-list-field-header-batch">
                                   <input type="checkbox" id="list_batch_checkbox" />
@@ -46,9 +46,9 @@ file that was distributed with this source code.
                 {% endblock %}
 
                 {% block table_body %}
-                    {% for object in datagrid.results %}
+                    {% for object in admin.datagrid.results %}
                         <tr>
-                            {% for field_description in list.elements %}
+                            {% for field_description in admin.list.elements %}
                                 {{ object|render_list_element(field_description) }}
                             {% endfor %}
                         </tr>
@@ -56,25 +56,25 @@ file that was distributed with this source code.
                 {% endblock %}
 
                 {% block table_footer %}
-                    {% if datagrid.pager.haveToPaginate() %}
+                    {% if admin.datagrid.pager.haveToPaginate() %}
                         <tr>
-                            <td colspan="{{ list.elements|length }}" class="pager">
+                            <td colspan="{{ admin.list.elements|length }}" class="pager">
                                 <ul>
-                                    {% if datagrid.pager.page != datagrid.pager.previouspage %}
-                                        <li><a href="{{ admin.generateUrl('list', datagrid.values|merge({'_page': datagrid.pager.previouspage})) }}">{% trans 'link_previous_pager' from 'AdminBundle' %}</a></li>
+                                    {% if admin.datagrid.pager.page != admin.datagrid.pager.previouspage %}
+                                        <li><a href="{{ admin.generateUrl('list', admin.datagrid.values|merge({'_page': admin.datagrid.pager.previouspage})) }}">{% trans 'link_previous_pager' from 'AdminBundle' %}</a></li>
                                     {% endif %}
 
                                     {# Set the number of pages to display in the pager #}
-                                    {% for page in datagrid.pager.getLinks(5) %}
-                                        {% if page == datagrid.pager.page %}
+                                    {% for page in admin.datagrid.pager.getLinks(5) %}
+                                        {% if page == admin.datagrid.pager.page %}
                                             <li>{{ page }}</li>
                                         {% else %}
-                                            <li><a href="{{ admin.generateUrl('list', datagrid.values|merge({'_page': page})) }}">{{ page }}</a></li>
+                                            <li><a href="{{ admin.generateUrl('list', admin.datagrid.values|merge({'_page': page})) }}">{{ page }}</a></li>
                                         {% endif %}
                                     {% endfor %}
 
-                                    {% if datagrid.pager.page != datagrid.pager.nextpage %}
-                                        <li><a href="{{ admin.generateUrl('list', datagrid.values|merge({'_page': datagrid.pager.nextpage})) }}">{% trans 'link_next_pager' from 'AdminBundle' %}</a></li>
+                                    {% if admin.datagrid.pager.page != admin.datagrid.pager.nextpage %}
+                                        <li><a href="{{ admin.generateUrl('list', admin.datagrid.values|merge({'_page': admin.datagrid.pager.nextpage})) }}">{% trans 'link_next_pager' from 'AdminBundle' %}</a></li>
                                     {% endif %}
                                 </ul>
                             </td>
@@ -106,14 +106,14 @@ file that was distributed with this source code.
     {% else %}
         <p class="notice">
           {% trans 'no_result' from 'AdminBundle' %}
-        </p>    
+        </p>
     {% endif %}
 {% endblock %}
 
 {% block list_filters %}
-    {% if datagrid.filters %}
+    {% if admin.datagrid.filters %}
         <form action="{{ admin.generateUrl('list') }}" method="GET">
-            {% for filter in datagrid.filters %}
+            {% for filter in admin.datagrid.filters %}
                 <div>
                     {{ filter|render_filter_element }}</td>
                 </div>

+ 7 - 7
Resources/views/standard_layout.html.twig

@@ -26,11 +26,11 @@ file that was distributed with this source code.
             <link rel="stylesheet" href="{{ asset('bundles/sonataadmin/css/layout.css') }}" type="text/css" media="all">
             <link rel="stylesheet" href="{{ asset('bundles/sonataadmin/css/colors.css') }}" type="text/css" media="all">
         {% endblock %}
-        
+
         {% block javascripts %}
             <script src="{{ asset('bundles/sonatajquery/jquery-1.4.4.js') }}" type="text/javascript"></script>
             <script src="{{ asset('bundles/sonatajquery/jquery-ui-1.8.6.custom.js') }}" type="text/javascript"></script>
-            <script src="{{ asset('bundles/sonatajquery/jquery-ui-i18n.js') }}" type="text/javascript"></script>        
+            <script src="{{ asset('bundles/sonatajquery/jquery-ui-i18n.js') }}" type="text/javascript"></script>
             <script src="{{ asset('bundles/sonataadmin/qtip/jquery.qtip-1.0.0-rc3.min.js') }}" type="text/javascript"></script>
             <script src="{{ asset('bundles/sonataadmin/jquery/jquery.form.js') }}" type="text/javascript"></script>
             <script src="{{ asset('bundles/sonataadmin/base.js') }}" type="text/javascript"></script>
@@ -38,9 +38,9 @@ file that was distributed with this source code.
 
         <title>
             {% block title %} {% trans 'Admin' from 'AdminBundle' %}
-                {% if breadcrumbs is defined %}
+                {% if action is defined %}
                     -
-                    {% for label, uri in breadcrumbs %}
+                    {% for label, uri in admin.breadcrumbs(action) %}
                         {% if not loop.first  %}
                             &gt;
                         {% endif %}
@@ -78,8 +78,8 @@ file that was distributed with this source code.
                 <div class="sonata-ba-breadcrumbs">
                     <h1>
                     {% block breadcrumb %}
-                        {% if breadcrumbs is defined %}
-                            {% for label, uri in breadcrumbs %}
+                        {% if action is defined %}
+                            {% for label, uri in admin.breadcrumbs(action) %}
                                 {% if not loop.first  %}
                                     &gt;
                                 {% endif %}
@@ -113,7 +113,7 @@ file that was distributed with this source code.
                     {% if form is not empty %}
                         <div class="sonata-ba-form">{{ form|raw }}</div>
                     {% endif %}
-    
+
                     {% if list_table is not empty or list_filters is not empty %}
                         {% if side_menu is not empty %}
                             <div class="sonata-ba-list">

+ 0 - 1
Route/RouteCollection.php

@@ -10,7 +10,6 @@
  */
 namespace Sonata\AdminBundle\Route;
 
-use Sonata\AdminBundle\Admin\FieldDescription;
 use Symfony\Component\Routing\Route;
 
 class RouteCollection

+ 3 - 2
Twig/Extension/SonataAdminExtension.php

@@ -91,9 +91,10 @@ class SonataAdminExtension extends \Twig_Extension
      * return the value related to FieldDescription, if the associated object does no
      * exists => a temporary one is created
      *
-     * @param  $object
+     * @param object $object
      * @param \Sonata\AdminBundle\Admin\FieldDescriptionInterface $fieldDescription
-     * @return
+     * @param array $params
+     * @return mixed
      */
     public function getValueFromFieldDescription($object, FieldDescriptionInterface $fieldDescription, array $params = array())
     {