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.
17
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
18
* @license http://framework.zend.com/license/new-bsd New BSD License
21
/** Zend_Validate_Interface */
22
require_once 'Zend/Validate/Interface.php';
29
* @copyright Copyright (c) 2005-2008 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 12787 2008-11-23 14:17:44Z matthew $
33
class Zend_Form implements Iterator, Countable, Zend_Validate_Interface
36
* Plugin loader type constants
38
const DECORATOR = 'DECORATOR';
39
const ELEMENT = 'ELEMENT';
43
* Method type constants
45
const METHOD_DELETE = 'delete';
46
const METHOD_GET = 'get';
47
const METHOD_POST = 'post';
48
const METHOD_PUT = 'put';
52
* Encoding type constants
54
const ENCTYPE_URLENCODED = 'application/x-www-form-urlencoded';
55
const ENCTYPE_MULTIPART = 'multipart/form-data';
59
* Form metadata and attributes
62
protected $_attribs = array();
65
* Decorators for rendering
68
protected $_decorators = array();
71
* Default display group class
74
protected $_defaultDisplayGroupClass = 'Zend_Form_DisplayGroup';
80
protected $_description;
83
* Should we disable loading the default decorators?
86
protected $_disableLoadDefaultDecorators = false;
89
* Display group prefix paths
92
protected $_displayGroupPrefixPaths = array();
95
* Groups of elements grouped for display purposes
98
protected $_displayGroups = array();
101
* Prefix paths to use when creating elements
104
protected $_elementPrefixPaths = array();
110
protected $_elements = array();
113
* Array to which elements belong (if any)
116
protected $_elementsBelongTo;
119
* Custom form-level error messages
122
protected $_errorMessages = array();
125
* Are there errors in the form?
128
protected $_errorsExist = false;
134
protected $_formOrder;
137
* Whether or not form elements are members of an array
140
protected $_isArray = false;
152
protected $_loaders = array();
155
* Allowed form methods
158
protected $_methods = array('delete', 'get', 'post', 'put');
161
* Order in which to display and iterate elements
164
protected $_order = array();
167
* Whether internal order has been updated or not
170
protected $_orderUpdated = false;
173
* Sub form prefix paths
176
protected $_subFormPrefixPaths = array();
182
protected $_subForms = array();
185
* @var Zend_Translate
187
protected $_translator;
190
* Global default translation adapter
191
* @var Zend_Translate
193
protected static $_translatorDefault;
196
* is the translator disabled?
199
protected $_translatorDisabled = false;
202
* @var Zend_View_Interface
209
* Registers form view helper as decorator
211
* @param mixed $options
214
public function __construct($options = null)
216
if (is_array($options)) {
217
$this->setOptions($options);
218
} elseif ($options instanceof Zend_Config) {
219
$this->setConfig($options);
225
$this->loadDefaultDecorators();
229
* Clone form object and all children
233
public function __clone()
236
foreach ($this->getElements() as $name => $element) {
237
$elements[] = clone $element;
239
$this->setElements($elements);
242
foreach ($this->getSubForms() as $name => $subForm) {
243
$subForms[$name] = clone $subForm;
245
$this->setSubForms($subForms);
247
$displayGroups = array();
248
foreach ($this->_displayGroups as $group) {
249
$clone = clone $group;
251
foreach ($clone->getElements() as $name => $e) {
252
$elements[] = $this->getElement($name);
254
$clone->setElements($elements);
255
$displayGroups[] = $clone;
257
$this->setDisplayGroups($displayGroups);
261
* Reset values of form
265
public function reset()
267
foreach ($this->getElements() as $element) {
268
$element->setValue(null);
270
foreach ($this->getSubForms() as $subForm) {
278
* Initialize form (used by extending classes)
282
public function init()
287
* Set form state from options array
289
* @param array $options
292
public function setOptions(array $options)
294
if (isset($options['prefixPath'])) {
295
$this->addPrefixPaths($options['prefixPath']);
296
unset($options['prefixPath']);
299
if (isset($options['elementPrefixPath'])) {
300
$this->addElementPrefixPaths($options['elementPrefixPath']);
301
unset($options['elementPrefixPath']);
304
if (isset($options['displayGroupPrefixPath'])) {
305
$this->addDisplayGroupPrefixPaths($options['displayGroupPrefixPath']);
306
unset($options['displayGroupPrefixPath']);
309
if (isset($options['elements'])) {
310
$this->setElements($options['elements']);
311
unset($options['elements']);
314
if (isset($options['elementDecorators'])) {
315
$elementDecorators = $options['elementDecorators'];
316
unset($options['elementDecorators']);
319
if (isset($options['defaultDisplayGroupClass'])) {
320
$this->setDefaultDisplayGroupClass($options['defaultDisplayGroupClass']);
321
unset($options['defaultDisplayGroupClass']);
324
if (isset($options['displayGroupDecorators'])) {
325
$displayGroupDecorators = $options['displayGroupDecorators'];
326
unset($options['displayGroupDecorators']);
329
if (isset($options['elementsBelongTo'])) {
330
$elementsBelongTo = $options['elementsBelongTo'];
331
unset($options['elementsBelongTo']);
334
if (isset($options['attribs'])) {
335
$this->addAttribs($options['attribs']);
336
unset($options['attribs']);
340
'Options', 'Config', 'PluginLoader', 'SubForms', 'View', 'Translator',
344
foreach ($options as $key => $value) {
345
$normalized = ucfirst($key);
346
if (in_array($normalized, $forbidden)) {
350
$method = 'set' . $normalized;
351
if (method_exists($this, $method)) {
352
$this->$method($value);
354
$this->setAttrib($key, $value);
358
if (isset($elementDecorators)) {
359
$this->setElementDecorators($elementDecorators);
362
if (isset($displayGroupDecorators)) {
363
$this->setDisplayGroupDecorators($displayGroupDecorators);
366
if (isset($elementsBelongTo)) {
367
$this->setElementsBelongTo($elementsBelongTo);
374
* Set form state from config object
376
* @param Zend_Config $config
379
public function setConfig(Zend_Config $config)
381
return $this->setOptions($config->toArray());
388
* Set plugin loaders for use with decorators and elements
390
* @param Zend_Loader_PluginLoader_Interface $loader
391
* @param string $type 'decorator' or 'element'
393
* @throws Zend_Form_Exception on invalid type
395
public function setPluginLoader(Zend_Loader_PluginLoader_Interface $loader, $type = null)
397
$type = strtoupper($type);
399
case self::DECORATOR:
401
$this->_loaders[$type] = $loader;
404
require_once 'Zend/Form/Exception.php';
405
throw new Zend_Form_Exception(sprintf('Invalid type "%s" provided to setPluginLoader()', $type));
410
* Retrieve plugin loader for given type
412
* $type may be one of:
416
* If a plugin loader does not exist for the given type, defaults are
419
* @param string $type
420
* @return Zend_Loader_PluginLoader_Interface
422
public function getPluginLoader($type = null)
424
$type = strtoupper($type);
425
if (!isset($this->_loaders[$type])) {
427
case self::DECORATOR:
428
$prefixSegment = 'Form_Decorator';
429
$pathSegment = 'Form/Decorator';
432
$prefixSegment = 'Form_Element';
433
$pathSegment = 'Form/Element';
436
require_once 'Zend/Form/Exception.php';
437
throw new Zend_Form_Exception(sprintf('Invalid type "%s" provided to getPluginLoader()', $type));
440
require_once 'Zend/Loader/PluginLoader.php';
441
$this->_loaders[$type] = new Zend_Loader_PluginLoader(
442
array('Zend_' . $prefixSegment . '_' => 'Zend/' . $pathSegment . '/')
446
return $this->_loaders[$type];
450
* Add prefix path for plugin loader
452
* If no $type specified, assumes it is a base path for both filters and
453
* validators, and sets each according to the following rules:
454
* - decorators: $prefix = $prefix . '_Decorator'
455
* - elements: $prefix = $prefix . '_Element'
457
* Otherwise, the path prefix is set on the appropriate plugin loader.
459
* If $type is 'decorators', sets the path in the decorator plugin loader
460
* for all elements. Additionally, if no $type is provided,
461
* {@link Zend_Form_Element::addPrefixPath()} is called on each element.
463
* @param string $path
465
* @throws Zend_Form_Exception for invalid type
467
public function addPrefixPath($prefix, $path, $type = null)
469
$type = strtoupper($type);
471
case self::DECORATOR:
473
$loader = $this->getPluginLoader($type);
474
$loader->addPrefixPath($prefix, $path);
477
$prefix = rtrim($prefix, '_');
478
$path = rtrim($path, DIRECTORY_SEPARATOR);
479
foreach (array(self::DECORATOR, self::ELEMENT) as $type) {
480
$cType = ucfirst(strtolower($type));
481
$pluginPath = $path . DIRECTORY_SEPARATOR . $cType . DIRECTORY_SEPARATOR;
482
$pluginPrefix = $prefix . '_' . $cType;
483
$loader = $this->getPluginLoader($type);
484
$loader->addPrefixPath($pluginPrefix, $pluginPath);
488
require_once 'Zend/Form/Exception.php';
489
throw new Zend_Form_Exception(sprintf('Invalid type "%s" provided to getPluginLoader()', $type));
494
* Add many prefix paths at once
499
public function addPrefixPaths(array $spec)
501
if (isset($spec['prefix']) && isset($spec['path'])) {
502
return $this->addPrefixPath($spec['prefix'], $spec['path']);
504
foreach ($spec as $type => $paths) {
505
if (is_numeric($type) && is_array($paths)) {
507
if (isset($paths['prefix']) && isset($paths['path'])) {
508
if (isset($paths['type'])) {
509
$type = $paths['type'];
511
$this->addPrefixPath($paths['prefix'], $paths['path'], $type);
513
} elseif (!is_numeric($type)) {
514
if (!isset($paths['prefix']) || !isset($paths['path'])) {
517
$this->addPrefixPath($paths['prefix'], $paths['path'], $type);
524
* Add prefix path for all elements
526
* @param string $prefix
527
* @param string $path
528
* @param string $type
531
public function addElementPrefixPath($prefix, $path, $type = null)
533
$this->_elementPrefixPaths[] = array(
539
foreach ($this->getElements() as $element) {
540
$element->addPrefixPath($prefix, $path, $type);
543
foreach ($this->getSubForms() as $subForm) {
544
$subForm->addElementPrefixPath($prefix, $path, $type);
551
* Add prefix paths for all elements
556
public function addElementPrefixPaths(array $spec)
558
$this->_elementPrefixPaths = $this->_elementPrefixPaths + $spec;
560
foreach ($this->getElements() as $element) {
561
$element->addPrefixPaths($spec);
568
* Add prefix path for all display groups
570
* @param string $prefix
571
* @param string $path
574
public function addDisplayGroupPrefixPath($prefix, $path)
576
$this->_displayGroupPrefixPaths[] = array(
581
foreach ($this->getDisplayGroups() as $group) {
582
$group->addPrefixPath($prefix, $path);
589
* Add multiple display group prefix paths at once
594
public function addDisplayGroupPrefixPaths(array $spec)
596
foreach ($spec as $key => $value) {
597
if (is_string($value) && !is_numeric($key)) {
598
$this->addDisplayGroupPrefixPath($key, $value);
602
if (is_string($value) && is_numeric($key)) {
606
if (is_array($value)) {
607
$count = count($value);
608
if (array_keys($value) === range(0, $count - 1)) {
612
$prefix = array_shift($value);
613
$path = array_shift($value);
614
$this->addDisplayGroupPrefixPath($prefix, $path);
617
if (array_key_exists('prefix', $value) && array_key_exists('path', $value)) {
618
$this->addDisplayGroupPrefixPath($value['prefix'], $value['path']);
631
* @param mixed $value
634
public function setAttrib($key, $value)
636
$key = (string) $key;
637
$this->_attribs[$key] = $value;
642
* Add multiple form attributes at once
644
* @param array $attribs
647
public function addAttribs(array $attribs)
649
foreach ($attribs as $key => $value) {
650
$this->setAttrib($key, $value);
656
* Set multiple form attributes at once
658
* Overwrites any previously set attributes.
660
* @param array $attribs
663
public function setAttribs(array $attribs)
665
$this->clearAttribs();
666
return $this->addAttribs($attribs);
670
* Retrieve a single form attribute
675
public function getAttrib($key)
677
$key = (string) $key;
678
if (!isset($this->_attribs[$key])) {
682
return $this->_attribs[$key];
686
* Retrieve all form attributes/metadata
690
public function getAttribs()
692
return $this->_attribs;
701
public function removeAttrib($key)
703
if (isset($this->_attribs[$key])) {
704
unset($this->_attribs[$key]);
712
* Clear all form attributes
716
public function clearAttribs()
718
$this->_attribs = array();
725
* @param string $action
728
public function setAction($action)
730
return $this->setAttrib('action', (string) $action);
736
* Sets default to '' if not set.
740
public function getAction()
742
$action = $this->getAttrib('action');
743
if (null === $action) {
745
$this->setAction($action);
753
* Only values in {@link $_methods()} allowed
755
* @param string $method
757
* @throws Zend_Form_Exception
759
public function setMethod($method)
761
$method = strtolower($method);
762
if (!in_array($method, $this->_methods)) {
763
require_once 'Zend/Form/Exception.php';
764
throw new Zend_Form_Exception(sprintf('"%s" is an invalid form method', $method));
766
$this->setAttrib('method', $method);
771
* Retrieve form method
775
public function getMethod()
777
if (null === ($method = $this->getAttrib('method'))) {
778
$method = self::METHOD_POST;
779
$this->setAttrib('method', $method);
781
return strtolower($method);
787
* @param string $value
790
public function setEnctype($value)
792
$this->setAttrib('enctype', $value);
801
public function getEnctype()
803
if (null === ($enctype = $this->getAttrib('enctype'))) {
804
$enctype = self::ENCTYPE_URLENCODED;
805
$this->setAttrib('enctype', $enctype);
807
return $this->getAttrib('enctype');
811
* Filter a name to only allow valid variable characters
813
* @param string $value
814
* @param bool $allowBrackets
817
public function filterName($value, $allowBrackets = false)
819
$charset = '^a-zA-Z0-9_\x7f-\xff';
820
if ($allowBrackets) {
823
return preg_replace('/[' . $charset . ']/', '', (string) $value);
829
* @param string $name
832
public function setName($name)
834
$name = $this->filterName($name);
835
if (('0' !== $name) && empty($name)) {
836
require_once 'Zend/Form/Exception.php';
837
throw new Zend_Form_Exception('Invalid name provided; must contain only valid variable characters and be non-empty');
840
return $this->setAttrib('name', $name);
846
* @return null|string
848
public function getName()
850
return $this->getAttrib('name');
854
* Get fully qualified name
856
* Places name as subitem of array and/or appends brackets.
860
public function getFullyQualifiedName()
862
return $this->getName();
870
public function getId()
872
if (null !== ($id = $this->getAttrib('id'))) {
876
$id = $this->getFullyQualifiedName();
878
// Bail early if no array notation detected
879
if (!strstr($id, '[')) {
883
// Strip array notation
884
if ('[]' == substr($id, -2)) {
885
$id = substr($id, 0, strlen($id) - 2);
887
$id = str_replace('][', '-', $id);
888
$id = str_replace(array(']', '['), '-', $id);
889
$id = trim($id, '-');
897
* @param string $value
900
public function setLegend($value)
902
$this->_legend = (string) $value;
911
public function getLegend()
913
return $this->_legend;
917
* Set form description
919
* @param string $value
922
public function setDescription($value)
924
$this->_description = (string) $value;
929
* Retrieve form description
933
public function getDescription()
935
return $this->_description;
944
public function setOrder($index)
946
$this->_formOrder = (int) $index;
955
public function getOrder()
957
return $this->_formOrder;
960
// Element interaction:
965
* $element may be either a string element type, or an object of type
966
* Zend_Form_Element. If a string element type is provided, $name must be
967
* provided, and $options may be optionally provided for configuring the
970
* If a Zend_Form_Element is provided, $name may be optionally provided,
971
* and any provided $options will be ignored.
973
* @param string|Zend_Form_Element $element
974
* @param string $name
975
* @param array|Zend_Config $options
978
public function addElement($element, $name = null, $options = null)
980
if (is_string($element)) {
981
if (null === $name) {
982
require_once 'Zend/Form/Exception.php';
983
throw new Zend_Form_Exception('Elements specified by string must have an accompanying name');
986
$this->_elements[$name] = $this->createElement($element, $name, $options);
987
} elseif ($element instanceof Zend_Form_Element) {
988
$prefixPaths = array();
989
$prefixPaths['decorator'] = $this->getPluginLoader('decorator')->getPaths();
990
if (!empty($this->_elementPrefixPaths)) {
991
$prefixPaths = array_merge($prefixPaths, $this->_elementPrefixPaths);
994
if (null === $name) {
995
$name = $element->getName();
998
$this->_elements[$name] = $element;
999
$this->_elements[$name]->addPrefixPaths($prefixPaths);
1002
$this->_order[$name] = $this->_elements[$name]->getOrder();
1003
$this->_orderUpdated = true;
1004
$this->_setElementsBelongTo($name);
1012
* Acts as a factory for creating elements. Elements created with this
1013
* method will not be attached to the form, but will contain element
1014
* settings as specified in the form object (including plugin loader
1015
* prefix paths, default decorators, etc.).
1017
* @param string $type
1018
* @param string $name
1019
* @param array|Zend_Config $options
1020
* @return Zend_Form_Element
1022
public function createElement($type, $name, $options = null)
1024
if (!is_string($type)) {
1025
require_once 'Zend/Form/Exception.php';
1026
throw new Zend_Form_Exception('Element type must be a string indicating type');
1029
if (!is_string($name)) {
1030
require_once 'Zend/Form/Exception.php';
1031
throw new Zend_Form_Exception('Element name must be a string');
1034
$prefixPaths = array();
1035
$prefixPaths['decorator'] = $this->getPluginLoader('decorator')->getPaths();
1036
if (!empty($this->_elementPrefixPaths)) {
1037
$prefixPaths = array_merge($prefixPaths, $this->_elementPrefixPaths);
1040
if ($options instanceof Zend_Config) {
1041
$options = $options->toArray();
1044
if ((null === $options) || !is_array($options)) {
1045
$options = array('prefixPath' => $prefixPaths);
1046
} elseif (is_array($options)) {
1047
if (array_key_exists('prefixPath', $options)) {
1048
$options['prefixPath'] = array_merge($prefixPaths, $options['prefixPath']);
1050
$options['prefixPath'] = $prefixPaths;
1054
$class = $this->getPluginLoader(self::ELEMENT)->load($type);
1055
$element = new $class($name, $options);
1061
* Add multiple elements at once
1063
* @param array $elements
1066
public function addElements(array $elements)
1068
foreach ($elements as $key => $spec) {
1070
if (!is_numeric($key)) {
1074
if (is_string($spec) || ($spec instanceof Zend_Form_Element)) {
1075
$this->addElement($spec, $name);
1079
if (is_array($spec)) {
1080
$argc = count($spec);
1082
if (isset($spec['type'])) {
1083
$type = $spec['type'];
1084
if (isset($spec['name'])) {
1085
$name = $spec['name'];
1087
if (isset($spec['options'])) {
1088
$options = $spec['options'];
1090
$this->addElement($type, $name, $options);
1096
$type = array_shift($spec);
1098
if (null === $name) {
1099
$name = array_shift($spec);
1101
$options = array_shift($spec);
1104
if (empty($options)) {
1105
$options = array_shift($spec);
1108
$this->addElement($type, $name, $options);
1117
* Set form elements (overwrites existing elements)
1119
* @param array $elements
1122
public function setElements(array $elements)
1124
$this->clearElements();
1125
return $this->addElements($elements);
1129
* Retrieve a single element
1131
* @param string $name
1132
* @return Zend_Form_Element|null
1134
public function getElement($name)
1136
if (array_key_exists($name, $this->_elements)) {
1137
return $this->_elements[$name];
1143
* Retrieve all elements
1147
public function getElements()
1149
return $this->_elements;
1155
* @param string $name
1158
public function removeElement($name)
1160
$name = (string) $name;
1161
if (isset($this->_elements[$name])) {
1162
unset($this->_elements[$name]);
1163
if (array_key_exists($name, $this->_order)) {
1164
unset($this->_order[$name]);
1165
$this->_orderUpdated = true;
1167
foreach ($this->_displayGroups as $group) {
1168
if (null !== $group->getElement($name)) {
1169
$group->removeElement($name);
1180
* Remove all form elements
1184
public function clearElements()
1186
foreach (array_keys($this->_elements) as $key) {
1187
if (array_key_exists($key, $this->_order)) {
1188
unset($this->_order[$key]);
1191
$this->_elements = array();
1192
$this->_orderUpdated = true;
1197
* Set default values for elements
1199
* If an element's name is not specified as a key in the array, its value
1202
* @param array $defaults
1205
public function setDefaults(array $defaults)
1207
foreach ($this->getElements() as $name => $element) {
1208
if (array_key_exists($name, $defaults)) {
1209
$this->setDefault($name, $defaults[$name]);
1212
foreach ($this->getSubForms() as $name => $form) {
1213
if (array_key_exists($name, $defaults)) {
1214
$form->setDefaults($defaults[$name]);
1216
$form->setDefaults($defaults);
1223
* Set default value for an element
1225
* @param string $name
1226
* @param mixed $value
1229
public function setDefault($name, $value)
1231
$name = (string) $name;
1232
if ($element = $this->getElement($name)) {
1233
$element->setValue($value);
1235
if (is_scalar($value)) {
1236
foreach ($this->getSubForms() as $subForm) {
1237
$subForm->setDefault($name, $value);
1239
} elseif (is_array($value) && ($subForm = $this->getSubForm($name))) {
1240
$subForm->setDefaults($value);
1247
* Retrieve value for single element
1249
* @param string $name
1252
public function getValue($name)
1254
if ($element = $this->getElement($name)) {
1255
return $element->getValue();
1258
if ($subForm = $this->getSubForm($name)) {
1259
return $subForm->getValues(true);
1262
foreach ($this->getSubForms() as $subForm) {
1263
if ($name == $subForm->getElementsBelongTo()) {
1264
return $subForm->getValues(true);
1271
* Retrieve all form element values
1273
* @param bool $suppressArrayNotation
1276
public function getValues($suppressArrayNotation = false)
1279
foreach ($this->getElements() as $key => $element) {
1280
if (!$element->getIgnore()) {
1281
$values[$key] = $element->getValue();
1284
foreach ($this->getSubForms() as $key => $subForm) {
1285
$fValues = $this->_attachToArray($subForm->getValues(true), $subForm->getElementsBelongTo());
1286
$values = array_merge($values, $fValues);
1289
if (!$suppressArrayNotation && $this->isArray()) {
1290
$values = $this->_attachToArray($values, $this->getElementsBelongTo());
1297
* Get unfiltered element value
1299
* @param string $name
1302
public function getUnfilteredValue($name)
1304
if ($element = $this->getElement($name)) {
1305
return $element->getUnfilteredValue();
1311
* Retrieve all unfiltered element values
1315
public function getUnfilteredValues()
1318
foreach ($this->getElements() as $key => $element) {
1319
$values[$key] = $element->getUnfilteredValue();
1326
* Set all elements' filters
1328
* @param array $filters
1331
public function setElementFilters(array $filters)
1333
foreach ($this->getElements() as $element) {
1334
$element->setFilters($filters);
1340
* Set name of array elements belong to
1342
* @param string $array
1345
public function setElementsBelongTo($array)
1347
$origName = $this->getElementsBelongTo();
1348
$name = $this->filterName($array, true);
1352
$this->_elementsBelongTo = $name;
1354
if (null === $name) {
1355
$this->setIsArray(false);
1356
if (null !== $origName) {
1357
$this->_setElementsBelongTo();
1360
$this->setIsArray(true);
1361
$this->_setElementsBelongTo();
1368
* Set array to which elements belong
1370
* @param string $name Element name
1373
protected function _setElementsBelongTo($name = null)
1375
$array = $this->getElementsBelongTo();
1377
if (null === $array) {
1381
if (null === $name) {
1382
foreach ($this->getElements() as $element) {
1383
$element->setBelongsTo($array);
1386
if (null !== ($element = $this->getElement($name))) {
1387
$element->setBelongsTo($array);
1393
* Get name of array elements belong to
1395
* @return string|null
1397
public function getElementsBelongTo()
1399
if ((null === $this->_elementsBelongTo) && $this->isArray()) {
1400
$name = $this->getName();
1401
if (!empty($name)) {
1405
return $this->_elementsBelongTo;
1409
* Set flag indicating elements belong to array
1411
* @param bool $flag Value of flag
1414
public function setIsArray($flag)
1416
$this->_isArray = (bool) $flag;
1421
* Get flag indicating if elements belong to an array
1425
public function isArray()
1427
return $this->_isArray;
1433
* Add a form group/subform
1435
* @param Zend_Form $form
1436
* @param string $name
1440
public function addSubForm(Zend_Form $form, $name, $order = null)
1442
$name = (string) $name;
1443
foreach ($this->_loaders as $type => $loader) {
1444
$loaderPaths = $loader->getPaths();
1445
foreach ($loaderPaths as $prefix => $paths) {
1446
foreach ($paths as $path) {
1447
$form->addPrefixPath($prefix, $path, $type);
1452
if (!empty($this->_elementPrefixPaths)) {
1453
foreach ($this->_elementPrefixPaths as $spec) {
1454
list($prefix, $path, $type) = array_values($spec);
1455
$form->addElementPrefixPath($prefix, $path, $type);
1459
if (!empty($this->_displayGroupPrefixPaths)) {
1460
foreach ($this->_displayGroupPrefixPaths as $spec) {
1461
list($prefix, $path) = array_values($spec);
1462
$form->addDisplayGroupPrefixPath($prefix, $path);
1466
if (null !== $order) {
1467
$form->setOrder($order);
1470
$form->setName($name);
1471
$this->_subForms[$name] = $form;
1472
$this->_order[$name] = $order;
1473
$this->_orderUpdated = true;
1478
* Add multiple form subForms/subforms at once
1480
* @param array $subForms
1483
public function addSubForms(array $subForms)
1485
foreach ($subForms as $key => $spec) {
1487
if (!is_numeric($key)) {
1491
if ($spec instanceof Zend_Form) {
1492
$this->addSubForm($spec, $name);
1496
if (is_array($spec)) {
1497
$argc = count($spec);
1503
$subForm = array_shift($spec);
1505
$name = array_shift($spec);
1507
$order = array_shift($spec);
1509
$this->addSubForm($subForm, $name, $order);
1517
* Set multiple form subForms/subforms (overwrites)
1519
* @param array $subForms
1522
public function setSubForms(array $subForms)
1524
$this->clearSubForms();
1525
return $this->addSubForms($subForms);
1529
* Retrieve a form subForm/subform
1531
* @param string $name
1532
* @return Zend_Form|null
1534
public function getSubForm($name)
1536
$name = (string) $name;
1537
if (isset($this->_subForms[$name])) {
1538
return $this->_subForms[$name];
1544
* Retrieve all form subForms/subforms
1548
public function getSubForms()
1550
return $this->_subForms;
1554
* Remove form subForm/subform
1556
* @param string $name
1559
public function removeSubForm($name)
1561
$name = (string) $name;
1562
if (array_key_exists($name, $this->_subForms)) {
1563
unset($this->_subForms[$name]);
1564
if (array_key_exists($name, $this->_order)) {
1565
unset($this->_order[$name]);
1566
$this->_orderUpdated = true;
1575
* Remove all form subForms/subforms
1579
public function clearSubForms()
1581
foreach (array_keys($this->_subForms) as $key) {
1582
if (array_key_exists($key, $this->_order)) {
1583
unset($this->_order[$key]);
1586
$this->_subForms = array();
1587
$this->_orderUpdated = true;
1595
* Set default display group class
1597
* @param string $class
1600
public function setDefaultDisplayGroupClass($class)
1602
$this->_defaultDisplayGroupClass = (string) $class;
1607
* Retrieve default display group class
1611
public function getDefaultDisplayGroupClass()
1613
return $this->_defaultDisplayGroupClass;
1617
* Add a display group
1619
* Groups named elements for display purposes.
1621
* If a referenced element does not yet exist in the form, it is omitted.
1623
* @param array $elements
1624
* @param string $name
1625
* @param array|Zend_Config $options
1627
* @throws Zend_Form_Exception if no valid elements provided
1629
public function addDisplayGroup(array $elements, $name, $options = null)
1632
foreach ($elements as $element) {
1633
if (isset($this->_elements[$element])) {
1634
$add = $this->getElement($element);
1635
if (null !== $add) {
1636
unset($this->_order[$element]);
1641
if (empty($group)) {
1642
require_once 'Zend/Form/Exception.php';
1643
throw new Zend_Form_Exception('No valid elements specified for display group');
1646
$name = (string) $name;
1648
if (is_array($options)) {
1649
$options['elements'] = $group;
1650
} elseif ($options instanceof Zend_Config) {
1651
$options = $options->toArray();
1652
$options['elements'] = $group;
1654
$options = array('elements' => $group);
1657
if (isset($options['displayGroupClass'])) {
1658
$class = $options['displayGroupClass'];
1659
unset($options['displayGroupClass']);
1661
$class = $this->getDefaultDisplayGroupClass();
1664
if (!class_exists($class)) {
1665
require_once 'Zend/Loader.php';
1666
Zend_Loader::loadClass($class);
1668
$this->_displayGroups[$name] = new $class(
1670
$this->getPluginLoader(self::DECORATOR),
1674
if (!empty($this->_displayGroupPrefixPaths)) {
1675
$this->_displayGroups[$name]->addPrefixPaths($this->_displayGroupPrefixPaths);
1678
$this->_order[$name] = $this->_displayGroups[$name]->getOrder();
1679
$this->_orderUpdated = true;
1684
* Add a display group object (used with cloning)
1686
* @param Zend_Form_DisplayGroup $group
1687
* @param string|null $name
1690
protected function _addDisplayGroupObject(Zend_Form_DisplayGroup $group, $name = null)
1692
if (null === $name) {
1693
$name = $group->getName();
1695
require_once 'Zend/Form/Exception.php';
1696
throw new Zend_Form_Exception('Invalid display group added; requires name');
1700
$this->_displayGroups[$name] = $group;
1702
if (!empty($this->_displayGroupPrefixPaths)) {
1703
$this->_displayGroups[$name]->addPrefixPaths($this->_displayGroupPrefixPaths);
1706
$this->_order[$name] = $this->_displayGroups[$name]->getOrder();
1707
$this->_orderUpdated = true;
1712
* Add multiple display groups at once
1714
* @param array $groups
1717
public function addDisplayGroups(array $groups)
1719
foreach ($groups as $key => $spec) {
1721
if (!is_numeric($key)) {
1725
if ($spec instanceof Zend_Form_DisplayGroup) {
1726
$this->_addDisplayGroupObject($spec);
1729
if (!is_array($spec) || empty($spec)) {
1733
$argc = count($spec);
1736
if (isset($spec['elements'])) {
1737
$elements = $spec['elements'];
1738
if (isset($spec['name'])) {
1739
$name = $spec['name'];
1741
if (isset($spec['options'])) {
1742
$options = $spec['options'];
1744
$this->addDisplayGroup($elements, $name, $options);
1748
$elements = array_shift($spec);
1749
if (!is_array($elements) && (null !== $name)) {
1750
$elements = array_merge((array) $elements, $spec);
1751
$this->addDisplayGroup($elements, $name);
1755
if (null !== $name) {
1756
$options = array_shift($spec);
1757
$this->addDisplayGroup($elements, $name, $options);
1760
$name = array_shift($spec);
1762
$options = array_shift($spec);
1764
$this->addDisplayGroup($elements, $name, $options);
1772
* Add multiple display groups (overwrites)
1774
* @param array $groups
1777
public function setDisplayGroups(array $groups)
1779
return $this->clearDisplayGroups()
1780
->addDisplayGroups($groups);
1784
* Return a display group
1786
* @param string $name
1787
* @return array|null
1789
public function getDisplayGroup($name)
1791
$name = (string) $name;
1792
if (isset($this->_displayGroups[$name])) {
1793
return $this->_displayGroups[$name];
1800
* Return all display groups
1804
public function getDisplayGroups()
1806
return $this->_displayGroups;
1810
* Remove a display group by name
1812
* @param string $name
1815
public function removeDisplayGroup($name)
1817
$name = (string) $name;
1818
if (array_key_exists($name, $this->_displayGroups)) {
1819
foreach ($this->_displayGroups[$name] as $key => $element) {
1820
if (array_key_exists($key, $this->_elements)) {
1821
$this->_order[$key] = $element->getOrder();
1822
$this->_orderUpdated = true;
1825
unset($this->_displayGroups[$name]);
1827
if (array_key_exists($name, $this->_order)) {
1828
unset($this->_order[$name]);
1829
$this->_orderUpdated = true;
1838
* Remove all display groups
1842
public function clearDisplayGroups()
1844
foreach ($this->_displayGroups as $key => $group) {
1845
if (array_key_exists($key, $this->_order)) {
1846
unset($this->_order[$key]);
1848
foreach ($group as $name => $element) {
1849
if (isset($this->_elements[$name])) {
1850
$this->_order[$name] = $element->getOrder();
1852
$this->_order[$name] = $element->getOrder();
1855
$this->_displayGroups = array();
1856
$this->_orderUpdated = true;
1866
* Proxies to {@link setDefaults()}
1868
* @param array $values
1871
public function populate(array $values)
1873
return $this->setDefaults($values);
1877
* Determine array key name from given value
1879
* Given a value such as foo[bar][baz], returns the last element (in this case, 'baz').
1881
* @param string $value
1884
protected function _getArrayName($value)
1886
if (empty($value) || !is_string($value)) {
1890
if (!strstr($value, '[')) {
1894
$endPos = strlen($value) - 1;
1895
if (']' != $value[$endPos]) {
1899
$start = strrpos($value, '[') + 1;
1900
$name = substr($value, $start, $endPos - $start);
1905
* Extract the value by walking the array using given array path.
1907
* Given an array path such as foo[bar][baz], returns the value of the last
1908
* element (in this case, 'baz').
1910
* @param array $value Array to walk
1911
* @param string $arrayPath Array notation path of the part to extract
1914
protected function _dissolveArrayValue($value, $arrayPath)
1916
// As long as we have more levels
1917
while ($arrayPos = strpos($arrayPath, '[')) {
1918
// Get the next key in the path
1919
$arrayKey = trim(substr($arrayPath, 0, $arrayPos), ']');
1921
// Set the potentially final value or the next search point in the array
1922
if (isset($value[$arrayKey])) {
1923
$value = $value[$arrayKey];
1926
// Set the next search point in the path
1927
$arrayPath = trim(substr($arrayPath, $arrayPos + 1), ']');
1930
if (isset($value[$arrayPath])) {
1931
$value = $value[$arrayPath];
1938
* Converts given arrayPath to an array and attaches given value at the end of it.
1940
* @param mixed $value The value to attach
1941
* @param string $arrayPath Given array path to convert and attach to.
1944
protected function _attachToArray($value, $arrayPath)
1946
// As long as we have more levels
1947
while ($arrayPos = strrpos($arrayPath, '[')) {
1948
// Get the next key in the path
1949
$arrayKey = trim(substr($arrayPath, $arrayPos + 1), ']');
1952
$value = array($arrayKey => $value);
1954
// Set the next search point in the path
1955
$arrayPath = trim(substr($arrayPath, 0, $arrayPos), ']');
1958
$value = array($arrayPath => $value);
1966
* @param array $data
1969
public function isValid($data)
1971
if (!is_array($data)) {
1972
require_once 'Zend/Form/Exception.php';
1973
throw new Zend_Form_Exception(__CLASS__ . '::' . __METHOD__ . ' expects an array');
1975
$translator = $this->getTranslator();
1978
if ($this->isArray()) {
1979
$data = $this->_dissolveArrayValue($data, $this->getElementsBelongTo());
1982
foreach ($this->getElements() as $key => $element) {
1983
$element->setTranslator($translator);
1984
if (!isset($data[$key])) {
1985
$valid = $element->isValid(null, $data) && $valid;
1987
$valid = $element->isValid($data[$key], $data) && $valid;
1990
foreach ($this->getSubForms() as $key => $form) {
1991
$form->setTranslator($translator);
1992
if (isset($data[$key])) {
1993
$valid = $form->isValid($data[$key]) && $valid;
1995
$valid = $form->isValid($data) && $valid;
1999
$this->_errorsExist = !$valid;
2004
* Validate a partial form
2006
* Does not check for required flags.
2008
* @param array $data
2011
public function isValidPartial(array $data)
2013
if ($this->isArray()) {
2014
$data = $this->_dissolveArrayValue($data, $this->getElementsBelongTo());
2017
$translator = $this->getTranslator();
2019
$validatedSubForms = array();
2021
foreach ($data as $key => $value) {
2022
if (null !== ($element = $this->getElement($key))) {
2023
if (null !== $translator) {
2024
$element->setTranslator($translator);
2026
$valid = $element->isValid($value, $data) && $valid;
2027
} elseif (null !== ($subForm = $this->getSubForm($key))) {
2028
if (null !== $translator) {
2029
$subForm->setTranslator($translator);
2031
$valid = $subForm->isValidPartial($data[$key]) && $valid;
2032
$validatedSubForms[] = $key;
2035
foreach ($this->getSubForms() as $key => $subForm) {
2036
if (!in_array($key, $validatedSubForms)) {
2037
if (null !== $translator) {
2038
$subForm->setTranslator($translator);
2041
$valid = $subForm->isValidPartial($data) && $valid;
2045
$this->_errorsExist = !$valid;
2050
* Process submitted AJAX data
2052
* Checks if provided $data is valid, via {@link isValidPartial()}. If so,
2053
* it returns JSON-encoded boolean true. If not, it returns JSON-encoded
2054
* error messages (as returned by {@link getMessages()}).
2056
* @param array $data
2057
* @return string JSON-encoded boolean true or error messages
2059
public function processAjax(array $data)
2061
require_once 'Zend/Json.php';
2062
if ($this->isValidPartial($data)) {
2063
return Zend_Json::encode(true);
2065
$messages = $this->getMessages();
2066
return Zend_Json::encode($messages);
2070
* Add a custom error message to return in the event of failed validation
2072
* @param string $message
2075
public function addErrorMessage($message)
2077
$this->_errorMessages[] = (string) $message;
2082
* Add multiple custom error messages to return in the event of failed validation
2084
* @param array $messages
2087
public function addErrorMessages(array $messages)
2089
foreach ($messages as $message) {
2090
$this->addErrorMessage($message);
2096
* Same as addErrorMessages(), but clears custom error message stack first
2098
* @param array $messages
2101
public function setErrorMessages(array $messages)
2103
$this->clearErrorMessages();
2104
return $this->addErrorMessages($messages);
2108
* Retrieve custom error messages
2112
public function getErrorMessages()
2114
return $this->_errorMessages;
2118
* Clear custom error messages stack
2122
public function clearErrorMessages()
2124
$this->_errorMessages = array();
2129
* Mark the element as being in a failed validation state
2133
public function markAsError()
2135
$this->_errorsExist = true;
2140
* Add an error message and mark element as failed validation
2142
* @param string $message
2145
public function addError($message)
2147
$this->addErrorMessage($message);
2148
$this->markAsError();
2153
* Add multiple error messages and flag element as failed validation
2155
* @param array $messages
2158
public function addErrors(array $messages)
2160
foreach ($messages as $message) {
2161
$this->addError($message);
2167
* Overwrite any previously set error messages and flag as failed validation
2169
* @param array $messages
2172
public function setErrors(array $messages)
2174
$this->clearErrorMessages();
2175
return $this->addErrors($messages);
2179
public function persistData()
2184
* Are there errors in the form?
2188
public function isErrors()
2190
return $this->_errorsExist;
2194
* Get error codes for all elements failing validation
2196
* @param string $name
2199
public function getErrors($name = null)
2202
if ((null !== $name) && isset($this->_elements[$name])) {
2203
$errors = $this->getElement($name)->getErrors();
2204
} elseif ((null !== $name) && isset($this->_subForms[$name])) {
2205
$errors = $this->getSubForm($name)->getErrors();
2207
foreach ($this->_elements as $key => $element) {
2208
$errors[$key] = $element->getErrors();
2210
foreach ($this->getSubForms() as $key => $subForm) {
2211
$fErrors = $this->_attachToArray($subForm->getErrors(), $subForm->getElementsBelongTo());
2212
$errors = array_merge($errors, $fErrors);
2219
* Retrieve error messages from elements failing validations
2221
* @param string $name
2222
* @param bool $suppressArrayNotation
2225
public function getMessages($name = null, $suppressArrayNotation = false)
2227
if ((null !== $name) && isset($this->_elements[$name])) {
2228
return $this->getElement($name)->getMessages();
2231
if ((null !== $name) && isset($this->_subForms[$name])) {
2232
return $this->getSubForm($name)->getMessages(null, true);
2235
$arrayKeys = array();
2236
foreach ($this->getSubForms() as $key => $subForm) {
2237
$array = $this->_getArrayName($subForm->getElementsBelongTo());
2238
if (!empty($array)) {
2239
if ($name == $array) {
2240
return $subForm->getMessages(null, true);
2242
$arrayKeys[$key] = $subForm->getElementsBelongTo();
2246
$customMessages = $this->_getErrorMessages();
2247
if ($this->isErrors() && !empty($customMessages)) {
2248
return $customMessages;
2251
$messages = array();
2253
foreach ($this->getElements() as $name => $element) {
2254
$eMessages = $element->getMessages();
2255
if (!empty($eMessages)) {
2256
$messages[$name] = $eMessages;
2260
foreach ($this->getSubForms() as $key => $subForm) {
2261
$fMessages = $subForm->getMessages(null, true);
2262
if (!empty($fMessages)) {
2263
if (array_key_exists($key, $arrayKeys)) {
2264
$fMessages = $this->_attachToArray($fMessages, $arrayKeys[$key]);
2265
$messages = array_merge($messages, $fMessages);
2267
$messages[$key] = $fMessages;
2272
if (!$suppressArrayNotation && $this->isArray()) {
2273
$messages = $this->_attachToArray($messages, $this->getElementsBelongTo());
2285
* @param Zend_View_Interface $view
2288
public function setView(Zend_View_Interface $view = null)
2290
$this->_view = $view;
2295
* Retrieve view object
2297
* If none registered, attempts to pull from ViewRenderer.
2299
* @return Zend_View_Interface|null
2301
public function getView()
2303
if (null === $this->_view) {
2304
require_once 'Zend/Controller/Action/HelperBroker.php';
2305
$viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
2306
$this->setView($viewRenderer->view);
2309
return $this->_view;
2313
* Instantiate a decorator based on class name or class name fragment
2315
* @param string $name
2316
* @param null|array $options
2317
* @return Zend_Form_Decorator_Interface
2319
protected function _getDecorator($name, $options)
2321
$class = $this->getPluginLoader(self::DECORATOR)->load($name);
2322
if (null === $options) {
2323
$decorator = new $class;
2325
$decorator = new $class($options);
2332
* Add a decorator for rendering the element
2334
* @param string|Zend_Form_Decorator_Interface $decorator
2335
* @param array|Zend_Config $options Options with which to initialize decorator
2338
public function addDecorator($decorator, $options = null)
2340
if ($decorator instanceof Zend_Form_Decorator_Interface) {
2341
$name = get_class($decorator);
2342
} elseif (is_string($decorator)) {
2345
'decorator' => $name,
2346
'options' => $options,
2348
} elseif (is_array($decorator)) {
2349
foreach ($decorator as $name => $spec) {
2352
if (is_numeric($name)) {
2353
require_once 'Zend/Form/Exception.php';
2354
throw new Zend_Form_Exception('Invalid alias provided to addDecorator; must be alphanumeric string');
2356
if (is_string($spec)) {
2358
'decorator' => $spec,
2359
'options' => $options,
2361
} elseif ($spec instanceof Zend_Form_Decorator_Interface) {
2365
require_once 'Zend/Form/Exception.php';
2366
throw new Zend_Form_Exception('Invalid decorator provided to addDecorator; must be string or Zend_Form_Decorator_Interface');
2369
$this->_decorators[$name] = $decorator;
2375
* Add many decorators at once
2377
* @param array $decorators
2380
public function addDecorators(array $decorators)
2382
foreach ($decorators as $decoratorInfo) {
2383
if (is_string($decoratorInfo)) {
2384
$this->addDecorator($decoratorInfo);
2385
} elseif ($decoratorInfo instanceof Zend_Form_Decorator_Interface) {
2386
$this->addDecorator($decoratorInfo);
2387
} elseif (is_array($decoratorInfo)) {
2388
$argc = count($decoratorInfo);
2390
if (isset($decoratorInfo['decorator'])) {
2391
$decorator = $decoratorInfo['decorator'];
2392
if (isset($decoratorInfo['options'])) {
2393
$options = $decoratorInfo['options'];
2395
$this->addDecorator($decorator, $options);
2401
$decorator = array_shift($decoratorInfo);
2403
$options = array_shift($decoratorInfo);
2405
$this->addDecorator($decorator, $options);
2410
require_once 'Zend/Form/Exception.php';
2411
throw new Zend_Form_Exception('Invalid decorator passed to addDecorators()');
2419
* Overwrite all decorators
2421
* @param array $decorators
2424
public function setDecorators(array $decorators)
2426
$this->clearDecorators();
2427
return $this->addDecorators($decorators);
2431
* Retrieve a registered decorator
2433
* @param string $name
2434
* @return false|Zend_Form_Decorator_Abstract
2436
public function getDecorator($name)
2438
if (!isset($this->_decorators[$name])) {
2439
$len = strlen($name);
2440
foreach ($this->_decorators as $localName => $decorator) {
2441
if ($len > strlen($localName)) {
2445
if (0 === substr_compare($localName, $name, -$len, $len, true)) {
2446
if (is_array($decorator)) {
2447
return $this->_loadDecorator($decorator, $localName);
2455
if (is_array($this->_decorators[$name])) {
2456
return $this->_loadDecorator($this->_decorators[$name], $name);
2459
return $this->_decorators[$name];
2463
* Retrieve all decorators
2467
public function getDecorators()
2469
foreach ($this->_decorators as $key => $value) {
2470
if (is_array($value)) {
2471
$this->_loadDecorator($value, $key);
2474
return $this->_decorators;
2478
* Remove a single decorator
2480
* @param string $name
2483
public function removeDecorator($name)
2485
$decorator = $this->getDecorator($name);
2487
if (array_key_exists($name, $this->_decorators)) {
2488
unset($this->_decorators[$name]);
2490
$class = get_class($decorator);
2491
if (!array_key_exists($class, $this->_decorators)) {
2494
unset($this->_decorators[$class]);
2503
* Clear all decorators
2507
public function clearDecorators()
2509
$this->_decorators = array();
2514
* Set all element decorators as specified
2516
* @param array $decorators
2517
* @param array|null $elements Specific elements to decorate or exclude from decoration
2518
* @param bool $include Whether $elements is an inclusion or exclusion list
2521
public function setElementDecorators(array $decorators, array $elements = null, $include = true)
2523
if (is_array($elements)) {
2525
$elementObjs = array();
2526
foreach ($elements as $name) {
2527
if (null !== ($element = $this->getElement($name))) {
2528
$elementObjs[] = $element;
2532
$elementObjs = $this->getElements();
2533
foreach ($elements as $name) {
2534
if (array_key_exists($name, $elementObjs)) {
2535
unset($elementObjs[$name]);
2540
$elementObjs = $this->getElements();
2543
foreach ($elementObjs as $element) {
2544
$element->setDecorators($decorators);
2551
* Set all display group decorators as specified
2553
* @param array $decorators
2556
public function setDisplayGroupDecorators(array $decorators)
2558
foreach ($this->getDisplayGroups() as $group) {
2559
$group->setDecorators($decorators);
2566
* Set all subform decorators as specified
2568
* @param array $decorators
2571
public function setSubFormDecorators(array $decorators)
2573
foreach ($this->getSubForms() as $form) {
2574
$form->setDecorators($decorators);
2583
* @param Zend_View_Interface $view
2586
public function render(Zend_View_Interface $view = null)
2588
if (null !== $view) {
2589
$this->setView($view);
2593
foreach ($this->getDecorators() as $decorator) {
2594
$decorator->setElement($this);
2595
$content = $decorator->render($content);
2601
* Serialize as string
2603
* Proxies to {@link render()}.
2607
public function __toString()
2610
$return = $this->render();
2612
} catch (Exception $e) {
2613
$message = "Exception caught by form: " . $e->getMessage()
2614
. "\nStack Trace:\n" . $e->getTraceAsString();
2615
trigger_error($message, E_USER_WARNING);
2624
* Set translator object
2626
* @param Zend_Translate|Zend_Translate_Adapter|null $translator
2629
public function setTranslator($translator = null)
2631
if (null === $translator) {
2632
$this->_translator = null;
2633
} elseif ($translator instanceof Zend_Translate_Adapter) {
2634
$this->_translator = $translator;
2635
} elseif ($translator instanceof Zend_Translate) {
2636
$this->_translator = $translator->getAdapter();
2638
require_once 'Zend/Form/Exception.php';
2639
throw new Zend_Form_Exception('Invalid translator specified');
2646
* Set global default translator object
2648
* @param Zend_Translate|Zend_Translate_Adapter|null $translator
2651
public static function setDefaultTranslator($translator = null)
2653
if (null === $translator) {
2654
self::$_translatorDefault = null;
2655
} elseif ($translator instanceof Zend_Translate_Adapter) {
2656
self::$_translatorDefault = $translator;
2657
} elseif ($translator instanceof Zend_Translate) {
2658
self::$_translatorDefault = $translator->getAdapter();
2660
require_once 'Zend/Form/Exception.php';
2661
throw new Zend_Form_Exception('Invalid translator specified');
2666
* Retrieve translator object
2668
* @return Zend_Translate|null
2670
public function getTranslator()
2672
if ($this->translatorIsDisabled()) {
2676
if (null === $this->_translator) {
2677
return self::getDefaultTranslator();
2680
return $this->_translator;
2684
* Get global default translator object
2686
* @return null|Zend_Translate
2688
public static function getDefaultTranslator()
2690
if (null === self::$_translatorDefault) {
2691
require_once 'Zend/Registry.php';
2692
if (Zend_Registry::isRegistered('Zend_Translate')) {
2693
$translator = Zend_Registry::get('Zend_Translate');
2694
if ($translator instanceof Zend_Translate_Adapter) {
2696
} elseif ($translator instanceof Zend_Translate) {
2697
return $translator->getAdapter();
2701
return self::$_translatorDefault;
2705
* Indicate whether or not translation should be disabled
2710
public function setDisableTranslator($flag)
2712
$this->_translatorDisabled = (bool) $flag;
2717
* Is translation disabled?
2721
public function translatorIsDisabled()
2723
return $this->_translatorDisabled;
2727
* Overloading: access to elements, form groups, and display groups
2729
* @param string $name
2730
* @return Zend_Form_Element|Zend_Form|null
2732
public function __get($name)
2734
if (isset($this->_elements[$name])) {
2735
return $this->_elements[$name];
2736
} elseif (isset($this->_subForms[$name])) {
2737
return $this->_subForms[$name];
2738
} elseif (isset($this->_displayGroups[$name])) {
2739
return $this->_displayGroups[$name];
2746
* Overloading: access to elements, form groups, and display groups
2748
* @param string $name
2749
* @param Zend_Form_Element|Zend_Form $value
2751
* @throws Zend_Form_Exception for invalid $value
2753
public function __set($name, $value)
2755
if ($value instanceof Zend_Form_Element) {
2756
$this->addElement($value, $name);
2758
} elseif ($value instanceof Zend_Form) {
2759
$this->addSubForm($value, $name);
2761
} elseif (is_array($value)) {
2762
$this->addDisplayGroup($value, $name);
2766
require_once 'Zend/Form/Exception.php';
2767
if (is_object($value)) {
2768
$type = get_class($value);
2770
$type = gettype($value);
2772
throw new Zend_Form_Exception('Only form elements and groups may be overloaded; variable of type "' . $type . '" provided');
2776
* Overloading: access to elements, form groups, and display groups
2778
* @param string $name
2781
public function __isset($name)
2783
if (isset($this->_elements[$name])
2784
|| isset($this->_subForms[$name])
2785
|| isset($this->_displayGroups[$name]))
2794
* Overloading: access to elements, form groups, and display groups
2796
* @param string $name
2799
public function __unset($name)
2801
if (isset($this->_elements[$name])) {
2802
unset($this->_elements[$name]);
2803
} elseif (isset($this->_subForms[$name])) {
2804
unset($this->_subForms[$name]);
2805
} elseif (isset($this->_displayGroups[$name])) {
2806
unset($this->_displayGroups[$name]);
2811
* Overloading: allow rendering specific decorators
2813
* Call renderDecoratorName() to render a specific decorator.
2815
* @param string $method
2816
* @param array $args
2818
* @throws Zend_Form_Exception for invalid decorator or invalid method call
2820
public function __call($method, $args)
2822
if ('render' == substr($method, 0, 6)) {
2823
$decoratorName = substr($method, 6);
2824
if (false !== ($decorator = $this->getDecorator($decoratorName))) {
2825
$decorator->setElement($this);
2827
if (0 < count($args)) {
2828
$seed = array_shift($args);
2830
return $decorator->render($seed);
2833
require_once 'Zend/Form/Exception.php';
2834
throw new Zend_Form_Exception(sprintf('Decorator by name %s does not exist', $decoratorName));
2837
require_once 'Zend/Form/Exception.php';
2838
throw new Zend_Form_Exception(sprintf('Method %s does not exist', $method));
2841
// Interfaces: Iterator, Countable
2844
* Current element/subform/display group
2846
* @return Zend_Form_Element|Zend_Form_DisplayGroup|Zend_Form
2848
public function current()
2851
current($this->_order);
2852
$key = key($this->_order);
2854
if (isset($this->_elements[$key])) {
2855
return $this->getElement($key);
2856
} elseif (isset($this->_subForms[$key])) {
2857
return $this->getSubForm($key);
2858
} elseif (isset($this->_displayGroups[$key])) {
2859
return $this->getDisplayGroup($key);
2861
require_once 'Zend/Form/Exception.php';
2862
throw new Zend_Form_Exception(sprintf('Corruption detected in form; invalid key ("%s") found in internal iterator', (string) $key));
2867
* Current element/subform/display group name
2871
public function key()
2874
return key($this->_order);
2878
* Move pointer to next element/subform/display group
2882
public function next()
2885
next($this->_order);
2889
* Move pointer to beginning of element/subform/display group loop
2893
public function rewind()
2896
reset($this->_order);
2900
* Determine if current element/subform/display group is valid
2904
public function valid()
2907
return (current($this->_order) !== false);
2911
* Count of elements/subforms that are iterable
2915
public function count()
2917
return count($this->_order);
2921
* Set flag to disable loading default decorators
2926
public function setDisableLoadDefaultDecorators($flag)
2928
$this->_disableLoadDefaultDecorators = (bool) $flag;
2933
* Should we load the default decorators?
2937
public function loadDefaultDecoratorsIsDisabled()
2939
return $this->_disableLoadDefaultDecorators;
2943
* Load the default decorators
2947
public function loadDefaultDecorators()
2949
if ($this->loadDefaultDecoratorsIsDisabled()) {
2953
$decorators = $this->getDecorators();
2954
if (empty($decorators)) {
2955
$this->addDecorator('FormElements')
2956
->addDecorator('HtmlTag', array('tag' => 'dl', 'class' => 'zend_form'))
2957
->addDecorator('Form');
2962
* Sort items according to their order
2966
protected function _sort()
2968
if ($this->_orderUpdated) {
2971
foreach ($this->_order as $key => $order) {
2972
if (null === $order) {
2973
if (null === ($order = $this->{$key}->getOrder())) {
2974
while (array_search($index, $this->_order, true)) {
2977
$items[$index] = $key;
2980
$items[$order] = $key;
2983
$items[$order] = $key;
2987
$items = array_flip($items);
2989
$this->_order = $items;
2990
$this->_orderUpdated = false;
2995
* Lazy-load a decorator
2997
* @param array $decorator Decorator type and options
2998
* @param mixed $name Decorator name or alias
2999
* @return Zend_Form_Decorator_Interface
3001
protected function _loadDecorator(array $decorator, $name)
3004
if ($name == $decorator['decorator']) {
3008
$instance = $this->_getDecorator($decorator['decorator'], $decorator['options']);
3010
$newName = get_class($instance);
3011
$decoratorNames = array_keys($this->_decorators);
3012
$order = array_flip($decoratorNames);
3013
$order[$newName] = $order[$name];
3014
$decoratorsExchange = array();
3015
unset($order[$name]);
3017
foreach ($order as $key => $index) {
3018
if ($key == $newName) {
3019
$decoratorsExchange[$key] = $instance;
3022
$decoratorsExchange[$key] = $this->_decorators[$key];
3024
$this->_decorators = $decoratorsExchange;
3026
$this->_decorators[$name] = $instance;
3033
* Retrieve optionally translated custom error messages
3037
protected function _getErrorMessages()
3039
$messages = $this->getErrorMessages();
3040
$translator = $this->getTranslator();
3041
if (null !== $translator) {
3042
foreach ($messages as $key => $message) {
3043
$messages[$key] = $translator->translate($message);