web/enmi/Zend/Form/Element.php
changeset 19 1c2f13fd785c
parent 0 4eba9c11703f
equal deleted inserted replaced
18:bd595ad770fc 19:1c2f13fd785c
       
     1 <?php
       
     2 /**
       
     3  * Zend Framework
       
     4  *
       
     5  * LICENSE
       
     6  *
       
     7  * This source file is subject to the new BSD license that is bundled
       
     8  * with this package in the file LICENSE.txt.
       
     9  * It is also available through the world-wide-web at this URL:
       
    10  * http://framework.zend.com/license/new-bsd
       
    11  * If you did not receive a copy of the license and are unable to
       
    12  * obtain it through the world-wide-web, please send an email
       
    13  * to license@zend.com so we can send you a copy immediately.
       
    14  *
       
    15  * @category   Zend
       
    16  * @package    Zend_Form
       
    17  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
       
    18  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    19  */
       
    20 
       
    21 /** @see Zend_Filter */
       
    22 require_once 'Zend/Filter.php';
       
    23 
       
    24 /** @see Zend_Form */
       
    25 require_once 'Zend/Form.php';
       
    26 
       
    27 /** @see Zend_Validate_Interface */
       
    28 require_once 'Zend/Validate/Interface.php';
       
    29 
       
    30 /** @see Zend_Validate_Abstract */
       
    31 require_once 'Zend/Validate/Abstract.php';
       
    32 
       
    33 /**
       
    34  * Zend_Form_Element
       
    35  *
       
    36  * @category   Zend
       
    37  * @package    Zend_Form
       
    38  * @subpackage Element
       
    39  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
       
    40  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    41  * @version    $Id: Element.php 22464 2010-06-19 17:31:21Z alab $
       
    42  */
       
    43 class Zend_Form_Element implements Zend_Validate_Interface
       
    44 {
       
    45     /**
       
    46      * Element Constants
       
    47      */
       
    48     const DECORATOR = 'DECORATOR';
       
    49     const FILTER    = 'FILTER';
       
    50     const VALIDATE  = 'VALIDATE';
       
    51 
       
    52     /**
       
    53      * Default view helper to use
       
    54      * @var string
       
    55      */
       
    56     public $helper = 'formText';
       
    57 
       
    58     /**
       
    59      * 'Allow empty' flag
       
    60      * @var bool
       
    61      */
       
    62     protected $_allowEmpty = true;
       
    63 
       
    64     /**
       
    65      * Flag indicating whether or not to insert NotEmpty validator when element is required
       
    66      * @var bool
       
    67      */
       
    68     protected $_autoInsertNotEmptyValidator = true;
       
    69 
       
    70     /**
       
    71      * Array to which element belongs
       
    72      * @var string
       
    73      */
       
    74     protected $_belongsTo;
       
    75 
       
    76     /**
       
    77      * Element decorators
       
    78      * @var array
       
    79      */
       
    80     protected $_decorators = array();
       
    81 
       
    82     /**
       
    83      * Element description
       
    84      * @var string
       
    85      */
       
    86     protected $_description;
       
    87 
       
    88     /**
       
    89      * Should we disable loading the default decorators?
       
    90      * @var bool
       
    91      */
       
    92     protected $_disableLoadDefaultDecorators = false;
       
    93 
       
    94     /**
       
    95      * Custom error messages
       
    96      * @var array
       
    97      */
       
    98     protected $_errorMessages = array();
       
    99 
       
   100     /**
       
   101      * Validation errors
       
   102      * @var array
       
   103      */
       
   104     protected $_errors = array();
       
   105 
       
   106     /**
       
   107      * Separator to use when concatenating aggregate error messages (for
       
   108      * elements having array values)
       
   109      * @var string
       
   110      */
       
   111     protected $_errorMessageSeparator = '; ';
       
   112 
       
   113     /**
       
   114      * Element filters
       
   115      * @var array
       
   116      */
       
   117     protected $_filters = array();
       
   118 
       
   119     /**
       
   120      * Ignore flag (used when retrieving values at form level)
       
   121      * @var bool
       
   122      */
       
   123     protected $_ignore = false;
       
   124 
       
   125     /**
       
   126      * Does the element represent an array?
       
   127      * @var bool
       
   128      */
       
   129     protected $_isArray = false;
       
   130 
       
   131     /**
       
   132      * Is the error marked as in an invalid state?
       
   133      * @var bool
       
   134      */
       
   135     protected $_isError = false;
       
   136 
       
   137     /**
       
   138      * Has the element been manually marked as invalid?
       
   139      * @var bool
       
   140      */
       
   141     protected $_isErrorForced = false;
       
   142 
       
   143     /**
       
   144      * Element label
       
   145      * @var string
       
   146      */
       
   147     protected $_label;
       
   148 
       
   149     /**
       
   150      * Plugin loaders for filter and validator chains
       
   151      * @var array
       
   152      */
       
   153     protected $_loaders = array();
       
   154 
       
   155     /**
       
   156      * Formatted validation error messages
       
   157      * @var array
       
   158      */
       
   159     protected $_messages = array();
       
   160 
       
   161     /**
       
   162      * Element name
       
   163      * @var string
       
   164      */
       
   165     protected $_name;
       
   166 
       
   167     /**
       
   168      * Order of element
       
   169      * @var int
       
   170      */
       
   171     protected $_order;
       
   172 
       
   173     /**
       
   174      * Required flag
       
   175      * @var bool
       
   176      */
       
   177     protected $_required = false;
       
   178 
       
   179     /**
       
   180      * @var Zend_Translate
       
   181      */
       
   182     protected $_translator;
       
   183 
       
   184     /**
       
   185      * Is translation disabled?
       
   186      * @var bool
       
   187      */
       
   188     protected $_translatorDisabled = false;
       
   189 
       
   190     /**
       
   191      * Element type
       
   192      * @var string
       
   193      */
       
   194     protected $_type;
       
   195 
       
   196     /**
       
   197      * Array of initialized validators
       
   198      * @var array Validators
       
   199      */
       
   200     protected $_validators = array();
       
   201 
       
   202     /**
       
   203      * Array of un-initialized validators
       
   204      * @var array
       
   205      */
       
   206     protected $_validatorRules = array();
       
   207 
       
   208     /**
       
   209      * Element value
       
   210      * @var mixed
       
   211      */
       
   212     protected $_value;
       
   213 
       
   214     /**
       
   215      * @var Zend_View_Interface
       
   216      */
       
   217     protected $_view;
       
   218 
       
   219     /**
       
   220      * Is a specific decorator being rendered via the magic renderDecorator()?
       
   221      *
       
   222      * This is to allow execution of logic inside the render() methods of child
       
   223      * elements during the magic call while skipping the parent render() method.
       
   224      *
       
   225      * @var bool
       
   226      */
       
   227     protected $_isPartialRendering = false;
       
   228 
       
   229     /**
       
   230      * Constructor
       
   231      *
       
   232      * $spec may be:
       
   233      * - string: name of element
       
   234      * - array: options with which to configure element
       
   235      * - Zend_Config: Zend_Config with options for configuring element
       
   236      *
       
   237      * @param  string|array|Zend_Config $spec
       
   238      * @param  array|Zend_Config $options
       
   239      * @return void
       
   240      * @throws Zend_Form_Exception if no element name after initialization
       
   241      */
       
   242     public function __construct($spec, $options = null)
       
   243     {
       
   244         if (is_string($spec)) {
       
   245             $this->setName($spec);
       
   246         } elseif (is_array($spec)) {
       
   247             $this->setOptions($spec);
       
   248         } elseif ($spec instanceof Zend_Config) {
       
   249             $this->setConfig($spec);
       
   250         }
       
   251 
       
   252         if (is_string($spec) && is_array($options)) {
       
   253             $this->setOptions($options);
       
   254         } elseif (is_string($spec) && ($options instanceof Zend_Config)) {
       
   255             $this->setConfig($options);
       
   256         }
       
   257 
       
   258         if (null === $this->getName()) {
       
   259             require_once 'Zend/Form/Exception.php';
       
   260             throw new Zend_Form_Exception('Zend_Form_Element requires each element to have a name');
       
   261         }
       
   262 
       
   263         /**
       
   264          * Extensions
       
   265          */
       
   266         $this->init();
       
   267 
       
   268         /**
       
   269          * Register ViewHelper decorator by default
       
   270          */
       
   271         $this->loadDefaultDecorators();
       
   272     }
       
   273 
       
   274     /**
       
   275      * Initialize object; used by extending classes
       
   276      *
       
   277      * @return void
       
   278      */
       
   279     public function init()
       
   280     {
       
   281     }
       
   282 
       
   283     /**
       
   284      * Set flag to disable loading default decorators
       
   285      *
       
   286      * @param  bool $flag
       
   287      * @return Zend_Form_Element
       
   288      */
       
   289     public function setDisableLoadDefaultDecorators($flag)
       
   290     {
       
   291         $this->_disableLoadDefaultDecorators = (bool) $flag;
       
   292         return $this;
       
   293     }
       
   294 
       
   295     /**
       
   296      * Should we load the default decorators?
       
   297      *
       
   298      * @return bool
       
   299      */
       
   300     public function loadDefaultDecoratorsIsDisabled()
       
   301     {
       
   302         return $this->_disableLoadDefaultDecorators;
       
   303     }
       
   304 
       
   305     /**
       
   306      * Load default decorators
       
   307      *
       
   308      * @return Zend_Form_Element
       
   309      */
       
   310     public function loadDefaultDecorators()
       
   311     {
       
   312         if ($this->loadDefaultDecoratorsIsDisabled()) {
       
   313             return $this;
       
   314         }
       
   315 
       
   316         $decorators = $this->getDecorators();
       
   317         if (empty($decorators)) {
       
   318             $getId = create_function('$decorator',
       
   319                                      'return $decorator->getElement()->getId()
       
   320                                              . "-element";');
       
   321             $this->addDecorator('ViewHelper')
       
   322                  ->addDecorator('Errors')
       
   323                  ->addDecorator('Description', array('tag' => 'p', 'class' => 'description'))
       
   324                  ->addDecorator('HtmlTag', array('tag' => 'dd',
       
   325                                                  'id'  => array('callback' => $getId)))
       
   326                  ->addDecorator('Label', array('tag' => 'dt'));
       
   327         }
       
   328         return $this;
       
   329     }
       
   330 
       
   331     /**
       
   332      * Set object state from options array
       
   333      *
       
   334      * @param  array $options
       
   335      * @return Zend_Form_Element
       
   336      */
       
   337     public function setOptions(array $options)
       
   338     {
       
   339         if (isset($options['prefixPath'])) {
       
   340             $this->addPrefixPaths($options['prefixPath']);
       
   341             unset($options['prefixPath']);
       
   342         }
       
   343 
       
   344         if (isset($options['disableTranslator'])) {
       
   345             $this->setDisableTranslator($options['disableTranslator']);
       
   346             unset($options['disableTranslator']);
       
   347         }
       
   348 
       
   349         unset($options['options']);
       
   350         unset($options['config']);
       
   351 
       
   352         foreach ($options as $key => $value) {
       
   353             $method = 'set' . ucfirst($key);
       
   354 
       
   355             if (in_array($method, array('setTranslator', 'setPluginLoader', 'setView'))) {
       
   356                 if (!is_object($value)) {
       
   357                     continue;
       
   358                 }
       
   359             }
       
   360 
       
   361             if (method_exists($this, $method)) {
       
   362                 // Setter exists; use it
       
   363                 $this->$method($value);
       
   364             } else {
       
   365                 // Assume it's metadata
       
   366                 $this->setAttrib($key, $value);
       
   367             }
       
   368         }
       
   369         return $this;
       
   370     }
       
   371 
       
   372     /**
       
   373      * Set object state from Zend_Config object
       
   374      *
       
   375      * @param  Zend_Config $config
       
   376      * @return Zend_Form_Element
       
   377      */
       
   378     public function setConfig(Zend_Config $config)
       
   379     {
       
   380         return $this->setOptions($config->toArray());
       
   381     }
       
   382 
       
   383 
       
   384     // Localization:
       
   385 
       
   386     /**
       
   387      * Set translator object for localization
       
   388      *
       
   389      * @param  Zend_Translate|null $translator
       
   390      * @return Zend_Form_Element
       
   391      */
       
   392     public function setTranslator($translator = null)
       
   393     {
       
   394         if (null === $translator) {
       
   395             $this->_translator = null;
       
   396         } elseif ($translator instanceof Zend_Translate_Adapter) {
       
   397             $this->_translator = $translator;
       
   398         } elseif ($translator instanceof Zend_Translate) {
       
   399             $this->_translator = $translator->getAdapter();
       
   400         } else {
       
   401             require_once 'Zend/Form/Exception.php';
       
   402             throw new Zend_Form_Exception('Invalid translator specified');
       
   403         }
       
   404         return $this;
       
   405     }
       
   406 
       
   407     /**
       
   408      * Retrieve localization translator object
       
   409      *
       
   410      * @return Zend_Translate_Adapter|null
       
   411      */
       
   412     public function getTranslator()
       
   413     {
       
   414         if ($this->translatorIsDisabled()) {
       
   415             return null;
       
   416         }
       
   417 
       
   418         if (null === $this->_translator) {
       
   419             return Zend_Form::getDefaultTranslator();
       
   420         }
       
   421         return $this->_translator;
       
   422     }
       
   423 
       
   424     /**
       
   425      * Does this element have its own specific translator?
       
   426      *
       
   427      * @return bool
       
   428      */
       
   429     public function hasTranslator()
       
   430     {
       
   431         return (bool)$this->_translator;
       
   432     }
       
   433 
       
   434     /**
       
   435      * Indicate whether or not translation should be disabled
       
   436      *
       
   437      * @param  bool $flag
       
   438      * @return Zend_Form_Element
       
   439      */
       
   440     public function setDisableTranslator($flag)
       
   441     {
       
   442         $this->_translatorDisabled = (bool) $flag;
       
   443         return $this;
       
   444     }
       
   445 
       
   446     /**
       
   447      * Is translation disabled?
       
   448      *
       
   449      * @return bool
       
   450      */
       
   451     public function translatorIsDisabled()
       
   452     {
       
   453         return $this->_translatorDisabled;
       
   454     }
       
   455 
       
   456     // Metadata
       
   457 
       
   458     /**
       
   459      * Filter a name to only allow valid variable characters
       
   460      *
       
   461      * @param  string $value
       
   462      * @param  bool $allowBrackets
       
   463      * @return string
       
   464      */
       
   465     public function filterName($value, $allowBrackets = false)
       
   466     {
       
   467         $charset = '^a-zA-Z0-9_\x7f-\xff';
       
   468         if ($allowBrackets) {
       
   469             $charset .= '\[\]';
       
   470         }
       
   471         return preg_replace('/[' . $charset . ']/', '', (string) $value);
       
   472     }
       
   473 
       
   474     /**
       
   475      * Set element name
       
   476      *
       
   477      * @param  string $name
       
   478      * @return Zend_Form_Element
       
   479      */
       
   480     public function setName($name)
       
   481     {
       
   482         $name = $this->filterName($name);
       
   483         if ('' === $name) {
       
   484             require_once 'Zend/Form/Exception.php';
       
   485             throw new Zend_Form_Exception('Invalid name provided; must contain only valid variable characters and be non-empty');
       
   486         }
       
   487 
       
   488         $this->_name = $name;
       
   489         return $this;
       
   490     }
       
   491 
       
   492     /**
       
   493      * Return element name
       
   494      *
       
   495      * @return string
       
   496      */
       
   497     public function getName()
       
   498     {
       
   499         return $this->_name;
       
   500     }
       
   501 
       
   502     /**
       
   503      * Get fully qualified name
       
   504      *
       
   505      * Places name as subitem of array and/or appends brackets.
       
   506      *
       
   507      * @return string
       
   508      */
       
   509     public function getFullyQualifiedName()
       
   510     {
       
   511         $name = $this->getName();
       
   512 
       
   513         if (null !== ($belongsTo = $this->getBelongsTo())) {
       
   514             $name = $belongsTo . '[' . $name . ']';
       
   515         }
       
   516 
       
   517         if ($this->isArray()) {
       
   518             $name .= '[]';
       
   519         }
       
   520 
       
   521         return $name;
       
   522     }
       
   523 
       
   524     /**
       
   525      * Get element id
       
   526      *
       
   527      * @return string
       
   528      */
       
   529     public function getId()
       
   530     {
       
   531         if (isset($this->id)) {
       
   532             return $this->id;
       
   533         }
       
   534 
       
   535         $id = $this->getFullyQualifiedName();
       
   536 
       
   537         // Bail early if no array notation detected
       
   538         if (!strstr($id, '[')) {
       
   539             return $id;
       
   540         }
       
   541 
       
   542         // Strip array notation
       
   543         if ('[]' == substr($id, -2)) {
       
   544             $id = substr($id, 0, strlen($id) - 2);
       
   545         }
       
   546         $id = str_replace('][', '-', $id);
       
   547         $id = str_replace(array(']', '['), '-', $id);
       
   548         $id = trim($id, '-');
       
   549 
       
   550         return $id;
       
   551     }
       
   552 
       
   553     /**
       
   554      * Set element value
       
   555      *
       
   556      * @param  mixed $value
       
   557      * @return Zend_Form_Element
       
   558      */
       
   559     public function setValue($value)
       
   560     {
       
   561         $this->_value = $value;
       
   562         return $this;
       
   563     }
       
   564 
       
   565     /**
       
   566      * Filter a value
       
   567      *
       
   568      * @param  string $value
       
   569      * @param  string $key
       
   570      * @return void
       
   571      */
       
   572     protected function _filterValue(&$value, &$key)
       
   573     {
       
   574         foreach ($this->getFilters() as $filter) {
       
   575             $value = $filter->filter($value);
       
   576         }
       
   577     }
       
   578 
       
   579     /**
       
   580      * Retrieve filtered element value
       
   581      *
       
   582      * @return mixed
       
   583      */
       
   584     public function getValue()
       
   585     {
       
   586         $valueFiltered = $this->_value;
       
   587 
       
   588         if ($this->isArray() && is_array($valueFiltered)) {
       
   589             array_walk_recursive($valueFiltered, array($this, '_filterValue'));
       
   590         } else {
       
   591             $this->_filterValue($valueFiltered, $valueFiltered);
       
   592         }
       
   593 
       
   594         return $valueFiltered;
       
   595     }
       
   596 
       
   597     /**
       
   598      * Retrieve unfiltered element value
       
   599      *
       
   600      * @return mixed
       
   601      */
       
   602     public function getUnfilteredValue()
       
   603     {
       
   604         return $this->_value;
       
   605     }
       
   606 
       
   607     /**
       
   608      * Set element label
       
   609      *
       
   610      * @param  string $label
       
   611      * @return Zend_Form_Element
       
   612      */
       
   613     public function setLabel($label)
       
   614     {
       
   615         $this->_label = (string) $label;
       
   616         return $this;
       
   617     }
       
   618 
       
   619     /**
       
   620      * Retrieve element label
       
   621      *
       
   622      * @return string
       
   623      */
       
   624     public function getLabel()
       
   625     {
       
   626         $translator = $this->getTranslator();
       
   627         if (null !== $translator) {
       
   628             return $translator->translate($this->_label);
       
   629         }
       
   630 
       
   631         return $this->_label;
       
   632     }
       
   633 
       
   634     /**
       
   635      * Set element order
       
   636      *
       
   637      * @param  int $order
       
   638      * @return Zend_Form_Element
       
   639      */
       
   640     public function setOrder($order)
       
   641     {
       
   642         $this->_order = (int) $order;
       
   643         return $this;
       
   644     }
       
   645 
       
   646     /**
       
   647      * Retrieve element order
       
   648      *
       
   649      * @return int
       
   650      */
       
   651     public function getOrder()
       
   652     {
       
   653         return $this->_order;
       
   654     }
       
   655 
       
   656     /**
       
   657      * Set required flag
       
   658      *
       
   659      * @param  bool $flag Default value is true
       
   660      * @return Zend_Form_Element
       
   661      */
       
   662     public function setRequired($flag = true)
       
   663     {
       
   664         $this->_required = (bool) $flag;
       
   665         return $this;
       
   666     }
       
   667 
       
   668     /**
       
   669      * Is the element required?
       
   670      *
       
   671      * @return bool
       
   672      */
       
   673     public function isRequired()
       
   674     {
       
   675         return $this->_required;
       
   676     }
       
   677 
       
   678     /**
       
   679      * Set flag indicating whether a NotEmpty validator should be inserted when element is required
       
   680      *
       
   681      * @param  bool $flag
       
   682      * @return Zend_Form_Element
       
   683      */
       
   684     public function setAutoInsertNotEmptyValidator($flag)
       
   685     {
       
   686         $this->_autoInsertNotEmptyValidator = (bool) $flag;
       
   687         return $this;
       
   688     }
       
   689 
       
   690     /**
       
   691      * Get flag indicating whether a NotEmpty validator should be inserted when element is required
       
   692      *
       
   693      * @return bool
       
   694      */
       
   695     public function autoInsertNotEmptyValidator()
       
   696     {
       
   697         return $this->_autoInsertNotEmptyValidator;
       
   698     }
       
   699 
       
   700     /**
       
   701      * Set element description
       
   702      *
       
   703      * @param  string $description
       
   704      * @return Zend_Form_Element
       
   705      */
       
   706     public function setDescription($description)
       
   707     {
       
   708         $this->_description = (string) $description;
       
   709         return $this;
       
   710     }
       
   711 
       
   712     /**
       
   713      * Retrieve element description
       
   714      *
       
   715      * @return string
       
   716      */
       
   717     public function getDescription()
       
   718     {
       
   719         return $this->_description;
       
   720     }
       
   721 
       
   722     /**
       
   723      * Set 'allow empty' flag
       
   724      *
       
   725      * When the allow empty flag is enabled and the required flag is false, the
       
   726      * element will validate with empty values.
       
   727      *
       
   728      * @param  bool $flag
       
   729      * @return Zend_Form_Element
       
   730      */
       
   731     public function setAllowEmpty($flag)
       
   732     {
       
   733         $this->_allowEmpty = (bool) $flag;
       
   734         return $this;
       
   735     }
       
   736 
       
   737     /**
       
   738      * Get 'allow empty' flag
       
   739      *
       
   740      * @return bool
       
   741      */
       
   742     public function getAllowEmpty()
       
   743     {
       
   744         return $this->_allowEmpty;
       
   745     }
       
   746 
       
   747     /**
       
   748      * Set ignore flag (used when retrieving values at form level)
       
   749      *
       
   750      * @param  bool $flag
       
   751      * @return Zend_Form_Element
       
   752      */
       
   753     public function setIgnore($flag)
       
   754     {
       
   755         $this->_ignore = (bool) $flag;
       
   756         return $this;
       
   757     }
       
   758 
       
   759     /**
       
   760      * Get ignore flag (used when retrieving values at form level)
       
   761      *
       
   762      * @return bool
       
   763      */
       
   764     public function getIgnore()
       
   765     {
       
   766         return $this->_ignore;
       
   767     }
       
   768 
       
   769     /**
       
   770      * Set flag indicating if element represents an array
       
   771      *
       
   772      * @param  bool $flag
       
   773      * @return Zend_Form_Element
       
   774      */
       
   775     public function setIsArray($flag)
       
   776     {
       
   777         $this->_isArray = (bool) $flag;
       
   778         return $this;
       
   779     }
       
   780 
       
   781     /**
       
   782      * Is the element representing an array?
       
   783      *
       
   784      * @return bool
       
   785      */
       
   786     public function isArray()
       
   787     {
       
   788         return $this->_isArray;
       
   789     }
       
   790 
       
   791     /**
       
   792      * Set array to which element belongs
       
   793      *
       
   794      * @param  string $array
       
   795      * @return Zend_Form_Element
       
   796      */
       
   797     public function setBelongsTo($array)
       
   798     {
       
   799         $array = $this->filterName($array, true);
       
   800         if (!empty($array)) {
       
   801             $this->_belongsTo = $array;
       
   802         }
       
   803 
       
   804         return $this;
       
   805     }
       
   806 
       
   807     /**
       
   808      * Return array name to which element belongs
       
   809      *
       
   810      * @return string
       
   811      */
       
   812     public function getBelongsTo()
       
   813     {
       
   814         return $this->_belongsTo;
       
   815     }
       
   816 
       
   817     /**
       
   818      * Return element type
       
   819      *
       
   820      * @return string
       
   821      */
       
   822     public function getType()
       
   823     {
       
   824         if (null === $this->_type) {
       
   825             $this->_type = get_class($this);
       
   826         }
       
   827 
       
   828         return $this->_type;
       
   829     }
       
   830 
       
   831     /**
       
   832      * Set element attribute
       
   833      *
       
   834      * @param  string $name
       
   835      * @param  mixed $value
       
   836      * @return Zend_Form_Element
       
   837      * @throws Zend_Form_Exception for invalid $name values
       
   838      */
       
   839     public function setAttrib($name, $value)
       
   840     {
       
   841         $name = (string) $name;
       
   842         if ('_' == $name[0]) {
       
   843             require_once 'Zend/Form/Exception.php';
       
   844             throw new Zend_Form_Exception(sprintf('Invalid attribute "%s"; must not contain a leading underscore', $name));
       
   845         }
       
   846 
       
   847         if (null === $value) {
       
   848             unset($this->$name);
       
   849         } else {
       
   850             $this->$name = $value;
       
   851         }
       
   852 
       
   853         return $this;
       
   854     }
       
   855 
       
   856     /**
       
   857      * Set multiple attributes at once
       
   858      *
       
   859      * @param  array $attribs
       
   860      * @return Zend_Form_Element
       
   861      */
       
   862     public function setAttribs(array $attribs)
       
   863     {
       
   864         foreach ($attribs as $key => $value) {
       
   865             $this->setAttrib($key, $value);
       
   866         }
       
   867 
       
   868         return $this;
       
   869     }
       
   870 
       
   871     /**
       
   872      * Retrieve element attribute
       
   873      *
       
   874      * @param  string $name
       
   875      * @return string
       
   876      */
       
   877     public function getAttrib($name)
       
   878     {
       
   879         $name = (string) $name;
       
   880         if (isset($this->$name)) {
       
   881             return $this->$name;
       
   882         }
       
   883 
       
   884         return null;
       
   885     }
       
   886 
       
   887     /**
       
   888      * Return all attributes
       
   889      *
       
   890      * @return array
       
   891      */
       
   892     public function getAttribs()
       
   893     {
       
   894         $attribs = get_object_vars($this);
       
   895         foreach ($attribs as $key => $value) {
       
   896             if ('_' == substr($key, 0, 1)) {
       
   897                 unset($attribs[$key]);
       
   898             }
       
   899         }
       
   900 
       
   901         return $attribs;
       
   902     }
       
   903 
       
   904     /**
       
   905      * Overloading: retrieve object property
       
   906      *
       
   907      * Prevents access to properties beginning with '_'.
       
   908      *
       
   909      * @param  string $key
       
   910      * @return mixed
       
   911      */
       
   912     public function __get($key)
       
   913     {
       
   914         if ('_' == $key[0]) {
       
   915             require_once 'Zend/Form/Exception.php';
       
   916             throw new Zend_Form_Exception(sprintf('Cannot retrieve value for protected/private property "%s"', $key));
       
   917         }
       
   918 
       
   919         if (!isset($this->$key)) {
       
   920             return null;
       
   921         }
       
   922 
       
   923         return $this->$key;
       
   924     }
       
   925 
       
   926     /**
       
   927      * Overloading: set object property
       
   928      *
       
   929      * @param  string $key
       
   930      * @param  mixed $value
       
   931      * @return voide
       
   932      */
       
   933     public function __set($key, $value)
       
   934     {
       
   935         $this->setAttrib($key, $value);
       
   936     }
       
   937 
       
   938     /**
       
   939      * Overloading: allow rendering specific decorators
       
   940      *
       
   941      * Call renderDecoratorName() to render a specific decorator.
       
   942      *
       
   943      * @param  string $method
       
   944      * @param  array $args
       
   945      * @return string
       
   946      * @throws Zend_Form_Exception for invalid decorator or invalid method call
       
   947      */
       
   948     public function __call($method, $args)
       
   949     {
       
   950         if ('render' == substr($method, 0, 6)) {
       
   951             $this->_isPartialRendering = true;
       
   952             $this->render();
       
   953             $this->_isPartialRendering = false;
       
   954             $decoratorName = substr($method, 6);
       
   955             if (false !== ($decorator = $this->getDecorator($decoratorName))) {
       
   956                 $decorator->setElement($this);
       
   957                 $seed = '';
       
   958                 if (0 < count($args)) {
       
   959                     $seed = array_shift($args);
       
   960                 }
       
   961                 return $decorator->render($seed);
       
   962             }
       
   963 
       
   964             require_once 'Zend/Form/Element/Exception.php';
       
   965             throw new Zend_Form_Element_Exception(sprintf('Decorator by name %s does not exist', $decoratorName));
       
   966         }
       
   967 
       
   968         require_once 'Zend/Form/Element/Exception.php';
       
   969         throw new Zend_Form_Element_Exception(sprintf('Method %s does not exist', $method));
       
   970     }
       
   971 
       
   972     // Loaders
       
   973 
       
   974     /**
       
   975      * Set plugin loader to use for validator or filter chain
       
   976      *
       
   977      * @param  Zend_Loader_PluginLoader_Interface $loader
       
   978      * @param  string $type 'decorator', 'filter', or 'validate'
       
   979      * @return Zend_Form_Element
       
   980      * @throws Zend_Form_Exception on invalid type
       
   981      */
       
   982     public function setPluginLoader(Zend_Loader_PluginLoader_Interface $loader, $type)
       
   983     {
       
   984         $type = strtoupper($type);
       
   985         switch ($type) {
       
   986             case self::DECORATOR:
       
   987             case self::FILTER:
       
   988             case self::VALIDATE:
       
   989                 $this->_loaders[$type] = $loader;
       
   990                 return $this;
       
   991             default:
       
   992                 require_once 'Zend/Form/Exception.php';
       
   993                 throw new Zend_Form_Exception(sprintf('Invalid type "%s" provided to setPluginLoader()', $type));
       
   994         }
       
   995     }
       
   996 
       
   997     /**
       
   998      * Retrieve plugin loader for validator or filter chain
       
   999      *
       
  1000      * Instantiates with default rules if none available for that type. Use
       
  1001      * 'decorator', 'filter', or 'validate' for $type.
       
  1002      *
       
  1003      * @param  string $type
       
  1004      * @return Zend_Loader_PluginLoader
       
  1005      * @throws Zend_Loader_Exception on invalid type.
       
  1006      */
       
  1007     public function getPluginLoader($type)
       
  1008     {
       
  1009         $type = strtoupper($type);
       
  1010         switch ($type) {
       
  1011             case self::FILTER:
       
  1012             case self::VALIDATE:
       
  1013                 $prefixSegment = ucfirst(strtolower($type));
       
  1014                 $pathSegment   = $prefixSegment;
       
  1015             case self::DECORATOR:
       
  1016                 if (!isset($prefixSegment)) {
       
  1017                     $prefixSegment = 'Form_Decorator';
       
  1018                     $pathSegment   = 'Form/Decorator';
       
  1019                 }
       
  1020                 if (!isset($this->_loaders[$type])) {
       
  1021                     require_once 'Zend/Loader/PluginLoader.php';
       
  1022                     $this->_loaders[$type] = new Zend_Loader_PluginLoader(
       
  1023                         array('Zend_' . $prefixSegment . '_' => 'Zend/' . $pathSegment . '/')
       
  1024                     );
       
  1025                 }
       
  1026                 return $this->_loaders[$type];
       
  1027             default:
       
  1028                 require_once 'Zend/Form/Exception.php';
       
  1029                 throw new Zend_Form_Exception(sprintf('Invalid type "%s" provided to getPluginLoader()', $type));
       
  1030         }
       
  1031     }
       
  1032 
       
  1033     /**
       
  1034      * Add prefix path for plugin loader
       
  1035      *
       
  1036      * If no $type specified, assumes it is a base path for both filters and
       
  1037      * validators, and sets each according to the following rules:
       
  1038      * - decorators: $prefix = $prefix . '_Decorator'
       
  1039      * - filters: $prefix = $prefix . '_Filter'
       
  1040      * - validators: $prefix = $prefix . '_Validate'
       
  1041      *
       
  1042      * Otherwise, the path prefix is set on the appropriate plugin loader.
       
  1043      *
       
  1044      * @param  string $prefix
       
  1045      * @param  string $path
       
  1046      * @param  string $type
       
  1047      * @return Zend_Form_Element
       
  1048      * @throws Zend_Form_Exception for invalid type
       
  1049      */
       
  1050     public function addPrefixPath($prefix, $path, $type = null)
       
  1051     {
       
  1052         $type = strtoupper($type);
       
  1053         switch ($type) {
       
  1054             case self::DECORATOR:
       
  1055             case self::FILTER:
       
  1056             case self::VALIDATE:
       
  1057                 $loader = $this->getPluginLoader($type);
       
  1058                 $loader->addPrefixPath($prefix, $path);
       
  1059                 return $this;
       
  1060             case null:
       
  1061                 $prefix = rtrim($prefix, '_');
       
  1062                 $path   = rtrim($path, DIRECTORY_SEPARATOR);
       
  1063                 foreach (array(self::DECORATOR, self::FILTER, self::VALIDATE) as $type) {
       
  1064                     $cType        = ucfirst(strtolower($type));
       
  1065                     $pluginPath   = $path . DIRECTORY_SEPARATOR . $cType . DIRECTORY_SEPARATOR;
       
  1066                     $pluginPrefix = $prefix . '_' . $cType;
       
  1067                     $loader       = $this->getPluginLoader($type);
       
  1068                     $loader->addPrefixPath($pluginPrefix, $pluginPath);
       
  1069                 }
       
  1070                 return $this;
       
  1071             default:
       
  1072                 require_once 'Zend/Form/Exception.php';
       
  1073                 throw new Zend_Form_Exception(sprintf('Invalid type "%s" provided to getPluginLoader()', $type));
       
  1074         }
       
  1075     }
       
  1076 
       
  1077     /**
       
  1078      * Add many prefix paths at once
       
  1079      *
       
  1080      * @param  array $spec
       
  1081      * @return Zend_Form_Element
       
  1082      */
       
  1083     public function addPrefixPaths(array $spec)
       
  1084     {
       
  1085         if (isset($spec['prefix']) && isset($spec['path'])) {
       
  1086             return $this->addPrefixPath($spec['prefix'], $spec['path']);
       
  1087         }
       
  1088         foreach ($spec as $type => $paths) {
       
  1089             if (is_numeric($type) && is_array($paths)) {
       
  1090                 $type = null;
       
  1091                 if (isset($paths['prefix']) && isset($paths['path'])) {
       
  1092                     if (isset($paths['type'])) {
       
  1093                         $type = $paths['type'];
       
  1094                     }
       
  1095                     $this->addPrefixPath($paths['prefix'], $paths['path'], $type);
       
  1096                 }
       
  1097             } elseif (!is_numeric($type)) {
       
  1098                 if (!isset($paths['prefix']) || !isset($paths['path'])) {
       
  1099                     foreach ($paths as $prefix => $spec) {
       
  1100                         if (is_array($spec)) {
       
  1101                             foreach ($spec as $path) {
       
  1102                                 if (!is_string($path)) {
       
  1103                                     continue;
       
  1104                                 }
       
  1105                                 $this->addPrefixPath($prefix, $path, $type);
       
  1106                             }
       
  1107                         } elseif (is_string($spec)) {
       
  1108                             $this->addPrefixPath($prefix, $spec, $type);
       
  1109                         }
       
  1110                     }
       
  1111                 } else {
       
  1112                     $this->addPrefixPath($paths['prefix'], $paths['path'], $type);
       
  1113                 }
       
  1114             }
       
  1115         }
       
  1116         return $this;
       
  1117     }
       
  1118 
       
  1119     // Validation
       
  1120 
       
  1121     /**
       
  1122      * Add validator to validation chain
       
  1123      *
       
  1124      * Note: will overwrite existing validators if they are of the same class.
       
  1125      *
       
  1126      * @param  string|Zend_Validate_Interface $validator
       
  1127      * @param  bool $breakChainOnFailure
       
  1128      * @param  array $options
       
  1129      * @return Zend_Form_Element
       
  1130      * @throws Zend_Form_Exception if invalid validator type
       
  1131      */
       
  1132     public function addValidator($validator, $breakChainOnFailure = false, $options = array())
       
  1133     {
       
  1134         if ($validator instanceof Zend_Validate_Interface) {
       
  1135             $name = get_class($validator);
       
  1136 
       
  1137             if (!isset($validator->zfBreakChainOnFailure)) {
       
  1138                 $validator->zfBreakChainOnFailure = $breakChainOnFailure;
       
  1139             }
       
  1140         } elseif (is_string($validator)) {
       
  1141             $name      = $validator;
       
  1142             $validator = array(
       
  1143                 'validator' => $validator,
       
  1144                 'breakChainOnFailure' => $breakChainOnFailure,
       
  1145                 'options'             => $options,
       
  1146             );
       
  1147         } else {
       
  1148             require_once 'Zend/Form/Exception.php';
       
  1149             throw new Zend_Form_Exception('Invalid validator provided to addValidator; must be string or Zend_Validate_Interface');
       
  1150         }
       
  1151 
       
  1152 
       
  1153         $this->_validators[$name] = $validator;
       
  1154 
       
  1155         return $this;
       
  1156     }
       
  1157 
       
  1158     /**
       
  1159      * Add multiple validators
       
  1160      *
       
  1161      * @param  array $validators
       
  1162      * @return Zend_Form_Element
       
  1163      */
       
  1164     public function addValidators(array $validators)
       
  1165     {
       
  1166         foreach ($validators as $validatorInfo) {
       
  1167             if (is_string($validatorInfo)) {
       
  1168                 $this->addValidator($validatorInfo);
       
  1169             } elseif ($validatorInfo instanceof Zend_Validate_Interface) {
       
  1170                 $this->addValidator($validatorInfo);
       
  1171             } elseif (is_array($validatorInfo)) {
       
  1172                 $argc                = count($validatorInfo);
       
  1173                 $breakChainOnFailure = false;
       
  1174                 $options             = array();
       
  1175                 if (isset($validatorInfo['validator'])) {
       
  1176                     $validator = $validatorInfo['validator'];
       
  1177                     if (isset($validatorInfo['breakChainOnFailure'])) {
       
  1178                         $breakChainOnFailure = $validatorInfo['breakChainOnFailure'];
       
  1179                     }
       
  1180                     if (isset($validatorInfo['options'])) {
       
  1181                         $options = $validatorInfo['options'];
       
  1182                     }
       
  1183                     $this->addValidator($validator, $breakChainOnFailure, $options);
       
  1184                 } else {
       
  1185                     switch (true) {
       
  1186                         case (0 == $argc):
       
  1187                             break;
       
  1188                         case (1 <= $argc):
       
  1189                             $validator  = array_shift($validatorInfo);
       
  1190                         case (2 <= $argc):
       
  1191                             $breakChainOnFailure = array_shift($validatorInfo);
       
  1192                         case (3 <= $argc):
       
  1193                             $options = array_shift($validatorInfo);
       
  1194                         default:
       
  1195                             $this->addValidator($validator, $breakChainOnFailure, $options);
       
  1196                             break;
       
  1197                     }
       
  1198                 }
       
  1199             } else {
       
  1200                 require_once 'Zend/Form/Exception.php';
       
  1201                 throw new Zend_Form_Exception('Invalid validator passed to addValidators()');
       
  1202             }
       
  1203         }
       
  1204 
       
  1205         return $this;
       
  1206     }
       
  1207 
       
  1208     /**
       
  1209      * Set multiple validators, overwriting previous validators
       
  1210      *
       
  1211      * @param  array $validators
       
  1212      * @return Zend_Form_Element
       
  1213      */
       
  1214     public function setValidators(array $validators)
       
  1215     {
       
  1216         $this->clearValidators();
       
  1217         return $this->addValidators($validators);
       
  1218     }
       
  1219 
       
  1220     /**
       
  1221      * Retrieve a single validator by name
       
  1222      *
       
  1223      * @param  string $name
       
  1224      * @return Zend_Validate_Interface|false False if not found, validator otherwise
       
  1225      */
       
  1226     public function getValidator($name)
       
  1227     {
       
  1228         if (!isset($this->_validators[$name])) {
       
  1229             $len = strlen($name);
       
  1230             foreach ($this->_validators as $localName => $validator) {
       
  1231                 if ($len > strlen($localName)) {
       
  1232                     continue;
       
  1233                 }
       
  1234                 if (0 === substr_compare($localName, $name, -$len, $len, true)) {
       
  1235                     if (is_array($validator)) {
       
  1236                         return $this->_loadValidator($validator);
       
  1237                     }
       
  1238                     return $validator;
       
  1239                 }
       
  1240             }
       
  1241             return false;
       
  1242         }
       
  1243 
       
  1244         if (is_array($this->_validators[$name])) {
       
  1245             return $this->_loadValidator($this->_validators[$name]);
       
  1246         }
       
  1247 
       
  1248         return $this->_validators[$name];
       
  1249     }
       
  1250 
       
  1251     /**
       
  1252      * Retrieve all validators
       
  1253      *
       
  1254      * @return array
       
  1255      */
       
  1256     public function getValidators()
       
  1257     {
       
  1258         $validators = array();
       
  1259         foreach ($this->_validators as $key => $value) {
       
  1260             if ($value instanceof Zend_Validate_Interface) {
       
  1261                 $validators[$key] = $value;
       
  1262                 continue;
       
  1263             }
       
  1264             $validator = $this->_loadValidator($value);
       
  1265             $validators[get_class($validator)] = $validator;
       
  1266         }
       
  1267         return $validators;
       
  1268     }
       
  1269 
       
  1270     /**
       
  1271      * Remove a single validator by name
       
  1272      *
       
  1273      * @param  string $name
       
  1274      * @return bool
       
  1275      */
       
  1276     public function removeValidator($name)
       
  1277     {
       
  1278         if (isset($this->_validators[$name])) {
       
  1279             unset($this->_validators[$name]);
       
  1280         } else {
       
  1281             $len = strlen($name);
       
  1282             foreach (array_keys($this->_validators) as $validator) {
       
  1283                 if ($len > strlen($validator)) {
       
  1284                     continue;
       
  1285                 }
       
  1286                 if (0 === substr_compare($validator, $name, -$len, $len, true)) {
       
  1287                     unset($this->_validators[$validator]);
       
  1288                     break;
       
  1289                 }
       
  1290             }
       
  1291         }
       
  1292 
       
  1293         return $this;
       
  1294     }
       
  1295 
       
  1296     /**
       
  1297      * Clear all validators
       
  1298      *
       
  1299      * @return Zend_Form_Element
       
  1300      */
       
  1301     public function clearValidators()
       
  1302     {
       
  1303         $this->_validators = array();
       
  1304         return $this;
       
  1305     }
       
  1306 
       
  1307     /**
       
  1308      * Validate element value
       
  1309      *
       
  1310      * If a translation adapter is registered, any error messages will be
       
  1311      * translated according to the current locale, using the given error code;
       
  1312      * if no matching translation is found, the original message will be
       
  1313      * utilized.
       
  1314      *
       
  1315      * Note: The *filtered* value is validated.
       
  1316      *
       
  1317      * @param  mixed $value
       
  1318      * @param  mixed $context
       
  1319      * @return boolean
       
  1320      */
       
  1321     public function isValid($value, $context = null)
       
  1322     {
       
  1323         $this->setValue($value);
       
  1324         $value = $this->getValue();
       
  1325 
       
  1326         if ((('' === $value) || (null === $value))
       
  1327             && !$this->isRequired()
       
  1328             && $this->getAllowEmpty()
       
  1329         ) {
       
  1330             return true;
       
  1331         }
       
  1332 
       
  1333         if ($this->isRequired()
       
  1334             && $this->autoInsertNotEmptyValidator()
       
  1335             && !$this->getValidator('NotEmpty'))
       
  1336         {
       
  1337             $validators = $this->getValidators();
       
  1338             $notEmpty   = array('validator' => 'NotEmpty', 'breakChainOnFailure' => true);
       
  1339             array_unshift($validators, $notEmpty);
       
  1340             $this->setValidators($validators);
       
  1341         }
       
  1342 
       
  1343         // Find the correct translator. Zend_Validate_Abstract::getDefaultTranslator()
       
  1344         // will get either the static translator attached to Zend_Validate_Abstract
       
  1345         // or the 'Zend_Translate' from Zend_Registry.
       
  1346         if (Zend_Validate_Abstract::hasDefaultTranslator() &&
       
  1347             !Zend_Form::hasDefaultTranslator())
       
  1348         {
       
  1349             $translator = Zend_Validate_Abstract::getDefaultTranslator();
       
  1350             if ($this->hasTranslator()) {
       
  1351                 // only pick up this element's translator if it was attached directly.
       
  1352                 $translator = $this->getTranslator();
       
  1353             }
       
  1354         } else {
       
  1355             $translator = $this->getTranslator();
       
  1356         }
       
  1357 
       
  1358         $this->_messages = array();
       
  1359         $this->_errors   = array();
       
  1360         $result          = true;
       
  1361         $isArray         = $this->isArray();
       
  1362         foreach ($this->getValidators() as $key => $validator) {
       
  1363             if (method_exists($validator, 'setTranslator')) {
       
  1364                 if (method_exists($validator, 'hasTranslator')) {
       
  1365                     if (!$validator->hasTranslator()) {
       
  1366                         $validator->setTranslator($translator);
       
  1367                     }
       
  1368                 } else {
       
  1369                     $validator->setTranslator($translator);
       
  1370                 }
       
  1371             }
       
  1372 
       
  1373             if (method_exists($validator, 'setDisableTranslator')) {
       
  1374                 $validator->setDisableTranslator($this->translatorIsDisabled());
       
  1375             }
       
  1376 
       
  1377             if ($isArray && is_array($value)) {
       
  1378                 $messages = array();
       
  1379                 $errors   = array();
       
  1380                 foreach ($value as $val) {
       
  1381                     if (!$validator->isValid($val, $context)) {
       
  1382                         $result = false;
       
  1383                         if ($this->_hasErrorMessages()) {
       
  1384                             $messages = $this->_getErrorMessages();
       
  1385                             $errors   = $messages;
       
  1386                         } else {
       
  1387                             $messages = array_merge($messages, $validator->getMessages());
       
  1388                             $errors   = array_merge($errors,   $validator->getErrors());
       
  1389                         }
       
  1390                     }
       
  1391                 }
       
  1392                 if ($result) {
       
  1393                     continue;
       
  1394                 }
       
  1395             } elseif ($validator->isValid($value, $context)) {
       
  1396                 continue;
       
  1397             } else {
       
  1398                 $result = false;
       
  1399                 if ($this->_hasErrorMessages()) {
       
  1400                     $messages = $this->_getErrorMessages();
       
  1401                     $errors   = $messages;
       
  1402                 } else {
       
  1403                     $messages = $validator->getMessages();
       
  1404                     $errors   = array_keys($messages);
       
  1405                 }
       
  1406             }
       
  1407 
       
  1408             $result          = false;
       
  1409             $this->_messages = array_merge($this->_messages, $messages);
       
  1410             $this->_errors   = array_merge($this->_errors,   $errors);
       
  1411 
       
  1412             if ($validator->zfBreakChainOnFailure) {
       
  1413                 break;
       
  1414             }
       
  1415         }
       
  1416 
       
  1417         // If element manually flagged as invalid, return false
       
  1418         if ($this->_isErrorForced) {
       
  1419             return false;
       
  1420         }
       
  1421 
       
  1422         return $result;
       
  1423     }
       
  1424 
       
  1425     /**
       
  1426      * Add a custom error message to return in the event of failed validation
       
  1427      *
       
  1428      * @param  string $message
       
  1429      * @return Zend_Form_Element
       
  1430      */
       
  1431     public function addErrorMessage($message)
       
  1432     {
       
  1433         $this->_errorMessages[] = (string) $message;
       
  1434         return $this;
       
  1435     }
       
  1436 
       
  1437     /**
       
  1438      * Add multiple custom error messages to return in the event of failed validation
       
  1439      *
       
  1440      * @param  array $messages
       
  1441      * @return Zend_Form_Element
       
  1442      */
       
  1443     public function addErrorMessages(array $messages)
       
  1444     {
       
  1445         foreach ($messages as $message) {
       
  1446             $this->addErrorMessage($message);
       
  1447         }
       
  1448         return $this;
       
  1449     }
       
  1450 
       
  1451     /**
       
  1452      * Same as addErrorMessages(), but clears custom error message stack first
       
  1453      *
       
  1454      * @param  array $messages
       
  1455      * @return Zend_Form_Element
       
  1456      */
       
  1457     public function setErrorMessages(array $messages)
       
  1458     {
       
  1459         $this->clearErrorMessages();
       
  1460         return $this->addErrorMessages($messages);
       
  1461     }
       
  1462 
       
  1463     /**
       
  1464      * Retrieve custom error messages
       
  1465      *
       
  1466      * @return array
       
  1467      */
       
  1468     public function getErrorMessages()
       
  1469     {
       
  1470         return $this->_errorMessages;
       
  1471     }
       
  1472 
       
  1473     /**
       
  1474      * Clear custom error messages stack
       
  1475      *
       
  1476      * @return Zend_Form_Element
       
  1477      */
       
  1478     public function clearErrorMessages()
       
  1479     {
       
  1480         $this->_errorMessages = array();
       
  1481         return $this;
       
  1482     }
       
  1483 
       
  1484     /**
       
  1485      * Get errorMessageSeparator
       
  1486      *
       
  1487      * @return string
       
  1488      */
       
  1489     public function getErrorMessageSeparator()
       
  1490     {
       
  1491         return $this->_errorMessageSeparator;
       
  1492     }
       
  1493 
       
  1494     /**
       
  1495      * Set errorMessageSeparator
       
  1496      *
       
  1497      * @param  string $separator
       
  1498      * @return Zend_Form_Element
       
  1499      */
       
  1500     public function setErrorMessageSeparator($separator)
       
  1501     {
       
  1502         $this->_errorMessageSeparator = $separator;
       
  1503         return $this;
       
  1504     }
       
  1505 
       
  1506     /**
       
  1507      * Mark the element as being in a failed validation state
       
  1508      *
       
  1509      * @return Zend_Form_Element
       
  1510      */
       
  1511     public function markAsError()
       
  1512     {
       
  1513         $messages       = $this->getMessages();
       
  1514         $customMessages = $this->_getErrorMessages();
       
  1515         $messages       = $messages + $customMessages;
       
  1516         if (empty($messages)) {
       
  1517             $this->_isError = true;
       
  1518         } else {
       
  1519             $this->_messages = $messages;
       
  1520         }
       
  1521         $this->_isErrorForced = true;
       
  1522         return $this;
       
  1523     }
       
  1524 
       
  1525     /**
       
  1526      * Add an error message and mark element as failed validation
       
  1527      *
       
  1528      * @param  string $message
       
  1529      * @return Zend_Form_Element
       
  1530      */
       
  1531     public function addError($message)
       
  1532     {
       
  1533         $this->addErrorMessage($message);
       
  1534         $this->markAsError();
       
  1535         return $this;
       
  1536     }
       
  1537 
       
  1538     /**
       
  1539      * Add multiple error messages and flag element as failed validation
       
  1540      *
       
  1541      * @param  array $messages
       
  1542      * @return Zend_Form_Element
       
  1543      */
       
  1544     public function addErrors(array $messages)
       
  1545     {
       
  1546         foreach ($messages as $message) {
       
  1547             $this->addError($message);
       
  1548         }
       
  1549         return $this;
       
  1550     }
       
  1551 
       
  1552     /**
       
  1553      * Overwrite any previously set error messages and flag as failed validation
       
  1554      *
       
  1555      * @param  array $messages
       
  1556      * @return Zend_Form_Element
       
  1557      */
       
  1558     public function setErrors(array $messages)
       
  1559     {
       
  1560         $this->clearErrorMessages();
       
  1561         return $this->addErrors($messages);
       
  1562     }
       
  1563 
       
  1564     /**
       
  1565      * Are there errors registered?
       
  1566      *
       
  1567      * @return bool
       
  1568      */
       
  1569     public function hasErrors()
       
  1570     {
       
  1571         return (!empty($this->_messages) || $this->_isError);
       
  1572     }
       
  1573 
       
  1574     /**
       
  1575      * Retrieve validator chain errors
       
  1576      *
       
  1577      * @return array
       
  1578      */
       
  1579     public function getErrors()
       
  1580     {
       
  1581         return $this->_errors;
       
  1582     }
       
  1583 
       
  1584     /**
       
  1585      * Retrieve error messages
       
  1586      *
       
  1587      * @return array
       
  1588      */
       
  1589     public function getMessages()
       
  1590     {
       
  1591         return $this->_messages;
       
  1592     }
       
  1593 
       
  1594 
       
  1595     // Filtering
       
  1596 
       
  1597     /**
       
  1598      * Add a filter to the element
       
  1599      *
       
  1600      * @param  string|Zend_Filter_Interface $filter
       
  1601      * @return Zend_Form_Element
       
  1602      */
       
  1603     public function addFilter($filter, $options = array())
       
  1604     {
       
  1605         if ($filter instanceof Zend_Filter_Interface) {
       
  1606             $name = get_class($filter);
       
  1607         } elseif (is_string($filter)) {
       
  1608             $name = $filter;
       
  1609             $filter = array(
       
  1610                 'filter'  => $filter,
       
  1611                 'options' => $options,
       
  1612             );
       
  1613             $this->_filters[$name] = $filter;
       
  1614         } else {
       
  1615             require_once 'Zend/Form/Exception.php';
       
  1616             throw new Zend_Form_Exception('Invalid filter provided to addFilter; must be string or Zend_Filter_Interface');
       
  1617         }
       
  1618 
       
  1619         $this->_filters[$name] = $filter;
       
  1620 
       
  1621         return $this;
       
  1622     }
       
  1623 
       
  1624     /**
       
  1625      * Add filters to element
       
  1626      *
       
  1627      * @param  array $filters
       
  1628      * @return Zend_Form_Element
       
  1629      */
       
  1630     public function addFilters(array $filters)
       
  1631     {
       
  1632         foreach ($filters as $filterInfo) {
       
  1633             if (is_string($filterInfo)) {
       
  1634                 $this->addFilter($filterInfo);
       
  1635             } elseif ($filterInfo instanceof Zend_Filter_Interface) {
       
  1636                 $this->addFilter($filterInfo);
       
  1637             } elseif (is_array($filterInfo)) {
       
  1638                 $argc                = count($filterInfo);
       
  1639                 $options             = array();
       
  1640                 if (isset($filterInfo['filter'])) {
       
  1641                     $filter = $filterInfo['filter'];
       
  1642                     if (isset($filterInfo['options'])) {
       
  1643                         $options = $filterInfo['options'];
       
  1644                     }
       
  1645                     $this->addFilter($filter, $options);
       
  1646                 } else {
       
  1647                     switch (true) {
       
  1648                         case (0 == $argc):
       
  1649                             break;
       
  1650                         case (1 <= $argc):
       
  1651                             $filter  = array_shift($filterInfo);
       
  1652                         case (2 <= $argc):
       
  1653                             $options = array_shift($filterInfo);
       
  1654                         default:
       
  1655                             $this->addFilter($filter, $options);
       
  1656                             break;
       
  1657                     }
       
  1658                 }
       
  1659             } else {
       
  1660                 require_once 'Zend/Form/Exception.php';
       
  1661                 throw new Zend_Form_Exception('Invalid filter passed to addFilters()');
       
  1662             }
       
  1663         }
       
  1664 
       
  1665         return $this;
       
  1666     }
       
  1667 
       
  1668     /**
       
  1669      * Add filters to element, overwriting any already existing
       
  1670      *
       
  1671      * @param  array $filters
       
  1672      * @return Zend_Form_Element
       
  1673      */
       
  1674     public function setFilters(array $filters)
       
  1675     {
       
  1676         $this->clearFilters();
       
  1677         return $this->addFilters($filters);
       
  1678     }
       
  1679 
       
  1680     /**
       
  1681      * Retrieve a single filter by name
       
  1682      *
       
  1683      * @param  string $name
       
  1684      * @return Zend_Filter_Interface
       
  1685      */
       
  1686     public function getFilter($name)
       
  1687     {
       
  1688         if (!isset($this->_filters[$name])) {
       
  1689             $len = strlen($name);
       
  1690             foreach ($this->_filters as $localName => $filter) {
       
  1691                 if ($len > strlen($localName)) {
       
  1692                     continue;
       
  1693                 }
       
  1694 
       
  1695                 if (0 === substr_compare($localName, $name, -$len, $len, true)) {
       
  1696                     if (is_array($filter)) {
       
  1697                         return $this->_loadFilter($filter);
       
  1698                     }
       
  1699                     return $filter;
       
  1700                 }
       
  1701             }
       
  1702             return false;
       
  1703         }
       
  1704 
       
  1705         if (is_array($this->_filters[$name])) {
       
  1706             return $this->_loadFilter($this->_filters[$name]);
       
  1707         }
       
  1708 
       
  1709         return $this->_filters[$name];
       
  1710     }
       
  1711 
       
  1712     /**
       
  1713      * Get all filters
       
  1714      *
       
  1715      * @return array
       
  1716      */
       
  1717     public function getFilters()
       
  1718     {
       
  1719         $filters = array();
       
  1720         foreach ($this->_filters as $key => $value) {
       
  1721             if ($value instanceof Zend_Filter_Interface) {
       
  1722                 $filters[$key] = $value;
       
  1723                 continue;
       
  1724             }
       
  1725             $filter = $this->_loadFilter($value);
       
  1726             $filters[get_class($filter)] = $filter;
       
  1727         }
       
  1728         return $filters;
       
  1729     }
       
  1730 
       
  1731     /**
       
  1732      * Remove a filter by name
       
  1733      *
       
  1734      * @param  string $name
       
  1735      * @return Zend_Form_Element
       
  1736      */
       
  1737     public function removeFilter($name)
       
  1738     {
       
  1739         if (isset($this->_filters[$name])) {
       
  1740             unset($this->_filters[$name]);
       
  1741         } else {
       
  1742             $len = strlen($name);
       
  1743             foreach (array_keys($this->_filters) as $filter) {
       
  1744                 if ($len > strlen($filter)) {
       
  1745                     continue;
       
  1746                 }
       
  1747                 if (0 === substr_compare($filter, $name, -$len, $len, true)) {
       
  1748                     unset($this->_filters[$filter]);
       
  1749                     break;
       
  1750                 }
       
  1751             }
       
  1752         }
       
  1753 
       
  1754         return $this;
       
  1755     }
       
  1756 
       
  1757     /**
       
  1758      * Clear all filters
       
  1759      *
       
  1760      * @return Zend_Form_Element
       
  1761      */
       
  1762     public function clearFilters()
       
  1763     {
       
  1764         $this->_filters = array();
       
  1765         return $this;
       
  1766     }
       
  1767 
       
  1768     // Rendering
       
  1769 
       
  1770     /**
       
  1771      * Set view object
       
  1772      *
       
  1773      * @param  Zend_View_Interface $view
       
  1774      * @return Zend_Form_Element
       
  1775      */
       
  1776     public function setView(Zend_View_Interface $view = null)
       
  1777     {
       
  1778         $this->_view = $view;
       
  1779         return $this;
       
  1780     }
       
  1781 
       
  1782     /**
       
  1783      * Retrieve view object
       
  1784      *
       
  1785      * Retrieves from ViewRenderer if none previously set.
       
  1786      *
       
  1787      * @return null|Zend_View_Interface
       
  1788      */
       
  1789     public function getView()
       
  1790     {
       
  1791         if (null === $this->_view) {
       
  1792             require_once 'Zend/Controller/Action/HelperBroker.php';
       
  1793             $viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
       
  1794             $this->setView($viewRenderer->view);
       
  1795         }
       
  1796         return $this->_view;
       
  1797     }
       
  1798 
       
  1799     /**
       
  1800      * Instantiate a decorator based on class name or class name fragment
       
  1801      *
       
  1802      * @param  string $name
       
  1803      * @param  null|array $options
       
  1804      * @return Zend_Form_Decorator_Interface
       
  1805      */
       
  1806     protected function _getDecorator($name, $options)
       
  1807     {
       
  1808         $class = $this->getPluginLoader(self::DECORATOR)->load($name);
       
  1809         if (null === $options) {
       
  1810             $decorator = new $class;
       
  1811         } else {
       
  1812             $decorator = new $class($options);
       
  1813         }
       
  1814 
       
  1815         return $decorator;
       
  1816     }
       
  1817 
       
  1818     /**
       
  1819      * Add a decorator for rendering the element
       
  1820      *
       
  1821      * @param  string|Zend_Form_Decorator_Interface $decorator
       
  1822      * @param  array|Zend_Config $options Options with which to initialize decorator
       
  1823      * @return Zend_Form_Element
       
  1824      */
       
  1825     public function addDecorator($decorator, $options = null)
       
  1826     {
       
  1827         if ($decorator instanceof Zend_Form_Decorator_Interface) {
       
  1828             $name = get_class($decorator);
       
  1829         } elseif (is_string($decorator)) {
       
  1830             $name      = $decorator;
       
  1831             $decorator = array(
       
  1832                 'decorator' => $name,
       
  1833                 'options'   => $options,
       
  1834             );
       
  1835         } elseif (is_array($decorator)) {
       
  1836             foreach ($decorator as $name => $spec) {
       
  1837                 break;
       
  1838             }
       
  1839             if (is_numeric($name)) {
       
  1840                 require_once 'Zend/Form/Exception.php';
       
  1841                 throw new Zend_Form_Exception('Invalid alias provided to addDecorator; must be alphanumeric string');
       
  1842             }
       
  1843             if (is_string($spec)) {
       
  1844                 $decorator = array(
       
  1845                     'decorator' => $spec,
       
  1846                     'options'   => $options,
       
  1847                 );
       
  1848             } elseif ($spec instanceof Zend_Form_Decorator_Interface) {
       
  1849                 $decorator = $spec;
       
  1850             }
       
  1851         } else {
       
  1852             require_once 'Zend/Form/Exception.php';
       
  1853             throw new Zend_Form_Exception('Invalid decorator provided to addDecorator; must be string or Zend_Form_Decorator_Interface');
       
  1854         }
       
  1855 
       
  1856         $this->_decorators[$name] = $decorator;
       
  1857 
       
  1858         return $this;
       
  1859     }
       
  1860 
       
  1861     /**
       
  1862      * Add many decorators at once
       
  1863      *
       
  1864      * @param  array $decorators
       
  1865      * @return Zend_Form_Element
       
  1866      */
       
  1867     public function addDecorators(array $decorators)
       
  1868     {
       
  1869         foreach ($decorators as $decoratorName => $decoratorInfo) {
       
  1870             if (is_string($decoratorInfo) ||
       
  1871                 $decoratorInfo instanceof Zend_Form_Decorator_Interface) {
       
  1872                 if (!is_numeric($decoratorName)) {
       
  1873                     $this->addDecorator(array($decoratorName => $decoratorInfo));
       
  1874                 } else {
       
  1875                     $this->addDecorator($decoratorInfo);
       
  1876                 }
       
  1877             } elseif (is_array($decoratorInfo)) {
       
  1878                 $argc    = count($decoratorInfo);
       
  1879                 $options = array();
       
  1880                 if (isset($decoratorInfo['decorator'])) {
       
  1881                     $decorator = $decoratorInfo['decorator'];
       
  1882                     if (isset($decoratorInfo['options'])) {
       
  1883                         $options = $decoratorInfo['options'];
       
  1884                     }
       
  1885                     $this->addDecorator($decorator, $options);
       
  1886                 } else {
       
  1887                     switch (true) {
       
  1888                         case (0 == $argc):
       
  1889                             break;
       
  1890                         case (1 <= $argc):
       
  1891                             $decorator  = array_shift($decoratorInfo);
       
  1892                         case (2 <= $argc):
       
  1893                             $options = array_shift($decoratorInfo);
       
  1894                         default:
       
  1895                             $this->addDecorator($decorator, $options);
       
  1896                             break;
       
  1897                     }
       
  1898                 }
       
  1899             } else {
       
  1900                 require_once 'Zend/Form/Exception.php';
       
  1901                 throw new Zend_Form_Exception('Invalid decorator passed to addDecorators()');
       
  1902             }
       
  1903         }
       
  1904 
       
  1905         return $this;
       
  1906     }
       
  1907 
       
  1908     /**
       
  1909      * Overwrite all decorators
       
  1910      *
       
  1911      * @param  array $decorators
       
  1912      * @return Zend_Form_Element
       
  1913      */
       
  1914     public function setDecorators(array $decorators)
       
  1915     {
       
  1916         $this->clearDecorators();
       
  1917         return $this->addDecorators($decorators);
       
  1918     }
       
  1919 
       
  1920     /**
       
  1921      * Retrieve a registered decorator
       
  1922      *
       
  1923      * @param  string $name
       
  1924      * @return false|Zend_Form_Decorator_Abstract
       
  1925      */
       
  1926     public function getDecorator($name)
       
  1927     {
       
  1928         if (!isset($this->_decorators[$name])) {
       
  1929             $len = strlen($name);
       
  1930             foreach ($this->_decorators as $localName => $decorator) {
       
  1931                 if ($len > strlen($localName)) {
       
  1932                     continue;
       
  1933                 }
       
  1934 
       
  1935                 if (0 === substr_compare($localName, $name, -$len, $len, true)) {
       
  1936                     if (is_array($decorator)) {
       
  1937                         return $this->_loadDecorator($decorator, $localName);
       
  1938                     }
       
  1939                     return $decorator;
       
  1940                 }
       
  1941             }
       
  1942             return false;
       
  1943         }
       
  1944 
       
  1945         if (is_array($this->_decorators[$name])) {
       
  1946             return $this->_loadDecorator($this->_decorators[$name], $name);
       
  1947         }
       
  1948 
       
  1949         return $this->_decorators[$name];
       
  1950     }
       
  1951 
       
  1952     /**
       
  1953      * Retrieve all decorators
       
  1954      *
       
  1955      * @return array
       
  1956      */
       
  1957     public function getDecorators()
       
  1958     {
       
  1959         foreach ($this->_decorators as $key => $value) {
       
  1960             if (is_array($value)) {
       
  1961                 $this->_loadDecorator($value, $key);
       
  1962             }
       
  1963         }
       
  1964         return $this->_decorators;
       
  1965     }
       
  1966 
       
  1967     /**
       
  1968      * Remove a single decorator
       
  1969      *
       
  1970      * @param  string $name
       
  1971      * @return Zend_Form_Element
       
  1972      */
       
  1973     public function removeDecorator($name)
       
  1974     {
       
  1975         if (isset($this->_decorators[$name])) {
       
  1976             unset($this->_decorators[$name]);
       
  1977         } else {
       
  1978             $len = strlen($name);
       
  1979             foreach (array_keys($this->_decorators) as $decorator) {
       
  1980                 if ($len > strlen($decorator)) {
       
  1981                     continue;
       
  1982                 }
       
  1983                 if (0 === substr_compare($decorator, $name, -$len, $len, true)) {
       
  1984                     unset($this->_decorators[$decorator]);
       
  1985                     break;
       
  1986                 }
       
  1987             }
       
  1988         }
       
  1989 
       
  1990         return $this;
       
  1991     }
       
  1992 
       
  1993     /**
       
  1994      * Clear all decorators
       
  1995      *
       
  1996      * @return Zend_Form_Element
       
  1997      */
       
  1998     public function clearDecorators()
       
  1999     {
       
  2000         $this->_decorators = array();
       
  2001         return $this;
       
  2002     }
       
  2003 
       
  2004     /**
       
  2005      * Render form element
       
  2006      *
       
  2007      * @param  Zend_View_Interface $view
       
  2008      * @return string
       
  2009      */
       
  2010     public function render(Zend_View_Interface $view = null)
       
  2011     {
       
  2012         if ($this->_isPartialRendering) {
       
  2013             return '';
       
  2014         }
       
  2015 
       
  2016         if (null !== $view) {
       
  2017             $this->setView($view);
       
  2018         }
       
  2019 
       
  2020         $content = '';
       
  2021         foreach ($this->getDecorators() as $decorator) {
       
  2022             $decorator->setElement($this);
       
  2023             $content = $decorator->render($content);
       
  2024         }
       
  2025         return $content;
       
  2026     }
       
  2027 
       
  2028     /**
       
  2029      * String representation of form element
       
  2030      *
       
  2031      * Proxies to {@link render()}.
       
  2032      *
       
  2033      * @return string
       
  2034      */
       
  2035     public function __toString()
       
  2036     {
       
  2037         try {
       
  2038             $return = $this->render();
       
  2039             return $return;
       
  2040         } catch (Exception $e) {
       
  2041             trigger_error($e->getMessage(), E_USER_WARNING);
       
  2042             return '';
       
  2043         }
       
  2044     }
       
  2045 
       
  2046     /**
       
  2047      * Lazy-load a filter
       
  2048      *
       
  2049      * @param  array $filter
       
  2050      * @return Zend_Filter_Interface
       
  2051      */
       
  2052     protected function _loadFilter(array $filter)
       
  2053     {
       
  2054         $origName = $filter['filter'];
       
  2055         $name     = $this->getPluginLoader(self::FILTER)->load($filter['filter']);
       
  2056 
       
  2057         if (array_key_exists($name, $this->_filters)) {
       
  2058             require_once 'Zend/Form/Exception.php';
       
  2059             throw new Zend_Form_Exception(sprintf('Filter instance already exists for filter "%s"', $origName));
       
  2060         }
       
  2061 
       
  2062         if (empty($filter['options'])) {
       
  2063             $instance = new $name;
       
  2064         } else {
       
  2065             $r = new ReflectionClass($name);
       
  2066             if ($r->hasMethod('__construct')) {
       
  2067                 $instance = $r->newInstanceArgs((array) $filter['options']);
       
  2068             } else {
       
  2069                 $instance = $r->newInstance();
       
  2070             }
       
  2071         }
       
  2072 
       
  2073         if ($origName != $name) {
       
  2074             $filterNames  = array_keys($this->_filters);
       
  2075             $order        = array_flip($filterNames);
       
  2076             $order[$name] = $order[$origName];
       
  2077             $filtersExchange = array();
       
  2078             unset($order[$origName]);
       
  2079             asort($order);
       
  2080             foreach ($order as $key => $index) {
       
  2081                 if ($key == $name) {
       
  2082                     $filtersExchange[$key] = $instance;
       
  2083                     continue;
       
  2084                 }
       
  2085                 $filtersExchange[$key] = $this->_filters[$key];
       
  2086             }
       
  2087             $this->_filters = $filtersExchange;
       
  2088         } else {
       
  2089             $this->_filters[$name] = $instance;
       
  2090         }
       
  2091 
       
  2092         return $instance;
       
  2093     }
       
  2094 
       
  2095     /**
       
  2096      * Lazy-load a validator
       
  2097      *
       
  2098      * @param  array $validator Validator definition
       
  2099      * @return Zend_Validate_Interface
       
  2100      */
       
  2101     protected function _loadValidator(array $validator)
       
  2102     {
       
  2103         $origName = $validator['validator'];
       
  2104         $name     = $this->getPluginLoader(self::VALIDATE)->load($validator['validator']);
       
  2105 
       
  2106         if (array_key_exists($name, $this->_validators)) {
       
  2107             require_once 'Zend/Form/Exception.php';
       
  2108             throw new Zend_Form_Exception(sprintf('Validator instance already exists for validator "%s"', $origName));
       
  2109         }
       
  2110 
       
  2111         $messages = false;
       
  2112         if (isset($validator['options']) && array_key_exists('messages', (array)$validator['options'])) {
       
  2113             $messages = $validator['options']['messages'];
       
  2114             unset($validator['options']['messages']);
       
  2115         }
       
  2116 
       
  2117         if (empty($validator['options'])) {
       
  2118             $instance = new $name;
       
  2119         } else {
       
  2120             $r = new ReflectionClass($name);
       
  2121             if ($r->hasMethod('__construct')) {
       
  2122                 $numeric = false;
       
  2123                 if (is_array($validator['options'])) {
       
  2124                     $keys    = array_keys($validator['options']);
       
  2125                     foreach($keys as $key) {
       
  2126                         if (is_numeric($key)) {
       
  2127                             $numeric = true;
       
  2128                             break;
       
  2129                         }
       
  2130                     }
       
  2131                 }
       
  2132 
       
  2133                 if ($numeric) {
       
  2134                     $instance = $r->newInstanceArgs((array) $validator['options']);
       
  2135                 } else {
       
  2136                     $instance = $r->newInstance($validator['options']);
       
  2137                 }
       
  2138             } else {
       
  2139                 $instance = $r->newInstance();
       
  2140             }
       
  2141         }
       
  2142 
       
  2143         if ($messages) {
       
  2144             if (is_array($messages)) {
       
  2145                 $instance->setMessages($messages);
       
  2146             } elseif (is_string($messages)) {
       
  2147                 $instance->setMessage($messages);
       
  2148             }
       
  2149         }
       
  2150         $instance->zfBreakChainOnFailure = $validator['breakChainOnFailure'];
       
  2151 
       
  2152         if ($origName != $name) {
       
  2153             $validatorNames     = array_keys($this->_validators);
       
  2154             $order              = array_flip($validatorNames);
       
  2155             $order[$name]       = $order[$origName];
       
  2156             $validatorsExchange = array();
       
  2157             unset($order[$origName]);
       
  2158             asort($order);
       
  2159             foreach ($order as $key => $index) {
       
  2160                 if ($key == $name) {
       
  2161                     $validatorsExchange[$key] = $instance;
       
  2162                     continue;
       
  2163                 }
       
  2164                 $validatorsExchange[$key] = $this->_validators[$key];
       
  2165             }
       
  2166             $this->_validators = $validatorsExchange;
       
  2167         } else {
       
  2168             $this->_validators[$name] = $instance;
       
  2169         }
       
  2170 
       
  2171         return $instance;
       
  2172     }
       
  2173 
       
  2174     /**
       
  2175      * Lazy-load a decorator
       
  2176      *
       
  2177      * @param  array $decorator Decorator type and options
       
  2178      * @param  mixed $name Decorator name or alias
       
  2179      * @return Zend_Form_Decorator_Interface
       
  2180      */
       
  2181     protected function _loadDecorator(array $decorator, $name)
       
  2182     {
       
  2183         $sameName = false;
       
  2184         if ($name == $decorator['decorator']) {
       
  2185             $sameName = true;
       
  2186         }
       
  2187 
       
  2188         $instance = $this->_getDecorator($decorator['decorator'], $decorator['options']);
       
  2189         if ($sameName) {
       
  2190             $newName            = get_class($instance);
       
  2191             $decoratorNames     = array_keys($this->_decorators);
       
  2192             $order              = array_flip($decoratorNames);
       
  2193             $order[$newName]    = $order[$name];
       
  2194             $decoratorsExchange = array();
       
  2195             unset($order[$name]);
       
  2196             asort($order);
       
  2197             foreach ($order as $key => $index) {
       
  2198                 if ($key == $newName) {
       
  2199                     $decoratorsExchange[$key] = $instance;
       
  2200                     continue;
       
  2201                 }
       
  2202                 $decoratorsExchange[$key] = $this->_decorators[$key];
       
  2203             }
       
  2204             $this->_decorators = $decoratorsExchange;
       
  2205         } else {
       
  2206             $this->_decorators[$name] = $instance;
       
  2207         }
       
  2208 
       
  2209         return $instance;
       
  2210     }
       
  2211 
       
  2212     /**
       
  2213      * Retrieve error messages and perform translation and value substitution
       
  2214      *
       
  2215      * @return array
       
  2216      */
       
  2217     protected function _getErrorMessages()
       
  2218     {
       
  2219         $translator = $this->getTranslator();
       
  2220         $messages   = $this->getErrorMessages();
       
  2221         $value      = $this->getValue();
       
  2222         foreach ($messages as $key => $message) {
       
  2223             if (null !== $translator) {
       
  2224                 $message = $translator->translate($message);
       
  2225             }
       
  2226             if (($this->isArray() || is_array($value))
       
  2227                 && !empty($value)
       
  2228             ) {
       
  2229                 $aggregateMessages = array();
       
  2230                 foreach ($value as $val) {
       
  2231                     $aggregateMessages[] = str_replace('%value%', $val, $message);
       
  2232                 }
       
  2233                 $messages[$key] = implode($this->getErrorMessageSeparator(), $aggregateMessages);
       
  2234             } else {
       
  2235                 $messages[$key] = str_replace('%value%', $value, $message);
       
  2236             }
       
  2237         }
       
  2238         return $messages;
       
  2239     }
       
  2240 
       
  2241     /**
       
  2242      * Are there custom error messages registered?
       
  2243      *
       
  2244      * @return bool
       
  2245      */
       
  2246     protected function _hasErrorMessages()
       
  2247     {
       
  2248         return !empty($this->_errorMessages);
       
  2249     }
       
  2250 }