|
1 <?php |
|
2 /** |
|
3 * Zend Framework |
|
4 * |
|
5 * LICENSE |
|
6 * |
|
7 * This source file is subject to the new BSD license that is bundled |
|
8 * with this package in the file LICENSE.txt. |
|
9 * It is also available through the world-wide-web at this URL: |
|
10 * http://framework.zend.com/license/new-bsd |
|
11 * If you did not receive a copy of the license and are unable to |
|
12 * obtain it through the world-wide-web, please send an email |
|
13 * to license@zend.com so we can send you a copy immediately. |
|
14 * |
|
15 * @category Zend |
|
16 * @package Zend_Form |
|
17 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) |
|
18 * @license http://framework.zend.com/license/new-bsd New BSD License |
|
19 */ |
|
20 |
|
21 /** @see Zend_Validate_Interface */ |
|
22 require_once 'Zend/Validate/Interface.php'; |
|
23 |
|
24 /** |
|
25 * Zend_Form |
|
26 * |
|
27 * @category Zend |
|
28 * @package Zend_Form |
|
29 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) |
|
30 * @license http://framework.zend.com/license/new-bsd New BSD License |
|
31 * @version $Id: Form.php 23429 2010-11-22 23:06:46Z bittarman $ |
|
32 */ |
|
33 class Zend_Form implements Iterator, Countable, Zend_Validate_Interface |
|
34 { |
|
35 /**#@+ |
|
36 * Plugin loader type constants |
|
37 */ |
|
38 const DECORATOR = 'DECORATOR'; |
|
39 const ELEMENT = 'ELEMENT'; |
|
40 /**#@-*/ |
|
41 |
|
42 /**#@+ |
|
43 * Method type constants |
|
44 */ |
|
45 const METHOD_DELETE = 'delete'; |
|
46 const METHOD_GET = 'get'; |
|
47 const METHOD_POST = 'post'; |
|
48 const METHOD_PUT = 'put'; |
|
49 /**#@-*/ |
|
50 |
|
51 /**#@+ |
|
52 * Encoding type constants |
|
53 */ |
|
54 const ENCTYPE_URLENCODED = 'application/x-www-form-urlencoded'; |
|
55 const ENCTYPE_MULTIPART = 'multipart/form-data'; |
|
56 /**#@-*/ |
|
57 |
|
58 /** |
|
59 * Form metadata and attributes |
|
60 * @var array |
|
61 */ |
|
62 protected $_attribs = array(); |
|
63 |
|
64 /** |
|
65 * Decorators for rendering |
|
66 * @var array |
|
67 */ |
|
68 protected $_decorators = array(); |
|
69 |
|
70 /** |
|
71 * Default display group class |
|
72 * @var string |
|
73 */ |
|
74 protected $_defaultDisplayGroupClass = 'Zend_Form_DisplayGroup'; |
|
75 |
|
76 /** |
|
77 * Form description |
|
78 * @var string |
|
79 */ |
|
80 protected $_description; |
|
81 |
|
82 /** |
|
83 * Should we disable loading the default decorators? |
|
84 * @var bool |
|
85 */ |
|
86 protected $_disableLoadDefaultDecorators = false; |
|
87 |
|
88 /** |
|
89 * Display group prefix paths |
|
90 * @var array |
|
91 */ |
|
92 protected $_displayGroupPrefixPaths = array(); |
|
93 |
|
94 /** |
|
95 * Groups of elements grouped for display purposes |
|
96 * @var array |
|
97 */ |
|
98 protected $_displayGroups = array(); |
|
99 |
|
100 /** |
|
101 * Global decorators to apply to all elements |
|
102 * @var null|array |
|
103 */ |
|
104 protected $_elementDecorators; |
|
105 |
|
106 /** |
|
107 * Prefix paths to use when creating elements |
|
108 * @var array |
|
109 */ |
|
110 protected $_elementPrefixPaths = array(); |
|
111 |
|
112 /** |
|
113 * Form elements |
|
114 * @var array |
|
115 */ |
|
116 protected $_elements = array(); |
|
117 |
|
118 /** |
|
119 * Array to which elements belong (if any) |
|
120 * @var string |
|
121 */ |
|
122 protected $_elementsBelongTo; |
|
123 |
|
124 /** |
|
125 * Custom form-level error messages |
|
126 * @var array |
|
127 */ |
|
128 protected $_errorMessages = array(); |
|
129 |
|
130 /** |
|
131 * Are there errors in the form? |
|
132 * @var bool |
|
133 */ |
|
134 protected $_errorsExist = false; |
|
135 |
|
136 /** |
|
137 * Has the form been manually flagged as an error? |
|
138 * @var bool |
|
139 */ |
|
140 protected $_errorsForced = false; |
|
141 |
|
142 /** |
|
143 * Form order |
|
144 * @var int|null |
|
145 */ |
|
146 protected $_formOrder; |
|
147 |
|
148 /** |
|
149 * Whether or not form elements are members of an array |
|
150 * @var bool |
|
151 */ |
|
152 protected $_isArray = false; |
|
153 |
|
154 /** |
|
155 * Form legend |
|
156 * @var string |
|
157 */ |
|
158 protected $_legend; |
|
159 |
|
160 /** |
|
161 * Plugin loaders |
|
162 * @var array |
|
163 */ |
|
164 protected $_loaders = array(); |
|
165 |
|
166 /** |
|
167 * Allowed form methods |
|
168 * @var array |
|
169 */ |
|
170 protected $_methods = array('delete', 'get', 'post', 'put'); |
|
171 |
|
172 /** |
|
173 * Order in which to display and iterate elements |
|
174 * @var array |
|
175 */ |
|
176 protected $_order = array(); |
|
177 |
|
178 /** |
|
179 * Whether internal order has been updated or not |
|
180 * @var bool |
|
181 */ |
|
182 protected $_orderUpdated = false; |
|
183 |
|
184 /** |
|
185 * Sub form prefix paths |
|
186 * @var array |
|
187 */ |
|
188 protected $_subFormPrefixPaths = array(); |
|
189 |
|
190 /** |
|
191 * Sub forms |
|
192 * @var array |
|
193 */ |
|
194 protected $_subForms = array(); |
|
195 |
|
196 /** |
|
197 * @var Zend_Translate |
|
198 */ |
|
199 protected $_translator; |
|
200 |
|
201 /** |
|
202 * Global default translation adapter |
|
203 * @var Zend_Translate |
|
204 */ |
|
205 protected static $_translatorDefault; |
|
206 |
|
207 /** |
|
208 * is the translator disabled? |
|
209 * @var bool |
|
210 */ |
|
211 protected $_translatorDisabled = false; |
|
212 |
|
213 /** |
|
214 * @var Zend_View_Interface |
|
215 */ |
|
216 protected $_view; |
|
217 |
|
218 /** |
|
219 * @var bool |
|
220 */ |
|
221 protected $_isRendered = false; |
|
222 |
|
223 /** |
|
224 * Constructor |
|
225 * |
|
226 * Registers form view helper as decorator |
|
227 * |
|
228 * @param mixed $options |
|
229 * @return void |
|
230 */ |
|
231 public function __construct($options = null) |
|
232 { |
|
233 if (is_array($options)) { |
|
234 $this->setOptions($options); |
|
235 } elseif ($options instanceof Zend_Config) { |
|
236 $this->setConfig($options); |
|
237 } |
|
238 |
|
239 // Extensions... |
|
240 $this->init(); |
|
241 |
|
242 $this->loadDefaultDecorators(); |
|
243 } |
|
244 |
|
245 /** |
|
246 * Clone form object and all children |
|
247 * |
|
248 * @return void |
|
249 */ |
|
250 public function __clone() |
|
251 { |
|
252 $elements = array(); |
|
253 foreach ($this->getElements() as $name => $element) { |
|
254 $elements[] = clone $element; |
|
255 } |
|
256 $this->setElements($elements); |
|
257 |
|
258 $subForms = array(); |
|
259 foreach ($this->getSubForms() as $name => $subForm) { |
|
260 $subForms[$name] = clone $subForm; |
|
261 } |
|
262 $this->setSubForms($subForms); |
|
263 |
|
264 $displayGroups = array(); |
|
265 foreach ($this->_displayGroups as $group) { |
|
266 $clone = clone $group; |
|
267 $elements = array(); |
|
268 foreach ($clone->getElements() as $name => $e) { |
|
269 $elements[] = $this->getElement($name); |
|
270 } |
|
271 $clone->setElements($elements); |
|
272 $displayGroups[] = $clone; |
|
273 } |
|
274 $this->setDisplayGroups($displayGroups); |
|
275 } |
|
276 |
|
277 /** |
|
278 * Reset values of form |
|
279 * |
|
280 * @return Zend_Form |
|
281 */ |
|
282 public function reset() |
|
283 { |
|
284 foreach ($this->getElements() as $element) { |
|
285 $element->setValue(null); |
|
286 } |
|
287 foreach ($this->getSubForms() as $subForm) { |
|
288 $subForm->reset(); |
|
289 } |
|
290 |
|
291 return $this; |
|
292 } |
|
293 |
|
294 /** |
|
295 * Initialize form (used by extending classes) |
|
296 * |
|
297 * @return void |
|
298 */ |
|
299 public function init() |
|
300 { |
|
301 } |
|
302 |
|
303 /** |
|
304 * Set form state from options array |
|
305 * |
|
306 * @param array $options |
|
307 * @return Zend_Form |
|
308 */ |
|
309 public function setOptions(array $options) |
|
310 { |
|
311 if (isset($options['prefixPath'])) { |
|
312 $this->addPrefixPaths($options['prefixPath']); |
|
313 unset($options['prefixPath']); |
|
314 } |
|
315 |
|
316 if (isset($options['elementPrefixPath'])) { |
|
317 $this->addElementPrefixPaths($options['elementPrefixPath']); |
|
318 unset($options['elementPrefixPath']); |
|
319 } |
|
320 |
|
321 if (isset($options['displayGroupPrefixPath'])) { |
|
322 $this->addDisplayGroupPrefixPaths($options['displayGroupPrefixPath']); |
|
323 unset($options['displayGroupPrefixPath']); |
|
324 } |
|
325 |
|
326 if (isset($options['elementDecorators'])) { |
|
327 $this->_elementDecorators = $options['elementDecorators']; |
|
328 unset($options['elementDecorators']); |
|
329 } |
|
330 |
|
331 if (isset($options['elements'])) { |
|
332 $this->setElements($options['elements']); |
|
333 unset($options['elements']); |
|
334 } |
|
335 |
|
336 if (isset($options['defaultDisplayGroupClass'])) { |
|
337 $this->setDefaultDisplayGroupClass($options['defaultDisplayGroupClass']); |
|
338 unset($options['defaultDisplayGroupClass']); |
|
339 } |
|
340 |
|
341 if (isset($options['displayGroupDecorators'])) { |
|
342 $displayGroupDecorators = $options['displayGroupDecorators']; |
|
343 unset($options['displayGroupDecorators']); |
|
344 } |
|
345 |
|
346 if (isset($options['elementsBelongTo'])) { |
|
347 $elementsBelongTo = $options['elementsBelongTo']; |
|
348 unset($options['elementsBelongTo']); |
|
349 } |
|
350 |
|
351 if (isset($options['attribs'])) { |
|
352 $this->addAttribs($options['attribs']); |
|
353 unset($options['attribs']); |
|
354 } |
|
355 |
|
356 $forbidden = array( |
|
357 'Options', 'Config', 'PluginLoader', 'SubForms', 'Translator', |
|
358 'Attrib', 'Default', |
|
359 ); |
|
360 |
|
361 foreach ($options as $key => $value) { |
|
362 $normalized = ucfirst($key); |
|
363 if (in_array($normalized, $forbidden)) { |
|
364 continue; |
|
365 } |
|
366 |
|
367 $method = 'set' . $normalized; |
|
368 if (method_exists($this, $method)) { |
|
369 if($normalized == 'View' && !($value instanceof Zend_View_Interface)) { |
|
370 continue; |
|
371 } |
|
372 $this->$method($value); |
|
373 } else { |
|
374 $this->setAttrib($key, $value); |
|
375 } |
|
376 } |
|
377 |
|
378 if (isset($displayGroupDecorators)) { |
|
379 $this->setDisplayGroupDecorators($displayGroupDecorators); |
|
380 } |
|
381 |
|
382 if (isset($elementsBelongTo)) { |
|
383 $this->setElementsBelongTo($elementsBelongTo); |
|
384 } |
|
385 |
|
386 return $this; |
|
387 } |
|
388 |
|
389 /** |
|
390 * Set form state from config object |
|
391 * |
|
392 * @param Zend_Config $config |
|
393 * @return Zend_Form |
|
394 */ |
|
395 public function setConfig(Zend_Config $config) |
|
396 { |
|
397 return $this->setOptions($config->toArray()); |
|
398 } |
|
399 |
|
400 |
|
401 // Loaders |
|
402 |
|
403 /** |
|
404 * Set plugin loaders for use with decorators and elements |
|
405 * |
|
406 * @param Zend_Loader_PluginLoader_Interface $loader |
|
407 * @param string $type 'decorator' or 'element' |
|
408 * @return Zend_Form |
|
409 * @throws Zend_Form_Exception on invalid type |
|
410 */ |
|
411 public function setPluginLoader(Zend_Loader_PluginLoader_Interface $loader, $type = null) |
|
412 { |
|
413 $type = strtoupper($type); |
|
414 switch ($type) { |
|
415 case self::DECORATOR: |
|
416 case self::ELEMENT: |
|
417 $this->_loaders[$type] = $loader; |
|
418 return $this; |
|
419 default: |
|
420 require_once 'Zend/Form/Exception.php'; |
|
421 throw new Zend_Form_Exception(sprintf('Invalid type "%s" provided to setPluginLoader()', $type)); |
|
422 } |
|
423 } |
|
424 |
|
425 /** |
|
426 * Retrieve plugin loader for given type |
|
427 * |
|
428 * $type may be one of: |
|
429 * - decorator |
|
430 * - element |
|
431 * |
|
432 * If a plugin loader does not exist for the given type, defaults are |
|
433 * created. |
|
434 * |
|
435 * @param string $type |
|
436 * @return Zend_Loader_PluginLoader_Interface |
|
437 */ |
|
438 public function getPluginLoader($type = null) |
|
439 { |
|
440 $type = strtoupper($type); |
|
441 if (!isset($this->_loaders[$type])) { |
|
442 switch ($type) { |
|
443 case self::DECORATOR: |
|
444 $prefixSegment = 'Form_Decorator'; |
|
445 $pathSegment = 'Form/Decorator'; |
|
446 break; |
|
447 case self::ELEMENT: |
|
448 $prefixSegment = 'Form_Element'; |
|
449 $pathSegment = 'Form/Element'; |
|
450 break; |
|
451 default: |
|
452 require_once 'Zend/Form/Exception.php'; |
|
453 throw new Zend_Form_Exception(sprintf('Invalid type "%s" provided to getPluginLoader()', $type)); |
|
454 } |
|
455 |
|
456 require_once 'Zend/Loader/PluginLoader.php'; |
|
457 $this->_loaders[$type] = new Zend_Loader_PluginLoader( |
|
458 array('Zend_' . $prefixSegment . '_' => 'Zend/' . $pathSegment . '/') |
|
459 ); |
|
460 } |
|
461 |
|
462 return $this->_loaders[$type]; |
|
463 } |
|
464 |
|
465 /** |
|
466 * Add prefix path for plugin loader |
|
467 * |
|
468 * If no $type specified, assumes it is a base path for both filters and |
|
469 * validators, and sets each according to the following rules: |
|
470 * - decorators: $prefix = $prefix . '_Decorator' |
|
471 * - elements: $prefix = $prefix . '_Element' |
|
472 * |
|
473 * Otherwise, the path prefix is set on the appropriate plugin loader. |
|
474 * |
|
475 * If $type is 'decorator', sets the path in the decorator plugin loader |
|
476 * for all elements. Additionally, if no $type is provided, |
|
477 * the prefix and path is added to both decorator and element |
|
478 * plugin loader with following settings: |
|
479 * $prefix . '_Decorator', $path . '/Decorator/' |
|
480 * $prefix . '_Element', $path . '/Element/' |
|
481 * |
|
482 * @param string $prefix |
|
483 * @param string $path |
|
484 * @param string $type |
|
485 * @return Zend_Form |
|
486 * @throws Zend_Form_Exception for invalid type |
|
487 */ |
|
488 public function addPrefixPath($prefix, $path, $type = null) |
|
489 { |
|
490 $type = strtoupper($type); |
|
491 switch ($type) { |
|
492 case self::DECORATOR: |
|
493 case self::ELEMENT: |
|
494 $loader = $this->getPluginLoader($type); |
|
495 $loader->addPrefixPath($prefix, $path); |
|
496 return $this; |
|
497 case null: |
|
498 $prefix = rtrim($prefix, '_'); |
|
499 $path = rtrim($path, DIRECTORY_SEPARATOR); |
|
500 foreach (array(self::DECORATOR, self::ELEMENT) as $type) { |
|
501 $cType = ucfirst(strtolower($type)); |
|
502 $pluginPath = $path . DIRECTORY_SEPARATOR . $cType . DIRECTORY_SEPARATOR; |
|
503 $pluginPrefix = $prefix . '_' . $cType; |
|
504 $loader = $this->getPluginLoader($type); |
|
505 $loader->addPrefixPath($pluginPrefix, $pluginPath); |
|
506 } |
|
507 return $this; |
|
508 default: |
|
509 require_once 'Zend/Form/Exception.php'; |
|
510 throw new Zend_Form_Exception(sprintf('Invalid type "%s" provided to getPluginLoader()', $type)); |
|
511 } |
|
512 } |
|
513 |
|
514 /** |
|
515 * Add many prefix paths at once |
|
516 * |
|
517 * @param array $spec |
|
518 * @return Zend_Form |
|
519 */ |
|
520 public function addPrefixPaths(array $spec) |
|
521 { |
|
522 if (isset($spec['prefix']) && isset($spec['path'])) { |
|
523 return $this->addPrefixPath($spec['prefix'], $spec['path']); |
|
524 } |
|
525 foreach ($spec as $type => $paths) { |
|
526 if (is_numeric($type) && is_array($paths)) { |
|
527 $type = null; |
|
528 if (isset($paths['prefix']) && isset($paths['path'])) { |
|
529 if (isset($paths['type'])) { |
|
530 $type = $paths['type']; |
|
531 } |
|
532 $this->addPrefixPath($paths['prefix'], $paths['path'], $type); |
|
533 } |
|
534 } elseif (!is_numeric($type)) { |
|
535 if (!isset($paths['prefix']) || !isset($paths['path'])) { |
|
536 continue; |
|
537 } |
|
538 $this->addPrefixPath($paths['prefix'], $paths['path'], $type); |
|
539 } |
|
540 } |
|
541 return $this; |
|
542 } |
|
543 |
|
544 /** |
|
545 * Add prefix path for all elements |
|
546 * |
|
547 * @param string $prefix |
|
548 * @param string $path |
|
549 * @param string $type |
|
550 * @return Zend_Form |
|
551 */ |
|
552 public function addElementPrefixPath($prefix, $path, $type = null) |
|
553 { |
|
554 $this->_elementPrefixPaths[] = array( |
|
555 'prefix' => $prefix, |
|
556 'path' => $path, |
|
557 'type' => $type, |
|
558 ); |
|
559 |
|
560 foreach ($this->getElements() as $element) { |
|
561 $element->addPrefixPath($prefix, $path, $type); |
|
562 } |
|
563 |
|
564 foreach ($this->getSubForms() as $subForm) { |
|
565 $subForm->addElementPrefixPath($prefix, $path, $type); |
|
566 } |
|
567 |
|
568 return $this; |
|
569 } |
|
570 |
|
571 /** |
|
572 * Add prefix paths for all elements |
|
573 * |
|
574 * @param array $spec |
|
575 * @return Zend_Form |
|
576 */ |
|
577 public function addElementPrefixPaths(array $spec) |
|
578 { |
|
579 $this->_elementPrefixPaths = $this->_elementPrefixPaths + $spec; |
|
580 |
|
581 foreach ($this->getElements() as $element) { |
|
582 $element->addPrefixPaths($spec); |
|
583 } |
|
584 |
|
585 return $this; |
|
586 } |
|
587 |
|
588 /** |
|
589 * Add prefix path for all display groups |
|
590 * |
|
591 * @param string $prefix |
|
592 * @param string $path |
|
593 * @return Zend_Form |
|
594 */ |
|
595 public function addDisplayGroupPrefixPath($prefix, $path) |
|
596 { |
|
597 $this->_displayGroupPrefixPaths[] = array( |
|
598 'prefix' => $prefix, |
|
599 'path' => $path, |
|
600 ); |
|
601 |
|
602 foreach ($this->getDisplayGroups() as $group) { |
|
603 $group->addPrefixPath($prefix, $path); |
|
604 } |
|
605 |
|
606 return $this; |
|
607 } |
|
608 |
|
609 /** |
|
610 * Add multiple display group prefix paths at once |
|
611 * |
|
612 * @param array $spec |
|
613 * @return Zend_Form |
|
614 */ |
|
615 public function addDisplayGroupPrefixPaths(array $spec) |
|
616 { |
|
617 foreach ($spec as $key => $value) { |
|
618 if (is_string($value) && !is_numeric($key)) { |
|
619 $this->addDisplayGroupPrefixPath($key, $value); |
|
620 continue; |
|
621 } |
|
622 |
|
623 if (is_string($value) && is_numeric($key)) { |
|
624 continue; |
|
625 } |
|
626 |
|
627 if (is_array($value)) { |
|
628 $count = count($value); |
|
629 if (array_keys($value) === range(0, $count - 1)) { |
|
630 if ($count < 2) { |
|
631 continue; |
|
632 } |
|
633 $prefix = array_shift($value); |
|
634 $path = array_shift($value); |
|
635 $this->addDisplayGroupPrefixPath($prefix, $path); |
|
636 continue; |
|
637 } |
|
638 if (array_key_exists('prefix', $value) && array_key_exists('path', $value)) { |
|
639 $this->addDisplayGroupPrefixPath($value['prefix'], $value['path']); |
|
640 } |
|
641 } |
|
642 } |
|
643 return $this; |
|
644 } |
|
645 |
|
646 // Form metadata: |
|
647 |
|
648 /** |
|
649 * Set form attribute |
|
650 * |
|
651 * @param string $key |
|
652 * @param mixed $value |
|
653 * @return Zend_Form |
|
654 */ |
|
655 public function setAttrib($key, $value) |
|
656 { |
|
657 $key = (string) $key; |
|
658 $this->_attribs[$key] = $value; |
|
659 return $this; |
|
660 } |
|
661 |
|
662 /** |
|
663 * Add multiple form attributes at once |
|
664 * |
|
665 * @param array $attribs |
|
666 * @return Zend_Form |
|
667 */ |
|
668 public function addAttribs(array $attribs) |
|
669 { |
|
670 foreach ($attribs as $key => $value) { |
|
671 $this->setAttrib($key, $value); |
|
672 } |
|
673 return $this; |
|
674 } |
|
675 |
|
676 /** |
|
677 * Set multiple form attributes at once |
|
678 * |
|
679 * Overwrites any previously set attributes. |
|
680 * |
|
681 * @param array $attribs |
|
682 * @return Zend_Form |
|
683 */ |
|
684 public function setAttribs(array $attribs) |
|
685 { |
|
686 $this->clearAttribs(); |
|
687 return $this->addAttribs($attribs); |
|
688 } |
|
689 |
|
690 /** |
|
691 * Retrieve a single form attribute |
|
692 * |
|
693 * @param string $key |
|
694 * @return mixed |
|
695 */ |
|
696 public function getAttrib($key) |
|
697 { |
|
698 $key = (string) $key; |
|
699 if (!isset($this->_attribs[$key])) { |
|
700 return null; |
|
701 } |
|
702 |
|
703 return $this->_attribs[$key]; |
|
704 } |
|
705 |
|
706 /** |
|
707 * Retrieve all form attributes/metadata |
|
708 * |
|
709 * @return array |
|
710 */ |
|
711 public function getAttribs() |
|
712 { |
|
713 return $this->_attribs; |
|
714 } |
|
715 |
|
716 /** |
|
717 * Remove attribute |
|
718 * |
|
719 * @param string $key |
|
720 * @return bool |
|
721 */ |
|
722 public function removeAttrib($key) |
|
723 { |
|
724 if (isset($this->_attribs[$key])) { |
|
725 unset($this->_attribs[$key]); |
|
726 return true; |
|
727 } |
|
728 |
|
729 return false; |
|
730 } |
|
731 |
|
732 /** |
|
733 * Clear all form attributes |
|
734 * |
|
735 * @return Zend_Form |
|
736 */ |
|
737 public function clearAttribs() |
|
738 { |
|
739 $this->_attribs = array(); |
|
740 return $this; |
|
741 } |
|
742 |
|
743 /** |
|
744 * Set form action |
|
745 * |
|
746 * @param string $action |
|
747 * @return Zend_Form |
|
748 */ |
|
749 public function setAction($action) |
|
750 { |
|
751 return $this->setAttrib('action', (string) $action); |
|
752 } |
|
753 |
|
754 /** |
|
755 * Get form action |
|
756 * |
|
757 * Sets default to '' if not set. |
|
758 * |
|
759 * @return string |
|
760 */ |
|
761 public function getAction() |
|
762 { |
|
763 $action = $this->getAttrib('action'); |
|
764 if (null === $action) { |
|
765 $action = ''; |
|
766 $this->setAction($action); |
|
767 } |
|
768 return $action; |
|
769 } |
|
770 |
|
771 /** |
|
772 * Set form method |
|
773 * |
|
774 * Only values in {@link $_methods()} allowed |
|
775 * |
|
776 * @param string $method |
|
777 * @return Zend_Form |
|
778 * @throws Zend_Form_Exception |
|
779 */ |
|
780 public function setMethod($method) |
|
781 { |
|
782 $method = strtolower($method); |
|
783 if (!in_array($method, $this->_methods)) { |
|
784 require_once 'Zend/Form/Exception.php'; |
|
785 throw new Zend_Form_Exception(sprintf('"%s" is an invalid form method', $method)); |
|
786 } |
|
787 $this->setAttrib('method', $method); |
|
788 return $this; |
|
789 } |
|
790 |
|
791 /** |
|
792 * Retrieve form method |
|
793 * |
|
794 * @return string |
|
795 */ |
|
796 public function getMethod() |
|
797 { |
|
798 if (null === ($method = $this->getAttrib('method'))) { |
|
799 $method = self::METHOD_POST; |
|
800 $this->setAttrib('method', $method); |
|
801 } |
|
802 return strtolower($method); |
|
803 } |
|
804 |
|
805 /** |
|
806 * Set encoding type |
|
807 * |
|
808 * @param string $value |
|
809 * @return Zend_Form |
|
810 */ |
|
811 public function setEnctype($value) |
|
812 { |
|
813 $this->setAttrib('enctype', $value); |
|
814 return $this; |
|
815 } |
|
816 |
|
817 /** |
|
818 * Get encoding type |
|
819 * |
|
820 * @return string |
|
821 */ |
|
822 public function getEnctype() |
|
823 { |
|
824 if (null === ($enctype = $this->getAttrib('enctype'))) { |
|
825 $enctype = self::ENCTYPE_URLENCODED; |
|
826 $this->setAttrib('enctype', $enctype); |
|
827 } |
|
828 return $this->getAttrib('enctype'); |
|
829 } |
|
830 |
|
831 /** |
|
832 * Filter a name to only allow valid variable characters |
|
833 * |
|
834 * @param string $value |
|
835 * @param bool $allowBrackets |
|
836 * @return string |
|
837 */ |
|
838 public function filterName($value, $allowBrackets = false) |
|
839 { |
|
840 $charset = '^a-zA-Z0-9_\x7f-\xff'; |
|
841 if ($allowBrackets) { |
|
842 $charset .= '\[\]'; |
|
843 } |
|
844 return preg_replace('/[' . $charset . ']/', '', (string) $value); |
|
845 } |
|
846 |
|
847 /** |
|
848 * Set form name |
|
849 * |
|
850 * @param string $name |
|
851 * @return Zend_Form |
|
852 */ |
|
853 public function setName($name) |
|
854 { |
|
855 $name = $this->filterName($name); |
|
856 if ('' === (string)$name) { |
|
857 require_once 'Zend/Form/Exception.php'; |
|
858 throw new Zend_Form_Exception('Invalid name provided; must contain only valid variable characters and be non-empty'); |
|
859 } |
|
860 |
|
861 return $this->setAttrib('name', $name); |
|
862 } |
|
863 |
|
864 /** |
|
865 * Get name attribute |
|
866 * |
|
867 * @return null|string |
|
868 */ |
|
869 public function getName() |
|
870 { |
|
871 return $this->getAttrib('name'); |
|
872 } |
|
873 |
|
874 /** |
|
875 * Get fully qualified name |
|
876 * |
|
877 * Places name as subitem of array and/or appends brackets. |
|
878 * |
|
879 * @return string |
|
880 */ |
|
881 public function getFullyQualifiedName() |
|
882 { |
|
883 return $this->getName(); |
|
884 } |
|
885 |
|
886 /** |
|
887 * Get element id |
|
888 * |
|
889 * @return string |
|
890 */ |
|
891 public function getId() |
|
892 { |
|
893 if (null !== ($id = $this->getAttrib('id'))) { |
|
894 return $id; |
|
895 } |
|
896 |
|
897 $id = $this->getFullyQualifiedName(); |
|
898 |
|
899 // Bail early if no array notation detected |
|
900 if (!strstr($id, '[')) { |
|
901 return $id; |
|
902 } |
|
903 |
|
904 // Strip array notation |
|
905 if ('[]' == substr($id, -2)) { |
|
906 $id = substr($id, 0, strlen($id) - 2); |
|
907 } |
|
908 $id = str_replace('][', '-', $id); |
|
909 $id = str_replace(array(']', '['), '-', $id); |
|
910 $id = trim($id, '-'); |
|
911 |
|
912 return $id; |
|
913 } |
|
914 |
|
915 /** |
|
916 * Set form legend |
|
917 * |
|
918 * @param string $value |
|
919 * @return Zend_Form |
|
920 */ |
|
921 public function setLegend($value) |
|
922 { |
|
923 $this->_legend = (string) $value; |
|
924 return $this; |
|
925 } |
|
926 |
|
927 /** |
|
928 * Get form legend |
|
929 * |
|
930 * @return string |
|
931 */ |
|
932 public function getLegend() |
|
933 { |
|
934 return $this->_legend; |
|
935 } |
|
936 |
|
937 /** |
|
938 * Set form description |
|
939 * |
|
940 * @param string $value |
|
941 * @return Zend_Form |
|
942 */ |
|
943 public function setDescription($value) |
|
944 { |
|
945 $this->_description = (string) $value; |
|
946 return $this; |
|
947 } |
|
948 |
|
949 /** |
|
950 * Retrieve form description |
|
951 * |
|
952 * @return string |
|
953 */ |
|
954 public function getDescription() |
|
955 { |
|
956 return $this->_description; |
|
957 } |
|
958 |
|
959 /** |
|
960 * Set form order |
|
961 * |
|
962 * @param int $index |
|
963 * @return Zend_Form |
|
964 */ |
|
965 public function setOrder($index) |
|
966 { |
|
967 $this->_formOrder = (int) $index; |
|
968 return $this; |
|
969 } |
|
970 |
|
971 /** |
|
972 * Get form order |
|
973 * |
|
974 * @return int|null |
|
975 */ |
|
976 public function getOrder() |
|
977 { |
|
978 return $this->_formOrder; |
|
979 } |
|
980 |
|
981 /** |
|
982 * When calling renderFormElements or render this method |
|
983 * is used to set $_isRendered member to prevent repeatedly |
|
984 * merging belongsTo setting |
|
985 */ |
|
986 protected function _setIsRendered() |
|
987 { |
|
988 $this->_isRendered = true; |
|
989 return $this; |
|
990 } |
|
991 |
|
992 /** |
|
993 * Get the value of $_isRendered member |
|
994 */ |
|
995 protected function _getIsRendered() |
|
996 { |
|
997 return (bool)$this->_isRendered; |
|
998 } |
|
999 |
|
1000 // Element interaction: |
|
1001 |
|
1002 /** |
|
1003 * Add a new element |
|
1004 * |
|
1005 * $element may be either a string element type, or an object of type |
|
1006 * Zend_Form_Element. If a string element type is provided, $name must be |
|
1007 * provided, and $options may be optionally provided for configuring the |
|
1008 * element. |
|
1009 * |
|
1010 * If a Zend_Form_Element is provided, $name may be optionally provided, |
|
1011 * and any provided $options will be ignored. |
|
1012 * |
|
1013 * @param string|Zend_Form_Element $element |
|
1014 * @param string $name |
|
1015 * @param array|Zend_Config $options |
|
1016 * @return Zend_Form |
|
1017 */ |
|
1018 public function addElement($element, $name = null, $options = null) |
|
1019 { |
|
1020 if (is_string($element)) { |
|
1021 if (null === $name) { |
|
1022 require_once 'Zend/Form/Exception.php'; |
|
1023 throw new Zend_Form_Exception('Elements specified by string must have an accompanying name'); |
|
1024 } |
|
1025 |
|
1026 if (is_array($this->_elementDecorators)) { |
|
1027 if (null === $options) { |
|
1028 $options = array('decorators' => $this->_elementDecorators); |
|
1029 } elseif ($options instanceof Zend_Config) { |
|
1030 $options = $options->toArray(); |
|
1031 } |
|
1032 if (is_array($options) |
|
1033 && !array_key_exists('decorators', $options) |
|
1034 ) { |
|
1035 $options['decorators'] = $this->_elementDecorators; |
|
1036 } |
|
1037 } |
|
1038 |
|
1039 $this->_elements[$name] = $this->createElement($element, $name, $options); |
|
1040 } elseif ($element instanceof Zend_Form_Element) { |
|
1041 $prefixPaths = array(); |
|
1042 $prefixPaths['decorator'] = $this->getPluginLoader('decorator')->getPaths(); |
|
1043 if (!empty($this->_elementPrefixPaths)) { |
|
1044 $prefixPaths = array_merge($prefixPaths, $this->_elementPrefixPaths); |
|
1045 } |
|
1046 |
|
1047 if (null === $name) { |
|
1048 $name = $element->getName(); |
|
1049 } |
|
1050 |
|
1051 $this->_elements[$name] = $element; |
|
1052 $this->_elements[$name]->addPrefixPaths($prefixPaths); |
|
1053 } |
|
1054 |
|
1055 $this->_order[$name] = $this->_elements[$name]->getOrder(); |
|
1056 $this->_orderUpdated = true; |
|
1057 $this->_setElementsBelongTo($name); |
|
1058 |
|
1059 return $this; |
|
1060 } |
|
1061 |
|
1062 /** |
|
1063 * Create an element |
|
1064 * |
|
1065 * Acts as a factory for creating elements. Elements created with this |
|
1066 * method will not be attached to the form, but will contain element |
|
1067 * settings as specified in the form object (including plugin loader |
|
1068 * prefix paths, default decorators, etc.). |
|
1069 * |
|
1070 * @param string $type |
|
1071 * @param string $name |
|
1072 * @param array|Zend_Config $options |
|
1073 * @return Zend_Form_Element |
|
1074 */ |
|
1075 public function createElement($type, $name, $options = null) |
|
1076 { |
|
1077 if (!is_string($type)) { |
|
1078 require_once 'Zend/Form/Exception.php'; |
|
1079 throw new Zend_Form_Exception('Element type must be a string indicating type'); |
|
1080 } |
|
1081 |
|
1082 if (!is_string($name)) { |
|
1083 require_once 'Zend/Form/Exception.php'; |
|
1084 throw new Zend_Form_Exception('Element name must be a string'); |
|
1085 } |
|
1086 |
|
1087 $prefixPaths = array(); |
|
1088 $prefixPaths['decorator'] = $this->getPluginLoader('decorator')->getPaths(); |
|
1089 if (!empty($this->_elementPrefixPaths)) { |
|
1090 $prefixPaths = array_merge($prefixPaths, $this->_elementPrefixPaths); |
|
1091 } |
|
1092 |
|
1093 if ($options instanceof Zend_Config) { |
|
1094 $options = $options->toArray(); |
|
1095 } |
|
1096 |
|
1097 if ((null === $options) || !is_array($options)) { |
|
1098 $options = array('prefixPath' => $prefixPaths); |
|
1099 } elseif (is_array($options)) { |
|
1100 if (array_key_exists('prefixPath', $options)) { |
|
1101 $options['prefixPath'] = array_merge($prefixPaths, $options['prefixPath']); |
|
1102 } else { |
|
1103 $options['prefixPath'] = $prefixPaths; |
|
1104 } |
|
1105 } |
|
1106 |
|
1107 $class = $this->getPluginLoader(self::ELEMENT)->load($type); |
|
1108 $element = new $class($name, $options); |
|
1109 |
|
1110 return $element; |
|
1111 } |
|
1112 |
|
1113 /** |
|
1114 * Add multiple elements at once |
|
1115 * |
|
1116 * @param array $elements |
|
1117 * @return Zend_Form |
|
1118 */ |
|
1119 public function addElements(array $elements) |
|
1120 { |
|
1121 foreach ($elements as $key => $spec) { |
|
1122 $name = null; |
|
1123 if (!is_numeric($key)) { |
|
1124 $name = $key; |
|
1125 } |
|
1126 |
|
1127 if (is_string($spec) || ($spec instanceof Zend_Form_Element)) { |
|
1128 $this->addElement($spec, $name); |
|
1129 continue; |
|
1130 } |
|
1131 |
|
1132 if (is_array($spec)) { |
|
1133 $argc = count($spec); |
|
1134 $options = array(); |
|
1135 if (isset($spec['type'])) { |
|
1136 $type = $spec['type']; |
|
1137 if (isset($spec['name'])) { |
|
1138 $name = $spec['name']; |
|
1139 } |
|
1140 if (isset($spec['options'])) { |
|
1141 $options = $spec['options']; |
|
1142 } |
|
1143 $this->addElement($type, $name, $options); |
|
1144 } else { |
|
1145 switch ($argc) { |
|
1146 case 0: |
|
1147 continue; |
|
1148 case (1 <= $argc): |
|
1149 $type = array_shift($spec); |
|
1150 case (2 <= $argc): |
|
1151 if (null === $name) { |
|
1152 $name = array_shift($spec); |
|
1153 } else { |
|
1154 $options = array_shift($spec); |
|
1155 } |
|
1156 case (3 <= $argc): |
|
1157 if (empty($options)) { |
|
1158 $options = array_shift($spec); |
|
1159 } |
|
1160 default: |
|
1161 $this->addElement($type, $name, $options); |
|
1162 } |
|
1163 } |
|
1164 } |
|
1165 } |
|
1166 return $this; |
|
1167 } |
|
1168 |
|
1169 /** |
|
1170 * Set form elements (overwrites existing elements) |
|
1171 * |
|
1172 * @param array $elements |
|
1173 * @return Zend_Form |
|
1174 */ |
|
1175 public function setElements(array $elements) |
|
1176 { |
|
1177 $this->clearElements(); |
|
1178 return $this->addElements($elements); |
|
1179 } |
|
1180 |
|
1181 /** |
|
1182 * Retrieve a single element |
|
1183 * |
|
1184 * @param string $name |
|
1185 * @return Zend_Form_Element|null |
|
1186 */ |
|
1187 public function getElement($name) |
|
1188 { |
|
1189 if (array_key_exists($name, $this->_elements)) { |
|
1190 return $this->_elements[$name]; |
|
1191 } |
|
1192 return null; |
|
1193 } |
|
1194 |
|
1195 /** |
|
1196 * Retrieve all elements |
|
1197 * |
|
1198 * @return array |
|
1199 */ |
|
1200 public function getElements() |
|
1201 { |
|
1202 return $this->_elements; |
|
1203 } |
|
1204 |
|
1205 /** |
|
1206 * Remove element |
|
1207 * |
|
1208 * @param string $name |
|
1209 * @return boolean |
|
1210 */ |
|
1211 public function removeElement($name) |
|
1212 { |
|
1213 $name = (string) $name; |
|
1214 if (isset($this->_elements[$name])) { |
|
1215 unset($this->_elements[$name]); |
|
1216 if (array_key_exists($name, $this->_order)) { |
|
1217 unset($this->_order[$name]); |
|
1218 $this->_orderUpdated = true; |
|
1219 } else { |
|
1220 foreach ($this->_displayGroups as $group) { |
|
1221 if (null !== $group->getElement($name)) { |
|
1222 $group->removeElement($name); |
|
1223 } |
|
1224 } |
|
1225 } |
|
1226 return true; |
|
1227 } |
|
1228 |
|
1229 return false; |
|
1230 } |
|
1231 |
|
1232 /** |
|
1233 * Remove all form elements |
|
1234 * |
|
1235 * @return Zend_Form |
|
1236 */ |
|
1237 public function clearElements() |
|
1238 { |
|
1239 foreach (array_keys($this->_elements) as $key) { |
|
1240 if (array_key_exists($key, $this->_order)) { |
|
1241 unset($this->_order[$key]); |
|
1242 } |
|
1243 } |
|
1244 $this->_elements = array(); |
|
1245 $this->_orderUpdated = true; |
|
1246 return $this; |
|
1247 } |
|
1248 |
|
1249 /** |
|
1250 * Set default values for elements |
|
1251 * |
|
1252 * Sets values for all elements specified in the array of $defaults. |
|
1253 * |
|
1254 * @param array $defaults |
|
1255 * @return Zend_Form |
|
1256 */ |
|
1257 public function setDefaults(array $defaults) |
|
1258 { |
|
1259 $eBelongTo = null; |
|
1260 |
|
1261 if ($this->isArray()) { |
|
1262 $eBelongTo = $this->getElementsBelongTo(); |
|
1263 $defaults = $this->_dissolveArrayValue($defaults, $eBelongTo); |
|
1264 } |
|
1265 foreach ($this->getElements() as $name => $element) { |
|
1266 $check = $defaults; |
|
1267 if (($belongsTo = $element->getBelongsTo()) !== $eBelongTo) { |
|
1268 $check = $this->_dissolveArrayValue($defaults, $belongsTo); |
|
1269 } |
|
1270 if (array_key_exists($name, $check)) { |
|
1271 $this->setDefault($name, $check[$name]); |
|
1272 $defaults = $this->_dissolveArrayUnsetKey($defaults, $belongsTo, $name); |
|
1273 } |
|
1274 } |
|
1275 foreach ($this->getSubForms() as $name => $form) { |
|
1276 if (!$form->isArray() && array_key_exists($name, $defaults)) { |
|
1277 $form->setDefaults($defaults[$name]); |
|
1278 } else { |
|
1279 $form->setDefaults($defaults); |
|
1280 } |
|
1281 } |
|
1282 return $this; |
|
1283 } |
|
1284 |
|
1285 /** |
|
1286 * Set default value for an element |
|
1287 * |
|
1288 * @param string $name |
|
1289 * @param mixed $value |
|
1290 * @return Zend_Form |
|
1291 */ |
|
1292 public function setDefault($name, $value) |
|
1293 { |
|
1294 $name = (string) $name; |
|
1295 if ($element = $this->getElement($name)) { |
|
1296 $element->setValue($value); |
|
1297 } else { |
|
1298 if (is_scalar($value)) { |
|
1299 foreach ($this->getSubForms() as $subForm) { |
|
1300 $subForm->setDefault($name, $value); |
|
1301 } |
|
1302 } elseif (is_array($value) && ($subForm = $this->getSubForm($name))) { |
|
1303 $subForm->setDefaults($value); |
|
1304 } |
|
1305 } |
|
1306 return $this; |
|
1307 } |
|
1308 |
|
1309 /** |
|
1310 * Retrieve value for single element |
|
1311 * |
|
1312 * @param string $name |
|
1313 * @return mixed |
|
1314 */ |
|
1315 public function getValue($name) |
|
1316 { |
|
1317 if ($element = $this->getElement($name)) { |
|
1318 return $element->getValue(); |
|
1319 } |
|
1320 |
|
1321 if ($subForm = $this->getSubForm($name)) { |
|
1322 return $subForm->getValues(true); |
|
1323 } |
|
1324 |
|
1325 foreach ($this->getSubForms() as $subForm) { |
|
1326 if ($name == $subForm->getElementsBelongTo()) { |
|
1327 return $subForm->getValues(true); |
|
1328 } |
|
1329 } |
|
1330 return null; |
|
1331 } |
|
1332 |
|
1333 /** |
|
1334 * Retrieve all form element values |
|
1335 * |
|
1336 * @param bool $suppressArrayNotation |
|
1337 * @return array |
|
1338 */ |
|
1339 public function getValues($suppressArrayNotation = false) |
|
1340 { |
|
1341 $values = array(); |
|
1342 $eBelongTo = null; |
|
1343 |
|
1344 if ($this->isArray()) { |
|
1345 $eBelongTo = $this->getElementsBelongTo(); |
|
1346 } |
|
1347 |
|
1348 foreach ($this->getElements() as $key => $element) { |
|
1349 if (!$element->getIgnore()) { |
|
1350 $merge = array(); |
|
1351 if (($belongsTo = $element->getBelongsTo()) !== $eBelongTo) { |
|
1352 if ('' !== (string)$belongsTo) { |
|
1353 $key = $belongsTo . '[' . $key . ']'; |
|
1354 } |
|
1355 } |
|
1356 $merge = $this->_attachToArray($element->getValue(), $key); |
|
1357 $values = $this->_array_replace_recursive($values, $merge); |
|
1358 } |
|
1359 } |
|
1360 foreach ($this->getSubForms() as $key => $subForm) { |
|
1361 $merge = array(); |
|
1362 if (!$subForm->isArray()) { |
|
1363 $merge[$key] = $subForm->getValues(); |
|
1364 } else { |
|
1365 $merge = $this->_attachToArray($subForm->getValues(true), |
|
1366 $subForm->getElementsBelongTo()); |
|
1367 } |
|
1368 $values = $this->_array_replace_recursive($values, $merge); |
|
1369 } |
|
1370 |
|
1371 if (!$suppressArrayNotation && |
|
1372 $this->isArray() && |
|
1373 !$this->_getIsRendered()) { |
|
1374 $values = $this->_attachToArray($values, $this->getElementsBelongTo()); |
|
1375 } |
|
1376 |
|
1377 return $values; |
|
1378 } |
|
1379 |
|
1380 /** |
|
1381 * Returns only the valid values from the given form input. |
|
1382 * |
|
1383 * For models that can be saved in a partially valid state, for example when following the builder, |
|
1384 * prototype or state patterns it is particularly interessting to retrieve all the current valid |
|
1385 * values to persist them. |
|
1386 * |
|
1387 * @param array $data |
|
1388 * @param bool $suppressArrayNotation |
|
1389 * @return array |
|
1390 */ |
|
1391 public function getValidValues($data, $suppressArrayNotation = false) |
|
1392 { |
|
1393 $values = array(); |
|
1394 $eBelongTo = null; |
|
1395 |
|
1396 if ($this->isArray()) { |
|
1397 $eBelongTo = $this->getElementsBelongTo(); |
|
1398 $data = $this->_dissolveArrayValue($data, $eBelongTo); |
|
1399 } |
|
1400 $context = $data; |
|
1401 foreach ($this->getElements() as $key => $element) { |
|
1402 if (!$element->getIgnore()) { |
|
1403 $check = $data; |
|
1404 if (($belongsTo = $element->getBelongsTo()) !== $eBelongTo) { |
|
1405 $check = $this->_dissolveArrayValue($data, $belongsTo); |
|
1406 } |
|
1407 if (isset($check[$key])) { |
|
1408 if($element->isValid($check[$key], $context)) { |
|
1409 $merge = array(); |
|
1410 if ($belongsTo !== $eBelongTo && '' !== (string)$belongsTo) { |
|
1411 $key = $belongsTo . '[' . $key . ']'; |
|
1412 } |
|
1413 $merge = $this->_attachToArray($element->getValue(), $key); |
|
1414 $values = $this->_array_replace_recursive($values, $merge); |
|
1415 } |
|
1416 $data = $this->_dissolveArrayUnsetKey($data, $belongsTo, $key); |
|
1417 } |
|
1418 } |
|
1419 } |
|
1420 foreach ($this->getSubForms() as $key => $form) { |
|
1421 $merge = array(); |
|
1422 if (isset($data[$key]) && !$form->isArray()) { |
|
1423 $tmp = $form->getValidValues($data[$key]); |
|
1424 if (!empty($tmp)) { |
|
1425 $merge[$key] = $tmp; |
|
1426 } |
|
1427 } else { |
|
1428 $tmp = $form->getValidValues($data, true); |
|
1429 if (!empty($tmp)) { |
|
1430 $merge = $this->_attachToArray($tmp, $form->getElementsBelongTo()); |
|
1431 } |
|
1432 } |
|
1433 $values = $this->_array_replace_recursive($values, $merge); |
|
1434 } |
|
1435 if (!$suppressArrayNotation && |
|
1436 $this->isArray() && |
|
1437 !empty($values) && |
|
1438 !$this->_getIsRendered()) { |
|
1439 $values = $this->_attachToArray($values, $this->getElementsBelongTo()); |
|
1440 } |
|
1441 |
|
1442 return $values; |
|
1443 } |
|
1444 |
|
1445 /** |
|
1446 * Get unfiltered element value |
|
1447 * |
|
1448 * @param string $name |
|
1449 * @return mixed |
|
1450 */ |
|
1451 public function getUnfilteredValue($name) |
|
1452 { |
|
1453 if ($element = $this->getElement($name)) { |
|
1454 return $element->getUnfilteredValue(); |
|
1455 } |
|
1456 return null; |
|
1457 } |
|
1458 |
|
1459 /** |
|
1460 * Retrieve all unfiltered element values |
|
1461 * |
|
1462 * @return array |
|
1463 */ |
|
1464 public function getUnfilteredValues() |
|
1465 { |
|
1466 $values = array(); |
|
1467 foreach ($this->getElements() as $key => $element) { |
|
1468 $values[$key] = $element->getUnfilteredValue(); |
|
1469 } |
|
1470 |
|
1471 return $values; |
|
1472 } |
|
1473 |
|
1474 /** |
|
1475 * Set all elements' filters |
|
1476 * |
|
1477 * @param array $filters |
|
1478 * @return Zend_Form |
|
1479 */ |
|
1480 public function setElementFilters(array $filters) |
|
1481 { |
|
1482 foreach ($this->getElements() as $element) { |
|
1483 $element->setFilters($filters); |
|
1484 } |
|
1485 return $this; |
|
1486 } |
|
1487 |
|
1488 /** |
|
1489 * Set name of array elements belong to |
|
1490 * |
|
1491 * @param string $array |
|
1492 * @return Zend_Form |
|
1493 */ |
|
1494 public function setElementsBelongTo($array) |
|
1495 { |
|
1496 $origName = $this->getElementsBelongTo(); |
|
1497 $name = $this->filterName($array, true); |
|
1498 if ('' === $name) { |
|
1499 $name = null; |
|
1500 } |
|
1501 $this->_elementsBelongTo = $name; |
|
1502 |
|
1503 if (null === $name) { |
|
1504 $this->setIsArray(false); |
|
1505 if (null !== $origName) { |
|
1506 $this->_setElementsBelongTo(); |
|
1507 } |
|
1508 } else { |
|
1509 $this->setIsArray(true); |
|
1510 $this->_setElementsBelongTo(); |
|
1511 } |
|
1512 |
|
1513 return $this; |
|
1514 } |
|
1515 |
|
1516 /** |
|
1517 * Set array to which elements belong |
|
1518 * |
|
1519 * @param string $name Element name |
|
1520 * @return void |
|
1521 */ |
|
1522 protected function _setElementsBelongTo($name = null) |
|
1523 { |
|
1524 $array = $this->getElementsBelongTo(); |
|
1525 |
|
1526 if (null === $array) { |
|
1527 return; |
|
1528 } |
|
1529 |
|
1530 if (null === $name) { |
|
1531 foreach ($this->getElements() as $element) { |
|
1532 $element->setBelongsTo($array); |
|
1533 } |
|
1534 } else { |
|
1535 if (null !== ($element = $this->getElement($name))) { |
|
1536 $element->setBelongsTo($array); |
|
1537 } |
|
1538 } |
|
1539 } |
|
1540 |
|
1541 /** |
|
1542 * Get name of array elements belong to |
|
1543 * |
|
1544 * @return string|null |
|
1545 */ |
|
1546 public function getElementsBelongTo() |
|
1547 { |
|
1548 if ((null === $this->_elementsBelongTo) && $this->isArray()) { |
|
1549 $name = $this->getName(); |
|
1550 if ('' !== (string)$name) { |
|
1551 return $name; |
|
1552 } |
|
1553 } |
|
1554 return $this->_elementsBelongTo; |
|
1555 } |
|
1556 |
|
1557 /** |
|
1558 * Set flag indicating elements belong to array |
|
1559 * |
|
1560 * @param bool $flag Value of flag |
|
1561 * @return Zend_Form |
|
1562 */ |
|
1563 public function setIsArray($flag) |
|
1564 { |
|
1565 $this->_isArray = (bool) $flag; |
|
1566 return $this; |
|
1567 } |
|
1568 |
|
1569 /** |
|
1570 * Get flag indicating if elements belong to an array |
|
1571 * |
|
1572 * @return bool |
|
1573 */ |
|
1574 public function isArray() |
|
1575 { |
|
1576 return $this->_isArray; |
|
1577 } |
|
1578 |
|
1579 // Element groups: |
|
1580 |
|
1581 /** |
|
1582 * Add a form group/subform |
|
1583 * |
|
1584 * @param Zend_Form $form |
|
1585 * @param string $name |
|
1586 * @param int $order |
|
1587 * @return Zend_Form |
|
1588 */ |
|
1589 public function addSubForm(Zend_Form $form, $name, $order = null) |
|
1590 { |
|
1591 $name = (string) $name; |
|
1592 foreach ($this->_loaders as $type => $loader) { |
|
1593 $loaderPaths = $loader->getPaths(); |
|
1594 foreach ($loaderPaths as $prefix => $paths) { |
|
1595 foreach ($paths as $path) { |
|
1596 $form->addPrefixPath($prefix, $path, $type); |
|
1597 } |
|
1598 } |
|
1599 } |
|
1600 |
|
1601 if (!empty($this->_elementPrefixPaths)) { |
|
1602 foreach ($this->_elementPrefixPaths as $spec) { |
|
1603 list($prefix, $path, $type) = array_values($spec); |
|
1604 $form->addElementPrefixPath($prefix, $path, $type); |
|
1605 } |
|
1606 } |
|
1607 |
|
1608 if (!empty($this->_displayGroupPrefixPaths)) { |
|
1609 foreach ($this->_displayGroupPrefixPaths as $spec) { |
|
1610 list($prefix, $path) = array_values($spec); |
|
1611 $form->addDisplayGroupPrefixPath($prefix, $path); |
|
1612 } |
|
1613 } |
|
1614 |
|
1615 if (null !== $order) { |
|
1616 $form->setOrder($order); |
|
1617 } |
|
1618 |
|
1619 if (($oldName = $form->getName()) && |
|
1620 $oldName !== $name && |
|
1621 $oldName === $form->getElementsBelongTo()) { |
|
1622 $form->setElementsBelongTo($name); |
|
1623 } |
|
1624 |
|
1625 $form->setName($name); |
|
1626 $this->_subForms[$name] = $form; |
|
1627 $this->_order[$name] = $order; |
|
1628 $this->_orderUpdated = true; |
|
1629 return $this; |
|
1630 } |
|
1631 |
|
1632 /** |
|
1633 * Add multiple form subForms/subforms at once |
|
1634 * |
|
1635 * @param array $subForms |
|
1636 * @return Zend_Form |
|
1637 */ |
|
1638 public function addSubForms(array $subForms) |
|
1639 { |
|
1640 foreach ($subForms as $key => $spec) { |
|
1641 $name = null; |
|
1642 if (!is_numeric($key)) { |
|
1643 $name = $key; |
|
1644 } |
|
1645 |
|
1646 if ($spec instanceof Zend_Form) { |
|
1647 $this->addSubForm($spec, $name); |
|
1648 continue; |
|
1649 } |
|
1650 |
|
1651 if (is_array($spec)) { |
|
1652 $argc = count($spec); |
|
1653 $order = null; |
|
1654 switch ($argc) { |
|
1655 case 0: |
|
1656 continue; |
|
1657 case (1 <= $argc): |
|
1658 $subForm = array_shift($spec); |
|
1659 case (2 <= $argc): |
|
1660 $name = array_shift($spec); |
|
1661 case (3 <= $argc): |
|
1662 $order = array_shift($spec); |
|
1663 default: |
|
1664 $this->addSubForm($subForm, $name, $order); |
|
1665 } |
|
1666 } |
|
1667 } |
|
1668 return $this; |
|
1669 } |
|
1670 |
|
1671 /** |
|
1672 * Set multiple form subForms/subforms (overwrites) |
|
1673 * |
|
1674 * @param array $subForms |
|
1675 * @return Zend_Form |
|
1676 */ |
|
1677 public function setSubForms(array $subForms) |
|
1678 { |
|
1679 $this->clearSubForms(); |
|
1680 return $this->addSubForms($subForms); |
|
1681 } |
|
1682 |
|
1683 /** |
|
1684 * Retrieve a form subForm/subform |
|
1685 * |
|
1686 * @param string $name |
|
1687 * @return Zend_Form|null |
|
1688 */ |
|
1689 public function getSubForm($name) |
|
1690 { |
|
1691 $name = (string) $name; |
|
1692 if (isset($this->_subForms[$name])) { |
|
1693 return $this->_subForms[$name]; |
|
1694 } |
|
1695 return null; |
|
1696 } |
|
1697 |
|
1698 /** |
|
1699 * Retrieve all form subForms/subforms |
|
1700 * |
|
1701 * @return array |
|
1702 */ |
|
1703 public function getSubForms() |
|
1704 { |
|
1705 return $this->_subForms; |
|
1706 } |
|
1707 |
|
1708 /** |
|
1709 * Remove form subForm/subform |
|
1710 * |
|
1711 * @param string $name |
|
1712 * @return boolean |
|
1713 */ |
|
1714 public function removeSubForm($name) |
|
1715 { |
|
1716 $name = (string) $name; |
|
1717 if (array_key_exists($name, $this->_subForms)) { |
|
1718 unset($this->_subForms[$name]); |
|
1719 if (array_key_exists($name, $this->_order)) { |
|
1720 unset($this->_order[$name]); |
|
1721 $this->_orderUpdated = true; |
|
1722 } |
|
1723 return true; |
|
1724 } |
|
1725 |
|
1726 return false; |
|
1727 } |
|
1728 |
|
1729 /** |
|
1730 * Remove all form subForms/subforms |
|
1731 * |
|
1732 * @return Zend_Form |
|
1733 */ |
|
1734 public function clearSubForms() |
|
1735 { |
|
1736 foreach (array_keys($this->_subForms) as $key) { |
|
1737 if (array_key_exists($key, $this->_order)) { |
|
1738 unset($this->_order[$key]); |
|
1739 } |
|
1740 } |
|
1741 $this->_subForms = array(); |
|
1742 $this->_orderUpdated = true; |
|
1743 return $this; |
|
1744 } |
|
1745 |
|
1746 |
|
1747 // Display groups: |
|
1748 |
|
1749 /** |
|
1750 * Set default display group class |
|
1751 * |
|
1752 * @param string $class |
|
1753 * @return Zend_Form |
|
1754 */ |
|
1755 public function setDefaultDisplayGroupClass($class) |
|
1756 { |
|
1757 $this->_defaultDisplayGroupClass = (string) $class; |
|
1758 return $this; |
|
1759 } |
|
1760 |
|
1761 /** |
|
1762 * Retrieve default display group class |
|
1763 * |
|
1764 * @return string |
|
1765 */ |
|
1766 public function getDefaultDisplayGroupClass() |
|
1767 { |
|
1768 return $this->_defaultDisplayGroupClass; |
|
1769 } |
|
1770 |
|
1771 /** |
|
1772 * Add a display group |
|
1773 * |
|
1774 * Groups named elements for display purposes. |
|
1775 * |
|
1776 * If a referenced element does not yet exist in the form, it is omitted. |
|
1777 * |
|
1778 * @param array $elements |
|
1779 * @param string $name |
|
1780 * @param array|Zend_Config $options |
|
1781 * @return Zend_Form |
|
1782 * @throws Zend_Form_Exception if no valid elements provided |
|
1783 */ |
|
1784 public function addDisplayGroup(array $elements, $name, $options = null) |
|
1785 { |
|
1786 $group = array(); |
|
1787 foreach ($elements as $element) { |
|
1788 if($element instanceof Zend_Form_Element) { |
|
1789 $element = $element->getId(); |
|
1790 } |
|
1791 |
|
1792 if (isset($this->_elements[$element])) { |
|
1793 $add = $this->getElement($element); |
|
1794 if (null !== $add) { |
|
1795 $group[] = $add; |
|
1796 } |
|
1797 } |
|
1798 } |
|
1799 if (empty($group)) { |
|
1800 require_once 'Zend/Form/Exception.php'; |
|
1801 throw new Zend_Form_Exception('No valid elements specified for display group'); |
|
1802 } |
|
1803 |
|
1804 $name = (string) $name; |
|
1805 |
|
1806 if (is_array($options)) { |
|
1807 $options['form'] = $this; |
|
1808 $options['elements'] = $group; |
|
1809 } elseif ($options instanceof Zend_Config) { |
|
1810 $options = $options->toArray(); |
|
1811 $options['form'] = $this; |
|
1812 $options['elements'] = $group; |
|
1813 } else { |
|
1814 $options = array( |
|
1815 'form' => $this, |
|
1816 'elements' => $group, |
|
1817 ); |
|
1818 } |
|
1819 |
|
1820 if (isset($options['displayGroupClass'])) { |
|
1821 $class = $options['displayGroupClass']; |
|
1822 unset($options['displayGroupClass']); |
|
1823 } else { |
|
1824 $class = $this->getDefaultDisplayGroupClass(); |
|
1825 } |
|
1826 |
|
1827 if (!class_exists($class)) { |
|
1828 require_once 'Zend/Loader.php'; |
|
1829 Zend_Loader::loadClass($class); |
|
1830 } |
|
1831 $this->_displayGroups[$name] = new $class( |
|
1832 $name, |
|
1833 $this->getPluginLoader(self::DECORATOR), |
|
1834 $options |
|
1835 ); |
|
1836 |
|
1837 if (!empty($this->_displayGroupPrefixPaths)) { |
|
1838 $this->_displayGroups[$name]->addPrefixPaths($this->_displayGroupPrefixPaths); |
|
1839 } |
|
1840 |
|
1841 $this->_order[$name] = $this->_displayGroups[$name]->getOrder(); |
|
1842 $this->_orderUpdated = true; |
|
1843 return $this; |
|
1844 } |
|
1845 |
|
1846 /** |
|
1847 * Add a display group object (used with cloning) |
|
1848 * |
|
1849 * @param Zend_Form_DisplayGroup $group |
|
1850 * @param string|null $name |
|
1851 * @return Zend_Form |
|
1852 */ |
|
1853 protected function _addDisplayGroupObject(Zend_Form_DisplayGroup $group, $name = null) |
|
1854 { |
|
1855 if (null === $name) { |
|
1856 $name = $group->getName(); |
|
1857 if ('' === (string)$name) { |
|
1858 require_once 'Zend/Form/Exception.php'; |
|
1859 throw new Zend_Form_Exception('Invalid display group added; requires name'); |
|
1860 } |
|
1861 } |
|
1862 |
|
1863 $this->_displayGroups[$name] = $group; |
|
1864 $group->setForm($this); |
|
1865 |
|
1866 if (!empty($this->_displayGroupPrefixPaths)) { |
|
1867 $this->_displayGroups[$name]->addPrefixPaths($this->_displayGroupPrefixPaths); |
|
1868 } |
|
1869 |
|
1870 $this->_order[$name] = $this->_displayGroups[$name]->getOrder(); |
|
1871 $this->_orderUpdated = true; |
|
1872 return $this; |
|
1873 } |
|
1874 |
|
1875 /** |
|
1876 * Add multiple display groups at once |
|
1877 * |
|
1878 * @param array $groups |
|
1879 * @return Zend_Form |
|
1880 */ |
|
1881 public function addDisplayGroups(array $groups) |
|
1882 { |
|
1883 foreach ($groups as $key => $spec) { |
|
1884 $name = null; |
|
1885 if (!is_numeric($key)) { |
|
1886 $name = $key; |
|
1887 } |
|
1888 |
|
1889 if ($spec instanceof Zend_Form_DisplayGroup) { |
|
1890 $this->_addDisplayGroupObject($spec); |
|
1891 } |
|
1892 |
|
1893 if (!is_array($spec) || empty($spec)) { |
|
1894 continue; |
|
1895 } |
|
1896 |
|
1897 $argc = count($spec); |
|
1898 $options = array(); |
|
1899 |
|
1900 if (isset($spec['elements'])) { |
|
1901 $elements = $spec['elements']; |
|
1902 if (isset($spec['name'])) { |
|
1903 $name = $spec['name']; |
|
1904 } |
|
1905 if (isset($spec['options'])) { |
|
1906 $options = $spec['options']; |
|
1907 } |
|
1908 $this->addDisplayGroup($elements, $name, $options); |
|
1909 } else { |
|
1910 switch ($argc) { |
|
1911 case (1 <= $argc): |
|
1912 $elements = array_shift($spec); |
|
1913 if (!is_array($elements) && (null !== $name)) { |
|
1914 $elements = array_merge((array) $elements, $spec); |
|
1915 $this->addDisplayGroup($elements, $name); |
|
1916 break; |
|
1917 } |
|
1918 case (2 <= $argc): |
|
1919 if (null !== $name) { |
|
1920 $options = array_shift($spec); |
|
1921 $this->addDisplayGroup($elements, $name, $options); |
|
1922 break; |
|
1923 } |
|
1924 $name = array_shift($spec); |
|
1925 case (3 <= $argc): |
|
1926 $options = array_shift($spec); |
|
1927 default: |
|
1928 $this->addDisplayGroup($elements, $name, $options); |
|
1929 } |
|
1930 } |
|
1931 } |
|
1932 return $this; |
|
1933 } |
|
1934 |
|
1935 /** |
|
1936 * Add multiple display groups (overwrites) |
|
1937 * |
|
1938 * @param array $groups |
|
1939 * @return Zend_Form |
|
1940 */ |
|
1941 public function setDisplayGroups(array $groups) |
|
1942 { |
|
1943 return $this->clearDisplayGroups() |
|
1944 ->addDisplayGroups($groups); |
|
1945 } |
|
1946 |
|
1947 /** |
|
1948 * Return a display group |
|
1949 * |
|
1950 * @param string $name |
|
1951 * @return Zend_Form_DisplayGroup|null |
|
1952 */ |
|
1953 public function getDisplayGroup($name) |
|
1954 { |
|
1955 $name = (string) $name; |
|
1956 if (isset($this->_displayGroups[$name])) { |
|
1957 return $this->_displayGroups[$name]; |
|
1958 } |
|
1959 |
|
1960 return null; |
|
1961 } |
|
1962 |
|
1963 /** |
|
1964 * Return all display groups |
|
1965 * |
|
1966 * @return array |
|
1967 */ |
|
1968 public function getDisplayGroups() |
|
1969 { |
|
1970 return $this->_displayGroups; |
|
1971 } |
|
1972 |
|
1973 /** |
|
1974 * Remove a display group by name |
|
1975 * |
|
1976 * @param string $name |
|
1977 * @return boolean |
|
1978 */ |
|
1979 public function removeDisplayGroup($name) |
|
1980 { |
|
1981 $name = (string) $name; |
|
1982 if (array_key_exists($name, $this->_displayGroups)) { |
|
1983 foreach ($this->_displayGroups[$name] as $key => $element) { |
|
1984 if (array_key_exists($key, $this->_elements)) { |
|
1985 $this->_order[$key] = $element->getOrder(); |
|
1986 $this->_orderUpdated = true; |
|
1987 } |
|
1988 } |
|
1989 unset($this->_displayGroups[$name]); |
|
1990 |
|
1991 if (array_key_exists($name, $this->_order)) { |
|
1992 unset($this->_order[$name]); |
|
1993 $this->_orderUpdated = true; |
|
1994 } |
|
1995 return true; |
|
1996 } |
|
1997 |
|
1998 return false; |
|
1999 } |
|
2000 |
|
2001 /** |
|
2002 * Remove all display groups |
|
2003 * |
|
2004 * @return Zend_Form |
|
2005 */ |
|
2006 public function clearDisplayGroups() |
|
2007 { |
|
2008 foreach ($this->_displayGroups as $key => $group) { |
|
2009 if (array_key_exists($key, $this->_order)) { |
|
2010 unset($this->_order[$key]); |
|
2011 } |
|
2012 foreach ($group as $name => $element) { |
|
2013 if (isset($this->_elements[$name])) { |
|
2014 $this->_order[$name] = $element->getOrder(); |
|
2015 } |
|
2016 $this->_order[$name] = $element->getOrder(); |
|
2017 } |
|
2018 } |
|
2019 $this->_displayGroups = array(); |
|
2020 $this->_orderUpdated = true; |
|
2021 return $this; |
|
2022 } |
|
2023 |
|
2024 |
|
2025 // Processing |
|
2026 |
|
2027 /** |
|
2028 * Populate form |
|
2029 * |
|
2030 * Proxies to {@link setDefaults()} |
|
2031 * |
|
2032 * @param array $values |
|
2033 * @return Zend_Form |
|
2034 */ |
|
2035 public function populate(array $values) |
|
2036 { |
|
2037 return $this->setDefaults($values); |
|
2038 } |
|
2039 |
|
2040 /** |
|
2041 * Determine array key name from given value |
|
2042 * |
|
2043 * Given a value such as foo[bar][baz], returns the last element (in this case, 'baz'). |
|
2044 * |
|
2045 * @param string $value |
|
2046 * @return string |
|
2047 */ |
|
2048 protected function _getArrayName($value) |
|
2049 { |
|
2050 if (!is_string($value) || '' === $value) { |
|
2051 return $value; |
|
2052 } |
|
2053 |
|
2054 if (!strstr($value, '[')) { |
|
2055 return $value; |
|
2056 } |
|
2057 |
|
2058 $endPos = strlen($value) - 1; |
|
2059 if (']' != $value[$endPos]) { |
|
2060 return $value; |
|
2061 } |
|
2062 |
|
2063 $start = strrpos($value, '[') + 1; |
|
2064 $name = substr($value, $start, $endPos - $start); |
|
2065 return $name; |
|
2066 } |
|
2067 |
|
2068 /** |
|
2069 * Extract the value by walking the array using given array path. |
|
2070 * |
|
2071 * Given an array path such as foo[bar][baz], returns the value of the last |
|
2072 * element (in this case, 'baz'). |
|
2073 * |
|
2074 * @param array $value Array to walk |
|
2075 * @param string $arrayPath Array notation path of the part to extract |
|
2076 * @return string |
|
2077 */ |
|
2078 protected function _dissolveArrayValue($value, $arrayPath) |
|
2079 { |
|
2080 // As long as we have more levels |
|
2081 while ($arrayPos = strpos($arrayPath, '[')) { |
|
2082 // Get the next key in the path |
|
2083 $arrayKey = trim(substr($arrayPath, 0, $arrayPos), ']'); |
|
2084 |
|
2085 // Set the potentially final value or the next search point in the array |
|
2086 if (isset($value[$arrayKey])) { |
|
2087 $value = $value[$arrayKey]; |
|
2088 } |
|
2089 |
|
2090 // Set the next search point in the path |
|
2091 $arrayPath = trim(substr($arrayPath, $arrayPos + 1), ']'); |
|
2092 } |
|
2093 |
|
2094 if (isset($value[$arrayPath])) { |
|
2095 $value = $value[$arrayPath]; |
|
2096 } |
|
2097 |
|
2098 return $value; |
|
2099 } |
|
2100 |
|
2101 /** |
|
2102 * Given an array, an optional arrayPath and a key this method |
|
2103 * dissolves the arrayPath and unsets the key within the array |
|
2104 * if it exists. |
|
2105 * |
|
2106 * @param array $array |
|
2107 * @param string|null $arrayPath |
|
2108 * @param string $key |
|
2109 * @return array |
|
2110 */ |
|
2111 protected function _dissolveArrayUnsetKey($array, $arrayPath, $key) |
|
2112 { |
|
2113 $unset =& $array; |
|
2114 $path = trim(strtr((string)$arrayPath, array('[' => '/', ']' => '')), '/'); |
|
2115 $segs = ('' !== $path) ? explode('/', $path) : array(); |
|
2116 |
|
2117 foreach ($segs as $seg) { |
|
2118 if (!array_key_exists($seg, (array)$unset)) { |
|
2119 return $array; |
|
2120 } |
|
2121 $unset =& $unset[$seg]; |
|
2122 } |
|
2123 if (array_key_exists($key, (array)$unset)) { |
|
2124 unset($unset[$key]); |
|
2125 } |
|
2126 return $array; |
|
2127 } |
|
2128 |
|
2129 /** |
|
2130 * Converts given arrayPath to an array and attaches given value at the end of it. |
|
2131 * |
|
2132 * @param mixed $value The value to attach |
|
2133 * @param string $arrayPath Given array path to convert and attach to. |
|
2134 * @return array |
|
2135 */ |
|
2136 protected function _attachToArray($value, $arrayPath) |
|
2137 { |
|
2138 // As long as we have more levels |
|
2139 while ($arrayPos = strrpos($arrayPath, '[')) { |
|
2140 // Get the next key in the path |
|
2141 $arrayKey = trim(substr($arrayPath, $arrayPos + 1), ']'); |
|
2142 |
|
2143 // Attach |
|
2144 $value = array($arrayKey => $value); |
|
2145 |
|
2146 // Set the next search point in the path |
|
2147 $arrayPath = trim(substr($arrayPath, 0, $arrayPos), ']'); |
|
2148 } |
|
2149 |
|
2150 $value = array($arrayPath => $value); |
|
2151 |
|
2152 return $value; |
|
2153 } |
|
2154 |
|
2155 /** |
|
2156 * Returns a one dimensional numerical indexed array with the |
|
2157 * Elements, SubForms and Elements from DisplayGroups as Values. |
|
2158 * |
|
2159 * Subitems are inserted based on their order Setting if set, |
|
2160 * otherwise they are appended, the resulting numerical index |
|
2161 * may differ from the order value. |
|
2162 * |
|
2163 * @access protected |
|
2164 * @return array |
|
2165 */ |
|
2166 public function getElementsAndSubFormsOrdered() |
|
2167 { |
|
2168 $ordered = array(); |
|
2169 foreach ($this->_order as $name => $order) { |
|
2170 $order = isset($order) ? $order : count($ordered); |
|
2171 if ($this->$name instanceof Zend_Form_Element || |
|
2172 $this->$name instanceof Zend_Form) { |
|
2173 array_splice($ordered, $order, 0, array($this->$name)); |
|
2174 } else if ($this->$name instanceof Zend_Form_DisplayGroup) { |
|
2175 $subordered = array(); |
|
2176 foreach ($this->$name->getElements() as $element) { |
|
2177 $suborder = $element->getOrder(); |
|
2178 $suborder = (null !== $suborder) ? $suborder : count($subordered); |
|
2179 array_splice($subordered, $suborder, 0, array($element)); |
|
2180 } |
|
2181 if (!empty($subordered)) { |
|
2182 array_splice($ordered, $order, 0, $subordered); |
|
2183 } |
|
2184 } |
|
2185 } |
|
2186 return $ordered; |
|
2187 } |
|
2188 |
|
2189 /** |
|
2190 * This is a helper function until php 5.3 is widespreaded |
|
2191 * |
|
2192 * @param array $into |
|
2193 * @access protected |
|
2194 * @return void |
|
2195 */ |
|
2196 protected function _array_replace_recursive(array $into) |
|
2197 { |
|
2198 $fromArrays = array_slice(func_get_args(),1); |
|
2199 |
|
2200 foreach ($fromArrays as $from) { |
|
2201 foreach ($from as $key => $value) { |
|
2202 if (is_array($value)) { |
|
2203 if (!isset($into[$key])) { |
|
2204 $into[$key] = array(); |
|
2205 } |
|
2206 $into[$key] = $this->_array_replace_recursive($into[$key], $from[$key]); |
|
2207 } else { |
|
2208 $into[$key] = $value; |
|
2209 } |
|
2210 } |
|
2211 } |
|
2212 return $into; |
|
2213 } |
|
2214 |
|
2215 /** |
|
2216 * Validate the form |
|
2217 * |
|
2218 * @param array $data |
|
2219 * @return boolean |
|
2220 */ |
|
2221 public function isValid($data) |
|
2222 { |
|
2223 if (!is_array($data)) { |
|
2224 require_once 'Zend/Form/Exception.php'; |
|
2225 throw new Zend_Form_Exception(__METHOD__ . ' expects an array'); |
|
2226 } |
|
2227 $translator = $this->getTranslator(); |
|
2228 $valid = true; |
|
2229 $eBelongTo = null; |
|
2230 |
|
2231 if ($this->isArray()) { |
|
2232 $eBelongTo = $this->getElementsBelongTo(); |
|
2233 $data = $this->_dissolveArrayValue($data, $eBelongTo); |
|
2234 } |
|
2235 $context = $data; |
|
2236 foreach ($this->getElements() as $key => $element) { |
|
2237 if (null !== $translator && $this->hasTranslator() |
|
2238 && !$element->hasTranslator()) { |
|
2239 $element->setTranslator($translator); |
|
2240 } |
|
2241 $check = $data; |
|
2242 if (($belongsTo = $element->getBelongsTo()) !== $eBelongTo) { |
|
2243 $check = $this->_dissolveArrayValue($data, $belongsTo); |
|
2244 } |
|
2245 if (!isset($check[$key])) { |
|
2246 $valid = $element->isValid(null, $context) && $valid; |
|
2247 } else { |
|
2248 $valid = $element->isValid($check[$key], $context) && $valid; |
|
2249 $data = $this->_dissolveArrayUnsetKey($data, $belongsTo, $key); |
|
2250 } |
|
2251 } |
|
2252 foreach ($this->getSubForms() as $key => $form) { |
|
2253 if (null !== $translator && !$form->hasTranslator()) { |
|
2254 $form->setTranslator($translator); |
|
2255 } |
|
2256 if (isset($data[$key]) && !$form->isArray()) { |
|
2257 $valid = $form->isValid($data[$key]) && $valid; |
|
2258 } else { |
|
2259 $valid = $form->isValid($data) && $valid; |
|
2260 } |
|
2261 } |
|
2262 |
|
2263 $this->_errorsExist = !$valid; |
|
2264 |
|
2265 // If manually flagged as an error, return invalid status |
|
2266 if ($this->_errorsForced) { |
|
2267 return false; |
|
2268 } |
|
2269 |
|
2270 return $valid; |
|
2271 } |
|
2272 |
|
2273 /** |
|
2274 * Validate a partial form |
|
2275 * |
|
2276 * Does not check for required flags. |
|
2277 * |
|
2278 * @param array $data |
|
2279 * @return boolean |
|
2280 */ |
|
2281 public function isValidPartial(array $data) |
|
2282 { |
|
2283 $eBelongTo = null; |
|
2284 |
|
2285 if ($this->isArray()) { |
|
2286 $eBelongTo = $this->getElementsBelongTo(); |
|
2287 $data = $this->_dissolveArrayValue($data, $eBelongTo); |
|
2288 } |
|
2289 |
|
2290 $translator = $this->getTranslator(); |
|
2291 $valid = true; |
|
2292 $context = $data; |
|
2293 |
|
2294 foreach ($this->getElements() as $key => $element) { |
|
2295 $check = $data; |
|
2296 if (($belongsTo = $element->getBelongsTo()) !== $eBelongTo) { |
|
2297 $check = $this->_dissolveArrayValue($data, $belongsTo); |
|
2298 } |
|
2299 if (isset($check[$key])) { |
|
2300 if (null !== $translator && !$element->hasTranslator()) { |
|
2301 $element->setTranslator($translator); |
|
2302 } |
|
2303 $valid = $element->isValid($check[$key], $context) && $valid; |
|
2304 $data = $this->_dissolveArrayUnsetKey($data, $belongsTo, $key); |
|
2305 } |
|
2306 } |
|
2307 foreach ($this->getSubForms() as $key => $form) { |
|
2308 if (null !== $translator && !$form->hasTranslator()) { |
|
2309 $form->setTranslator($translator); |
|
2310 } |
|
2311 if (isset($data[$key]) && !$form->isArray()) { |
|
2312 $valid = $form->isValidPartial($data[$key]) && $valid; |
|
2313 } else { |
|
2314 $valid = $form->isValidPartial($data) && $valid; |
|
2315 } |
|
2316 } |
|
2317 |
|
2318 $this->_errorsExist = !$valid; |
|
2319 return $valid; |
|
2320 } |
|
2321 |
|
2322 /** |
|
2323 * Process submitted AJAX data |
|
2324 * |
|
2325 * Checks if provided $data is valid, via {@link isValidPartial()}. If so, |
|
2326 * it returns JSON-encoded boolean true. If not, it returns JSON-encoded |
|
2327 * error messages (as returned by {@link getMessages()}). |
|
2328 * |
|
2329 * @param array $data |
|
2330 * @return string JSON-encoded boolean true or error messages |
|
2331 */ |
|
2332 public function processAjax(array $data) |
|
2333 { |
|
2334 require_once 'Zend/Json.php'; |
|
2335 if ($this->isValidPartial($data)) { |
|
2336 return Zend_Json::encode(true); |
|
2337 } |
|
2338 $messages = $this->getMessages(); |
|
2339 return Zend_Json::encode($messages); |
|
2340 } |
|
2341 |
|
2342 /** |
|
2343 * Add a custom error message to return in the event of failed validation |
|
2344 * |
|
2345 * @param string $message |
|
2346 * @return Zend_Form |
|
2347 */ |
|
2348 public function addErrorMessage($message) |
|
2349 { |
|
2350 $this->_errorMessages[] = (string) $message; |
|
2351 return $this; |
|
2352 } |
|
2353 |
|
2354 /** |
|
2355 * Add multiple custom error messages to return in the event of failed validation |
|
2356 * |
|
2357 * @param array $messages |
|
2358 * @return Zend_Form |
|
2359 */ |
|
2360 public function addErrorMessages(array $messages) |
|
2361 { |
|
2362 foreach ($messages as $message) { |
|
2363 $this->addErrorMessage($message); |
|
2364 } |
|
2365 return $this; |
|
2366 } |
|
2367 |
|
2368 /** |
|
2369 * Same as addErrorMessages(), but clears custom error message stack first |
|
2370 * |
|
2371 * @param array $messages |
|
2372 * @return Zend_Form |
|
2373 */ |
|
2374 public function setErrorMessages(array $messages) |
|
2375 { |
|
2376 $this->clearErrorMessages(); |
|
2377 return $this->addErrorMessages($messages); |
|
2378 } |
|
2379 |
|
2380 /** |
|
2381 * Retrieve custom error messages |
|
2382 * |
|
2383 * @return array |
|
2384 */ |
|
2385 public function getErrorMessages() |
|
2386 { |
|
2387 return $this->_errorMessages; |
|
2388 } |
|
2389 |
|
2390 /** |
|
2391 * Clear custom error messages stack |
|
2392 * |
|
2393 * @return Zend_Form |
|
2394 */ |
|
2395 public function clearErrorMessages() |
|
2396 { |
|
2397 $this->_errorMessages = array(); |
|
2398 return $this; |
|
2399 } |
|
2400 |
|
2401 /** |
|
2402 * Mark the element as being in a failed validation state |
|
2403 * |
|
2404 * @return Zend_Form |
|
2405 */ |
|
2406 public function markAsError() |
|
2407 { |
|
2408 $this->_errorsExist = true; |
|
2409 $this->_errorsForced = true; |
|
2410 return $this; |
|
2411 } |
|
2412 |
|
2413 /** |
|
2414 * Add an error message and mark element as failed validation |
|
2415 * |
|
2416 * @param string $message |
|
2417 * @return Zend_Form |
|
2418 */ |
|
2419 public function addError($message) |
|
2420 { |
|
2421 $this->addErrorMessage($message); |
|
2422 $this->markAsError(); |
|
2423 return $this; |
|
2424 } |
|
2425 |
|
2426 /** |
|
2427 * Add multiple error messages and flag element as failed validation |
|
2428 * |
|
2429 * @param array $messages |
|
2430 * @return Zend_Form |
|
2431 */ |
|
2432 public function addErrors(array $messages) |
|
2433 { |
|
2434 foreach ($messages as $message) { |
|
2435 $this->addError($message); |
|
2436 } |
|
2437 return $this; |
|
2438 } |
|
2439 |
|
2440 /** |
|
2441 * Overwrite any previously set error messages and flag as failed validation |
|
2442 * |
|
2443 * @param array $messages |
|
2444 * @return Zend_Form |
|
2445 */ |
|
2446 public function setErrors(array $messages) |
|
2447 { |
|
2448 $this->clearErrorMessages(); |
|
2449 return $this->addErrors($messages); |
|
2450 } |
|
2451 |
|
2452 |
|
2453 public function persistData() |
|
2454 { |
|
2455 } |
|
2456 |
|
2457 /** |
|
2458 * Are there errors in the form? |
|
2459 * |
|
2460 * @return bool |
|
2461 */ |
|
2462 public function isErrors() |
|
2463 { |
|
2464 return $this->_errorsExist; |
|
2465 } |
|
2466 |
|
2467 /** |
|
2468 * Get error codes for all elements failing validation |
|
2469 * |
|
2470 * @param string $name |
|
2471 * @return array |
|
2472 */ |
|
2473 public function getErrors($name = null, $suppressArrayNotation = false) |
|
2474 { |
|
2475 $errors = array(); |
|
2476 if (null !== $name) { |
|
2477 if (isset($this->_elements[$name])) { |
|
2478 return $this->getElement($name)->getErrors(); |
|
2479 } else if (isset($this->_subForms[$name])) { |
|
2480 return $this->getSubForm($name)->getErrors(null, true); |
|
2481 } |
|
2482 } |
|
2483 |
|
2484 foreach ($this->_elements as $key => $element) { |
|
2485 $errors[$key] = $element->getErrors(); |
|
2486 } |
|
2487 foreach ($this->getSubForms() as $key => $subForm) { |
|
2488 $merge = array(); |
|
2489 if (!$subForm->isArray()) { |
|
2490 $merge[$key] = $subForm->getErrors(); |
|
2491 } else { |
|
2492 $merge = $this->_attachToArray($subForm->getErrors(null, true), |
|
2493 $subForm->getElementsBelongTo()); |
|
2494 } |
|
2495 $errors = $this->_array_replace_recursive($errors, $merge); |
|
2496 } |
|
2497 |
|
2498 if (!$suppressArrayNotation && |
|
2499 $this->isArray() && |
|
2500 !$this->_getIsRendered()) { |
|
2501 $errors = $this->_attachToArray($errors, $this->getElementsBelongTo()); |
|
2502 } |
|
2503 |
|
2504 return $errors; |
|
2505 } |
|
2506 |
|
2507 /** |
|
2508 * Retrieve error messages from elements failing validations |
|
2509 * |
|
2510 * @param string $name |
|
2511 * @param bool $suppressArrayNotation |
|
2512 * @return array |
|
2513 */ |
|
2514 public function getMessages($name = null, $suppressArrayNotation = false) |
|
2515 { |
|
2516 if (null !== $name) { |
|
2517 if (isset($this->_elements[$name])) { |
|
2518 return $this->getElement($name)->getMessages(); |
|
2519 } else if (isset($this->_subForms[$name])) { |
|
2520 return $this->getSubForm($name)->getMessages(null, true); |
|
2521 } |
|
2522 foreach ($this->getSubForms() as $key => $subForm) { |
|
2523 if ($subForm->isArray()) { |
|
2524 $belongTo = $subForm->getElementsBelongTo(); |
|
2525 if ($name == $this->_getArrayName($belongTo)) { |
|
2526 return $subForm->getMessages(null, true); |
|
2527 } |
|
2528 } |
|
2529 } |
|
2530 } |
|
2531 |
|
2532 $customMessages = $this->_getErrorMessages(); |
|
2533 if ($this->isErrors() && !empty($customMessages)) { |
|
2534 return $customMessages; |
|
2535 } |
|
2536 |
|
2537 $messages = array(); |
|
2538 |
|
2539 foreach ($this->getElements() as $name => $element) { |
|
2540 $eMessages = $element->getMessages(); |
|
2541 if (!empty($eMessages)) { |
|
2542 $messages[$name] = $eMessages; |
|
2543 } |
|
2544 } |
|
2545 |
|
2546 foreach ($this->getSubForms() as $key => $subForm) { |
|
2547 $merge = $subForm->getMessages(null, true); |
|
2548 if (!empty($merge)) { |
|
2549 if (!$subForm->isArray()) { |
|
2550 $merge = array($key => $merge); |
|
2551 } else { |
|
2552 $merge = $this->_attachToArray($merge, |
|
2553 $subForm->getElementsBelongTo()); |
|
2554 } |
|
2555 $messages = $this->_array_replace_recursive($messages, $merge); |
|
2556 } |
|
2557 } |
|
2558 |
|
2559 if (!$suppressArrayNotation && |
|
2560 $this->isArray() && |
|
2561 !$this->_getIsRendered()) { |
|
2562 $messages = $this->_attachToArray($messages, $this->getElementsBelongTo()); |
|
2563 } |
|
2564 |
|
2565 return $messages; |
|
2566 } |
|
2567 |
|
2568 /** |
|
2569 * Retrieve translated custom error messages |
|
2570 * Proxies to {@link _getErrorMessages()}. |
|
2571 * |
|
2572 * @return array |
|
2573 */ |
|
2574 public function getCustomMessages() |
|
2575 { |
|
2576 return $this->_getErrorMessages(); |
|
2577 } |
|
2578 |
|
2579 |
|
2580 // Rendering |
|
2581 |
|
2582 /** |
|
2583 * Set view object |
|
2584 * |
|
2585 * @param Zend_View_Interface $view |
|
2586 * @return Zend_Form |
|
2587 */ |
|
2588 public function setView(Zend_View_Interface $view = null) |
|
2589 { |
|
2590 $this->_view = $view; |
|
2591 return $this; |
|
2592 } |
|
2593 |
|
2594 /** |
|
2595 * Retrieve view object |
|
2596 * |
|
2597 * If none registered, attempts to pull from ViewRenderer. |
|
2598 * |
|
2599 * @return Zend_View_Interface|null |
|
2600 */ |
|
2601 public function getView() |
|
2602 { |
|
2603 if (null === $this->_view) { |
|
2604 require_once 'Zend/Controller/Action/HelperBroker.php'; |
|
2605 $viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer'); |
|
2606 $this->setView($viewRenderer->view); |
|
2607 } |
|
2608 |
|
2609 return $this->_view; |
|
2610 } |
|
2611 |
|
2612 /** |
|
2613 * Instantiate a decorator based on class name or class name fragment |
|
2614 * |
|
2615 * @param string $name |
|
2616 * @param null|array $options |
|
2617 * @return Zend_Form_Decorator_Interface |
|
2618 */ |
|
2619 protected function _getDecorator($name, $options) |
|
2620 { |
|
2621 $class = $this->getPluginLoader(self::DECORATOR)->load($name); |
|
2622 if (null === $options) { |
|
2623 $decorator = new $class; |
|
2624 } else { |
|
2625 $decorator = new $class($options); |
|
2626 } |
|
2627 |
|
2628 return $decorator; |
|
2629 } |
|
2630 |
|
2631 /** |
|
2632 * Add a decorator for rendering the element |
|
2633 * |
|
2634 * @param string|Zend_Form_Decorator_Interface $decorator |
|
2635 * @param array|Zend_Config $options Options with which to initialize decorator |
|
2636 * @return Zend_Form |
|
2637 */ |
|
2638 public function addDecorator($decorator, $options = null) |
|
2639 { |
|
2640 if ($decorator instanceof Zend_Form_Decorator_Interface) { |
|
2641 $name = get_class($decorator); |
|
2642 } elseif (is_string($decorator)) { |
|
2643 $name = $decorator; |
|
2644 $decorator = array( |
|
2645 'decorator' => $name, |
|
2646 'options' => $options, |
|
2647 ); |
|
2648 } elseif (is_array($decorator)) { |
|
2649 foreach ($decorator as $name => $spec) { |
|
2650 break; |
|
2651 } |
|
2652 if (is_numeric($name)) { |
|
2653 require_once 'Zend/Form/Exception.php'; |
|
2654 throw new Zend_Form_Exception('Invalid alias provided to addDecorator; must be alphanumeric string'); |
|
2655 } |
|
2656 if (is_string($spec)) { |
|
2657 $decorator = array( |
|
2658 'decorator' => $spec, |
|
2659 'options' => $options, |
|
2660 ); |
|
2661 } elseif ($spec instanceof Zend_Form_Decorator_Interface) { |
|
2662 $decorator = $spec; |
|
2663 } |
|
2664 } else { |
|
2665 require_once 'Zend/Form/Exception.php'; |
|
2666 throw new Zend_Form_Exception('Invalid decorator provided to addDecorator; must be string or Zend_Form_Decorator_Interface'); |
|
2667 } |
|
2668 |
|
2669 $this->_decorators[$name] = $decorator; |
|
2670 |
|
2671 return $this; |
|
2672 } |
|
2673 |
|
2674 /** |
|
2675 * Add many decorators at once |
|
2676 * |
|
2677 * @param array $decorators |
|
2678 * @return Zend_Form |
|
2679 */ |
|
2680 public function addDecorators(array $decorators) |
|
2681 { |
|
2682 foreach ($decorators as $decoratorName => $decoratorInfo) { |
|
2683 if (is_string($decoratorInfo) || |
|
2684 $decoratorInfo instanceof Zend_Form_Decorator_Interface) { |
|
2685 if (!is_numeric($decoratorName)) { |
|
2686 $this->addDecorator(array($decoratorName => $decoratorInfo)); |
|
2687 } else { |
|
2688 $this->addDecorator($decoratorInfo); |
|
2689 } |
|
2690 } elseif (is_array($decoratorInfo)) { |
|
2691 $argc = count($decoratorInfo); |
|
2692 $options = array(); |
|
2693 if (isset($decoratorInfo['decorator'])) { |
|
2694 $decorator = $decoratorInfo['decorator']; |
|
2695 if (isset($decoratorInfo['options'])) { |
|
2696 $options = $decoratorInfo['options']; |
|
2697 } |
|
2698 $this->addDecorator($decorator, $options); |
|
2699 } else { |
|
2700 switch (true) { |
|
2701 case (0 == $argc): |
|
2702 break; |
|
2703 case (1 <= $argc): |
|
2704 $decorator = array_shift($decoratorInfo); |
|
2705 case (2 <= $argc): |
|
2706 $options = array_shift($decoratorInfo); |
|
2707 default: |
|
2708 $this->addDecorator($decorator, $options); |
|
2709 break; |
|
2710 } |
|
2711 } |
|
2712 } else { |
|
2713 require_once 'Zend/Form/Exception.php'; |
|
2714 throw new Zend_Form_Exception('Invalid decorator passed to addDecorators()'); |
|
2715 } |
|
2716 } |
|
2717 |
|
2718 return $this; |
|
2719 } |
|
2720 |
|
2721 /** |
|
2722 * Overwrite all decorators |
|
2723 * |
|
2724 * @param array $decorators |
|
2725 * @return Zend_Form |
|
2726 */ |
|
2727 public function setDecorators(array $decorators) |
|
2728 { |
|
2729 $this->clearDecorators(); |
|
2730 return $this->addDecorators($decorators); |
|
2731 } |
|
2732 |
|
2733 /** |
|
2734 * Retrieve a registered decorator |
|
2735 * |
|
2736 * @param string $name |
|
2737 * @return false|Zend_Form_Decorator_Abstract |
|
2738 */ |
|
2739 public function getDecorator($name) |
|
2740 { |
|
2741 if (!isset($this->_decorators[$name])) { |
|
2742 $len = strlen($name); |
|
2743 foreach ($this->_decorators as $localName => $decorator) { |
|
2744 if ($len > strlen($localName)) { |
|
2745 continue; |
|
2746 } |
|
2747 |
|
2748 if (0 === substr_compare($localName, $name, -$len, $len, true)) { |
|
2749 if (is_array($decorator)) { |
|
2750 return $this->_loadDecorator($decorator, $localName); |
|
2751 } |
|
2752 return $decorator; |
|
2753 } |
|
2754 } |
|
2755 return false; |
|
2756 } |
|
2757 |
|
2758 if (is_array($this->_decorators[$name])) { |
|
2759 return $this->_loadDecorator($this->_decorators[$name], $name); |
|
2760 } |
|
2761 |
|
2762 return $this->_decorators[$name]; |
|
2763 } |
|
2764 |
|
2765 /** |
|
2766 * Retrieve all decorators |
|
2767 * |
|
2768 * @return array |
|
2769 */ |
|
2770 public function getDecorators() |
|
2771 { |
|
2772 foreach ($this->_decorators as $key => $value) { |
|
2773 if (is_array($value)) { |
|
2774 $this->_loadDecorator($value, $key); |
|
2775 } |
|
2776 } |
|
2777 return $this->_decorators; |
|
2778 } |
|
2779 |
|
2780 /** |
|
2781 * Remove a single decorator |
|
2782 * |
|
2783 * @param string $name |
|
2784 * @return bool |
|
2785 */ |
|
2786 public function removeDecorator($name) |
|
2787 { |
|
2788 $decorator = $this->getDecorator($name); |
|
2789 if ($decorator) { |
|
2790 if (array_key_exists($name, $this->_decorators)) { |
|
2791 unset($this->_decorators[$name]); |
|
2792 } else { |
|
2793 $class = get_class($decorator); |
|
2794 if (!array_key_exists($class, $this->_decorators)) { |
|
2795 return false; |
|
2796 } |
|
2797 unset($this->_decorators[$class]); |
|
2798 } |
|
2799 return true; |
|
2800 } |
|
2801 |
|
2802 return false; |
|
2803 } |
|
2804 |
|
2805 /** |
|
2806 * Clear all decorators |
|
2807 * |
|
2808 * @return Zend_Form |
|
2809 */ |
|
2810 public function clearDecorators() |
|
2811 { |
|
2812 $this->_decorators = array(); |
|
2813 return $this; |
|
2814 } |
|
2815 |
|
2816 /** |
|
2817 * Set all element decorators as specified |
|
2818 * |
|
2819 * @param array $decorators |
|
2820 * @param array|null $elements Specific elements to decorate or exclude from decoration |
|
2821 * @param bool $include Whether $elements is an inclusion or exclusion list |
|
2822 * @return Zend_Form |
|
2823 */ |
|
2824 public function setElementDecorators(array $decorators, array $elements = null, $include = true) |
|
2825 { |
|
2826 if (is_array($elements)) { |
|
2827 if ($include) { |
|
2828 $elementObjs = array(); |
|
2829 foreach ($elements as $name) { |
|
2830 if (null !== ($element = $this->getElement($name))) { |
|
2831 $elementObjs[] = $element; |
|
2832 } |
|
2833 } |
|
2834 } else { |
|
2835 $elementObjs = $this->getElements(); |
|
2836 foreach ($elements as $name) { |
|
2837 if (array_key_exists($name, $elementObjs)) { |
|
2838 unset($elementObjs[$name]); |
|
2839 } |
|
2840 } |
|
2841 } |
|
2842 } else { |
|
2843 $elementObjs = $this->getElements(); |
|
2844 } |
|
2845 |
|
2846 foreach ($elementObjs as $element) { |
|
2847 $element->setDecorators($decorators); |
|
2848 } |
|
2849 |
|
2850 $this->_elementDecorators = $decorators; |
|
2851 |
|
2852 return $this; |
|
2853 } |
|
2854 |
|
2855 /** |
|
2856 * Set all display group decorators as specified |
|
2857 * |
|
2858 * @param array $decorators |
|
2859 * @return Zend_Form |
|
2860 */ |
|
2861 public function setDisplayGroupDecorators(array $decorators) |
|
2862 { |
|
2863 foreach ($this->getDisplayGroups() as $group) { |
|
2864 $group->setDecorators($decorators); |
|
2865 } |
|
2866 |
|
2867 return $this; |
|
2868 } |
|
2869 |
|
2870 /** |
|
2871 * Set all subform decorators as specified |
|
2872 * |
|
2873 * @param array $decorators |
|
2874 * @return Zend_Form |
|
2875 */ |
|
2876 public function setSubFormDecorators(array $decorators) |
|
2877 { |
|
2878 foreach ($this->getSubForms() as $form) { |
|
2879 $form->setDecorators($decorators); |
|
2880 } |
|
2881 |
|
2882 return $this; |
|
2883 } |
|
2884 |
|
2885 /** |
|
2886 * Render form |
|
2887 * |
|
2888 * @param Zend_View_Interface $view |
|
2889 * @return string |
|
2890 */ |
|
2891 public function render(Zend_View_Interface $view = null) |
|
2892 { |
|
2893 if (null !== $view) { |
|
2894 $this->setView($view); |
|
2895 } |
|
2896 |
|
2897 $content = ''; |
|
2898 foreach ($this->getDecorators() as $decorator) { |
|
2899 $decorator->setElement($this); |
|
2900 $content = $decorator->render($content); |
|
2901 } |
|
2902 $this->_setIsRendered(); |
|
2903 return $content; |
|
2904 } |
|
2905 |
|
2906 /** |
|
2907 * Serialize as string |
|
2908 * |
|
2909 * Proxies to {@link render()}. |
|
2910 * |
|
2911 * @return string |
|
2912 */ |
|
2913 public function __toString() |
|
2914 { |
|
2915 try { |
|
2916 $return = $this->render(); |
|
2917 return $return; |
|
2918 } catch (Exception $e) { |
|
2919 $message = "Exception caught by form: " . $e->getMessage() |
|
2920 . "\nStack Trace:\n" . $e->getTraceAsString(); |
|
2921 trigger_error($message, E_USER_WARNING); |
|
2922 return ''; |
|
2923 } |
|
2924 } |
|
2925 |
|
2926 |
|
2927 // Localization: |
|
2928 |
|
2929 /** |
|
2930 * Set translator object |
|
2931 * |
|
2932 * @param Zend_Translate|Zend_Translate_Adapter|null $translator |
|
2933 * @return Zend_Form |
|
2934 */ |
|
2935 public function setTranslator($translator = null) |
|
2936 { |
|
2937 if (null === $translator) { |
|
2938 $this->_translator = null; |
|
2939 } elseif ($translator instanceof Zend_Translate_Adapter) { |
|
2940 $this->_translator = $translator; |
|
2941 } elseif ($translator instanceof Zend_Translate) { |
|
2942 $this->_translator = $translator->getAdapter(); |
|
2943 } else { |
|
2944 require_once 'Zend/Form/Exception.php'; |
|
2945 throw new Zend_Form_Exception('Invalid translator specified'); |
|
2946 } |
|
2947 |
|
2948 return $this; |
|
2949 } |
|
2950 |
|
2951 /** |
|
2952 * Set global default translator object |
|
2953 * |
|
2954 * @param Zend_Translate|Zend_Translate_Adapter|null $translator |
|
2955 * @return void |
|
2956 */ |
|
2957 public static function setDefaultTranslator($translator = null) |
|
2958 { |
|
2959 if (null === $translator) { |
|
2960 self::$_translatorDefault = null; |
|
2961 } elseif ($translator instanceof Zend_Translate_Adapter) { |
|
2962 self::$_translatorDefault = $translator; |
|
2963 } elseif ($translator instanceof Zend_Translate) { |
|
2964 self::$_translatorDefault = $translator->getAdapter(); |
|
2965 } else { |
|
2966 require_once 'Zend/Form/Exception.php'; |
|
2967 throw new Zend_Form_Exception('Invalid translator specified'); |
|
2968 } |
|
2969 } |
|
2970 |
|
2971 /** |
|
2972 * Retrieve translator object |
|
2973 * |
|
2974 * @return Zend_Translate|null |
|
2975 */ |
|
2976 public function getTranslator() |
|
2977 { |
|
2978 if ($this->translatorIsDisabled()) { |
|
2979 return null; |
|
2980 } |
|
2981 |
|
2982 if (null === $this->_translator) { |
|
2983 return self::getDefaultTranslator(); |
|
2984 } |
|
2985 |
|
2986 return $this->_translator; |
|
2987 } |
|
2988 |
|
2989 /** |
|
2990 * Does this form have its own specific translator? |
|
2991 * |
|
2992 * @return bool |
|
2993 */ |
|
2994 public function hasTranslator() |
|
2995 { |
|
2996 return (bool)$this->_translator; |
|
2997 } |
|
2998 |
|
2999 /** |
|
3000 * Get global default translator object |
|
3001 * |
|
3002 * @return null|Zend_Translate |
|
3003 */ |
|
3004 public static function getDefaultTranslator() |
|
3005 { |
|
3006 if (null === self::$_translatorDefault) { |
|
3007 require_once 'Zend/Registry.php'; |
|
3008 if (Zend_Registry::isRegistered('Zend_Translate')) { |
|
3009 $translator = Zend_Registry::get('Zend_Translate'); |
|
3010 if ($translator instanceof Zend_Translate_Adapter) { |
|
3011 return $translator; |
|
3012 } elseif ($translator instanceof Zend_Translate) { |
|
3013 return $translator->getAdapter(); |
|
3014 } |
|
3015 } |
|
3016 } |
|
3017 return self::$_translatorDefault; |
|
3018 } |
|
3019 |
|
3020 /** |
|
3021 * Is there a default translation object set? |
|
3022 * |
|
3023 * @return boolean |
|
3024 */ |
|
3025 public static function hasDefaultTranslator() |
|
3026 { |
|
3027 return (bool)self::$_translatorDefault; |
|
3028 } |
|
3029 |
|
3030 /** |
|
3031 * Indicate whether or not translation should be disabled |
|
3032 * |
|
3033 * @param bool $flag |
|
3034 * @return Zend_Form |
|
3035 */ |
|
3036 public function setDisableTranslator($flag) |
|
3037 { |
|
3038 $this->_translatorDisabled = (bool) $flag; |
|
3039 return $this; |
|
3040 } |
|
3041 |
|
3042 /** |
|
3043 * Is translation disabled? |
|
3044 * |
|
3045 * @return bool |
|
3046 */ |
|
3047 public function translatorIsDisabled() |
|
3048 { |
|
3049 return $this->_translatorDisabled; |
|
3050 } |
|
3051 |
|
3052 /** |
|
3053 * Overloading: access to elements, form groups, and display groups |
|
3054 * |
|
3055 * @param string $name |
|
3056 * @return Zend_Form_Element|Zend_Form|null |
|
3057 */ |
|
3058 public function __get($name) |
|
3059 { |
|
3060 if (isset($this->_elements[$name])) { |
|
3061 return $this->_elements[$name]; |
|
3062 } elseif (isset($this->_subForms[$name])) { |
|
3063 return $this->_subForms[$name]; |
|
3064 } elseif (isset($this->_displayGroups[$name])) { |
|
3065 return $this->_displayGroups[$name]; |
|
3066 } |
|
3067 |
|
3068 return null; |
|
3069 } |
|
3070 |
|
3071 /** |
|
3072 * Overloading: access to elements, form groups, and display groups |
|
3073 * |
|
3074 * @param string $name |
|
3075 * @param Zend_Form_Element|Zend_Form $value |
|
3076 * @return void |
|
3077 * @throws Zend_Form_Exception for invalid $value |
|
3078 */ |
|
3079 public function __set($name, $value) |
|
3080 { |
|
3081 if ($value instanceof Zend_Form_Element) { |
|
3082 $this->addElement($value, $name); |
|
3083 return; |
|
3084 } elseif ($value instanceof Zend_Form) { |
|
3085 $this->addSubForm($value, $name); |
|
3086 return; |
|
3087 } elseif (is_array($value)) { |
|
3088 $this->addDisplayGroup($value, $name); |
|
3089 return; |
|
3090 } |
|
3091 |
|
3092 require_once 'Zend/Form/Exception.php'; |
|
3093 if (is_object($value)) { |
|
3094 $type = get_class($value); |
|
3095 } else { |
|
3096 $type = gettype($value); |
|
3097 } |
|
3098 throw new Zend_Form_Exception('Only form elements and groups may be overloaded; variable of type "' . $type . '" provided'); |
|
3099 } |
|
3100 |
|
3101 /** |
|
3102 * Overloading: access to elements, form groups, and display groups |
|
3103 * |
|
3104 * @param string $name |
|
3105 * @return boolean |
|
3106 */ |
|
3107 public function __isset($name) |
|
3108 { |
|
3109 if (isset($this->_elements[$name]) |
|
3110 || isset($this->_subForms[$name]) |
|
3111 || isset($this->_displayGroups[$name])) |
|
3112 { |
|
3113 return true; |
|
3114 } |
|
3115 |
|
3116 return false; |
|
3117 } |
|
3118 |
|
3119 /** |
|
3120 * Overloading: access to elements, form groups, and display groups |
|
3121 * |
|
3122 * @param string $name |
|
3123 * @return void |
|
3124 */ |
|
3125 public function __unset($name) |
|
3126 { |
|
3127 if (isset($this->_elements[$name])) { |
|
3128 unset($this->_elements[$name]); |
|
3129 } elseif (isset($this->_subForms[$name])) { |
|
3130 unset($this->_subForms[$name]); |
|
3131 } elseif (isset($this->_displayGroups[$name])) { |
|
3132 unset($this->_displayGroups[$name]); |
|
3133 } |
|
3134 } |
|
3135 |
|
3136 /** |
|
3137 * Overloading: allow rendering specific decorators |
|
3138 * |
|
3139 * Call renderDecoratorName() to render a specific decorator. |
|
3140 * |
|
3141 * @param string $method |
|
3142 * @param array $args |
|
3143 * @return string |
|
3144 * @throws Zend_Form_Exception for invalid decorator or invalid method call |
|
3145 */ |
|
3146 public function __call($method, $args) |
|
3147 { |
|
3148 if ('render' == substr($method, 0, 6)) { |
|
3149 $decoratorName = substr($method, 6); |
|
3150 if (false !== ($decorator = $this->getDecorator($decoratorName))) { |
|
3151 $decorator->setElement($this); |
|
3152 $seed = ''; |
|
3153 if (0 < count($args)) { |
|
3154 $seed = array_shift($args); |
|
3155 } |
|
3156 if ($decoratorName === 'FormElements' || |
|
3157 $decoratorName === 'PrepareElements') { |
|
3158 $this->_setIsRendered(); |
|
3159 } |
|
3160 return $decorator->render($seed); |
|
3161 } |
|
3162 |
|
3163 require_once 'Zend/Form/Exception.php'; |
|
3164 throw new Zend_Form_Exception(sprintf('Decorator by name %s does not exist', $decoratorName)); |
|
3165 } |
|
3166 |
|
3167 require_once 'Zend/Form/Exception.php'; |
|
3168 throw new Zend_Form_Exception(sprintf('Method %s does not exist', $method)); |
|
3169 } |
|
3170 |
|
3171 // Interfaces: Iterator, Countable |
|
3172 |
|
3173 /** |
|
3174 * Current element/subform/display group |
|
3175 * |
|
3176 * @return Zend_Form_Element|Zend_Form_DisplayGroup|Zend_Form |
|
3177 */ |
|
3178 public function current() |
|
3179 { |
|
3180 $this->_sort(); |
|
3181 current($this->_order); |
|
3182 $key = key($this->_order); |
|
3183 |
|
3184 if (isset($this->_elements[$key])) { |
|
3185 return $this->getElement($key); |
|
3186 } elseif (isset($this->_subForms[$key])) { |
|
3187 return $this->getSubForm($key); |
|
3188 } elseif (isset($this->_displayGroups[$key])) { |
|
3189 return $this->getDisplayGroup($key); |
|
3190 } else { |
|
3191 require_once 'Zend/Form/Exception.php'; |
|
3192 throw new Zend_Form_Exception(sprintf('Corruption detected in form; invalid key ("%s") found in internal iterator', (string) $key)); |
|
3193 } |
|
3194 } |
|
3195 |
|
3196 /** |
|
3197 * Current element/subform/display group name |
|
3198 * |
|
3199 * @return string |
|
3200 */ |
|
3201 public function key() |
|
3202 { |
|
3203 $this->_sort(); |
|
3204 return key($this->_order); |
|
3205 } |
|
3206 |
|
3207 /** |
|
3208 * Move pointer to next element/subform/display group |
|
3209 * |
|
3210 * @return void |
|
3211 */ |
|
3212 public function next() |
|
3213 { |
|
3214 $this->_sort(); |
|
3215 next($this->_order); |
|
3216 } |
|
3217 |
|
3218 /** |
|
3219 * Move pointer to beginning of element/subform/display group loop |
|
3220 * |
|
3221 * @return void |
|
3222 */ |
|
3223 public function rewind() |
|
3224 { |
|
3225 $this->_sort(); |
|
3226 reset($this->_order); |
|
3227 } |
|
3228 |
|
3229 /** |
|
3230 * Determine if current element/subform/display group is valid |
|
3231 * |
|
3232 * @return bool |
|
3233 */ |
|
3234 public function valid() |
|
3235 { |
|
3236 $this->_sort(); |
|
3237 return (current($this->_order) !== false); |
|
3238 } |
|
3239 |
|
3240 /** |
|
3241 * Count of elements/subforms that are iterable |
|
3242 * |
|
3243 * @return int |
|
3244 */ |
|
3245 public function count() |
|
3246 { |
|
3247 return count($this->_order); |
|
3248 } |
|
3249 |
|
3250 /** |
|
3251 * Set flag to disable loading default decorators |
|
3252 * |
|
3253 * @param bool $flag |
|
3254 * @return Zend_Form |
|
3255 */ |
|
3256 public function setDisableLoadDefaultDecorators($flag) |
|
3257 { |
|
3258 $this->_disableLoadDefaultDecorators = (bool) $flag; |
|
3259 return $this; |
|
3260 } |
|
3261 |
|
3262 /** |
|
3263 * Should we load the default decorators? |
|
3264 * |
|
3265 * @return bool |
|
3266 */ |
|
3267 public function loadDefaultDecoratorsIsDisabled() |
|
3268 { |
|
3269 return $this->_disableLoadDefaultDecorators; |
|
3270 } |
|
3271 |
|
3272 /** |
|
3273 * Load the default decorators |
|
3274 * |
|
3275 * @return void |
|
3276 */ |
|
3277 public function loadDefaultDecorators() |
|
3278 { |
|
3279 if ($this->loadDefaultDecoratorsIsDisabled()) { |
|
3280 return $this; |
|
3281 } |
|
3282 |
|
3283 $decorators = $this->getDecorators(); |
|
3284 if (empty($decorators)) { |
|
3285 $this->addDecorator('FormElements') |
|
3286 ->addDecorator('HtmlTag', array('tag' => 'dl', 'class' => 'zend_form')) |
|
3287 ->addDecorator('Form'); |
|
3288 } |
|
3289 return $this; |
|
3290 } |
|
3291 |
|
3292 /** |
|
3293 * Remove an element from iteration |
|
3294 * |
|
3295 * @param string $name Element/group/form name |
|
3296 * @return void |
|
3297 */ |
|
3298 public function removeFromIteration($name) |
|
3299 { |
|
3300 if (array_key_exists($name, $this->_order)) { |
|
3301 unset($this->_order[$name]); |
|
3302 $this->_orderUpdated = true; |
|
3303 } |
|
3304 } |
|
3305 |
|
3306 /** |
|
3307 * Sort items according to their order |
|
3308 * |
|
3309 * @return void |
|
3310 */ |
|
3311 protected function _sort() |
|
3312 { |
|
3313 if ($this->_orderUpdated) { |
|
3314 $items = array(); |
|
3315 $index = 0; |
|
3316 foreach ($this->_order as $key => $order) { |
|
3317 if (null === $order) { |
|
3318 if (null === ($order = $this->{$key}->getOrder())) { |
|
3319 while (array_search($index, $this->_order, true)) { |
|
3320 ++$index; |
|
3321 } |
|
3322 $items[$index] = $key; |
|
3323 ++$index; |
|
3324 } else { |
|
3325 $items[$order] = $key; |
|
3326 } |
|
3327 } else { |
|
3328 $items[$order] = $key; |
|
3329 } |
|
3330 } |
|
3331 |
|
3332 $items = array_flip($items); |
|
3333 asort($items); |
|
3334 $this->_order = $items; |
|
3335 $this->_orderUpdated = false; |
|
3336 } |
|
3337 } |
|
3338 |
|
3339 /** |
|
3340 * Lazy-load a decorator |
|
3341 * |
|
3342 * @param array $decorator Decorator type and options |
|
3343 * @param mixed $name Decorator name or alias |
|
3344 * @return Zend_Form_Decorator_Interface |
|
3345 */ |
|
3346 protected function _loadDecorator(array $decorator, $name) |
|
3347 { |
|
3348 $sameName = false; |
|
3349 if ($name == $decorator['decorator']) { |
|
3350 $sameName = true; |
|
3351 } |
|
3352 |
|
3353 $instance = $this->_getDecorator($decorator['decorator'], $decorator['options']); |
|
3354 if ($sameName) { |
|
3355 $newName = get_class($instance); |
|
3356 $decoratorNames = array_keys($this->_decorators); |
|
3357 $order = array_flip($decoratorNames); |
|
3358 $order[$newName] = $order[$name]; |
|
3359 $decoratorsExchange = array(); |
|
3360 unset($order[$name]); |
|
3361 asort($order); |
|
3362 foreach ($order as $key => $index) { |
|
3363 if ($key == $newName) { |
|
3364 $decoratorsExchange[$key] = $instance; |
|
3365 continue; |
|
3366 } |
|
3367 $decoratorsExchange[$key] = $this->_decorators[$key]; |
|
3368 } |
|
3369 $this->_decorators = $decoratorsExchange; |
|
3370 } else { |
|
3371 $this->_decorators[$name] = $instance; |
|
3372 } |
|
3373 |
|
3374 return $instance; |
|
3375 } |
|
3376 |
|
3377 /** |
|
3378 * Retrieve optionally translated custom error messages |
|
3379 * |
|
3380 * @return array |
|
3381 */ |
|
3382 protected function _getErrorMessages() |
|
3383 { |
|
3384 $messages = $this->getErrorMessages(); |
|
3385 $translator = $this->getTranslator(); |
|
3386 if (null !== $translator) { |
|
3387 foreach ($messages as $key => $message) { |
|
3388 $messages[$key] = $translator->translate($message); |
|
3389 } |
|
3390 } |
|
3391 return $messages; |
|
3392 } |
|
3393 } |