options = [];
foreach ($options as $value => $label) {
$option = (new RadioOption($value, $label))
->setDisabled(
in_array($value, $this->disabledOptions, ! is_int($value))
|| ($value === '' && in_array(null, $this->disabledOptions, true))
);
$this->options[$value] = $option;
}
$this->disabledOptions = [];
return $this;
}
/**
* Get the option with specified value
*
* @param string|int $value
*
* @return RadioOption
*
* @throws InvalidArgumentException If no option with the specified value exists
*/
public function getOption($value): RadioOption
{
if (! isset($this->options[$value])) {
throw new InvalidArgumentException(sprintf('There is no such option "%s"', $value));
}
return $this->options[$value];
}
/**
* Set the specified options as disable
*
* @param array $disabledOptions
*
* @return $this
*/
public function setDisabledOptions(array $disabledOptions): self
{
if (! empty($this->options)) {
foreach ($this->options as $value => $option) {
$option->setDisabled(
in_array($value, $disabledOptions, ! is_int($value))
|| ($value === '' && in_array(null, $disabledOptions, true))
);
}
$this->disabledOptions = [];
} else {
$this->disabledOptions = $disabledOptions;
}
return $this;
}
public function renderUnwrapped()
{
// Parent::renderUnwrapped() requires $tag and the content should be empty. However, since we are wrapping
// each button in a label, the call to parent cannot work here and must be overridden.
return HtmlDocument::renderUnwrapped();
}
protected function assemble()
{
foreach ($this->options as $option) {
$radio = (new InputElement($this->getValueOfNameAttribute()))
->setType($this->type)
->setValue($option->getValue());
// Only add the non-callback attributes to all options
foreach ($this->getAttributes() as $attribute) {
$radio->getAttributes()->addAttribute(clone $attribute);
}
$radio->getAttributes()
->merge($option->getAttributes())
->registerAttributeCallback(
'checked',
function () use ($option) {
$optionValue = $option->getValue();
return ! is_int($optionValue)
? $this->getValue() === $optionValue
: $this->getValue() == $optionValue;
}
)
->registerAttributeCallback(
'disabled',
function () use ($option) {
return $this->getAttributes()->get('disabled')->getValue() || $option->isDisabled();
}
);
$label = new HtmlElement(
'label',
new Attributes(['class' => $option->getLabelCssClass()]),
$radio,
Text::create($option->getLabel())
);
$this->addHtml($label);
}
}
protected function addDefaultValidators(ValidatorChain $chain): void
{
$chain->add(new DeferredInArrayValidator(function (): array {
$possibleValues = [];
foreach ($this->options as $option) {
if ($option->isDisabled()) {
continue;
}
$possibleValues[] = $option->getValue();
}
return $possibleValues;
}));
}
protected function registerAttributeCallbacks(Attributes $attributes)
{
parent::registerAttributeCallbacks($attributes);
$this->getAttributes()->registerAttributeCallback(
'options',
null,
[$this, 'setOptions']
);
$this->getAttributes()->registerAttributeCallback(
'disabledOptions',
null,
[$this, 'setDisabledOptions']
);
}
}