Browse Source

RadioWidget and MultiCheckboxWidget now actually use the "id" if passed; If not, they behave as before.
Split the _id method of the IdGeneratorTrait into two methods so the suffix can be generated separately.
Since idPrefix must be ignored when id was passed explicitly, we need to generate the suffix separately from the idPrefix and name.

Lars Ebert 6 years ago
parent
commit
6890aa73d3

+ 15 - 1
src/View/Helper/IdGeneratorTrait.php

@@ -59,7 +59,21 @@ trait IdGeneratorTrait
     protected function _id($name, $val)
     {
         $name = $this->_domId($name);
+        $suffix = $this->_idSuffix($val);
 
+        return trim($name . '-' . $suffix, '-');
+    }
+
+    /**
+     * Generate an ID suffix.
+     *
+     * Ensures that id's for a given set of fields are unique.
+     *
+     * @param string $val The ID attribute value.
+     * @return string Generated id suffix.
+     */
+    protected function _idSuffix($val)
+    {
         $idSuffix = mb_strtolower(str_replace(['/', '@', '<', '>', ' ', '"', '\''], '-', $val));
         $count = 1;
         $check = $idSuffix;
@@ -68,7 +82,7 @@ trait IdGeneratorTrait
         }
         $this->_idSuffixes[] = $check;
 
-        return trim($name . '-' . $check, '-');
+        return $check;
     }
 
     /**

+ 8 - 1
src/View/Widget/MultiCheckboxWidget.php

@@ -164,7 +164,14 @@ class MultiCheckboxWidget implements WidgetInterface
             $checkbox['checked'] = $this->_isSelected($checkbox['value'], $data['val']);
             $checkbox['disabled'] = $this->_isDisabled($checkbox['value'], $data['disabled']);
             if (empty($checkbox['id'])) {
-                $checkbox['id'] = $this->_id($checkbox['name'], $checkbox['value']);
+                if(isset($data['id'])) {
+                    $checkbox['id'] = $data['id'] . '-' . trim(
+                        $this->_idSuffix($checkbox['value']),
+                        '-'
+                    );
+                } else {
+                    $checkbox['id'] = $this->_id($checkbox['name'], $checkbox['value']);
+                }
             }
             $out[] = $this->_renderInput($checkbox + $data, $context);
         }

+ 8 - 1
src/View/Widget/RadioWidget.php

@@ -165,7 +165,14 @@ class RadioWidget implements WidgetInterface
         }
 
         if (empty($radio['id'])) {
-            $radio['id'] = $this->_id($radio['name'], $radio['value']);
+            if(isset($data['id'])) {
+                $radio['id'] = $data['id'] . '-' . trim(
+                    $this->_idSuffix($radio['value']),
+                    '-'
+                );
+            } else {
+                $radio['id'] = $this->_id($radio['name'], $radio['value']);
+            }
         }
         if (isset($data['val']) && is_bool($data['val'])) {
             $data['val'] = $data['val'] ? 1 : 0;

+ 27 - 0
tests/TestCase/View/Widget/MultiCheckboxWidgetTest.php

@@ -665,6 +665,7 @@ class MultiCheckboxWidgetTest extends TestCase
             'name' => 'field',
             'options' => ['value1', 'value2'],
             'id' => 'alternative-id',
+            'idPrefix' => 'willBeIgnored',
         ];
         $result = $input->render($data, $this->context);
         $expected = [
@@ -686,5 +687,31 @@ class MultiCheckboxWidgetTest extends TestCase
             '/div',
         ];
         $this->assertHtml($expected, $result);
+
+        $data = [
+            'name' => 'field',
+            'options' => ['value1', 'value2'],
+            'idPrefix' => 'formprefix',
+        ];
+        $result = $input->render($data, $this->context);
+        $expected = [
+            [
+                'div' => ['class' => 'checkbox'],
+                'input' => ['type' => 'checkbox', 'name' => 'field[]', 'value' => '0', 'id' => 'formprefix-field-0'],
+                'label' => ['for' => 'formprefix-field-0'],
+            ],
+            'value1',
+            '/label',
+            '/div',
+            [
+                'div' => ['class' => 'checkbox'],
+                'input' => ['type' => 'checkbox', 'name' => 'field[]', 'value' => '1', 'id' => 'formprefix-field-1'],
+                'label' => ['for' => 'formprefix-field-1'],
+            ],
+            'value2',
+            '/label',
+            '/div',
+        ];
+        $this->assertHtml($expected, $result);
     }
 }

+ 23 - 0
tests/TestCase/View/Widget/RadioWidgetTest.php

@@ -797,6 +797,7 @@ class RadioWidgetTest extends TestCase
             'name' => 'field',
             'options' => ['value1', 'value2'],
             'id' => 'alternative-id',
+            'idPrefix' => 'willBeIgnored',
         ];
         $result = $input->render($data, $this->context);
         $expected = [
@@ -814,5 +815,27 @@ class RadioWidgetTest extends TestCase
             '/label',
         ];
         $this->assertHtml($expected, $result);
+
+        $data = [
+            'name' => 'field',
+            'options' => ['value1', 'value2'],
+            'idPrefix' => 'formprefix',
+        ];
+        $result = $input->render($data, $this->context);
+        $expected = [
+            [
+                'label' => ['for' => 'formprefix-field-0'],
+                'input' => ['type' => 'radio', 'name' => 'field', 'value' => '0', 'id' => 'formprefix-field-0'],
+            ],
+            'value1',
+            '/label',
+            [
+                'label' => ['for' => 'formprefix-field-1'],
+                'input' => ['type' => 'radio', 'name' => 'field', 'value' => '1', 'id' => 'formprefix-field-1'],
+            ],
+            'value2',
+            '/label',
+        ];
+        $this->assertHtml($expected, $result);
     }
 }