Browse Source

Added support for editable association fields from type choice (#4449)

Christin Gruber 8 năm trước cách đây
mục cha
commit
d8493f1fab

+ 41 - 13
Controller/HelperController.php

@@ -227,7 +227,7 @@ class HelperController
         $field = $request->get('field');
         $code = $request->get('code');
         $objectId = $request->get('objectId');
-        $value = $request->get('value');
+        $value = $originalValue = $request->get('value');
         $context = $request->get('context');
 
         $admin = $this->pool->getInstance($code);
@@ -235,39 +235,36 @@ class HelperController
 
         // alter should be done by using a post method
         if (!$request->isXmlHttpRequest()) {
-            return new JsonResponse(array('status' => 'KO', 'message' => 'Expected a XmlHttpRequest request header'));
+            return new JsonResponse('Expected an XmlHttpRequest request header', 405);
         }
 
         if ($request->getMethod() != 'POST') {
-            return new JsonResponse(array('status' => 'KO', 'message' => 'Expected a POST Request'));
+            return new JsonResponse('Expected a POST Request', 405);
         }
 
         $rootObject = $object = $admin->getObject($objectId);
 
         if (!$object) {
-            return new JsonResponse(array('status' => 'KO', 'message' => 'Object does not exist'));
+            return new JsonResponse('Object does not exist', 404);
         }
 
         // check user permission
         if (false === $admin->hasAccess('edit', $object)) {
-            return new JsonResponse(array('status' => 'KO', 'message' => 'Invalid permissions'));
+            return new JsonResponse('Invalid permissions', 403);
         }
 
         if ($context == 'list') {
             $fieldDescription = $admin->getListFieldDescription($field);
         } else {
-            return new JsonResponse(array('status' => 'KO', 'message' => 'Invalid context'));
+            return new JsonResponse('Invalid context', 400);
         }
 
         if (!$fieldDescription) {
-            return new JsonResponse(array('status' => 'KO', 'message' => 'The field does not exist'));
+            return new JsonResponse('The field does not exist', 400);
         }
 
         if (!$fieldDescription->getOption('editable')) {
-            return new JsonResponse(array(
-                'status' => 'KO',
-                'message' => 'The field cannot be edit, editable option must be set to true',
-            ));
+            return new JsonResponse('The field cannot be edited, editable option must be set to true', 400);
         }
 
         $propertyPath = new PropertyPath($field);
@@ -291,6 +288,37 @@ class HelperController
             $value = filter_var($value, FILTER_VALIDATE_BOOLEAN);
         }
 
+        // Handle entity choice association type, transforming the value into entity
+        if ('' !== $value && $fieldDescription->getType() == 'choice' && $fieldDescription->getOption('class')) {
+            // Get existing associations for current object
+            $associations = $admin->getModelManager()
+                ->getEntityManager($admin->getClass())->getClassMetadata($admin->getClass())
+                ->getAssociationNames();
+
+            if (!in_array($field, $associations)) {
+                return new JsonResponse(
+                    sprintf(
+                        'Unknown association "%s", association does not exist in entity "%s", available associations are "%s".',
+                        $field,
+                        $this->admin->getClass(),
+                        implode(', ', $associations)),
+                    404);
+            }
+
+            $value = $admin->getConfigurationPool()->getContainer()->get('doctrine')->getManager()
+                ->getRepository($fieldDescription->getOption('class'))
+                ->find($value);
+
+            if (!$value) {
+                return new JsonResponse(
+                    sprintf(
+                        'Edit failed, object with id "%s" not found in association "%s".',
+                        $originalValue,
+                        $field),
+                    404);
+            }
+        }
+
         $this->pool->getPropertyAccessor()->setValue($object, $propertyPath, '' !== $value ? $value : null);
 
         $violations = $this->validator->validate($object);
@@ -302,7 +330,7 @@ class HelperController
                 $messages[] = $violation->getMessage();
             }
 
-            return new JsonResponse(array('status' => 'KO', 'message' => implode("\n", $messages)));
+            return new JsonResponse(implode("\n", $messages), 400);
         }
 
         $admin->update($object);
@@ -313,7 +341,7 @@ class HelperController
 
         $content = $extension->renderListElement($this->twig, $rootObject, $fieldDescription);
 
-        return new JsonResponse(array('status' => 'OK', 'content' => $content));
+        return new JsonResponse($content, 200);
     }
 
     /**

+ 13 - 0
Resources/doc/reference/action_list.rst

@@ -67,6 +67,17 @@ Here is an example:
                 'editable' => true
             ))
 
+            // editable association field
+            ->add('status', 'choice', array(
+                'editable' => true,
+                'class' => 'Vendor\ExampleBundle\Entity\ExampleStatus',
+                'choices' => array(
+                    1 => 'Active',
+                    2 => 'Inactive',
+                    3 => 'Draft',
+                ),
+            ))
+
             // we can add options to the field depending on the type
             ->add('price', 'currency', array(
                 'currency' => $this->currencyDetector->getCurrency()->getLabel()
@@ -141,6 +152,8 @@ Available types and associated options
 |           | delimiter      | Separator of values if multiple.                                      |
 +           +----------------+-----------------------------------------------------------------------+
 |           | catalogue      | Translation catalogue.                                                |
++           +----------------+-----------------------------------------------------------------------+
+|           | class          | Class path for editable association field.                            |
 +-----------+----------------+-----------------------------------------------------------------------+
 | currency  | currency (m)   | A currency string (EUR or USD for instance).                          |
 +-----------+----------------+-----------------------------------------------------------------------+

+ 1 - 1
Resources/doc/reference/field_types.rst

@@ -26,7 +26,7 @@ html            display (and optionally truncate or strip tags from) raw html
 ============    =============================================
 
 Theses types accept an ``editable`` parameter to edit the value from within the list action.
-This is currently limited to scalar types (text, integer, url...).
+This is currently limited to scalar types (text, integer, url...) and choice types with association field.
 
 .. note::
 

+ 16 - 21
Resources/public/Admin.js

@@ -55,7 +55,7 @@ var Admin = {
             padding: 15,
             overflow: 'auto'
         });
-      
+
         jQuery(modal).trigger('sonata-admin-setup-list-modal');
     },
     setup_select2: function(subject) {
@@ -114,17 +114,14 @@ var Admin = {
             container: 'body',
             placement: 'auto',
             success: function(response) {
-                if('KO' === response.status) {
-                    return response.message;
-                }
-
-                var html = jQuery(response.content);
+                var html = jQuery(response);
                 Admin.setup_xeditable(html);
-
                 jQuery(this)
                     .closest('td')
-                    .replaceWith(html)
-                ;
+                    .replaceWith(html);
+            },
+            error: function(xhr, statusText, errorThrown) {
+                return xhr.responseText;
             }
         });
     },
@@ -241,22 +238,20 @@ var Admin = {
         this.log(jQuery('a.sonata-ba-edit-inline', subject));
         jQuery('a.sonata-ba-edit-inline', subject).click(function(event) {
             Admin.stopEvent(event);
-
             var subject = jQuery(this);
             jQuery.ajax({
                 url: subject.attr('href'),
                 type: 'POST',
-                success: function(json) {
-                    if(json.status === "OK") {
-                        var elm = jQuery(subject).parent();
-                        elm.children().remove();
-                        // fix issue with html comment ...
-                        elm.html(jQuery(json.content.replace(/<!--[\s\S]*?-->/g, "")).html());
-                        elm.effect("highlight", {'color' : '#57A957'}, 2000);
-                        Admin.set_object_field_value(elm);
-                    } else {
-                        jQuery(subject).parent().effect("highlight", {'color' : '#C43C35'}, 2000);
-                    }
+                success: function(response) {
+                    var elm = jQuery(subject).parent();
+                    elm.children().remove();
+                    // fix issue with html comment ...
+                    elm.html(jQuery(response.replace(/<!--[\s\S]*?-->/g, "")).html());
+                    elm.effect("highlight", {'color' : '#57A957'}, 2000);
+                    Admin.set_object_field_value(elm);
+                },
+                error: function(xhr, statusText, errorThrown) {
+                    jQuery(subject).parent().effect("highlight", {'color' : '#C43C35'}, 2000);
                 }
             });
         });

+ 3 - 2
Tests/Controller/HelperControllerTest.php

@@ -305,7 +305,7 @@ class HelperControllerTest extends PHPUnit_Framework_TestCase
 
         $response = $controller->setObjectFieldValueAction($request);
 
-        $this->assertSame('{"status":"OK","content":"\u003Cfoo \/\u003E"}', $response->getContent());
+        $this->assertEquals(200, $response->getStatusCode());
     }
 
     /**
@@ -538,7 +538,8 @@ class HelperControllerTest extends PHPUnit_Framework_TestCase
 
         $response = $controller->setObjectFieldValueAction($request);
 
-        $this->assertSame('{"status":"KO","message":"error1\nerror2"}', $response->getContent());
+        $this->assertEquals(400, $response->getStatusCode());
+        $this->assertSame(json_encode("error1\nerror2"), $response->getContent());
     }
 
     /**