File indexing completed on 2024-12-22 05:36:42

0001 <?php
0002 /**
0003  * Zend Framework
0004  *
0005  * LICENSE
0006  *
0007  * This source file is subject to the new BSD license that is bundled
0008  * with this package in the file LICENSE.txt.
0009  * It is also available through the world-wide-web at this URL:
0010  * http://framework.zend.com/license/new-bsd
0011  * If you did not receive a copy of the license and are unable to
0012  * obtain it through the world-wide-web, please send an email
0013  * to license@zend.com so we can send you a copy immediately.
0014  *
0015  * @category   Zend
0016  * @package    Zend_Form
0017  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0018  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0019  */
0020 
0021 /**
0022  * Zend_Form_DisplayGroup
0023  *
0024  * @category   Zend
0025  * @package    Zend_Form
0026  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0027  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0028  * @version    $Id$
0029  */
0030 class Zend_Form_DisplayGroup implements Iterator,Countable
0031 {
0032     /**
0033      * Group attributes
0034      * @var array
0035      */
0036     protected $_attribs = array();
0037 
0038     /**
0039      * Display group decorators
0040      * @var array
0041      */
0042     protected $_decorators = array();
0043 
0044     /**
0045      * Description
0046      * @var string
0047      */
0048     protected $_description;
0049 
0050     /**
0051      * Should we disable loading the default decorators?
0052      * @var bool
0053      */
0054     protected $_disableLoadDefaultDecorators = false;
0055 
0056     /**
0057      * Element order
0058      * @var array
0059      */
0060     protected $_elementOrder = array();
0061 
0062     /**
0063      * Elements
0064      * @var array
0065      */
0066     protected $_elements = array();
0067 
0068     /**
0069      * Form object to which the display group is currently registered
0070      *
0071      * @var Zend_Form
0072      */
0073     protected $_form;
0074 
0075     /**
0076      * Whether or not a new element has been added to the group
0077      * @var bool
0078      */
0079     protected $_groupUpdated = false;
0080 
0081     /**
0082      * Plugin loader for decorators
0083      * @var Zend_Loader_PluginLoader
0084      */
0085     protected $_loader;
0086 
0087     /**
0088      * Group name
0089      * @var string
0090      */
0091     protected $_name;
0092 
0093     /**
0094      * Group order
0095      * @var int
0096      */
0097     protected $_order;
0098 
0099     /**
0100      * @var Zend_Translate
0101      */
0102     protected $_translator;
0103 
0104     /**
0105      * Is translation disabled?
0106      * @var bool
0107      */
0108     protected $_translatorDisabled = false;
0109 
0110     /**
0111      * @var Zend_View_Interface
0112      */
0113     protected $_view;
0114 
0115     /**
0116      * Constructor
0117      *
0118      * @param  string $name
0119      * @param  Zend_Loader_PluginLoader $loader
0120      * @param  array|Zend_Config $options
0121      * @return void
0122      */
0123     public function __construct($name, Zend_Loader_PluginLoader $loader, $options = null)
0124     {
0125         $this->setName($name);
0126 
0127         $this->setPluginLoader($loader);
0128 
0129         if (is_array($options)) {
0130             $this->setOptions($options);
0131         } elseif ($options instanceof Zend_Config) {
0132             $this->setConfig($options);
0133         }
0134 
0135         // Extensions...
0136         $this->init();
0137 
0138         $this->loadDefaultDecorators();
0139     }
0140 
0141     /**
0142      * Initialize object; used by extending classes
0143      *
0144      * @return void
0145      */
0146     public function init()
0147     {
0148     }
0149 
0150     /**
0151      * Set options
0152      *
0153      * @param  array $options
0154      * @return Zend_Form_DisplayGroup
0155      */
0156     public function setOptions(array $options)
0157     {
0158         $forbidden = array(
0159             'Options', 'Config', 'PluginLoader', 'View',
0160             'Translator', 'Attrib'
0161         );
0162         foreach ($options as $key => $value) {
0163             $normalized = ucfirst($key);
0164 
0165             if (in_array($normalized, $forbidden)) {
0166                 continue;
0167             }
0168 
0169             $method = 'set' . $normalized;
0170             if (method_exists($this, $method)) {
0171                 $this->$method($value);
0172             } else {
0173                 $this->setAttrib($key, $value);
0174             }
0175         }
0176         return $this;
0177     }
0178 
0179     /**
0180      * Set options from config object
0181      *
0182      * @param  Zend_Config $config
0183      * @return Zend_Form_DisplayGroup
0184      */
0185     public function setConfig(Zend_Config $config)
0186     {
0187         return $this->setOptions($config->toArray());
0188     }
0189 
0190     /**
0191      * Set group attribute
0192      *
0193      * @param  string $key
0194      * @param  mixed $value
0195      * @return Zend_Form_DisplayGroup
0196      */
0197     public function setAttrib($key, $value)
0198     {
0199         $key = (string) $key;
0200         $this->_attribs[$key] = $value;
0201         return $this;
0202     }
0203 
0204     /**
0205      * Add multiple form attributes at once
0206      *
0207      * @param  array $attribs
0208      * @return Zend_Form_DisplayGroup
0209      */
0210     public function addAttribs(array $attribs)
0211     {
0212         foreach ($attribs as $key => $value) {
0213             $this->setAttrib($key, $value);
0214         }
0215         return $this;
0216     }
0217 
0218     /**
0219      * Set multiple form attributes at once
0220      *
0221      * Overwrites any previously set attributes.
0222      *
0223      * @param  array $attribs
0224      * @return Zend_Form_DisplayGroup
0225      */
0226     public function setAttribs(array $attribs)
0227     {
0228         $this->clearAttribs();
0229         return $this->addAttribs($attribs);
0230     }
0231 
0232     /**
0233      * Retrieve a single form attribute
0234      *
0235      * @param  string $key
0236      * @return mixed
0237      */
0238     public function getAttrib($key)
0239     {
0240         $key = (string) $key;
0241         if (!isset($this->_attribs[$key])) {
0242             return null;
0243         }
0244 
0245         return $this->_attribs[$key];
0246     }
0247 
0248     /**
0249      * Retrieve all form attributes/metadata
0250      *
0251      * @return array
0252      */
0253     public function getAttribs()
0254     {
0255         return $this->_attribs;
0256     }
0257 
0258     /**
0259      * Remove attribute
0260      *
0261      * @param  string $key
0262      * @return bool
0263      */
0264     public function removeAttrib($key)
0265     {
0266         if (array_key_exists($key, $this->_attribs)) {
0267             unset($this->_attribs[$key]);
0268             return true;
0269         }
0270 
0271         return false;
0272     }
0273 
0274     /**
0275      * Clear all form attributes
0276      *
0277      * @return Zend_Form
0278      */
0279     public function clearAttribs()
0280     {
0281         $this->_attribs = array();
0282         return $this;
0283     }
0284 
0285     /**
0286      * Set form object to which the display group is attached
0287      *
0288      * @param  Zend_Form $form
0289      * @return Zend_Form_DisplayGroup
0290      */
0291     public function setForm(Zend_Form $form)
0292     {
0293         $this->_form = $form;
0294 
0295         // Ensure any elements attached prior to setting the form are now
0296         // removed from iteration by the form
0297         foreach ($this->getElements() as $element) {
0298             $form->removeFromIteration($element->getName());
0299         }
0300 
0301         return $this;
0302     }
0303 
0304     /**
0305      * Get form object to which the group is attached
0306      *
0307      * @return Zend_Form|null
0308      */
0309     public function getForm()
0310     {
0311         return $this->_form;
0312     }
0313 
0314     /**
0315      * Filter a name to only allow valid variable characters
0316      *
0317      * @param  string $value
0318      * @return string
0319      */
0320     public function filterName($value)
0321     {
0322         return preg_replace('/[^a-zA-Z0-9_\x7f-\xff]/', '', (string) $value);
0323     }
0324 
0325     /**
0326      * Set group name
0327      *
0328      * @param  string $name
0329      * @return Zend_Form_DisplayGroup
0330      */
0331     public function setName($name)
0332     {
0333         $name = $this->filtername($name);
0334         if (('0' !== $name) && empty($name)) {
0335             // require_once 'Zend/Form/Exception.php';
0336             throw new Zend_Form_Exception('Invalid name provided; must contain only valid variable characters and be non-empty');
0337         }
0338 
0339         $this->_name = $name;
0340         return $this;
0341     }
0342 
0343     /**
0344      * Retrieve group name
0345      *
0346      * @return string
0347      */
0348     public function getName()
0349     {
0350         return $this->_name;
0351     }
0352 
0353     /**
0354      * Get fully qualified name
0355      *
0356      * Places name as subitem of array and/or appends brackets.
0357      *
0358      * @return string
0359      */
0360     public function getFullyQualifiedName()
0361     {
0362         return $this->getName();
0363     }
0364 
0365     /**
0366      * Get element id
0367      *
0368      * @return string
0369      */
0370     public function getId()
0371     {
0372         if (isset($this->id)) {
0373             return $this->id;
0374         }
0375 
0376         $id = $this->getFullyQualifiedName();
0377 
0378         // Bail early if no array notation detected
0379         if (!strstr($id, '[')) {
0380             return $id;
0381         }
0382 
0383         // Strip array notation
0384         if ('[]' == substr($id, -2)) {
0385             $id = substr($id, 0, strlen($id) - 2);
0386         }
0387         $id = str_replace('][', '-', $id);
0388         $id = str_replace(array(']', '['), '-', $id);
0389         $id = trim($id, '-');
0390 
0391         return $id;
0392     }
0393 
0394     /**
0395      * Set group legend
0396      *
0397      * @param  string $legend
0398      * @return Zend_Form_DisplayGroup
0399      */
0400     public function setLegend($legend)
0401     {
0402         return $this->setAttrib('legend', (string) $legend);
0403     }
0404 
0405     /**
0406      * Retrieve group legend
0407      *
0408      * @return string
0409      */
0410     public function getLegend()
0411     {
0412         return $this->getAttrib('legend');
0413     }
0414 
0415     /**
0416      * Set description
0417      *
0418      * @param  string $value
0419      * @return Zend_Form_DisplayGroup
0420      */
0421     public function setDescription($value)
0422     {
0423         $this->_description = (string) $value;
0424         return $this;
0425     }
0426 
0427     /**
0428      * Get description
0429      *
0430      * @return string
0431      */
0432     public function getDescription()
0433     {
0434         return $this->_description;
0435     }
0436 
0437     /**
0438      * Set group order
0439      *
0440      * @param  int $order
0441      * @return Zend_Form_Element
0442      */
0443     public function setOrder($order)
0444     {
0445         $this->_order = (int) $order;
0446         return $this;
0447     }
0448 
0449     /**
0450      * Retrieve group order
0451      *
0452      * @return int
0453      */
0454     public function getOrder()
0455     {
0456         return $this->_order;
0457     }
0458 
0459     // Elements
0460 
0461     /**
0462      * Add element to stack
0463      *
0464      * @param  Zend_Form_Element $element
0465      * @return Zend_Form_DisplayGroup
0466      */
0467     public function addElement(Zend_Form_Element $element)
0468     {
0469         $this->_elements[$element->getName()] = $element;
0470         $this->_groupUpdated = true;
0471 
0472         // Display group will now handle display of element
0473         if (null !== ($form = $this->getForm())) {
0474             $form->removeFromIteration($element->getName());
0475         }
0476 
0477         return $this;
0478     }
0479 
0480     /**
0481      * Add multiple elements at once
0482      *
0483      * @param  array $elements
0484      * @return Zend_Form_DisplayGroup
0485      * @throws Zend_Form_Exception if any element is not a Zend_Form_Element
0486      */
0487     public function addElements(array $elements)
0488     {
0489         foreach ($elements as $element) {
0490             if (!$element instanceof Zend_Form_Element) {
0491                 // require_once 'Zend/Form/Exception.php';
0492                 throw new Zend_Form_Exception('elements passed via array to addElements() must be Zend_Form_Elements only');
0493             }
0494             $this->addElement($element);
0495         }
0496         return $this;
0497     }
0498 
0499     /**
0500      * Set multiple elements at once (overwrites)
0501      *
0502      * @param  array $elements
0503      * @return Zend_Form_DisplayGroup
0504      */
0505     public function setElements(array $elements)
0506     {
0507         $this->clearElements();
0508         return $this->addElements($elements);
0509     }
0510 
0511     /**
0512      * Retrieve element
0513      *
0514      * @param  string $name
0515      * @return Zend_Form_Element|null
0516      */
0517     public function getElement($name)
0518     {
0519         $name = (string) $name;
0520         if (isset($this->_elements[$name])) {
0521             return $this->_elements[$name];
0522         }
0523 
0524         return null;
0525     }
0526 
0527     /**
0528      * Retrieve elements
0529      * @return array
0530      */
0531     public function getElements()
0532     {
0533         return $this->_elements;
0534     }
0535 
0536     /**
0537      * Remove a single element
0538      *
0539      * @param  string $name
0540      * @return boolean
0541      */
0542     public function removeElement($name)
0543     {
0544         $name = (string) $name;
0545         if (array_key_exists($name, $this->_elements)) {
0546             unset($this->_elements[$name]);
0547             $this->_groupUpdated = true;
0548             return true;
0549         }
0550 
0551         return false;
0552     }
0553 
0554     /**
0555      * Remove all elements
0556      *
0557      * @return Zend_Form_DisplayGroup
0558      */
0559     public function clearElements()
0560     {
0561         $this->_elements = array();
0562         $this->_groupUpdated = true;
0563         return $this;
0564     }
0565 
0566     // Plugin loader (for decorators)
0567 
0568     /**
0569      * Set plugin loader
0570      *
0571      * @param  Zend_Loader_PluginLoader $loader
0572      * @return Zend_Form_DisplayGroup
0573      */
0574     public function setPluginLoader(Zend_Loader_PluginLoader $loader)
0575     {
0576         $this->_loader = $loader;
0577         return $this;
0578     }
0579 
0580     /**
0581      * Retrieve plugin loader
0582      *
0583      * @return Zend_Loader_PluginLoader
0584      */
0585     public function getPluginLoader()
0586     {
0587         return $this->_loader;
0588     }
0589 
0590     /**
0591      * Add a prefix path for the plugin loader
0592      *
0593      * @param  string $prefix
0594      * @param  string $path
0595      * @return Zend_Form_DisplayGroup
0596      */
0597     public function addPrefixPath($prefix, $path)
0598     {
0599         $this->getPluginLoader()->addPrefixPath($prefix, $path);
0600         return $this;
0601     }
0602 
0603     /**
0604      * Add several prefix paths at once
0605      *
0606      * @param  array $spec
0607      * @return Zend_Form_DisplayGroup
0608      */
0609     public function addPrefixPaths(array $spec)
0610     {
0611         if (isset($spec['prefix']) && isset($spec['path'])) {
0612             return $this->addPrefixPath($spec['prefix'], $spec['path']);
0613         }
0614         foreach ($spec as $prefix => $paths) {
0615             if (is_numeric($prefix) && is_array($paths)) {
0616                 $prefix = null;
0617                 if (isset($paths['prefix']) && isset($paths['path'])) {
0618                     $this->addPrefixPath($paths['prefix'], $paths['path']);
0619                 }
0620             } elseif (!is_numeric($prefix)) {
0621                 if (is_string($paths)) {
0622                     $this->addPrefixPath($prefix, $paths);
0623                 } elseif (is_array($paths)) {
0624                     foreach ($paths as $path) {
0625                         $this->addPrefixPath($prefix, $path);
0626                     }
0627                 }
0628             }
0629         }
0630         return $this;
0631     }
0632 
0633     // Decorators
0634 
0635     /**
0636      * Set flag to disable loading default decorators
0637      *
0638      * @param  bool $flag
0639      * @return Zend_Form_Element
0640      */
0641     public function setDisableLoadDefaultDecorators($flag)
0642     {
0643         $this->_disableLoadDefaultDecorators = (bool) $flag;
0644         return $this;
0645     }
0646 
0647     /**
0648      * Should we load the default decorators?
0649      *
0650      * @return bool
0651      */
0652     public function loadDefaultDecoratorsIsDisabled()
0653     {
0654         return $this->_disableLoadDefaultDecorators;
0655     }
0656 
0657     /**
0658      * Load default decorators
0659      *
0660      * @return Zend_Form_DisplayGroup
0661      */
0662     public function loadDefaultDecorators()
0663     {
0664         if ($this->loadDefaultDecoratorsIsDisabled()) {
0665             return $this;
0666         }
0667 
0668         $decorators = $this->getDecorators();
0669         if (empty($decorators)) {
0670             $this->addDecorator('FormElements')
0671                  ->addDecorator('HtmlTag', array('tag' => 'dl'))
0672                  ->addDecorator('Fieldset')
0673                  ->addDecorator('DtDdWrapper');
0674         }
0675         return $this;
0676     }
0677 
0678     /**
0679      * Instantiate a decorator based on class name or class name fragment
0680      *
0681      * @param  string $name
0682      * @param  null|array $options
0683      * @return Zend_Form_Decorator_Interface
0684      */
0685     protected function _getDecorator($name, $options = null)
0686     {
0687         $class = $this->getPluginLoader()->load($name);
0688         if (null === $options) {
0689             $decorator = new $class;
0690         } else {
0691             $decorator = new $class($options);
0692         }
0693 
0694         return $decorator;
0695     }
0696 
0697     /**
0698      * Add a decorator for rendering the group
0699      *
0700      * @param  string|Zend_Form_Decorator_Interface $decorator
0701      * @param  array|Zend_Config $options Options with which to initialize decorator
0702      * @return Zend_Form_DisplayGroup
0703      */
0704     public function addDecorator($decorator, $options = null)
0705     {
0706         if ($decorator instanceof Zend_Form_Decorator_Interface) {
0707             $name = get_class($decorator);
0708         } elseif (is_string($decorator)) {
0709             $name      = $decorator;
0710             $decorator = array(
0711                 'decorator' => $name,
0712                 'options'   => $options,
0713             );
0714         } elseif (is_array($decorator)) {
0715             foreach ($decorator as $name => $spec) {
0716                 break;
0717             }
0718             if (is_numeric($name)) {
0719                 // require_once 'Zend/Form/Exception.php';
0720                 throw new Zend_Form_Exception('Invalid alias provided to addDecorator; must be alphanumeric string');
0721             }
0722             if (is_string($spec)) {
0723                 $decorator = array(
0724                     'decorator' => $spec,
0725                     'options'   => $options,
0726                 );
0727             } elseif ($spec instanceof Zend_Form_Decorator_Interface) {
0728                 $decorator = $spec;
0729             }
0730         } else {
0731             // require_once 'Zend/Form/Exception.php';
0732             throw new Zend_Form_Exception('Invalid decorator provided to addDecorator; must be string or Zend_Form_Decorator_Interface');
0733         }
0734 
0735         $this->_decorators[$name] = $decorator;
0736 
0737         return $this;
0738     }
0739 
0740     /**
0741      * Add many decorators at once
0742      *
0743      * @param  array $decorators
0744      * @return Zend_Form_DisplayGroup
0745      */
0746     public function addDecorators(array $decorators)
0747     {
0748         foreach ($decorators as $decoratorName => $decoratorInfo) {
0749             if (is_string($decoratorInfo) ||
0750                 $decoratorInfo instanceof Zend_Form_Decorator_Interface) {
0751                 if (!is_numeric($decoratorName)) {
0752                     $this->addDecorator(array($decoratorName => $decoratorInfo));
0753                 } else {
0754                     $this->addDecorator($decoratorInfo);
0755                 }
0756             } elseif (is_array($decoratorInfo)) {
0757                 $argc    = count($decoratorInfo);
0758                 $options = array();
0759                 if (isset($decoratorInfo['decorator'])) {
0760                     $decorator = $decoratorInfo['decorator'];
0761                     if (isset($decoratorInfo['options'])) {
0762                         $options = $decoratorInfo['options'];
0763                     }
0764                     $this->addDecorator($decorator, $options);
0765                 } else {
0766                     switch (true) {
0767                         case (0 == $argc):
0768                             break;
0769                         case (1 <= $argc):
0770                             $decorator  = array_shift($decoratorInfo);
0771                         case (2 <= $argc):
0772                             $options = array_shift($decoratorInfo);
0773                         default:
0774                             $this->addDecorator($decorator, $options);
0775                             break;
0776                     }
0777                 }
0778             } else {
0779                 // require_once 'Zend/Form/Exception.php';
0780                 throw new Zend_Form_Exception('Invalid decorator passed to addDecorators()');
0781             }
0782         }
0783 
0784         return $this;
0785     }
0786 
0787     /**
0788      * Overwrite all decorators
0789      *
0790      * @param  array $decorators
0791      * @return Zend_Form_DisplayGroup
0792      */
0793     public function setDecorators(array $decorators)
0794     {
0795         $this->clearDecorators();
0796         return $this->addDecorators($decorators);
0797     }
0798 
0799     /**
0800      * Retrieve a registered decorator
0801      *
0802      * @param  string $name
0803      * @return false|Zend_Form_Decorator_Abstract
0804      */
0805     public function getDecorator($name)
0806     {
0807         if (!isset($this->_decorators[$name])) {
0808             $len = strlen($name);
0809             foreach ($this->_decorators as $localName => $decorator) {
0810                 if ($len > strlen($localName)) {
0811                     continue;
0812                 }
0813 
0814                 if (0 === substr_compare($localName, $name, -$len, $len, true)) {
0815                     if (is_array($decorator)) {
0816                         return $this->_loadDecorator($decorator, $localName);
0817                     }
0818                     return $decorator;
0819                 }
0820             }
0821             return false;
0822         }
0823 
0824         if (is_array($this->_decorators[$name])) {
0825             return $this->_loadDecorator($this->_decorators[$name], $name);
0826         }
0827 
0828         return $this->_decorators[$name];
0829     }
0830 
0831     /**
0832      * Retrieve all decorators
0833      *
0834      * @return array
0835      */
0836     public function getDecorators()
0837     {
0838         foreach ($this->_decorators as $key => $value) {
0839             if (is_array($value)) {
0840                 $this->_loadDecorator($value, $key);
0841             }
0842         }
0843         return $this->_decorators;
0844     }
0845 
0846     /**
0847      * Remove a single decorator
0848      *
0849      * @param  string $name
0850      * @return bool
0851      */
0852     public function removeDecorator($name)
0853     {
0854         $decorator = $this->getDecorator($name);
0855         if ($decorator) {
0856             if (array_key_exists($name, $this->_decorators)) {
0857                 unset($this->_decorators[$name]);
0858             } else {
0859                 $class = get_class($decorator);
0860                 unset($this->_decorators[$class]);
0861             }
0862             return true;
0863         }
0864 
0865         return false;
0866     }
0867 
0868     /**
0869      * Clear all decorators
0870      *
0871      * @return Zend_Form_DisplayGroup
0872      */
0873     public function clearDecorators()
0874     {
0875         $this->_decorators = array();
0876         return $this;
0877     }
0878 
0879     /**
0880      * Set view
0881      *
0882      * @param  Zend_View_Interface $view
0883      * @return Zend_Form_DisplayGroup
0884      */
0885     public function setView(Zend_View_Interface $view = null)
0886     {
0887         $this->_view = $view;
0888         return $this;
0889     }
0890 
0891     /**
0892      * Retrieve view
0893      *
0894      * @return Zend_View_Interface
0895      */
0896     public function getView()
0897     {
0898         if (null === $this->_view) {
0899             // require_once 'Zend/Controller/Action/HelperBroker.php';
0900             $viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
0901             $this->setView($viewRenderer->view);
0902         }
0903 
0904         return $this->_view;
0905     }
0906 
0907     /**
0908      * Render display group
0909      *
0910      * @return string
0911      */
0912     public function render(Zend_View_Interface $view = null)
0913     {
0914         if (null !== $view) {
0915             $this->setView($view);
0916         }
0917         $content = '';
0918         foreach ($this->getDecorators() as $decorator) {
0919             $decorator->setElement($this);
0920             $content = $decorator->render($content);
0921         }
0922         return $content;
0923     }
0924 
0925     /**
0926      * String representation of group
0927      *
0928      * @return string
0929      */
0930     public function __toString()
0931     {
0932         try {
0933             $return = $this->render();
0934             return $return;
0935         } catch (Exception $e) {
0936             trigger_error($e->getMessage(), E_USER_WARNING);
0937             return '';
0938         }
0939     }
0940 
0941     /**
0942      * Set translator object
0943      *
0944      * @param  Zend_Translate|Zend_Translate_Adapter|null $translator
0945      * @return Zend_Form_DisplayGroup
0946      */
0947     public function setTranslator($translator = null)
0948     {
0949         if ((null === $translator) || ($translator instanceof Zend_Translate_Adapter)) {
0950             $this->_translator = $translator;
0951         } elseif ($translator instanceof Zend_Translate) {
0952             $this->_translator = $translator->getAdapter();
0953         } else {
0954             // require_once 'Zend/Form/Exception.php';
0955             throw new Zend_Form_Exception('Invalid translator specified');
0956         }
0957         return $this;
0958     }
0959 
0960     /**
0961      * Retrieve translator object
0962      *
0963      * @return Zend_Translate_Adapter|null
0964      */
0965     public function getTranslator()
0966     {
0967         if ($this->translatorIsDisabled()) {
0968             return null;
0969         }
0970 
0971         if (null === $this->_translator) {
0972             // require_once 'Zend/Form.php';
0973             return Zend_Form::getDefaultTranslator();
0974         }
0975 
0976         return $this->_translator;
0977     }
0978 
0979     /**
0980      * Does this display group have its own specific translator?
0981      *
0982      * @return bool
0983      */
0984     public function hasTranslator()
0985     {
0986         return (bool) $this->getTranslator();
0987     }
0988 
0989     /**
0990      * Indicate whether or not translation should be disabled
0991      *
0992      * @param  bool $flag
0993      * @return Zend_Form_DisplayGroup
0994      */
0995     public function setDisableTranslator($flag)
0996     {
0997         $this->_translatorDisabled = (bool) $flag;
0998         return $this;
0999     }
1000 
1001     /**
1002      * Is translation disabled?
1003      *
1004      * @return bool
1005      */
1006     public function translatorIsDisabled()
1007     {
1008         return $this->_translatorDisabled;
1009     }
1010 
1011     /**
1012      * Overloading: allow rendering specific decorators
1013      *
1014      * Call renderDecoratorName() to render a specific decorator.
1015      *
1016      * @param  string $method
1017      * @param  array $args
1018      * @return string
1019      * @throws Zend_Form_Exception for invalid decorator or invalid method call
1020      */
1021     public function __call($method, $args)
1022     {
1023         if ('render' == substr($method, 0, 6)) {
1024             $decoratorName = substr($method, 6);
1025             if (false !== ($decorator = $this->getDecorator($decoratorName))) {
1026                 $decorator->setElement($this);
1027                 $seed = '';
1028                 if (0 < count($args)) {
1029                     $seed = array_shift($args);
1030                 }
1031                 return $decorator->render($seed);
1032             }
1033 
1034             // require_once 'Zend/Form/Exception.php';
1035             throw new Zend_Form_Exception(sprintf('Decorator by name %s does not exist', $decoratorName));
1036         }
1037 
1038         // require_once 'Zend/Form/Exception.php';
1039         throw new Zend_Form_Exception(sprintf('Method %s does not exist', $method));
1040     }
1041 
1042     // Interfaces: Iterator, Countable
1043 
1044     /**
1045      * Current element
1046      *
1047      * @return Zend_Form_Element
1048      */
1049     public function current()
1050     {
1051         $this->_sort();
1052         current($this->_elementOrder);
1053         $key = key($this->_elementOrder);
1054         return $this->getElement($key);
1055     }
1056 
1057     /**
1058      * Current element
1059      *
1060      * @return string
1061      */
1062     public function key()
1063     {
1064         $this->_sort();
1065         return key($this->_elementOrder);
1066     }
1067 
1068     /**
1069      * Move pointer to next element
1070      *
1071      * @return void
1072      */
1073     public function next()
1074     {
1075         $this->_sort();
1076         next($this->_elementOrder);
1077     }
1078 
1079     /**
1080      * Move pointer to beginning of element loop
1081      *
1082      * @return void
1083      */
1084     public function rewind()
1085     {
1086         $this->_sort();
1087         reset($this->_elementOrder);
1088     }
1089 
1090     /**
1091      * Determine if current element/subform/display group is valid
1092      *
1093      * @return bool
1094      */
1095     public function valid()
1096     {
1097         $this->_sort();
1098         return (current($this->_elementOrder) !== false);
1099     }
1100 
1101     /**
1102      * Count of elements/subforms that are iterable
1103      *
1104      * @return int
1105      */
1106     public function count()
1107     {
1108         return count($this->_elements);
1109     }
1110 
1111     /**
1112      * Sort items according to their order
1113      *
1114      * @return void
1115      */
1116     protected function _sort()
1117     {
1118         if ($this->_groupUpdated || !is_array($this->_elementOrder)) {
1119             $elementOrder = array();
1120             foreach ($this->getElements() as $key => $element) {
1121                 $elementOrder[$key] = $element->getOrder();
1122             }
1123 
1124             $items = array();
1125             $index = 0;
1126             foreach ($elementOrder as $key => $order) {
1127                 if (null === $order) {
1128                     while (array_search($index, $elementOrder, true)) {
1129                         ++$index;
1130                     }
1131                     $items[$index] = $key;
1132                     ++$index;
1133                 } else {
1134                     $items[$order] = $key;
1135                 }
1136             }
1137 
1138             $items = array_flip($items);
1139             asort($items);
1140             $this->_elementOrder = $items;
1141             $this->_groupUpdated = false;
1142         }
1143     }
1144 
1145     /**
1146      * Lazy-load a decorator
1147      *
1148      * @param  array $decorator Decorator type and options
1149      * @param  mixed $name Decorator name or alias
1150      * @return Zend_Form_Decorator_Interface
1151      */
1152     protected function _loadDecorator(array $decorator, $name)
1153     {
1154         $sameName = false;
1155         if ($name == $decorator['decorator']) {
1156             $sameName = true;
1157         }
1158 
1159         $instance = $this->_getDecorator($decorator['decorator'], $decorator['options']);
1160         if ($sameName) {
1161             $newName            = get_class($instance);
1162             $decoratorNames     = array_keys($this->_decorators);
1163             $order              = array_flip($decoratorNames);
1164             $order[$newName]    = $order[$name];
1165             $decoratorsExchange = array();
1166             unset($order[$name]);
1167             asort($order);
1168             foreach ($order as $key => $index) {
1169                 if ($key == $newName) {
1170                     $decoratorsExchange[$key] = $instance;
1171                     continue;
1172                 }
1173                 $decoratorsExchange[$key] = $this->_decorators[$key];
1174             }
1175             $this->_decorators = $decoratorsExchange;
1176         } else {
1177             $this->_decorators[$name] = $instance;
1178         }
1179 
1180         return $instance;
1181     }
1182 }