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
22
require_once 'Zend/Filter.php';
24
/** Zend_Validate_Interface */
25
require_once 'Zend/Validate/Interface.php';
33
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
34
* @license http://framework.zend.com/license/new-bsd New BSD License
35
* @version $Id: Element.php 13615 2009-01-13 19:52:10Z norm2782 $
37
class Zend_Form_Element implements Zend_Validate_Interface
42
const DECORATOR = 'DECORATOR';
43
const FILTER = 'FILTER';
44
const VALIDATE = 'VALIDATE';
47
* Default view helper to use
50
public $helper = 'formText';
56
protected $_allowEmpty = true;
59
* Flag indicating whether or not to insert NotEmpty validator when element is required
62
protected $_autoInsertNotEmptyValidator = true;
65
* Array to which element belongs
68
protected $_belongsTo;
74
protected $_decorators = array();
80
protected $_description;
83
* Should we disable loading the default decorators?
86
protected $_disableLoadDefaultDecorators = false;
89
* Custom error messages
92
protected $_errorMessages = array();
98
protected $_errors = array();
104
protected $_filters = array();
107
* Ignore flag (used when retrieving values at form level)
110
protected $_ignore = false;
113
* Does the element represent an array?
116
protected $_isArray = false;
119
* Is the error marked as in an invalid state?
122
protected $_isError = false;
131
* Plugin loaders for filter and validator chains
134
protected $_loaders = array();
137
* Formatted validation error messages
140
protected $_messages = array();
158
protected $_required = false;
161
* @var Zend_Translate
163
protected $_translator;
166
* Is translation disabled?
169
protected $_translatorDisabled = false;
178
* Array of initialized validators
179
* @var array Validators
181
protected $_validators = array();
184
* Array of un-initialized validators
187
protected $_validatorRules = array();
196
* @var Zend_View_Interface
204
* - string: name of element
205
* - array: options with which to configure element
206
* - Zend_Config: Zend_Config with options for configuring element
208
* @param string|array|Zend_Config $spec
210
* @throws Zend_Form_Exception if no element name after initialization
212
public function __construct($spec, $options = null)
214
if (is_string($spec)) {
215
$this->setName($spec);
216
} elseif (is_array($spec)) {
217
$this->setOptions($spec);
218
} elseif ($spec instanceof Zend_Config) {
219
$this->setConfig($spec);
222
if (is_string($spec) && is_array($options)) {
223
$this->setOptions($options);
224
} elseif (is_string($spec) && ($options instanceof Zend_Config)) {
225
$this->setConfig($options);
228
if (null === $this->getName()) {
229
require_once 'Zend/Form/Exception.php';
230
throw new Zend_Form_Exception('Zend_Form_Element requires each element to have a name');
239
* Register ViewHelper decorator by default
241
$this->loadDefaultDecorators();
245
* Initialize object; used by extending classes
249
public function init()
254
* Set flag to disable loading default decorators
257
* @return Zend_Form_Element
259
public function setDisableLoadDefaultDecorators($flag)
261
$this->_disableLoadDefaultDecorators = (bool) $flag;
266
* Should we load the default decorators?
270
public function loadDefaultDecoratorsIsDisabled()
272
return $this->_disableLoadDefaultDecorators;
276
* Load default decorators
280
public function loadDefaultDecorators()
282
if ($this->loadDefaultDecoratorsIsDisabled()) {
286
$decorators = $this->getDecorators();
287
if (empty($decorators)) {
288
$this->addDecorator('ViewHelper')
289
->addDecorator('Errors')
290
->addDecorator('Description', array('tag' => 'p', 'class' => 'description'))
291
->addDecorator('HtmlTag', array('tag' => 'dd',
292
'id' => $this->getName() . '-element'))
293
->addDecorator('Label', array('tag' => 'dt'));
298
* Set object state from options array
300
* @param array $options
301
* @return Zend_Form_Element
303
public function setOptions(array $options)
305
if (isset($options['prefixPath'])) {
306
$this->addPrefixPaths($options['prefixPath']);
307
unset($options['prefixPath']);
310
if (isset($options['disableTranslator'])) {
311
$this->setDisableTranslator($options['disableTranslator']);
312
unset($options['disableTranslator']);
315
unset($options['options']);
316
unset($options['config']);
318
foreach ($options as $key => $value) {
319
$method = 'set' . ucfirst($key);
321
if (in_array($method, array('setTranslator', 'setPluginLoader', 'setView'))) {
322
if (!is_object($value)) {
327
if (method_exists($this, $method)) {
328
// Setter exists; use it
329
$this->$method($value);
331
// Assume it's metadata
332
$this->setAttrib($key, $value);
339
* Set object state from Zend_Config object
341
* @param Zend_Config $config
342
* @return Zend_Form_Element
344
public function setConfig(Zend_Config $config)
346
return $this->setOptions($config->toArray());
353
* Set translator object for localization
355
* @param Zend_Translate|null $translator
356
* @return Zend_Form_Element
358
public function setTranslator($translator = null)
360
if (null === $translator) {
361
$this->_translator = null;
362
} elseif ($translator instanceof Zend_Translate_Adapter) {
363
$this->_translator = $translator;
364
} elseif ($translator instanceof Zend_Translate) {
365
$this->_translator = $translator->getAdapter();
367
require_once 'Zend/Form/Exception.php';
368
throw new Zend_Form_Exception('Invalid translator specified');
374
* Retrieve localization translator object
376
* @return Zend_Translate_Adapter|null
378
public function getTranslator()
380
if ($this->translatorIsDisabled()) {
384
if (null === $this->_translator) {
385
require_once 'Zend/Form.php';
386
return Zend_Form::getDefaultTranslator();
388
return $this->_translator;
392
* Indicate whether or not translation should be disabled
395
* @return Zend_Form_Element
397
public function setDisableTranslator($flag)
399
$this->_translatorDisabled = (bool) $flag;
404
* Is translation disabled?
408
public function translatorIsDisabled()
410
return $this->_translatorDisabled;
416
* Filter a name to only allow valid variable characters
418
* @param string $value
419
* @param bool $allowBrackets
422
public function filterName($value, $allowBrackets = false)
424
$charset = '^a-zA-Z0-9_\x7f-\xff';
425
if ($allowBrackets) {
428
return preg_replace('/[' . $charset . ']/', '', (string) $value);
434
* @param string $name
435
* @return Zend_Form_Element
437
public function setName($name)
439
$name = $this->filterName($name);
441
require_once 'Zend/Form/Exception.php';
442
throw new Zend_Form_Exception('Invalid name provided; must contain only valid variable characters and be non-empty');
445
$this->_name = $name;
450
* Return element name
454
public function getName()
460
* Get fully qualified name
462
* Places name as subitem of array and/or appends brackets.
466
public function getFullyQualifiedName()
468
$name = $this->getName();
470
if (null !== ($belongsTo = $this->getBelongsTo())) {
471
$name = $belongsTo . '[' . $name . ']';
474
if ($this->isArray()) {
486
public function getId()
488
if (isset($this->id)) {
492
$id = $this->getFullyQualifiedName();
494
// Bail early if no array notation detected
495
if (!strstr($id, '[')) {
499
// Strip array notation
500
if ('[]' == substr($id, -2)) {
501
$id = substr($id, 0, strlen($id) - 2);
503
$id = str_replace('][', '-', $id);
504
$id = str_replace(array(']', '['), '-', $id);
505
$id = trim($id, '-');
513
* @param mixed $value
514
* @return Zend_Form_Element
516
public function setValue($value)
518
$this->_value = $value;
525
* @param string $value
529
protected function _filterValue(&$value, &$key)
531
foreach ($this->getFilters() as $filter) {
532
$value = $filter->filter($value);
537
* Retrieve filtered element value
541
public function getValue()
543
$valueFiltered = $this->_value;
545
if ($this->isArray() && is_array($valueFiltered)) {
546
array_walk_recursive($valueFiltered, array($this, '_filterValue'));
548
$this->_filterValue($valueFiltered, $valueFiltered);
551
return $valueFiltered;
555
* Retrieve unfiltered element value
559
public function getUnfilteredValue()
561
return $this->_value;
567
* @param string $label
568
* @return Zend_Form_Element
570
public function setLabel($label)
572
$this->_label = (string) $label;
577
* Retrieve element label
581
public function getLabel()
583
return $this->_label;
590
* @return Zend_Form_Element
592
public function setOrder($order)
594
$this->_order = (int) $order;
599
* Retrieve element order
603
public function getOrder()
605
return $this->_order;
611
* @param bool $flag Default value is true
612
* @return Zend_Form_Element
614
public function setRequired($flag = true)
616
$this->_required = (bool) $flag;
621
* Is the element required?
625
public function isRequired()
627
return $this->_required;
631
* Set flag indicating whether a NotEmpty validator should be inserted when element is required
634
* @return Zend_Form_Element
636
public function setAutoInsertNotEmptyValidator($flag)
638
$this->_autoInsertNotEmptyValidator = (bool) $flag;
643
* Get flag indicating whether a NotEmpty validator should be inserted when element is required
647
public function autoInsertNotEmptyValidator()
649
return $this->_autoInsertNotEmptyValidator;
653
* Set element description
655
* @param string $description
656
* @return Zend_Form_Element
658
public function setDescription($description)
660
$this->_description = (string) $description;
665
* Retrieve element description
669
public function getDescription()
671
return $this->_description;
675
* Set 'allow empty' flag
677
* When the allow empty flag is enabled and the required flag is false, the
678
* element will validate with empty values.
681
* @return Zend_Form_Element
683
public function setAllowEmpty($flag)
685
$this->_allowEmpty = (bool) $flag;
690
* Get 'allow empty' flag
694
public function getAllowEmpty()
696
return $this->_allowEmpty;
700
* Set ignore flag (used when retrieving values at form level)
703
* @return Zend_Form_Element
705
public function setIgnore($flag)
707
$this->_ignore = (bool) $flag;
712
* Get ignore flag (used when retrieving values at form level)
716
public function getIgnore()
718
return $this->_ignore;
722
* Set flag indicating if element represents an array
725
* @return Zend_Form_Element
727
public function setIsArray($flag)
729
$this->_isArray = (bool) $flag;
734
* Is the element representing an array?
738
public function isArray()
740
return $this->_isArray;
744
* Set array to which element belongs
746
* @param string $array
747
* @return Zend_Form_Element
749
public function setBelongsTo($array)
751
$array = $this->filterName($array, true);
752
if (!empty($array)) {
753
$this->_belongsTo = $array;
760
* Return array name to which element belongs
764
public function getBelongsTo()
766
return $this->_belongsTo;
770
* Return element type
774
public function getType()
776
if (null === $this->_type) {
777
$this->_type = get_class($this);
784
* Set element attribute
786
* @param string $name
787
* @param mixed $value
788
* @return Zend_Form_Element
789
* @throws Zend_Form_Exception for invalid $name values
791
public function setAttrib($name, $value)
793
$name = (string) $name;
794
if ('_' == $name[0]) {
795
require_once 'Zend/Form/Exception.php';
796
throw new Zend_Form_Exception(sprintf('Invalid attribute "%s"; must not contain a leading underscore', $name));
799
if (null === $value) {
802
$this->$name = $value;
809
* Set multiple attributes at once
811
* @param array $attribs
812
* @return Zend_Form_Element
814
public function setAttribs(array $attribs)
816
foreach ($attribs as $key => $value) {
817
$this->setAttrib($key, $value);
824
* Retrieve element attribute
826
* @param string $name
829
public function getAttrib($name)
831
$name = (string) $name;
832
if (isset($this->$name)) {
840
* Return all attributes
844
public function getAttribs()
846
$attribs = get_object_vars($this);
847
foreach ($attribs as $key => $value) {
848
if ('_' == substr($key, 0, 1)) {
849
unset($attribs[$key]);
857
* Overloading: retrieve object property
859
* Prevents access to properties beginning with '_'.
864
public function __get($key)
866
if ('_' == $key[0]) {
867
require_once 'Zend/Form/Exception.php';
868
throw new Zend_Form_Exception(sprintf('Cannot retrieve value for protected/private property "%s"', $key));
871
if (!isset($this->$key)) {
879
* Overloading: set object property
882
* @param mixed $value
885
public function __set($key, $value)
887
$this->setAttrib($key, $value);
891
* Overloading: allow rendering specific decorators
893
* Call renderDecoratorName() to render a specific decorator.
895
* @param string $method
898
* @throws Zend_Form_Exception for invalid decorator or invalid method call
900
public function __call($method, $args)
902
if ('render' == substr($method, 0, 6)) {
903
$decoratorName = substr($method, 6);
904
if (false !== ($decorator = $this->getDecorator($decoratorName))) {
905
$decorator->setElement($this);
907
if (0 < count($args)) {
908
$seed = array_shift($args);
910
return $decorator->render($seed);
913
require_once 'Zend/Form/Element/Exception.php';
914
throw new Zend_Form_Element_Exception(sprintf('Decorator by name %s does not exist', $decoratorName));
917
require_once 'Zend/Form/Element/Exception.php';
918
throw new Zend_Form_Element_Exception(sprintf('Method %s does not exist', $method));
924
* Set plugin loader to use for validator or filter chain
926
* @param Zend_Loader_PluginLoader_Interface $loader
927
* @param string $type 'decorator', 'filter', or 'validate'
928
* @return Zend_Form_Element
929
* @throws Zend_Form_Exception on invalid type
931
public function setPluginLoader(Zend_Loader_PluginLoader_Interface $loader, $type)
933
$type = strtoupper($type);
935
case self::DECORATOR:
938
$this->_loaders[$type] = $loader;
941
require_once 'Zend/Form/Exception.php';
942
throw new Zend_Form_Exception(sprintf('Invalid type "%s" provided to setPluginLoader()', $type));
947
* Retrieve plugin loader for validator or filter chain
949
* Instantiates with default rules if none available for that type. Use
950
* 'decorator', 'filter', or 'validate' for $type.
952
* @param string $type
953
* @return Zend_Loader_PluginLoader
954
* @throws Zend_Loader_Exception on invalid type.
956
public function getPluginLoader($type)
958
$type = strtoupper($type);
962
$prefixSegment = ucfirst(strtolower($type));
963
$pathSegment = $prefixSegment;
964
case self::DECORATOR:
965
if (!isset($prefixSegment)) {
966
$prefixSegment = 'Form_Decorator';
967
$pathSegment = 'Form/Decorator';
969
if (!isset($this->_loaders[$type])) {
970
require_once 'Zend/Loader/PluginLoader.php';
971
$this->_loaders[$type] = new Zend_Loader_PluginLoader(
972
array('Zend_' . $prefixSegment . '_' => 'Zend/' . $pathSegment . '/')
975
return $this->_loaders[$type];
977
require_once 'Zend/Form/Exception.php';
978
throw new Zend_Form_Exception(sprintf('Invalid type "%s" provided to getPluginLoader()', $type));
983
* Add prefix path for plugin loader
985
* If no $type specified, assumes it is a base path for both filters and
986
* validators, and sets each according to the following rules:
987
* - decorators: $prefix = $prefix . '_Decorator'
988
* - filters: $prefix = $prefix . '_Filter'
989
* - validators: $prefix = $prefix . '_Validate'
991
* Otherwise, the path prefix is set on the appropriate plugin loader.
993
* @param string $path
994
* @return Zend_Form_Element
995
* @throws Zend_Form_Exception for invalid type
997
public function addPrefixPath($prefix, $path, $type = null)
999
$type = strtoupper($type);
1001
case self::DECORATOR:
1003
case self::VALIDATE:
1004
$loader = $this->getPluginLoader($type);
1005
$loader->addPrefixPath($prefix, $path);
1008
$prefix = rtrim($prefix, '_');
1009
$path = rtrim($path, DIRECTORY_SEPARATOR);
1010
foreach (array(self::DECORATOR, self::FILTER, self::VALIDATE) as $type) {
1011
$cType = ucfirst(strtolower($type));
1012
$pluginPath = $path . DIRECTORY_SEPARATOR . $cType . DIRECTORY_SEPARATOR;
1013
$pluginPrefix = $prefix . '_' . $cType;
1014
$loader = $this->getPluginLoader($type);
1015
$loader->addPrefixPath($pluginPrefix, $pluginPath);
1019
require_once 'Zend/Form/Exception.php';
1020
throw new Zend_Form_Exception(sprintf('Invalid type "%s" provided to getPluginLoader()', $type));
1025
* Add many prefix paths at once
1027
* @param array $spec
1028
* @return Zend_Form_Element
1030
public function addPrefixPaths(array $spec)
1032
if (isset($spec['prefix']) && isset($spec['path'])) {
1033
return $this->addPrefixPath($spec['prefix'], $spec['path']);
1035
foreach ($spec as $type => $paths) {
1036
if (is_numeric($type) && is_array($paths)) {
1038
if (isset($paths['prefix']) && isset($paths['path'])) {
1039
if (isset($paths['type'])) {
1040
$type = $paths['type'];
1042
$this->addPrefixPath($paths['prefix'], $paths['path'], $type);
1044
} elseif (!is_numeric($type)) {
1045
if (!isset($paths['prefix']) || !isset($paths['path'])) {
1046
foreach ($paths as $prefix => $spec) {
1047
if (is_array($spec)) {
1048
foreach ($spec as $path) {
1049
if (!is_string($path)) {
1052
$this->addPrefixPath($prefix, $path, $type);
1054
} elseif (is_string($spec)) {
1055
$this->addPrefixPath($prefix, $spec, $type);
1059
$this->addPrefixPath($paths['prefix'], $paths['path'], $type);
1069
* Add validator to validation chain
1071
* Note: will overwrite existing validators if they are of the same class.
1073
* @param string|Zend_Validate_Interface $validator
1074
* @param bool $breakChainOnFailure
1075
* @param array $options
1076
* @return Zend_Form_Element
1077
* @throws Zend_Form_Exception if invalid validator type
1079
public function addValidator($validator, $breakChainOnFailure = false, $options = array())
1081
if ($validator instanceof Zend_Validate_Interface) {
1082
$name = get_class($validator);
1084
if (!isset($validator->zfBreakChainOnFailure)) {
1085
$validator->zfBreakChainOnFailure = $breakChainOnFailure;
1087
} elseif (is_string($validator)) {
1090
'validator' => $validator,
1091
'breakChainOnFailure' => $breakChainOnFailure,
1092
'options' => $options,
1095
require_once 'Zend/Form/Exception.php';
1096
throw new Zend_Form_Exception('Invalid validator provided to addValidator; must be string or Zend_Validate_Interface');
1100
$this->_validators[$name] = $validator;
1106
* Add multiple validators
1108
* @param array $validators
1109
* @return Zend_Form_Element
1111
public function addValidators(array $validators)
1113
foreach ($validators as $validatorInfo) {
1114
if (is_string($validatorInfo)) {
1115
$this->addValidator($validatorInfo);
1116
} elseif ($validatorInfo instanceof Zend_Validate_Interface) {
1117
$this->addValidator($validatorInfo);
1118
} elseif (is_array($validatorInfo)) {
1119
$argc = count($validatorInfo);
1120
$breakChainOnFailure = false;
1122
if (isset($validatorInfo['validator'])) {
1123
$validator = $validatorInfo['validator'];
1124
if (isset($validatorInfo['breakChainOnFailure'])) {
1125
$breakChainOnFailure = $validatorInfo['breakChainOnFailure'];
1127
if (isset($validatorInfo['options'])) {
1128
$options = $validatorInfo['options'];
1130
$this->addValidator($validator, $breakChainOnFailure, $options);
1136
$validator = array_shift($validatorInfo);
1138
$breakChainOnFailure = array_shift($validatorInfo);
1140
$options = array_shift($validatorInfo);
1142
$this->addValidator($validator, $breakChainOnFailure, $options);
1147
require_once 'Zend/Form/Exception.php';
1148
throw new Zend_Form_Exception('Invalid validator passed to addValidators()');
1156
* Set multiple validators, overwriting previous validators
1158
* @param array $validators
1159
* @return Zend_Form_Element
1161
public function setValidators(array $validators)
1163
$this->clearValidators();
1164
return $this->addValidators($validators);
1168
* Retrieve a single validator by name
1170
* @param string $name
1171
* @return Zend_Validate_Interface|false False if not found, validator otherwise
1173
public function getValidator($name)
1175
if (!isset($this->_validators[$name])) {
1176
$len = strlen($name);
1177
foreach ($this->_validators as $localName => $validator) {
1178
if ($len > strlen($localName)) {
1181
if (0 === substr_compare($localName, $name, -$len, $len, true)) {
1182
if (is_array($validator)) {
1183
return $this->_loadValidator($validator);
1191
if (is_array($this->_validators[$name])) {
1192
return $this->_loadValidator($this->_validators[$name]);
1195
return $this->_validators[$name];
1199
* Retrieve all validators
1203
public function getValidators()
1205
$validators = array();
1206
foreach ($this->_validators as $key => $value) {
1207
if ($value instanceof Zend_Validate_Interface) {
1208
$validators[$key] = $value;
1211
$validator = $this->_loadValidator($value);
1212
$validators[get_class($validator)] = $validator;
1218
* Remove a single validator by name
1220
* @param string $name
1223
public function removeValidator($name)
1225
if (isset($this->_validators[$name])) {
1226
unset($this->_validators[$name]);
1228
$len = strlen($name);
1229
foreach (array_keys($this->_validators) as $validator) {
1230
if ($len > strlen($validator)) {
1233
if (0 === substr_compare($validator, $name, -$len, $len, true)) {
1234
unset($this->_validators[$validator]);
1244
* Clear all validators
1246
* @return Zend_Form_Element
1248
public function clearValidators()
1250
$this->_validators = array();
1255
* Validate element value
1257
* If a translation adapter is registered, any error messages will be
1258
* translated according to the current locale, using the given error code;
1259
* if no matching translation is found, the original message will be
1262
* Note: The *filtered* value is validated.
1264
* @param mixed $value
1265
* @param mixed $context
1268
public function isValid($value, $context = null)
1270
$this->setValue($value);
1271
$value = $this->getValue();
1273
if ((('' === $value) || (null === $value))
1274
&& !$this->isRequired()
1275
&& $this->getAllowEmpty()
1280
if ($this->isRequired()
1281
&& $this->autoInsertNotEmptyValidator()
1282
&& !$this->getValidator('NotEmpty'))
1284
$validators = $this->getValidators();
1285
$notEmpty = array('validator' => 'NotEmpty', 'breakChainOnFailure' => true);
1286
array_unshift($validators, $notEmpty);
1287
$this->setValidators($validators);
1290
$this->_messages = array();
1291
$this->_errors = array();
1293
$translator = $this->getTranslator();
1294
$isArray = $this->isArray();
1295
foreach ($this->getValidators() as $key => $validator) {
1296
if (method_exists($validator, 'setTranslator')) {
1297
$validator->setTranslator($translator);
1300
if ($isArray && is_array($value)) {
1301
$messages = array();
1303
foreach ($value as $val) {
1304
if (!$validator->isValid($val, $context)) {
1306
if ($this->_hasErrorMessages()) {
1307
$messages = $this->_getErrorMessages();
1308
$errors = $messages;
1310
$messages = array_merge($messages, $validator->getMessages());
1311
$errors = array_merge($errors, $validator->getErrors());
1318
} elseif ($validator->isValid($value, $context)) {
1322
if ($this->_hasErrorMessages()) {
1323
$messages = $this->_getErrorMessages();
1324
$errors = $messages;
1326
$messages = $validator->getMessages();
1327
$errors = array_keys($messages);
1332
$this->_messages = array_merge($this->_messages, $messages);
1333
$this->_errors = array_merge($this->_errors, $errors);
1335
if ($validator->zfBreakChainOnFailure) {
1344
* Add a custom error message to return in the event of failed validation
1346
* @param string $message
1347
* @return Zend_Form_Element
1349
public function addErrorMessage($message)
1351
$this->_errorMessages[] = (string) $message;
1356
* Add multiple custom error messages to return in the event of failed validation
1358
* @param array $messages
1359
* @return Zend_Form_Element
1361
public function addErrorMessages(array $messages)
1363
foreach ($messages as $message) {
1364
$this->addErrorMessage($message);
1370
* Same as addErrorMessages(), but clears custom error message stack first
1372
* @param array $messages
1373
* @return Zend_Form_Element
1375
public function setErrorMessages(array $messages)
1377
$this->clearErrorMessages();
1378
return $this->addErrorMessages($messages);
1382
* Retrieve custom error messages
1386
public function getErrorMessages()
1388
return $this->_errorMessages;
1392
* Clear custom error messages stack
1394
* @return Zend_Form_Element
1396
public function clearErrorMessages()
1398
$this->_errorMessages = array();
1403
* Mark the element as being in a failed validation state
1405
* @return Zend_Form_Element
1407
public function markAsError()
1409
$messages = $this->getMessages();
1410
$customMessages = $this->_getErrorMessages();
1411
$messages = $messages + $customMessages;
1412
if (empty($messages)) {
1413
$this->_isError = true;
1415
$this->_messages = $messages;
1421
* Add an error message and mark element as failed validation
1423
* @param string $message
1424
* @return Zend_Form_Element
1426
public function addError($message)
1428
$this->addErrorMessage($message);
1429
$this->markAsError();
1434
* Add multiple error messages and flag element as failed validation
1436
* @param array $messages
1437
* @return Zend_Form_Element
1439
public function addErrors(array $messages)
1441
foreach ($messages as $message) {
1442
$this->addError($message);
1448
* Overwrite any previously set error messages and flag as failed validation
1450
* @param array $messages
1451
* @return Zend_Form_Element
1453
public function setErrors(array $messages)
1455
$this->clearErrorMessages();
1456
return $this->addErrors($messages);
1460
* Are there errors registered?
1464
public function hasErrors()
1466
return (!empty($this->_messages) || $this->_isError);
1470
* Retrieve validator chain errors
1474
public function getErrors()
1476
return $this->_errors;
1480
* Retrieve error messages
1484
public function getMessages()
1486
return $this->_messages;
1493
* Add a filter to the element
1495
* @param string|Zend_Filter_Interface $filter
1496
* @return Zend_Form_Element
1498
public function addFilter($filter, $options = array())
1500
if ($filter instanceof Zend_Filter_Interface) {
1501
$name = get_class($filter);
1502
} elseif (is_string($filter)) {
1505
'filter' => $filter,
1506
'options' => $options,
1508
$this->_filters[$name] = $filter;
1510
require_once 'Zend/Form/Exception.php';
1511
throw new Zend_Form_Exception('Invalid filter provided to addFilter; must be string or Zend_Filter_Interface');
1514
$this->_filters[$name] = $filter;
1520
* Add filters to element
1522
* @param array $filters
1523
* @return Zend_Form_Element
1525
public function addFilters(array $filters)
1527
foreach ($filters as $filterInfo) {
1528
if (is_string($filterInfo)) {
1529
$this->addFilter($filterInfo);
1530
} elseif ($filterInfo instanceof Zend_Filter_Interface) {
1531
$this->addFilter($filterInfo);
1532
} elseif (is_array($filterInfo)) {
1533
$argc = count($filterInfo);
1535
if (isset($filterInfo['filter'])) {
1536
$filter = $filterInfo['filter'];
1537
if (isset($filterInfo['options'])) {
1538
$options = $filterInfo['options'];
1540
$this->addFilter($filter, $options);
1546
$filter = array_shift($filterInfo);
1548
$options = array_shift($filterInfo);
1550
$this->addFilter($filter, $options);
1555
require_once 'Zend/Form/Exception.php';
1556
throw new Zend_Form_Exception('Invalid filter passed to addFilters()');
1564
* Add filters to element, overwriting any already existing
1566
* @param array $filters
1567
* @return Zend_Form_Element
1569
public function setFilters(array $filters)
1571
$this->clearFilters();
1572
return $this->addFilters($filters);
1576
* Retrieve a single filter by name
1578
* @param string $name
1579
* @return Zend_Filter_Interface
1581
public function getFilter($name)
1583
if (!isset($this->_filters[$name])) {
1584
$len = strlen($name);
1585
foreach ($this->_filters as $localName => $filter) {
1586
if ($len > strlen($localName)) {
1590
if (0 === substr_compare($localName, $name, -$len, $len, true)) {
1591
if (is_array($filter)) {
1592
return $this->_loadFilter($filter);
1600
if (is_array($this->_filters[$name])) {
1601
return $this->_loadFilter($this->_filters[$name]);
1604
return $this->_filters[$name];
1612
public function getFilters()
1615
foreach ($this->_filters as $key => $value) {
1616
if ($value instanceof Zend_Filter_Interface) {
1617
$filters[$key] = $value;
1620
$filter = $this->_loadFilter($value);
1621
$filters[get_class($filter)] = $filter;
1627
* Remove a filter by name
1629
* @param string $name
1630
* @return Zend_Form_Element
1632
public function removeFilter($name)
1634
if (isset($this->_filters[$name])) {
1635
unset($this->_filters[$name]);
1637
$len = strlen($name);
1638
foreach (array_keys($this->_filters) as $filter) {
1639
if ($len > strlen($filter)) {
1642
if (0 === substr_compare($filter, $name, -$len, $len, true)) {
1643
unset($this->_filters[$filter]);
1655
* @return Zend_Form_Element
1657
public function clearFilters()
1659
$this->_filters = array();
1668
* @param Zend_View_Interface $view
1669
* @return Zend_Form_Element
1671
public function setView(Zend_View_Interface $view = null)
1673
$this->_view = $view;
1678
* Retrieve view object
1680
* Retrieves from ViewRenderer if none previously set.
1682
* @return null|Zend_View_Interface
1684
public function getView()
1686
if (null === $this->_view) {
1687
require_once 'Zend/Controller/Action/HelperBroker.php';
1688
$viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
1689
$this->setView($viewRenderer->view);
1691
return $this->_view;
1695
* Instantiate a decorator based on class name or class name fragment
1697
* @param string $name
1698
* @param null|array $options
1699
* @return Zend_Form_Decorator_Interface
1701
protected function _getDecorator($name, $options)
1703
$class = $this->getPluginLoader(self::DECORATOR)->load($name);
1704
if (null === $options) {
1705
$decorator = new $class;
1707
$decorator = new $class($options);
1714
* Add a decorator for rendering the element
1716
* @param string|Zend_Form_Decorator_Interface $decorator
1717
* @param array|Zend_Config $options Options with which to initialize decorator
1718
* @return Zend_Form_Element
1720
public function addDecorator($decorator, $options = null)
1722
if ($decorator instanceof Zend_Form_Decorator_Interface) {
1723
$name = get_class($decorator);
1724
} elseif (is_string($decorator)) {
1727
'decorator' => $name,
1728
'options' => $options,
1730
} elseif (is_array($decorator)) {
1731
foreach ($decorator as $name => $spec) {
1734
if (is_numeric($name)) {
1735
require_once 'Zend/Form/Exception.php';
1736
throw new Zend_Form_Exception('Invalid alias provided to addDecorator; must be alphanumeric string');
1738
if (is_string($spec)) {
1740
'decorator' => $spec,
1741
'options' => $options,
1743
} elseif ($spec instanceof Zend_Form_Decorator_Interface) {
1747
require_once 'Zend/Form/Exception.php';
1748
throw new Zend_Form_Exception('Invalid decorator provided to addDecorator; must be string or Zend_Form_Decorator_Interface');
1751
$this->_decorators[$name] = $decorator;
1757
* Add many decorators at once
1759
* @param array $decorators
1760
* @return Zend_Form_Element
1762
public function addDecorators(array $decorators)
1764
foreach ($decorators as $decoratorInfo) {
1765
if (is_string($decoratorInfo)) {
1766
$this->addDecorator($decoratorInfo);
1767
} elseif ($decoratorInfo instanceof Zend_Form_Decorator_Interface) {
1768
$this->addDecorator($decoratorInfo);
1769
} elseif (is_array($decoratorInfo)) {
1770
$argc = count($decoratorInfo);
1772
if (isset($decoratorInfo['decorator'])) {
1773
$decorator = $decoratorInfo['decorator'];
1774
if (isset($decoratorInfo['options'])) {
1775
$options = $decoratorInfo['options'];
1777
$this->addDecorator($decorator, $options);
1783
$decorator = array_shift($decoratorInfo);
1785
$options = array_shift($decoratorInfo);
1787
$this->addDecorator($decorator, $options);
1792
require_once 'Zend/Form/Exception.php';
1793
throw new Zend_Form_Exception('Invalid decorator passed to addDecorators()');
1801
* Overwrite all decorators
1803
* @param array $decorators
1804
* @return Zend_Form_Element
1806
public function setDecorators(array $decorators)
1808
$this->clearDecorators();
1809
return $this->addDecorators($decorators);
1813
* Retrieve a registered decorator
1815
* @param string $name
1816
* @return false|Zend_Form_Decorator_Abstract
1818
public function getDecorator($name)
1820
if (!isset($this->_decorators[$name])) {
1821
$len = strlen($name);
1822
foreach ($this->_decorators as $localName => $decorator) {
1823
if ($len > strlen($localName)) {
1827
if (0 === substr_compare($localName, $name, -$len, $len, true)) {
1828
if (is_array($decorator)) {
1829
return $this->_loadDecorator($decorator, $localName);
1837
if (is_array($this->_decorators[$name])) {
1838
return $this->_loadDecorator($this->_decorators[$name], $name);
1841
return $this->_decorators[$name];
1845
* Retrieve all decorators
1849
public function getDecorators()
1851
foreach ($this->_decorators as $key => $value) {
1852
if (is_array($value)) {
1853
$this->_loadDecorator($value, $key);
1856
return $this->_decorators;
1860
* Remove a single decorator
1862
* @param string $name
1865
public function removeDecorator($name)
1867
if (isset($this->_decorators[$name])) {
1868
unset($this->_decorators[$name]);
1870
$len = strlen($name);
1871
foreach (array_keys($this->_decorators) as $decorator) {
1872
if ($len > strlen($decorator)) {
1875
if (0 === substr_compare($decorator, $name, -$len, $len, true)) {
1876
unset($this->_decorators[$decorator]);
1886
* Clear all decorators
1888
* @return Zend_Form_Element
1890
public function clearDecorators()
1892
$this->_decorators = array();
1897
* Render form element
1899
* @param Zend_View_Interface $view
1902
public function render(Zend_View_Interface $view = null)
1904
if (null !== $view) {
1905
$this->setView($view);
1909
foreach ($this->getDecorators() as $decorator) {
1910
$decorator->setElement($this);
1911
$content = $decorator->render($content);
1917
* String representation of form element
1919
* Proxies to {@link render()}.
1923
public function __toString()
1926
$return = $this->render();
1928
} catch (Exception $e) {
1929
trigger_error($e->getMessage(), E_USER_WARNING);
1935
* Lazy-load a filter
1937
* @param array $filter
1938
* @return Zend_Filter_Interface
1940
protected function _loadFilter(array $filter)
1942
$origName = $filter['filter'];
1943
$name = $this->getPluginLoader(self::FILTER)->load($filter['filter']);
1945
if (array_key_exists($name, $this->_filters)) {
1946
require_once 'Zend/Form/Exception.php';
1947
throw new Zend_Form_Exception(sprintf('Filter instance already exists for filter "%s"', $origName));
1950
if (empty($filter['options'])) {
1951
$instance = new $name;
1953
$r = new ReflectionClass($name);
1954
if ($r->hasMethod('__construct')) {
1955
$instance = $r->newInstanceArgs((array) $filter['options']);
1957
$instance = $r->newInstance();
1961
if ($origName != $name) {
1962
$filterNames = array_keys($this->_filters);
1963
$order = array_flip($filterNames);
1964
$order[$name] = $order[$origName];
1965
$filtersExchange = array();
1966
unset($order[$origName]);
1968
foreach ($order as $key => $index) {
1969
if ($key == $name) {
1970
$filtersExchange[$key] = $instance;
1973
$filtersExchange[$key] = $this->_filters[$key];
1975
$this->_filters = $filtersExchange;
1977
$this->_filters[$name] = $instance;
1984
* Lazy-load a validator
1986
* @param array $validator Validator definition
1987
* @return Zend_Validate_Interface
1989
protected function _loadValidator(array $validator)
1991
$origName = $validator['validator'];
1992
$name = $this->getPluginLoader(self::VALIDATE)->load($validator['validator']);
1994
if (array_key_exists($name, $this->_validators)) {
1995
require_once 'Zend/Form/Exception.php';
1996
throw new Zend_Form_Exception(sprintf('Validator instance already exists for validator "%s"', $origName));
1999
if (empty($validator['options'])) {
2000
$instance = new $name;
2003
if (isset($validator['options']['messages'])) {
2004
$messages = $validator['options']['messages'];
2005
unset($validator['options']['messages']);
2008
$r = new ReflectionClass($name);
2009
if ($r->hasMethod('__construct')) {
2010
$instance = $r->newInstanceArgs((array) $validator['options']);
2012
$instance = $r->newInstance();
2016
if (is_array($messages)) {
2017
$instance->setMessages($messages);
2018
} elseif (is_string($messages)) {
2019
$instance->setMessage($messages);
2024
$instance->zfBreakChainOnFailure = $validator['breakChainOnFailure'];
2026
if ($origName != $name) {
2027
$validatorNames = array_keys($this->_validators);
2028
$order = array_flip($validatorNames);
2029
$order[$name] = $order[$origName];
2030
$validatorsExchange = array();
2031
unset($order[$origName]);
2033
foreach ($order as $key => $index) {
2034
if ($key == $name) {
2035
$validatorsExchange[$key] = $instance;
2038
$validatorsExchange[$key] = $this->_validators[$key];
2040
$this->_validators = $validatorsExchange;
2042
$this->_validators[$name] = $instance;
2049
* Lazy-load a decorator
2051
* @param array $decorator Decorator type and options
2052
* @param mixed $name Decorator name or alias
2053
* @return Zend_Form_Decorator_Interface
2055
protected function _loadDecorator(array $decorator, $name)
2058
if ($name == $decorator['decorator']) {
2062
$instance = $this->_getDecorator($decorator['decorator'], $decorator['options']);
2064
$newName = get_class($instance);
2065
$decoratorNames = array_keys($this->_decorators);
2066
$order = array_flip($decoratorNames);
2067
$order[$newName] = $order[$name];
2068
$decoratorsExchange = array();
2069
unset($order[$name]);
2071
foreach ($order as $key => $index) {
2072
if ($key == $newName) {
2073
$decoratorsExchange[$key] = $instance;
2076
$decoratorsExchange[$key] = $this->_decorators[$key];
2078
$this->_decorators = $decoratorsExchange;
2080
$this->_decorators[$name] = $instance;
2087
* Retrieve error messages and perform translation and value substitution
2091
protected function _getErrorMessages()
2093
$translator = $this->getTranslator();
2094
$messages = $this->getErrorMessages();
2095
$value = $this->getValue();
2096
foreach ($messages as $key => $message) {
2097
if (null !== $translator) {
2098
$message = $translator->translate($message);
2100
if ($this->isArray() || is_array($value)) {
2101
$aggregateMessages = array();
2102
foreach ($value as $val) {
2103
$aggregateMessages[] = str_replace('%value%', $val, $message);
2105
$messages[$key] = $aggregateMessages;
2107
$messages[$key] = str_replace('%value%', $value, $message);
2114
* Are there custom error messages registered?
2118
protected function _hasErrorMessages()
2120
return !empty($this->_errorMessages);