Преглед на файлове

Migrate the CoreController into helper service and create a dedicated controller

Thomas Rabaix преди 14 години
родител
ревизия
452b644f02

+ 4 - 1
Admin/Admin.php

@@ -841,11 +841,14 @@ abstract class Admin implements AdminInterface
      */
     public function getFormBuilder($object = null, $options = array())
     {
-
         if (!$object) {
             $object = $this->getSubject();
         }
 
+        if (!$object) {
+            $object = $this->getNewInstance();
+        }
+
         $formBuilder = $this->getFormContractor()->getFormBuilder(
             $this->getUniqid(),
             array_merge($this->formOptions, $options)

+ 153 - 2
Admin/AdminHelper.php

@@ -1,4 +1,155 @@
 <?php
+/*
+ * This file is part of the Sonata package.
+ *
+ * (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
 
-namespace Sonata\AdminBundle\Admin
-use AdminInterface
+namespace Sonata\AdminBundle\Admin;
+
+use Symfony\Component\Form\FormBuilder;
+
+class AdminHelper
+{
+    protected $pool;
+
+    /**
+     * @param Pool $pool
+     */
+    public function __construct(Pool $pool)
+    {
+        $this->pool = $pool;
+    }
+
+    /**
+     * @throws \RuntimeException
+     * @param \Symfony\Component\Form\FormBuilder $formBuider
+     * @param  $elementId
+     * @return \Symfony\Component\Form\FormBuilder
+     */
+    public function getChildFormBuilder(FormBuilder $formBuider, $elementId)
+    {
+        // todo : warning this introduce a bug if the field name = 'field_name',
+        //        add a check to field will always be 'fieldName'
+        $elements = explode('_', $elementId);
+
+        // always remove the first element : form's name
+        array_shift($elements);
+
+        while ($elementName = array_shift($elements)) {
+            if (!$formBuider->has($elementName)) {
+                throw new \RuntimeException(sprintf('The element `%s` does not exists', $elementName));
+            }
+
+            $formBuider = $formBuider->get($elementName);
+        }
+
+        return $formBuider;
+    }
+
+    /**
+     * @param string $code
+     * @return \Sonata\AdminBundle\Admin\AdminInterface
+     */
+    public function getAdmin($code)
+    {
+        return $this->pool->getInstance($code);
+    }
+
+    /**
+     * Note:
+     *   This code is ugly, but there is no better way of doing it.
+     *   For now the append form element action used to add a new row works
+     *   only for direct FieldDescription (not nested one)
+     *
+     * @throws \RuntimeException
+     * @param \Sonata\AdminBundle\Admin\AdminInterface $admin
+     * @param  $elementId
+     * @return void
+     */
+    public function appendFormFieldElement(AdminInterface $admin, $elementId)
+    {
+        // retrieve the subject
+        $formBuilder = $admin->getFormBuilder();
+
+        $form  = $formBuilder->getForm();
+        $form->bindRequest($admin->getRequest());
+
+        // get the field element
+        $childFormBuilder = $this->getChildFormBuilder($formBuilder, $elementId);
+
+        // retrieve the FieldDescription
+        $fieldDescription = $admin->getFormFieldDescription($childFormBuilder->getName());
+
+        $value = $fieldDescription->getValue($form->getData());
+
+        // retrieve the posted data
+        $data = $admin->getRequest()->get($formBuilder->getName());
+
+        if (!isset($data[$childFormBuilder->getName()])) {
+            $data[$childFormBuilder->getName()] = array();
+        }
+
+        $objectCount   = count($value);
+        $postCount     = count($data[$childFormBuilder->getName()]);
+
+        $fields = array_keys($fieldDescription->getAssociationAdmin()->getFormFieldDescriptions());
+
+        // for now, not sure how to do that
+        $value = array();
+        foreach ($fields as $name) {
+            $value[$name] = '';
+        }
+
+        // add new elements to the subject
+        while($objectCount < $postCount) {
+            // append a new instance into the object
+            $this->addNewInstance($form->getData(), $fieldDescription);
+            $objectCount++;
+        }
+
+        $this->addNewInstance($form->getData(), $fieldDescription);
+        $data[$childFormBuilder->getName()][] = $value;
+
+        $form = $admin->getFormBuilder($form->getData())->getForm();
+
+        // bind the data
+        $form->bind($data);
+
+        $admin->setSubject($form->getData());
+
+        return array($fieldDescription, $formBuilder);
+    }
+
+    /**
+     * Add a new instance to the related FieldDescriptionInterface value
+     *
+     * @param object $object
+     * @param \Sonata\AdminBundle\Admin\FieldDescriptionInterface $fieldDescription
+     * @return void
+     */
+    public function addNewInstance($object, FieldDescriptionInterface $fieldDescription)
+    {
+        $instance = $fieldDescription->getAssociationAdmin()->getNewInstance();
+        $mapping  = $fieldDescription->getAssociationMapping();
+
+        $method = sprintf('add%s', $this->camelize($mapping['fieldName']));
+
+        $object->$method($instance);
+    }
+
+    /**
+     * Camelize a string
+     *
+     * @static
+     * @param string $property
+     * @return string
+     */
+    public function camelize($property)
+    {
+       return preg_replace(array('/(^|_| )+(.)/e', '/\.(.)/e'), array("strtoupper('\\2')", "'_'.strtoupper('\\1')"), $property);
+    }
+}

+ 12 - 12
Admin/BaseFieldDescription.php

@@ -364,18 +364,6 @@ abstract class BaseFieldDescription implements FieldDescriptionInterface
         return $this->admin;
     }
 
-    /**
-     * Camelize a string
-     *
-     * @static
-     * @param string $property
-     * @return string
-     */
-    public static function camelize($property)
-    {
-       return preg_replace(array('/(^|_| )+(.)/e', '/\.(.)/e'), array("strtoupper('\\2')", "'_'.strtoupper('\\1')"), $property);
-    }
-
     /**
      * merge option values related to the provided option name
      *
@@ -429,4 +417,16 @@ abstract class BaseFieldDescription implements FieldDescriptionInterface
     {
         return $this->mappingType;
     }
+
+    /**
+     * Camelize a string
+     *
+     * @static
+     * @param string $property
+     * @return string
+     */
+    public static function camelize($property)
+    {
+       return preg_replace(array('/(^|_| )+(.)/e', '/\.(.)/e'), array("strtoupper('\\2')", "'_'.strtoupper('\\1')"), $property);
+    }
 }

+ 5 - 19
Builder/ORM/FormContractor.php

@@ -120,23 +120,6 @@ class FormContractor implements FormContractorInterface
         return $typeName;
     }
 
-    /**
-     * Add a new instance to the related FieldDescriptionInterface value
-     *
-     * @param object $object
-     * @param \Sonata\AdminBundle\Admin\FieldDescriptionInterface $fieldDescription
-     * @return void
-     */
-    public function addNewInstance($object, FieldDescriptionInterface $fieldDescription)
-    {
-        $instance = $fieldDescription->getAssociationAdmin()->getNewInstance();
-        $mapping  = $fieldDescription->getAssociationMapping();
-
-        $method = sprintf('add%s', FieldDescription::camelize($mapping['fieldName']));
-
-        $object->$method($instance);
-    }
-
     /**
      * Returns an OneToOne associated field
      *
@@ -178,11 +161,12 @@ class FormContractor implements FormContractorInterface
             // create a collection type with the generated prototype
             $options = $fieldDescription->getOption('form_field_options', array());
             $options['type'] = new AdminType;
+            $options['modifiable'] = true;
             $options['type_options'] = array(
                 'field_description' => $fieldDescription,
             );
 
-            $formBuilder->add($fieldDescription->getFieldName(), 'collection', $options);
+            $formBuilder->add($fieldDescription->getFieldName(), 'sonata_admin_collection', $options);
 
             return;
 //            $value = $fieldDescription->getValue($formBuilder->getData());
@@ -257,9 +241,11 @@ class FormContractor implements FormContractorInterface
     }
 
     /**
-     * The method define the correct default settings for the provided FieldDescription
+     * The method defines the correct default settings for the provided FieldDescription
      *
+     * @param \Sonata\AdminBundle\Admin\AdminInterface
      * @param \Sonata\AdminBundle\Admin\FieldDescriptionInterface $fieldDescription
+     * @param array $options
      * @return void
      */
     public function fixFieldDescription(AdminInterface $admin, FieldDescriptionInterface $fieldDescription, array $options = array())

+ 2 - 2
Controller/CRUDController.php

@@ -205,8 +205,8 @@ class CRUDController extends Controller
      * @param  $object
      * @return \Symfony\Component\HttpFoundation\Response
      */
-    public function redirectTo($object) {
-
+    public function redirectTo($object)
+    {
         $url = false;
 
         if ($this->get('request')->get('btn_update_and_list')) {

+ 4 - 175
Controller/CoreController.php

@@ -19,190 +19,19 @@ use Sonata\AdminBundle\Form\RecursiveFieldIterator;
 
 class CoreController extends Controller
 {
-
     public function getBaseTemplate()
-    {        
-        if ($this->get('request')->isXmlHttpRequest()) {
-            return $this->container->getParameter('sonata_admin.templates.ajax');
-        }
-
-        return $this->container->getParameter('sonata_admin.templates.layout');
-    }
-
-    public function retrieveFormFieldElementAction()
-    {
-        $code = $this->get('request')->get('code');
-        $elementId = $this->get('request')->get('elementId');
-
-        $admin = $this->getAdmin($code);
-        
-        $form = $this->getForm($admin, $code);
-
-        $form->bind($this->get('request'));
-        
-        $field_element = $this->getFieldElement($form, $elementId);
-
-        // render the widget
-        // todo : fix this, the twig environment variable is not set inside the extension ...
-        $twig = $this->get('twig');
-        $extension = $twig->getExtension('form');
-        $extension->initRuntime($this->get('twig'));
-
-        return new Response($extension->renderField($field_element));
-    }
-
-    public function getAdmin($code)
-    {
-        // todo : refactor the code into inside the admin
-        $admin = $this->container
-           ->get('sonata_admin.admin.pool')
-           ->getInstance($code);
-
-        $admin->setRequest($this->container->get('request'));
-        
-        return $admin;
-    }
-    
-    public function getForm($admin, $code)
     {
-
-        if (is_numeric($this->get('request')->get('object_id'))) {
-            $object = $admin->getObject($this->get('request')->get('object_id'));
-        } else {
-            $class = $admin->getClass();
-            $object = new $class;
-        }
-
-        if (!$object) {
-            throw new NotFoundHttpException(sprintf('unable to find the object with id : `%s`', $this->get('request')->get('object_id')));
-        }
-
-        return $admin->getForm($object);
-    }
-
-    public function getFieldElement($form, $element_id)
-    {
-        $iterator = new RecursiveFieldIterator($form);
-        $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::CHILD_FIRST);
-
-        $field_element = false;
-        foreach ($iterator as $field) {
-
-            if ($field->getId() == $element_id) {
-                // find the targeted element
-                return $field;
-            }
-        }
-
-        if (!$field_element) {
-            throw new NotFoundHttpException(sprintf('unable to retrieve the form field element with id : `%s`', $element_id));
-        }
-    }
-    
-    public function appendFormFieldElementAction()
-    {
-
-        $code = $this->get('request')->get('code');
-        $elementId = $this->get('request')->get('elementId');
-
-        // Note : This code is ugly, I guess there is a better way of doing it.
-        //        For now the append form element action used to add a new row works
-        //        only for direct FieldDescription (not nested one)
-
-        // retrieve the admin
-        $admin            = $this->getAdmin($code);
-        
-        // retrieve the subject
-        $form = $this->getForm($admin, $code);
-
-        // get the field element
-        $field_element = $this->getFieldElement($form, $elementId);
-
-        // retrieve the FieldDescription
-        $fieldDescription       = $admin->getFormFieldDescription($field_element->getKey());
-
-        $subject = $form->getData();
-        $value = $fieldDescription->getValue($subject);
-
-        // retrieve the posted data
-        $data = $this->get('request')->get($form->getName());
-
-        if (!isset($data[$field_element->getKey()])) {
-            $data[$field_element->getKey()] = array();
-        }
-
-        $object_count   = count($value);
-        $post_count     = count($data[$field_element->getKey()]);
-
-        // for now, not sure how to do that
-        $value = array();
-        foreach ($field_element->getPrototype()->getFields() as $name => $t) {
-            $value[$name] = '';
-        }
-
-        // add new elements to the subject
-        while($object_count < $post_count) {
-            // append a new instance into the object
-            $admin->getFormBuilder()->addNewInstance($subject, $fieldDescription);
-
-            $object_count++;
-        }
-
-        $admin->getFormBuilder()->addNewInstance($subject, $fieldDescription);
-        $data[$field_element->getKey()][] = $value;
-
-        $form   = $admin->getForm($subject);
-
-        // bind the data
-        $form->submit($data);
-
-        $admin->setSubject($subject);
-        
-        // render the widget
-        // todo : fix this, the twig environment variable is not set inside the extension ...
-        $twig = $this->get('twig');
-        $extension = $twig->getExtension('sonata_admin');
-        $extension->initRuntime($this->get('twig'));
-
-        return new Response($extension->renderFormElement($fieldDescription, $form, $form->getData()));
-    }
-
-    public function getShortObjectDescriptionAction($code = null, $objectId = null, $uniqid = null)
-    {
-
-        $code       = $code     ?: $this->get('request')->query->get('code');
-        $objectId   = $objectId ?: $this->get('request')->query->get('objectId');
-        $uniqid     = $uniqid   ?: $this->get('request')->get('uniqid');
-
-        $admin  = $this->container->get('sonata_admin.admin.pool')->getInstance($code);
-        if ($uniqid) {
-            $admin->setUniqid($uniqid);
-        }
-        
-        $object = $admin->getObject($objectId);
-
-        if (!$object) {
-            throw new NotFoundHttpException(sprintf('unable to find the object with id : %s', $objectId));
-        }
-
-        $description = 'no description available';
-        foreach (array('getTitle', 'getName', '__toString') as $method) {
-            if (method_exists($object, $method)) {
-                $description = $object->$method();
-                break;
-            }
+        if ($this->get('request')->isXmlHttpRequest()) {
+            return $this->container->getParameter('sonata.admin.templates.ajax');
         }
 
-        $description = sprintf('<a href="%s" target="new">%s</a>', $admin->generateUrl('edit', array('id' => $objectId)), $description);
-
-        return new Response($description);
+        return $this->container->getParameter('sonata.admin.templates.layout');
     }
 
     public function dashboardAction()
     {
-
         return $this->render('SonataAdminBundle:Core:dashboard.html.twig', array(
-            'groups' => $this->get('sonata_admin.admin.pool')->getDashboardGroups(),
+            'groups' => $this->get('sonata.admin.pool')->getDashboardGroups(),
             'base_template'  => $this->getBaseTemplate(),
         ));
     }

+ 117 - 0
Controller/HelperController.php

@@ -0,0 +1,117 @@
+<?php
+
+/*
+ * This file is part of the Sonata package.
+ *
+ * (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Sonata\AdminBundle\Controller;
+
+use Symfony\Bundle\FrameworkBundle\Controller\Controller;
+use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
+use Symfony\Component\HttpFoundation\Response;
+
+use Sonata\AdminBundle\Form\RecursiveFieldIterator;
+
+class HelperController extends Controller
+{
+
+    /**
+     * @return \Sonata\AdminBundle\Admin\AdminHelper
+     */
+    public function getAdminHelper()
+    {
+        return $this->container->get('sonata.admin.helper');
+    }
+
+    public function appendFormFieldElementAction()
+    {
+        $helper     = $this->getAdminHelper();
+        $request    = $this->get('request');
+        $code       = $request->get('code');
+        $elementId  = $request->get('elementId');
+        $objectId   = $request->get('objectId');
+
+        $admin = $helper->getAdmin($code);
+
+        $subject = $admin->getModelManager()->findOne($admin->getClass(), $objectId);
+        if (!$subject) {
+            $subject = $admin->getNewInstance();
+        }
+
+        $admin->setSubject($subject);
+        $admin->setRequest($request);
+
+        list($fieldDescription, $formBuilder) = $helper->appendFormFieldElement($admin, $elementId);
+
+        // render the widget
+        // todo : fix this, the twig environment variable is not set inside the extension ...
+        $twig = $this->get('twig');
+        $extension = $twig->getExtension('sonata_admin');
+        $extension->initRuntime($this->get('twig'));
+
+        return new Response($extension->renderFormElement($fieldDescription, $formBuilder->getForm()->createView(), $formBuilder->getData()));
+    }
+
+    public function retrieveFormFieldElementAction()
+    {
+        $helper     = $this->getAdminHelper();
+        $code       = $this->get('request')->get('code');
+        $elementId  = $this->get('request')->get('elementId');
+        $admin      = $helper->getAdmin($code);
+
+        $subject = $admin->getModelManager()->findOne($admin->getClass(), $elementId);
+        if (!$subject) {
+            throw new NotFoundHttpException(sprintf('Unable to find the object id: %s, class: %s', $admin->getClass(), $elementId));
+        }
+
+        $formBuilder = $admin->getFormBuilder($subject);
+
+        $form = $formBuilder->getForm();
+        $form->bindRequest($this->get('request'));
+
+        $childFormBuilder = $helper->getChildFormBuilder($formBuilder, $elementId);
+
+        // render the widget
+        // todo : fix this, the twig environment variable is not set inside the extension ...
+        $twig = $this->get('twig');
+        $extension = $twig->getExtension('form');
+        $extension->initRuntime($this->get('twig'));
+
+        return new Response($extension->renderWidget($childFormBuilder->getForm()->createView()));
+    }
+
+    public function getShortObjectDescriptionAction($code = null, $objectId = null, $uniqid = null)
+    {
+        $code       = $code     ?: $this->get('request')->query->get('code');
+        $objectId   = $objectId ?: $this->get('request')->query->get('objectId');
+        $uniqid     = $uniqid   ?: $this->get('request')->get('uniqid');
+
+        $admin  = $this->container->get('sonata.admin.pool')->getInstance($code);
+        if ($uniqid) {
+            $admin->setUniqid($uniqid);
+        }
+
+        $object = $admin->getObject($objectId);
+
+        if (!$object) {
+            throw new NotFoundHttpException(sprintf('unable to find the object with id : %s', $objectId));
+        }
+
+        $description = 'no description available';
+        foreach (array('getTitle', 'getName', '__toString') as $method) {
+            if (method_exists($object, $method)) {
+                $description = $object->$method();
+                break;
+            }
+        }
+
+        $description = sprintf('<a href="%s" target="new">%s</a>', $admin->generateUrl('edit', array('id' => $objectId)), $description);
+
+        return new Response($description);
+    }
+}

+ 7 - 3
Form/FormMapper.php

@@ -103,14 +103,16 @@ class FormMapper
 
         // nothing to build as a Field is provided
         if ($fieldType) {
-            return $this->formBuilder->add($fieldType);
+            $this->formBuilder->add($fieldType);
         }
 
         // add the field with the FormBuilder
-        return $this->formContractor->addField(
+        $this->formContractor->addField(
             $this->formBuilder,
             $fieldDescription
         );
+
+        return $this;
     }
 
     /**
@@ -136,7 +138,9 @@ class FormMapper
 
         $this->admin->addFormFieldDescription($name, $fieldDescription);
 
-        return $this->formBuilder->add($name, $type, $options);
+        $this->formBuilder->add($name, $type, $options);
+
+        return $this;
     }
 
     /**

+ 4 - 0
Resources/config/core.xml

@@ -14,6 +14,10 @@
             <tag name="routing.loader" />
         </service>
 
+        <service id="sonata.admin.helper" class="Sonata\AdminBundle\Admin\AdminHelper">
+            <argument type="service" id="sonata.admin.pool" />
+        </service>
+
     </services>
 
 </container>

+ 3 - 3
Resources/config/routing/sonata_admin.xml

@@ -9,14 +9,14 @@
     </route>
 
     <route id="sonata_admin_retrieve_form_element" pattern="/core/get-form-field-element">
-        <default key="_controller">SonataAdminBundle:Core:retrieveFormFieldElement</default>
+        <default key="_controller">SonataAdminBundle:Helper:retrieveFormFieldElement</default>
     </route>
 
     <route id="sonata_admin_append_form_element" pattern="/core/append-form-field-element">
-        <default key="_controller">SonataAdminBundle:Core:appendFormFieldElement</default>
+        <default key="_controller">SonataAdminBundle:Helper:appendFormFieldElement</default>
     </route>
 
     <route id="sonata_admin_short_object_information" pattern="/core/get-short-object-description">
-        <default key="_controller">SonataAdminBundle:Core:getShortObjectDescription</default>
+        <default key="_controller">SonataAdminBundle:Helper:getShortObjectDescription</default>
     </route>
 </routes>

+ 2 - 2
Resources/views/CRUD/edit_orm_many_to_one.html.twig

@@ -24,14 +24,14 @@ file that was distributed with this source code.
             {% if field_description.options.edit == 'list' %}
                 <span id="field_widget_{{ field_element.vars.id }}" >
                     {% if value.id %}
-                        {% render 'SonataAdminBundle:Core:getShortObjectDescription' with {
+                        {% render 'SonataAdminBundle:Helper:getShortObjectDescription' with {
                             'code': field_description.associationadmin.code,
                             'objectId': value.id,
                             'uniqid':  field_description.associationadmin.uniqid
                         }%}
                     {% endif %}
                 </span>
-                <span style="display: block" >
+                <span style="display: none" >
                     {{ form_widget(field_element) }}
                 </span>
             {% else %}

+ 2 - 2
Resources/views/CRUD/edit_orm_one_to_one.html.twig

@@ -24,14 +24,14 @@ file that was distributed with this source code.
             {% if field_description.options.edit == 'list' %}
                 <span id="field_widget_{{ field_element.vars.id }}" >
                     {% if value.id %}
-                        {% render 'SonataAdminBundle:Core:getShortObjectDescription' with {
+                        {% render 'SonataAdminBundle:Helper:getShortObjectDescription' with {
                             'code': field_description.associationadmin.code,
                             'objectId': value.id,
                             'uniqid':  field_description.associationadmin.uniqid
                         }%}
                     {% endif %}
                 </span>
-                <span style="display: block" >
+                <span style="display: none" >
                     {{ form_widget(field_element) }}
                 </span>
             {% else %}