Преглед изворни кода

sanitize choice mask fields like in formMapper (#4405)

* sanitize choice mask fields like in formMapper

* add test on sanitized fields name

* styleci patch

* make FormMapper::sanitizeFieldName protected
Samuel Laulhau пре 8 година
родитељ
комит
3a75cad5e1
3 измењених фајлова са 44 додато и 7 уклоњено
  1. 23 3
      Form/FormMapper.php
  2. 7 4
      Form/Type/ChoiceFieldMaskType.php
  3. 14 0
      Tests/Form/FormMapperTest.php

+ 23 - 3
Form/FormMapper.php

@@ -70,11 +70,11 @@ class FormMapper extends BaseGroupedMapper
         }
         }
 
 
         // "Dot" notation is not allowed as form name, but can be used as property path to access nested data.
         // "Dot" notation is not allowed as form name, but can be used as property path to access nested data.
-        if (!$name instanceof FormBuilderInterface && strpos($fieldName, '.') !== false && !isset($options['property_path'])) {
+        if (!$name instanceof FormBuilderInterface && !isset($options['property_path'])) {
             $options['property_path'] = $fieldName;
             $options['property_path'] = $fieldName;
 
 
-             // fix the form name
-             $fieldName = str_replace('.', '__', $fieldName);
+            // fix the form name
+            $fieldName = $this->sanitizeFieldName($fieldName);
         }
         }
 
 
         // change `collection` to `sonata_type_native_collection` form type to
         // change `collection` to `sonata_type_native_collection` form type to
@@ -153,6 +153,8 @@ class FormMapper extends BaseGroupedMapper
      */
      */
     public function get($name)
     public function get($name)
     {
     {
+        $name = $this->sanitizeFieldName($name);
+
         return $this->formBuilder->get($name);
         return $this->formBuilder->get($name);
     }
     }
 
 
@@ -161,6 +163,8 @@ class FormMapper extends BaseGroupedMapper
      */
      */
     public function has($key)
     public function has($key)
     {
     {
+        $key = $this->sanitizeFieldName($key);
+
         return $this->formBuilder->has($key);
         return $this->formBuilder->has($key);
     }
     }
 
 
@@ -177,6 +181,7 @@ class FormMapper extends BaseGroupedMapper
      */
      */
     public function remove($key)
     public function remove($key)
     {
     {
+        $key = $this->sanitizeFieldName($key);
         $this->admin->removeFormFieldDescription($key);
         $this->admin->removeFormFieldDescription($key);
         $this->admin->removeFieldFromFormGroup($key);
         $this->admin->removeFieldFromFormGroup($key);
         $this->formBuilder->remove($key);
         $this->formBuilder->remove($key);
@@ -274,6 +279,21 @@ class FormMapper extends BaseGroupedMapper
         return $this;
         return $this;
     }
     }
 
 
+    /**
+     * Symfony default form class sadly can't handle
+     * form element with dots in its name (when data
+     * get bound, the default dataMapper is a PropertyPathMapper).
+     * So use this trick to avoid any issue.
+     *
+     * @param string $fieldName
+     *
+     * @return string
+     */
+    protected function sanitizeFieldName($fieldName)
+    {
+        return str_replace(array('__', '.'), array('____', '__'), $fieldName);
+    }
+
     /**
     /**
      * {@inheritdoc}
      * {@inheritdoc}
      */
      */

+ 7 - 4
Form/Type/ChoiceFieldMaskType.php

@@ -27,16 +27,19 @@ class ChoiceFieldMaskType extends AbstractType
      */
      */
     public function buildView(FormView $view, FormInterface $form, array $options)
     public function buildView(FormView $view, FormInterface $form, array $options)
     {
     {
-        $allFieldNames = array();
+        $sanitizedMap = array();
         foreach ($options['map'] as $value => $fieldNames) {
         foreach ($options['map'] as $value => $fieldNames) {
             foreach ($fieldNames as $fieldName) {
             foreach ($fieldNames as $fieldName) {
-                $allFieldNames[$fieldName] = $fieldName;
+                $sanitizedMap[$value][] =
+                    str_replace(array('__', '.'), array('____', '__'), $fieldName);
             }
             }
         }
         }
-        $allFieldNames = array_values($allFieldNames);
+
+        $allFieldNames = call_user_func_array('array_merge', $sanitizedMap);
+        $allFieldNames = array_unique($allFieldNames);
 
 
         $view->vars['all_fields'] = $allFieldNames;
         $view->vars['all_fields'] = $allFieldNames;
-        $view->vars['map'] = $options['map'];
+        $view->vars['map'] = $sanitizedMap;
 
 
         $options['expanded'] = false;
         $options['expanded'] = false;
 
 

+ 14 - 0
Tests/Form/FormMapperTest.php

@@ -429,6 +429,20 @@ class FormMapperTest extends PHPUnit_Framework_TestCase
         $this->assertSame(array('foo', 'baz'), $this->formMapper->keys());
         $this->assertSame(array('foo', 'baz'), $this->formMapper->keys());
     }
     }
 
 
+    public function testFieldNameIsSanitized()
+    {
+        $this->contractor->expects($this->any())
+            ->method('getDefaultOptions')
+            ->will($this->returnValue(array()));
+
+        $this->formMapper
+            ->add('fo.o', 'bar')
+            ->add('ba__z', 'foobaz')
+        ;
+
+        $this->assertSame(array('fo__o', 'ba____z'), $this->formMapper->keys());
+    }
+
     private function getFieldDescriptionMock($name = null, $label = null, $translationDomain = null)
     private function getFieldDescriptionMock($name = null, $label = null, $translationDomain = null)
     {
     {
         $fieldDescription = $this->getMockForAbstractClass('Sonata\AdminBundle\Admin\BaseFieldDescription');
         $fieldDescription = $this->getMockForAbstractClass('Sonata\AdminBundle\Admin\BaseFieldDescription');