From 36c7d03040edcad7346a4f9229efe8582046e16b Mon Sep 17 00:00:00 2001 From: Sebastian Marek Date: Thu, 24 Nov 2011 15:42:41 +0000 Subject: [PATCH] Fixed GH-2720 - Fix disabled atrribute handling for radio form elements --- .../DomCrawler/Field/ChoiceFormField.php | 91 +++++++++++++++++-- .../DomCrawler/Field/ChoiceFormFieldTest.php | 16 ++++ 2 files changed, 97 insertions(+), 10 deletions(-) diff --git a/src/Symfony/Component/DomCrawler/Field/ChoiceFormField.php b/src/Symfony/Component/DomCrawler/Field/ChoiceFormField.php index e9f3c958e7..a3eacb7883 100644 --- a/src/Symfony/Component/DomCrawler/Field/ChoiceFormField.php +++ b/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; + } } diff --git a/tests/Symfony/Tests/Component/DomCrawler/Field/ChoiceFormFieldTest.php b/tests/Symfony/Tests/Component/DomCrawler/Field/ChoiceFormFieldTest.php index 928973bdef..f54c766c2a 100644 --- a/tests/Symfony/Tests/Component/DomCrawler/Field/ChoiceFormFieldTest.php +++ b/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'));