/vendor/zendframework/zend-form/src/View/Helper/FormSelect.php
PHP | 326 lines | 188 code | 44 blank | 94 comment | 31 complexity | 47c5a33dccf411e610e51430c9d821d7 MD5 | raw file
- <?php
- /**
- * Zend Framework (http://framework.zend.com/)
- *
- * @link http://github.com/zendframework/zf2 for the canonical source repository
- * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
- * @license http://framework.zend.com/license/new-bsd New BSD License
- */
- namespace Zend\Form\View\Helper;
- use Zend\Form\Element\Hidden;
- use Zend\Form\ElementInterface;
- use Zend\Form\Element\Select as SelectElement;
- use Zend\Form\Exception;
- use Zend\Stdlib\ArrayUtils;
- class FormSelect extends AbstractHelper
- {
- /**
- * Attributes valid for the current tag
- *
- * Will vary based on whether a select, option, or optgroup is being rendered
- *
- * @var array
- */
- protected $validTagAttributes;
- /**
- * Attributes valid for select
- *
- * @var array
- */
- protected $validSelectAttributes = array(
- 'name' => true,
- 'autocomplete' => true,
- 'autofocus' => true,
- 'disabled' => true,
- 'form' => true,
- 'multiple' => true,
- 'required' => true,
- 'size' => true
- );
- /**
- * Attributes valid for options
- *
- * @var array
- */
- protected $validOptionAttributes = array(
- 'disabled' => true,
- 'selected' => true,
- 'label' => true,
- 'value' => true,
- );
- /**
- * Attributes valid for option groups
- *
- * @var array
- */
- protected $validOptgroupAttributes = array(
- 'disabled' => true,
- 'label' => true,
- );
- protected $translatableAttributes = array(
- 'label' => true,
- );
- /**
- * @var FormHidden|null
- */
- protected $formHiddenHelper;
- /**
- * Invoke helper as functor
- *
- * Proxies to {@link render()}.
- *
- * @param ElementInterface|null $element
- * @return string|FormSelect
- */
- public function __invoke(ElementInterface $element = null)
- {
- if (!$element) {
- return $this;
- }
- return $this->render($element);
- }
- /**
- * Render a form <select> element from the provided $element
- *
- * @param ElementInterface $element
- * @throws Exception\InvalidArgumentException
- * @throws Exception\DomainException
- * @return string
- */
- public function render(ElementInterface $element)
- {
- if (!$element instanceof SelectElement) {
- throw new Exception\InvalidArgumentException(sprintf(
- '%s requires that the element is of type Zend\Form\Element\Select',
- __METHOD__
- ));
- }
- $name = $element->getName();
- if (empty($name) && $name !== 0) {
- throw new Exception\DomainException(sprintf(
- '%s requires that the element has an assigned name; none discovered',
- __METHOD__
- ));
- }
- $options = $element->getValueOptions();
- if (($emptyOption = $element->getEmptyOption()) !== null) {
- $options = array('' => $emptyOption) + $options;
- }
- $attributes = $element->getAttributes();
- $value = $this->validateMultiValue($element->getValue(), $attributes);
- $attributes['name'] = $name;
- if (array_key_exists('multiple', $attributes) && $attributes['multiple']) {
- $attributes['name'] .= '[]';
- }
- $this->validTagAttributes = $this->validSelectAttributes;
- $rendered = sprintf(
- '<select %s>%s</select>',
- $this->createAttributesString($attributes),
- $this->renderOptions($options, $value)
- );
- // Render hidden element
- $useHiddenElement = method_exists($element, 'useHiddenElement')
- && method_exists($element, 'getUnselectedValue')
- && $element->useHiddenElement();
- if ($useHiddenElement) {
- $rendered = $this->renderHiddenElement($element) . $rendered;
- }
- return $rendered;
- }
- /**
- * Render an array of options
- *
- * Individual options should be of the form:
- *
- * <code>
- * array(
- * 'value' => 'value',
- * 'label' => 'label',
- * 'disabled' => $booleanFlag,
- * 'selected' => $booleanFlag,
- * )
- * </code>
- *
- * @param array $options
- * @param array $selectedOptions Option values that should be marked as selected
- * @return string
- */
- public function renderOptions(array $options, array $selectedOptions = array())
- {
- $template = '<option %s>%s</option>';
- $optionStrings = array();
- $escapeHtml = $this->getEscapeHtmlHelper();
- foreach ($options as $key => $optionSpec) {
- $value = '';
- $label = '';
- $selected = false;
- $disabled = false;
- if (is_scalar($optionSpec)) {
- $optionSpec = array(
- 'label' => $optionSpec,
- 'value' => $key
- );
- }
- if (isset($optionSpec['options']) && is_array($optionSpec['options'])) {
- $optionStrings[] = $this->renderOptgroup($optionSpec, $selectedOptions);
- continue;
- }
- if (isset($optionSpec['value'])) {
- $value = $optionSpec['value'];
- }
- if (isset($optionSpec['label'])) {
- $label = $optionSpec['label'];
- }
- if (isset($optionSpec['selected'])) {
- $selected = $optionSpec['selected'];
- }
- if (isset($optionSpec['disabled'])) {
- $disabled = $optionSpec['disabled'];
- }
- if (ArrayUtils::inArray($value, $selectedOptions)) {
- $selected = true;
- }
- if (null !== ($translator = $this->getTranslator())) {
- $label = $translator->translate(
- $label,
- $this->getTranslatorTextDomain()
- );
- }
- $attributes = compact('value', 'selected', 'disabled');
- if (isset($optionSpec['attributes']) && is_array($optionSpec['attributes'])) {
- $attributes = array_merge($attributes, $optionSpec['attributes']);
- }
- $this->validTagAttributes = $this->validOptionAttributes;
- $optionStrings[] = sprintf(
- $template,
- $this->createAttributesString($attributes),
- $escapeHtml($label)
- );
- }
- return implode("\n", $optionStrings);
- }
- /**
- * Render an optgroup
- *
- * See {@link renderOptions()} for the options specification. Basically,
- * an optgroup is simply an option that has an additional "options" key
- * with an array following the specification for renderOptions().
- *
- * @param array $optgroup
- * @param array $selectedOptions
- * @return string
- */
- public function renderOptgroup(array $optgroup, array $selectedOptions = array())
- {
- $template = '<optgroup%s>%s</optgroup>';
- $options = array();
- if (isset($optgroup['options']) && is_array($optgroup['options'])) {
- $options = $optgroup['options'];
- unset($optgroup['options']);
- }
- $this->validTagAttributes = $this->validOptgroupAttributes;
- $attributes = $this->createAttributesString($optgroup);
- if (!empty($attributes)) {
- $attributes = ' ' . $attributes;
- }
- return sprintf(
- $template,
- $attributes,
- $this->renderOptions($options, $selectedOptions)
- );
- }
- /**
- * Ensure that the value is set appropriately
- *
- * If the element's value attribute is an array, but there is no multiple
- * attribute, or that attribute does not evaluate to true, then we have
- * a domain issue -- you cannot have multiple options selected unless the
- * multiple attribute is present and enabled.
- *
- * @param mixed $value
- * @param array $attributes
- * @return array
- * @throws Exception\DomainException
- */
- protected function validateMultiValue($value, array $attributes)
- {
- if (null === $value) {
- return array();
- }
- if (!is_array($value)) {
- return (array) $value;
- }
- if (!isset($attributes['multiple']) || !$attributes['multiple']) {
- throw new Exception\DomainException(sprintf(
- '%s does not allow specifying multiple selected values when the element does not have a multiple attribute set to a boolean true',
- __CLASS__
- ));
- }
- return $value;
- }
- protected function renderHiddenElement(ElementInterface $element)
- {
- $hiddenElement = new Hidden($element->getName());
- $hiddenElement->setValue($element->getUnselectedValue());
- return $this->getFormHiddenHelper()->__invoke($hiddenElement);
- }
- /**
- * @return FormHidden
- */
- protected function getFormHiddenHelper()
- {
- if (!$this->formHiddenHelper) {
- if (method_exists($this->view, 'plugin')) {
- $this->formHiddenHelper = $this->view->plugin('formhidden');
- }
- if (!$this->formHiddenHelper instanceof FormHidden) {
- $this->formHiddenHelper = new FormHidden();
- }
- }
- return $this->formHiddenHelper;
- }
- }