Selaa lähdekoodia

merged branch proofek/domcrawlerform-radiodisabled (PR #2768)

Commits
-------

36c7d03 Fixed GH-2720 - Fix disabled atrribute handling for radio form elements

Discussion
----------

Fixed GH-2720 - Fix disabled atrribute handling for radio form elements

Bug fix: yes
Feature addition: no
Backwards compatibility break: no
Symfony2 tests pass: yes
Fixes the following tickets: - GH-2720

I wasn't really sure about the correct approach. This one is very minimalistic and following the existing concept of not duplicating nodes of the same name, but only storing multiple values for the same node. If you think that should be changed, let me know. Hints appreciated.

Thanks
Fabien Potencier 13 vuotta sitten
vanhempi
commit
648fae7746

+ 81 - 10
src/Symfony/Component/DomCrawler/Field/ChoiceFormField.php

@@ -41,6 +41,22 @@ class ChoiceFormField extends FormField
         return true;
     }
 
+    /**
+     * Check if the current selected option is disabled
+     * 
+     * @return bool
+     */
+    public function isDisabled()
+    {
+        foreach ($this->options as $option) {
+            if ($option['value'] == $this->value && $option['disabled']) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+    
     /**
      * Sets the value of the field.
      *
@@ -101,7 +117,7 @@ class ChoiceFormField extends FormField
             $this->value = null;
         } elseif ('checkbox' == $this->type && true === $value) {
             // check
-            $this->value = $this->options[0];
+            $this->value = $this->options[0]['value'];
         } else {
             if (is_array($value)) {
                 if (!$this->multiple) {
@@ -109,12 +125,12 @@ class ChoiceFormField extends FormField
                 }
 
                 foreach ($value as $v) {
-                    if (!in_array($v, $this->options)) {
-                        throw new \InvalidArgumentException(sprintf('Input "%s" cannot take "%s" as a value (possible values: %s).', $this->name, $v, implode(', ', $this->options)));
+                    if (!$this->containsOption($v, $this->options)) {
+                        throw new \InvalidArgumentException(sprintf('Input "%s" cannot take "%s" as a value (possible values: %s).', $this->name, $v, implode(', ', $this->availableOptionValues())));
                     }
                 }
-            } elseif (!in_array($value, $this->options)) {
-                throw new \InvalidArgumentException(sprintf('Input "%s" cannot take "%s" as a value (possible values: %s).', $this->name, $value, implode(', ', $this->options)));
+            } elseif (!$this->containsOption($value, $this->options)) {
+                throw new \InvalidArgumentException(sprintf('Input "%s" cannot take "%s" as a value (possible values: %s).', $this->name, $value, implode(', ', $this->availableOptionValues())));
             }
 
             if ($this->multiple) {
@@ -144,10 +160,11 @@ class ChoiceFormField extends FormField
             throw new \LogicException(sprintf('Unable to add a choice for "%s" as it is not multiple or is not a radio button.', $this->name));
         }
 
-        $this->options[] = $value = $node->hasAttribute('value') ? $node->getAttribute('value') : '1';
+        $option = $this->buildOptionValue($node);
+        $this->options[] = $option;
 
         if ($node->getAttribute('checked')) {
-            $this->value = $value;
+            $this->value = $option['value'];
         }
     }
 
@@ -192,10 +209,11 @@ class ChoiceFormField extends FormField
 
         if ('input' == $this->node->nodeName) {
             $this->type = $this->node->getAttribute('type');
-            $this->options[] = $value = $this->node->hasAttribute('value') ? $this->node->getAttribute('value') : '1';
+            $optionValue = $this->buildOptionValue($this->node);
+            $this->options[] = $optionValue;
 
             if ($this->node->getAttribute('checked')) {
-                $this->value = $value;
+                $this->value = $optionValue['value'];
             }
         } else {
             $this->type = 'select';
@@ -207,7 +225,7 @@ class ChoiceFormField extends FormField
 
             $found = false;
             foreach ($this->xpath->query('descendant::option', $this->node) as $option) {
-                $this->options[] = $option->hasAttribute('value') ? $option->getAttribute('value') : $option->nodeValue;
+                $this->options[] = $this->buildOptionValue($option);
 
                 if ($option->getAttribute('selected')) {
                     $found = true;
@@ -226,4 +244,57 @@ class ChoiceFormField extends FormField
             }
         }
     }
+
+    /**
+     * Returns option value with associated disabled flag
+     *
+     * @param type $node
+     * 
+     * @return array
+     */
+    private function buildOptionValue($node)
+    {
+        $option = array();
+
+        $defaultValue = (isset($node->nodeValue) && !empty($node->nodeValue)) ? $node->nodeValue : '1';
+        $option['value'] = $node->hasAttribute('value') ? $node->getAttribute('value') : $defaultValue;
+        $option['disabled'] = ($node->hasAttribute('disabled') && $node->getAttribute('disabled') == 'disabled');
+            
+        return $option;
+    }
+
+    /**
+     * Checks whether given vale is in the existing options
+     *
+     * @param string $optionValue
+     * @param array  $options
+     * 
+     * @return bool
+     */
+    public function containsOption($optionValue, $options)
+    {
+        foreach ($options as $option) {
+            if ($option['value'] == $optionValue) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Returns list of available field options
+     *
+     * @return array
+     */
+    public function availableOptionValues()
+    {
+        $values = array();
+
+        foreach ($this->options as $option) {
+            $values[] = $option['value'];
+        }
+
+        return $values;
+    }
 }

+ 16 - 0
tests/Symfony/Tests/Component/DomCrawler/Field/ChoiceFormFieldTest.php

@@ -168,6 +168,22 @@ class ChoiceFormFieldTest extends FormFieldTestCase
         }
     }
 
+    public function testRadioButtonIsDisabled()
+    {
+        $node = $this->createNode('input', '', array('type' => 'radio', 'name' => 'name', 'value' => 'foo', 'disabled' => 'disabled'));
+        $field = new ChoiceFormField($node);
+        $node = $this->createNode('input', '', array('type' => 'radio', 'name' => 'name', 'value' => 'bar'));
+        $field->addChoice($node);
+
+        $field->select('foo');
+        $this->assertEquals('foo', $field->getValue(), '->getValue() returns the value attribute of the selected radio button');
+        $this->assertTrue($field->isDisabled());
+
+        $field->select('bar');
+        $this->assertEquals('bar', $field->getValue(), '->getValue() returns the value attribute of the selected radio button');
+        $this->assertFalse($field->isDisabled());
+    }
+    
     public function testCheckboxes()
     {
         $node = $this->createNode('input', '', array('type' => 'checkbox', 'name' => 'name'));