diff --git a/src/FormElement/RadioElement.php b/src/FormElement/RadioElement.php index c02ad772..dd3a3963 100644 --- a/src/FormElement/RadioElement.php +++ b/src/FormElement/RadioElement.php @@ -36,7 +36,10 @@ public function setOptions(array $options): self $this->options = []; foreach ($options as $value => $label) { $option = (new RadioOption($value, $label)) - ->setDisabled(in_array($value, $this->disabledOptions, true)); + ->setDisabled( + in_array($value, $this->disabledOptions, ! is_int($value)) + || ($value === '' && in_array(null, $this->disabledOptions)) + ); $this->options[$value] = $option; } @@ -74,9 +77,10 @@ public function getOption($value): RadioOption public function setDisabledOptions(array $disabledOptions): self { if (! empty($this->options)) { - foreach ($this->options as $option) { + foreach ($this->options as $value => $option) { $option->setDisabled( - in_array($option->getValue(), $disabledOptions, true) + in_array($value, $disabledOptions, ! is_int($value)) + || ($value === '' && in_array(null, $disabledOptions)) ); } @@ -111,12 +115,7 @@ protected function assemble() ->merge($option->getAttributes()) ->registerAttributeCallback('checked', function () use ($option) { - $optionValue = $option->getValue(); - - if ($optionValue === '') { - $optionValue = null; - } - return $this->getValue() === $optionValue; + return $this->getValue() === $option->getValue(); } ) ->registerAttributeCallback('disabled', @@ -126,7 +125,7 @@ function () use ($option) { ); $labelAttributes = (new Attributes(['class' => RadioOption::LABEL_CLASS])) - ->add('class', $option->getlabelCssClass()); + ->add('class', $option->getLabelCssClass()); $label = new HtmlElement( 'label', diff --git a/src/FormElement/RadioOption.php b/src/FormElement/RadioOption.php index e2cd75d1..bb723724 100644 --- a/src/FormElement/RadioOption.php +++ b/src/FormElement/RadioOption.php @@ -27,11 +27,13 @@ class RadioOption /** * RadioOption constructor. * - * @param string|int $value + * @param string|int|null $value * @param string $label */ public function __construct($value, string $label) { + $value = $value === '' ? null : $value; + $this->value = $value; $this->label = $label; } @@ -73,7 +75,7 @@ public function getValue() /** * Add css class to the option label * - * @param string|array|Attribute $labelCssClass + * @param string|string[] $labelCssClass * * @return $this */ diff --git a/tests/FormElement/RadioElementTest.php b/tests/FormElement/RadioElementTest.php index 808eda49..a5800199 100644 --- a/tests/FormElement/RadioElementTest.php +++ b/tests/FormElement/RadioElementTest.php @@ -280,5 +280,131 @@ public function testNullAndTheEmptyStringAreEquallyHandled() HTML; $this->assertHtml($html, $radio2); + + $radio->setDisabledOptions([null, 'foo']); + $radio2->setDisabledOptions(['', 'foo']); + + $html = <<<'HTML' + +HTML; + + $this->assertHtml($html, $radio); + + $html = <<<'HTML' + +HTML; + + $this->assertHtml($html, $radio2); + } + + public function testSetOptionsResetsOptions() + { + $radio = new RadioElement('radio'); + $radio->setOptions(['foo' => 'Foo', 'bar' => 'Bar']); + + $this->assertInstanceOf(RadioOption::class, $radio->getOption('foo')); + $this->assertInstanceOf(RadioOption::class, $radio->getOption('bar')); + + $radio->setOptions(['car' => 'Car', 'train' => 'Train']); + + $this->expectExceptionMessage('There is no such option "foo"'); + $radio->getOption('foo'); + + $this->expectExceptionMessage('There is no such option "bar"'); + $radio->getOption('bar'); + + $this->assertInstanceOf(RadioOption::class, $radio->getOption('car')); + $this->assertInstanceOf(RadioOption::class, $radio->getOption('train')); + } + + public function testOrderOfOptionsAndDisabledOptionsDoesNotMatter() + { + $radio = new RadioElement('test', [ + 'label' => 'Test', + 'options' => [ + 'foo' => 'Foo', + 'bar' => 'Bar' + ], + 'disabledOptions' => ['foo', 'bar'] + ]); + + $html = <<<'HTML' + + +HTML; + $this->assertHtml($html, $radio); + + $radio = new RadioElement('test', [ + 'disabledOptions' => ['foo', 'bar'], + 'label' => 'Test', + 'options' => [ + 'foo' => 'Foo', + 'bar' => 'Bar' + ] + ]); + + $this->assertHtml($html, $radio); + } + + public function testGetOptionReturnsPreviouslySetOption() + { + $radio = new RadioElement('radio'); + $radio->setOptions(['' => 'Empty String', 'foo' => 'Foo', 'bar' => 'Bar']); + + $this->assertNull($radio->getOption('')->getValue()); + $this->assertSame('Empty String', $radio->getOption('')->getLabel()); + + $this->assertSame('foo', $radio->getOption('foo')->getValue()); + $this->assertSame('Foo', $radio->getOption('foo')->getLabel()); + + $radio->setOptions(['' => 'Please Choose', 'car' => 'Car', 'train' => 'Train']); + + $this->assertNull($radio->getOption('')->getValue()); + $this->assertSame('Please Choose', $radio->getOption('')->getLabel()); + + $this->assertSame('car', $radio->getOption('car')->getValue()); + $this->assertSame('Car', $radio->getOption('car')->getLabel()); + } + + public function testNullAndTheEmptyStringAreAlsoEquallyHandledWhileDisablingOptions() + { + $radio = new RadioElement('radio'); + $radio->setOptions([null => 'Foo', 'bar' => 'Bar']); + $radio->setDisabledOptions([null]); + + $this->assertTrue($radio->getOption(null)->isDisabled()); + + $radio = new RadioElement('radio'); + $radio->setOptions(['' => 'Foo', 'bar' => 'Bar']); + $radio->setDisabledOptions(['']); + + $this->assertTrue($radio->getOption('')->isDisabled()); + + $radio = new RadioElement('radio'); + $radio->setOptions([null => 'Foo', 'bar' => 'Bar']); + $radio->setDisabledOptions(['']); + + $this->assertTrue($radio->getOption(null)->isDisabled()); + $radio = new RadioElement('radio'); + $radio->setOptions(['' => 'Foo', 'bar' => 'Bar']); + $radio->setDisabledOptions([null]); + + $this->assertTrue($radio->getOption('')->isDisabled()); + } + + public function testGetOptionGetValueAndElementGetValueHandleNullAndTheEmptyStringEqually() + { + $radio = new RadioElement('radio'); + $radio->setOptions(['' => 'Foo']); + $radio->setValue(''); + + $this->assertNull($radio->getValue()); + $this->assertNull($radio->getOption('')->getValue()); + + $radio = new RadioElement('radio'); + $radio->setOptions([null => 'Foo']); + + $this->assertNull($radio->getValue()); + $this->assertNull($radio->getOption(null)->getValue()); } }