-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
239b215
commit ea466be
Showing
2 changed files
with
318 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
<?php | ||
|
||
namespace ipl\Html\FormElement; | ||
|
||
use ipl\Html\Attributes; | ||
use ipl\Html\HtmlElement; | ||
use ipl\Html\HtmlString; | ||
use ipl\I18n\Translation; | ||
|
||
class RadioElement extends InputElement | ||
{ | ||
use Translation; | ||
|
||
protected $type = 'radio'; | ||
|
||
protected $optionContent; | ||
|
||
public function __construct($name, $attributes = null) | ||
{ | ||
$this->setName($name); | ||
|
||
$this->getAttributes()->registerAttributeCallback( | ||
'options', | ||
null, | ||
[$this, 'setOptions'] | ||
); | ||
|
||
// ZF1 compatibility: | ||
$this->getAttributes()->registerAttributeCallback( | ||
'multiOptions', | ||
null, | ||
[$this, 'setOptions'] | ||
); | ||
|
||
$this->getAttributes()->registerAttributeCallback( | ||
'disabled', | ||
null, | ||
[$this, 'disableOptions'] | ||
); | ||
|
||
parent::__construct($name, $attributes); | ||
} | ||
|
||
/** | ||
* Disable radio button that contains given value | ||
* | ||
* @param string $value | ||
* | ||
* @return $this | ||
*/ | ||
public function disableOption(string $value): RadioElement | ||
{ | ||
if ($option = $this->getOption($value)) { | ||
$option->getAttributes()->add('disabled', true); | ||
} | ||
|
||
if ($this->getValue() == $value) { | ||
$this->valid = false; | ||
$this->addMessage("'$value' is not allowed here"); | ||
} | ||
|
||
return $this; | ||
} | ||
|
||
/** | ||
* Disable radio buttons that contain given values | ||
* | ||
* @param mixed $values array or string | ||
* | ||
* @return $this | ||
*/ | ||
public function disableOptions($values): RadioElement | ||
{ | ||
$values = (array) $values; | ||
foreach ($values as $value) { | ||
$this->disableOption($value); | ||
} | ||
|
||
return $this; | ||
} | ||
|
||
/** | ||
* Get radio button with given value | ||
* | ||
* @param string $value | ||
* | ||
* @return InputElement|null | ||
*/ | ||
public function getOption(string $value): ?InputElement | ||
{ | ||
foreach ($this->optionContent as $radio) { | ||
if ($radio->getValueAttribute() === $value) { | ||
return $radio; | ||
} | ||
} | ||
|
||
return null; | ||
} | ||
|
||
public function setValue($value) | ||
{ | ||
parent::setValue($value); | ||
|
||
foreach ($this->optionContent as $radio) { | ||
$radio->getAttributes()->remove('checked'); | ||
if ($radio->getValueAttribute() === $value) { | ||
$radio->addAttributes(['checked' => true]); | ||
} | ||
} | ||
} | ||
|
||
public function validate() | ||
{ | ||
$value = $this->getValue(); | ||
if ( | ||
$value !== null | ||
&& (! ($option = $this->getOption($value)) || $option->getAttributes()->has('disabled')) | ||
) { | ||
$this->valid = false; | ||
$this->addMessage(sprintf($this->translate("'%s' is not allowed here"), $value)); | ||
|
||
return $this; | ||
} | ||
|
||
return parent::validate(); | ||
} | ||
|
||
/** | ||
* Prepare options | ||
* | ||
* @param array $options | ||
* | ||
* @return $this | ||
*/ | ||
public function setOptions(array $options): RadioElement | ||
{ | ||
foreach ($options as $value => $label) { | ||
$input = new InputElement($this->getName(), [ | ||
'name' => $this->getName(), | ||
'type' => $this->type, | ||
'value' => $value | ||
]); | ||
|
||
$this->optionContent[$label] = $input; | ||
} | ||
|
||
return $this; | ||
} | ||
|
||
public function renderUnwrapped() | ||
{ | ||
return $this->renderContent(); | ||
} | ||
|
||
protected function assemble() | ||
{ | ||
foreach ($this->optionContent as $label => $radioElm) { | ||
$labelElm = new HtmlElement( | ||
'label', | ||
Attributes::create(['class' => 'radio-label']), | ||
$radioElm, | ||
HtmlString::create($label) | ||
); | ||
|
||
$this->addHtml($labelElm); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
<?php | ||
|
||
namespace ipl\Tests\Html\FormElement; | ||
|
||
use ipl\Html\FormElement\RadioElement; | ||
use ipl\I18n\NoopTranslator; | ||
use ipl\I18n\StaticTranslator; | ||
use ipl\Tests\Html\TestCase; | ||
|
||
class RadioElementTest extends TestCase | ||
{ | ||
public function testCreateRadioElementsCorrectly() | ||
{ | ||
$radio = new RadioElement('test', [ | ||
'label' => 'Test', | ||
'multiOptions' => [ | ||
'foo' => 'Foo', | ||
'bar' => 'Bar', | ||
'yes' => 'Yes' | ||
] | ||
]); | ||
|
||
$this->assertHtml( | ||
'<label class="radio-label"><input value="foo" name="test" type="radio">Foo</label>' | ||
. '<label class="radio-label"><input value="bar" name="test" type="radio">Bar</label>' | ||
. '<label class="radio-label"><input value="yes" name="test" type="radio">Yes</label>', | ||
$radio | ||
); | ||
} | ||
|
||
public function testCheckCorrectRadio() | ||
{ | ||
$radio = new RadioElement('test', [ | ||
'label' => 'Test', | ||
'multiOptions' => [ | ||
'foo' => 'Foo', | ||
'bar' => 'Bar', | ||
'yes' => 'Yes' | ||
], | ||
'value' => 'bar' | ||
]); | ||
|
||
$this->assertHtml( | ||
'<label class="radio-label"><input value="foo" name="test" type="radio">Foo</label>' | ||
. '<label class="radio-label"><input value="bar" name="test" type="radio" checked>Bar</label>' | ||
. '<label class="radio-label"><input value="yes" name="test" type="radio">Yes</label>', | ||
$radio | ||
); | ||
|
||
$radio->setValue('yes'); | ||
|
||
$this->assertHtml( | ||
'<label class="radio-label"><input value="foo" name="test" type="radio">Foo</label>' | ||
. '<label class="radio-label"><input value="bar" name="test" type="radio">Bar</label>' | ||
. '<label class="radio-label"><input value="yes" name="test" type="radio" checked>Yes</label>', | ||
$radio | ||
); | ||
|
||
$radio->setValue('no'); | ||
|
||
$this->assertHtml( | ||
'<label class="radio-label"><input value="foo" name="test" type="radio">Foo</label>' | ||
. '<label class="radio-label"><input value="bar" name="test" type="radio">Bar</label>' | ||
. '<label class="radio-label"><input value="yes" name="test" type="radio">Yes</label>', | ||
$radio | ||
); | ||
} | ||
|
||
public function testDisableRadio() | ||
{ | ||
$radio = new RadioElement('test', [ | ||
'label' => 'Test', | ||
'multiOptions' => [ | ||
'foo' => 'Foo', | ||
'bar' => 'Bar', | ||
'yes' => 'Yes', | ||
'no' => 'No' | ||
], | ||
'value' => 'bar', | ||
'disabled' => 'yes' | ||
]); | ||
|
||
$this->assertHtml( | ||
'<label class="radio-label"><input value="foo" name="test" type="radio">Foo</label>' | ||
. '<label class="radio-label"><input value="bar" name="test" type="radio" checked>Bar</label>' | ||
. '<label class="radio-label"><input value="yes" name="test" type="radio" disabled>Yes</label>' | ||
. '<label class="radio-label"><input value="no" name="test" type="radio">No</label>', | ||
$radio | ||
); | ||
|
||
$radio->disableOptions(['yes', 'no', 'foo']); | ||
|
||
$this->assertHtml( | ||
'<label class="radio-label"><input value="foo" name="test" type="radio" disabled>Foo</label>' | ||
. '<label class="radio-label"><input value="bar" name="test" type="radio" checked>Bar</label>' | ||
. '<label class="radio-label"><input value="yes" name="test" type="radio" disabled>Yes</label>' | ||
. '<label class="radio-label"><input value="no" name="test" type="radio" disabled>No</label>', | ||
$radio | ||
); | ||
} | ||
|
||
public function testRadioNotValidIfCheckedValueIsInvalid() | ||
{ | ||
StaticTranslator::$instance = new NoopTranslator(); | ||
$radio = new RadioElement('test', [ | ||
'label' => 'Test', | ||
'multiOptions' => [ | ||
'foo' => 'Foo', | ||
'bar' => 'Bar', | ||
'yes' => 'Yes' | ||
], | ||
'value' => 'bar', | ||
'disabled' => 'yes' | ||
]); | ||
|
||
$this->assertTrue($radio->isValid()); | ||
|
||
$radio->setValue('no'); | ||
$this->assertFalse($radio->isValid()); | ||
|
||
$radio->setValue('tom'); | ||
$this->assertFalse($radio->isValid()); | ||
} | ||
|
||
public function testRadioNotValidIfCheckedValueIsDisabled() | ||
{ | ||
StaticTranslator::$instance = new NoopTranslator(); | ||
$radio = new RadioElement('test', [ | ||
'label' => 'Test', | ||
'multiOptions' => [ | ||
'foo' => 'Foo', | ||
'bar' => 'Bar', | ||
'yes' => 'Yes' | ||
], | ||
'value' => 'bar', | ||
'disabled' => 'yes' | ||
]); | ||
|
||
$this->assertTrue($radio->isValid()); | ||
|
||
$radio->setValue('yes'); | ||
$this->assertFalse($radio->isValid()); | ||
|
||
$radio->setValue('bar'); | ||
$this->assertTrue($radio->isValid()); | ||
|
||
$radio->disableOptions(['bar', 'yes', 'foo']); | ||
$this->assertFalse($radio->isValid()); | ||
} | ||
} |