Browse Source

Fix disabled attribute calculation.

Take the work done in #10770 and account for the complex options and
non-empty disabled option sets.

Refs #10770
mark_story 8 years ago
parent
commit
e8090bce40
2 changed files with 68 additions and 11 deletions
  1. 37 11
      src/View/Helper/FormHelper.php
  2. 31 0
      tests/TestCase/View/Helper/FormHelperTest.php

+ 37 - 11
src/View/Helper/FormHelper.php

@@ -2577,17 +2577,7 @@ class FormHelper extends Helper
         if ($context->hasError($field)) {
             $options = $this->addClass($options, $this->_config['errorClass']);
         }
-        $isDisabled = false;
-        if (isset($options['disabled'])) {
-            $isDisabled = (
-                $options['disabled'] === true ||
-                $options['disabled'] === 'disabled' ||
-                (is_array($options['disabled']) &&
-                    !empty($options['options']) &&
-                    array_diff($options['options'], $options['disabled']) === []
-                )
-            );
-        }
+        $isDisabled = $this->_isDisabled($options);
         if ($isDisabled) {
             $options['secure'] = self::SECURE_SKIP;
         }
@@ -2602,6 +2592,42 @@ class FormHelper extends Helper
     }
 
     /**
+     * Determine if a field is disabled.
+     *
+     * @param array $options The option set.
+     * @return bool Whether or not the field is disabled.
+     */
+    protected function _isDisabled(array $options)
+    {
+        if (!isset($options['disabled'])) {
+            return false;
+        }
+        if (is_scalar($options['disabled'])) {
+            return ($options['disabled'] === true || $options['disabled'] === 'disabled');
+        }
+        if (!isset($options['options'])) {
+            return false;
+        }
+        if (is_array($options['options'])) {
+            // Simple list options
+            $first = $options['options'][array_keys($options['options'])[0]];
+            if (is_scalar($first)) {
+                return array_diff($options['options'], $options['disabled']) === [];
+            }
+            // Complex option types
+            if (is_array($first)) {
+                $disabled = array_filter($options['options'], function ($i) use ($options)  {
+                    return in_array($i['value'], $options['disabled']);
+                });
+
+                return count($disabled) > 0;
+            }
+        }
+
+        return false;
+    }
+
+    /**
      * Get the field name for use with _secure().
      *
      * Parses the name attribute to create a dot separated name value for use

+ 31 - 0
tests/TestCase/View/Helper/FormHelperTest.php

@@ -4628,6 +4628,37 @@ class FormHelperTest extends TestCase
     }
 
     /**
+     * Test radio with complex options and empty disabled data.
+     *
+     * @return void
+     */
+    public function testRadioComplexDisabled()
+    {
+        $options = [
+            ['value' => 'r', 'text' => 'red'],
+            ['value' => 'b', 'text' => 'blue'],
+        ];
+        $attrs = ['disabled' => []];
+        $result = $this->Form->radio('Model.field', $options, $attrs);
+        $expected = [
+            'input' => ['type' => 'hidden', 'name' => 'Model[field]', 'value' => ''],
+            ['label' => ['for' => 'model-field-r']],
+            ['input' => ['type' => 'radio', 'name' => 'Model[field]', 'value' => 'r', 'id' => 'model-field-r']],
+            'red',
+            '/label',
+            ['label' => ['for' => 'model-field-b']],
+            ['input' => ['type' => 'radio', 'name' => 'Model[field]', 'value' => 'b', 'id' => 'model-field-b']],
+            'blue',
+            '/label',
+        ];
+        $this->assertHtml($expected, $result);
+
+        $attrs = ['disabled' => ['r']];
+        $result = $this->Form->radio('Model.field', $options, $attrs);
+        $this->assertContains('disabled="disabled"', $result);
+    }
+
+    /**
      * testRadioDefaultValue method
      *
      * Test default value setting on radio() method.