3 * Zend Framework (http://framework.zend.com/)
5 * @link http://github.com/zendframework/zf2 for the canonical source repository
6 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
7 * @license http://framework.zend.com/license/new-bsd New BSD License
10 namespace Zend\Form\View\Helper
;
12 use Zend\Form\ElementInterface
;
13 use Zend\Form\Element\Select
as SelectElement
;
14 use Zend\Form\Exception
;
15 use Zend\Stdlib\ArrayUtils
;
17 class FormSelect
extends AbstractHelper
20 * Attributes valid for the current tag
22 * Will vary based on whether a select, option, or optgroup is being rendered
26 protected $validTagAttributes;
29 * Attributes valid for select
33 protected $validSelectAttributes = array(
44 * Attributes valid for options
48 protected $validOptionAttributes = array(
56 * Attributes valid for option groups
60 protected $validOptgroupAttributes = array(
65 protected $translatableAttributes = array(
70 * Invoke helper as functor
72 * Proxies to {@link render()}.
74 * @param ElementInterface|null $element
75 * @return string|FormSelect
77 public function __invoke(ElementInterface
$element = null)
83 return $this->render($element);
87 * Render a form <select> element from the provided $element
89 * @param ElementInterface $element
90 * @throws Exception\InvalidArgumentException
91 * @throws Exception\DomainException
94 public function render(ElementInterface
$element)
96 if (!$element instanceof SelectElement
) {
97 throw new Exception\
InvalidArgumentException(sprintf(
98 '%s requires that the element is of type Zend\Form\Element\Select',
103 $name = $element->getName();
104 if (empty($name) && $name !== 0) {
105 throw new Exception\
DomainException(sprintf(
106 '%s requires that the element has an assigned name; none discovered',
111 $options = $element->getValueOptions();
113 if (($emptyOption = $element->getEmptyOption()) !== null) {
114 $options = array('' => $emptyOption) +
$options;
117 $attributes = $element->getAttributes();
118 $value = $this->validateMultiValue($element->getValue(), $attributes);
120 $attributes['name'] = $name;
121 if (array_key_exists('multiple', $attributes) && $attributes['multiple']) {
122 $attributes['name'] .= '[]';
124 $this->validTagAttributes
= $this->validSelectAttributes
;
127 '<select %s>%s</select>',
128 $this->createAttributesString($attributes),
129 $this->renderOptions($options, $value)
134 * Render an array of options
136 * Individual options should be of the form:
140 * 'value' => 'value',
141 * 'label' => 'label',
142 * 'disabled' => $booleanFlag,
143 * 'selected' => $booleanFlag,
147 * @param array $options
148 * @param array $selectedOptions Option values that should be marked as selected
151 public function renderOptions(array $options, array $selectedOptions = array())
153 $template = '<option %s>%s</option>';
154 $optionStrings = array();
155 $escapeHtml = $this->getEscapeHtmlHelper();
157 foreach ($options as $key => $optionSpec) {
163 if (is_scalar($optionSpec)) {
165 'label' => $optionSpec,
170 if (isset($optionSpec['options']) && is_array($optionSpec['options'])) {
171 $optionStrings[] = $this->renderOptgroup($optionSpec, $selectedOptions);
175 if (isset($optionSpec['value'])) {
176 $value = $optionSpec['value'];
178 if (isset($optionSpec['label'])) {
179 $label = $optionSpec['label'];
181 if (isset($optionSpec['selected'])) {
182 $selected = $optionSpec['selected'];
184 if (isset($optionSpec['disabled'])) {
185 $disabled = $optionSpec['disabled'];
188 if (ArrayUtils
::inArray($value, $selectedOptions)) {
192 if (null !== ($translator = $this->getTranslator())) {
193 $label = $translator->translate(
194 $label, $this->getTranslatorTextDomain()
198 $attributes = compact('value', 'selected', 'disabled');
200 if (isset($optionSpec['attributes']) && is_array($optionSpec['attributes'])) {
201 $attributes = array_merge($attributes, $optionSpec['attributes']);
204 $this->validTagAttributes
= $this->validOptionAttributes
;
205 $optionStrings[] = sprintf(
207 $this->createAttributesString($attributes),
212 return implode("\n", $optionStrings);
218 * See {@link renderOptions()} for the options specification. Basically,
219 * an optgroup is simply an option that has an additional "options" key
220 * with an array following the specification for renderOptions().
222 * @param array $optgroup
223 * @param array $selectedOptions
226 public function renderOptgroup(array $optgroup, array $selectedOptions = array())
228 $template = '<optgroup%s>%s</optgroup>';
231 if (isset($optgroup['options']) && is_array($optgroup['options'])) {
232 $options = $optgroup['options'];
233 unset($optgroup['options']);
236 $this->validTagAttributes
= $this->validOptgroupAttributes
;
237 $attributes = $this->createAttributesString($optgroup);
238 if (!empty($attributes)) {
239 $attributes = ' ' . $attributes;
245 $this->renderOptions($options, $selectedOptions)
250 * Ensure that the value is set appropriately
252 * If the element's value attribute is an array, but there is no multiple
253 * attribute, or that attribute does not evaluate to true, then we have
254 * a domain issue -- you cannot have multiple options selected unless the
255 * multiple attribute is present and enabled.
257 * @param mixed $value
258 * @param array $attributes
260 * @throws Exception\DomainException
262 protected function validateMultiValue($value, array $attributes)
264 if (null === $value) {
268 if (!is_array($value)) {
269 return (array) $value;
272 if (!isset($attributes['multiple']) ||
!$attributes['multiple']) {
273 throw new Exception\
DomainException(sprintf(
274 '%s does not allow specifying multiple selected values when the element does not have a multiple attribute set to a boolean true',