*prechod na novsiu verziu ZF
[sport-group.git] / library / Zend / Form / DisplayGroup.php
blob44fcf3dc764a186dac8b0e0bece0790f098eb2e2
1 <?php
2 /**
3 * Zend Framework
5 * LICENSE
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.
15 * @category Zend
16 * @package Zend_Form
17 * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
18 * @license http://framework.zend.com/license/new-bsd New BSD License
21 /**
22 * Zend_Form_DisplayGroup
24 * @category Zend
25 * @package Zend_Form
26 * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
27 * @license http://framework.zend.com/license/new-bsd New BSD License
28 * @version $Id: DisplayGroup.php 16218 2009-06-21 19:44:04Z thomas $
30 class Zend_Form_DisplayGroup implements Iterator,Countable
32 /**
33 * Group attributes
34 * @var array
36 protected $_attribs = array();
38 /**
39 * Display group decorators
40 * @var array
42 protected $_decorators = array();
44 /**
45 * Description
46 * @var string
48 protected $_description;
50 /**
51 * Should we disable loading the default decorators?
52 * @var bool
54 protected $_disableLoadDefaultDecorators = false;
56 /**
57 * Element order
58 * @var array
60 protected $_elementOrder = array();
62 /**
63 * Elements
64 * @var array
66 protected $_elements = array();
68 /**
69 * Whether or not a new element has been added to the group
70 * @var bool
72 protected $_groupUpdated = false;
74 /**
75 * Plugin loader for decorators
76 * @var Zend_Loader_PluginLoader
78 protected $_loader;
80 /**
81 * Group name
82 * @var string
84 protected $_name;
86 /**
87 * Group order
88 * @var int
90 protected $_order;
92 /**
93 * @var Zend_Translate
95 protected $_translator;
97 /**
98 * Is translation disabled?
99 * @var bool
101 protected $_translatorDisabled = false;
104 * @var Zend_View_Interface
106 protected $_view;
109 * Constructor
111 * @param string $name
112 * @param Zend_Loader_PluginLoader $loader
113 * @param array|Zend_Config $options
114 * @return void
116 public function __construct($name, Zend_Loader_PluginLoader $loader, $options = null)
118 $this->setName($name);
120 $this->setPluginLoader($loader);
122 if (is_array($options)) {
123 $this->setOptions($options);
124 } elseif ($options instanceof Zend_Config) {
125 $this->setConfig($options);
128 // Extensions...
129 $this->init();
131 $this->loadDefaultDecorators();
135 * Initialize object; used by extending classes
137 * @return void
139 public function init()
144 * Set options
146 * @param array $options
147 * @return Zend_Form_DisplayGroup
149 public function setOptions(array $options)
151 $forbidden = array(
152 'Options', 'Config', 'PluginLoader', 'View',
153 'Translator', 'Attrib'
155 foreach ($options as $key => $value) {
156 $normalized = ucfirst($key);
158 if (in_array($normalized, $forbidden)) {
159 continue;
162 $method = 'set' . $normalized;
163 if (method_exists($this, $method)) {
164 $this->$method($value);
165 } else {
166 $this->setAttrib($key, $value);
169 return $this;
173 * Set options from config object
175 * @param Zend_Config $config
176 * @return Zend_Form_DisplayGroup
178 public function setConfig(Zend_Config $config)
180 return $this->setOptions($config->toArray());
184 * Set group attribute
186 * @param string $key
187 * @param mixed $value
188 * @return Zend_Form_DisplayGroup
190 public function setAttrib($key, $value)
192 $key = (string) $key;
193 $this->_attribs[$key] = $value;
194 return $this;
198 * Add multiple form attributes at once
200 * @param array $attribs
201 * @return Zend_Form_DisplayGroup
203 public function addAttribs(array $attribs)
205 foreach ($attribs as $key => $value) {
206 $this->setAttrib($key, $value);
208 return $this;
212 * Set multiple form attributes at once
214 * Overwrites any previously set attributes.
216 * @param array $attribs
217 * @return Zend_Form_DisplayGroup
219 public function setAttribs(array $attribs)
221 $this->clearAttribs();
222 return $this->addAttribs($attribs);
226 * Retrieve a single form attribute
228 * @param string $key
229 * @return mixed
231 public function getAttrib($key)
233 $key = (string) $key;
234 if (!isset($this->_attribs[$key])) {
235 return null;
238 return $this->_attribs[$key];
242 * Retrieve all form attributes/metadata
244 * @return array
246 public function getAttribs()
248 return $this->_attribs;
252 * Remove attribute
254 * @param string $key
255 * @return bool
257 public function removeAttrib($key)
259 if (array_key_exists($key, $this->_attribs)) {
260 unset($this->_attribs[$key]);
261 return true;
264 return false;
268 * Clear all form attributes
270 * @return Zend_Form
272 public function clearAttribs()
274 $this->_attribs = array();
275 return $this;
279 * Filter a name to only allow valid variable characters
281 * @param string $value
282 * @return string
284 public function filterName($value)
286 return preg_replace('/[^a-zA-Z0-9_\x7f-\xff]/', '', (string) $value);
290 * Set group name
292 * @param string $name
293 * @return Zend_Form_DisplayGroup
295 public function setName($name)
297 $name = $this->filtername($name);
298 if (('0' !== $name) && empty($name)) {
299 require_once 'Zend/Form/Exception.php';
300 throw new Zend_Form_Exception('Invalid name provided; must contain only valid variable characters and be non-empty');
303 $this->_name = $name;
304 return $this;
308 * Retrieve group name
310 * @return string
312 public function getName()
314 return $this->_name;
318 * Get fully qualified name
320 * Places name as subitem of array and/or appends brackets.
322 * @return string
324 public function getFullyQualifiedName()
326 return $this->getName();
330 * Get element id
332 * @return string
334 public function getId()
336 if (isset($this->id)) {
337 return $this->id;
340 $id = $this->getFullyQualifiedName();
342 // Bail early if no array notation detected
343 if (!strstr($id, '[')) {
344 return $id;
347 // Strip array notation
348 if ('[]' == substr($id, -2)) {
349 $id = substr($id, 0, strlen($id) - 2);
351 $id = str_replace('][', '-', $id);
352 $id = str_replace(array(']', '['), '-', $id);
353 $id = trim($id, '-');
355 return $id;
359 * Set group legend
361 * @param string $legend
362 * @return Zend_Form_DisplayGroup
364 public function setLegend($legend)
366 return $this->setAttrib('legend', (string) $legend);
370 * Retrieve group legend
372 * @return string
374 public function getLegend()
376 return $this->getAttrib('legend');
380 * Set description
382 * @param string $value
383 * @return Zend_Form_DisplayGroup
385 public function setDescription($value)
387 $this->_description = (string) $value;
388 return $this;
392 * Get description
394 * @return string
396 public function getDescription()
398 return $this->_description;
402 * Set group order
404 * @param int $order
405 * @return Zend_Form_Element
407 public function setOrder($order)
409 $this->_order = (int) $order;
410 return $this;
414 * Retrieve group order
416 * @return int
418 public function getOrder()
420 return $this->_order;
423 // Elements
426 * Add element to stack
428 * @param Zend_Form_Element $element
429 * @return Zend_Form_DisplayGroup
431 public function addElement(Zend_Form_Element $element)
433 $this->_elements[$element->getName()] = $element;
434 $this->_groupUpdated = true;
435 return $this;
439 * Add multiple elements at once
441 * @param array $elements
442 * @return Zend_Form_DisplayGroup
443 * @throws Zend_Form_Exception if any element is not a Zend_Form_Element
445 public function addElements(array $elements)
447 foreach ($elements as $element) {
448 if (!$element instanceof Zend_Form_Element) {
449 require_once 'Zend/Form/Exception.php';
450 throw new Zend_Form_Exception('elements passed via array to addElements() must be Zend_Form_Elements only');
452 $this->addElement($element);
454 return $this;
458 * Set multiple elements at once (overwrites)
460 * @param array $elements
461 * @return Zend_Form_DisplayGroup
463 public function setElements(array $elements)
465 $this->clearElements();
466 return $this->addElements($elements);
470 * Retrieve element
472 * @param string $name
473 * @return Zend_Form_Element|null
475 public function getElement($name)
477 $name = (string) $name;
478 if (isset($this->_elements[$name])) {
479 return $this->_elements[$name];
482 return null;
486 * Retrieve elements
487 * @return array
489 public function getElements()
491 return $this->_elements;
495 * Remove a single element
497 * @param string $name
498 * @return boolean
500 public function removeElement($name)
502 $name = (string) $name;
503 if (array_key_exists($name, $this->_elements)) {
504 unset($this->_elements[$name]);
505 $this->_groupUpdated = true;
506 return true;
509 return false;
513 * Remove all elements
515 * @return Zend_Form_DisplayGroup
517 public function clearElements()
519 $this->_elements = array();
520 $this->_groupUpdated = true;
521 return $this;
524 // Plugin loader (for decorators)
527 * Set plugin loader
529 * @param Zend_Loader_PluginLoader $loader
530 * @return Zend_Form_DisplayGroup
532 public function setPluginLoader(Zend_Loader_PluginLoader $loader)
534 $this->_loader = $loader;
535 return $this;
539 * Retrieve plugin loader
541 * @return Zend_Loader_PluginLoader
543 public function getPluginLoader()
545 return $this->_loader;
549 * Add a prefix path for the plugin loader
551 * @param string $prefix
552 * @param string $path
553 * @return Zend_Form_DisplayGroup
555 public function addPrefixPath($prefix, $path)
557 $this->getPluginLoader()->addPrefixPath($prefix, $path);
558 return $this;
562 * Add several prefix paths at once
564 * @param array $spec
565 * @return Zend_Form_DisplayGroup
567 public function addPrefixPaths(array $spec)
569 if (isset($spec['prefix']) && isset($spec['path'])) {
570 return $this->addPrefixPath($spec['prefix'], $spec['path']);
572 foreach ($spec as $prefix => $paths) {
573 if (is_numeric($prefix) && is_array($paths)) {
574 $prefix = null;
575 if (isset($paths['prefix']) && isset($paths['path'])) {
576 $this->addPrefixPath($paths['prefix'], $paths['path']);
578 } elseif (!is_numeric($prefix)) {
579 if (is_string($paths)) {
580 $this->addPrefixPath($prefix, $paths);
581 } elseif (is_array($paths)) {
582 foreach ($paths as $path) {
583 $this->addPrefixPath($prefix, $path);
588 return $this;
591 // Decorators
594 * Set flag to disable loading default decorators
596 * @param bool $flag
597 * @return Zend_Form_Element
599 public function setDisableLoadDefaultDecorators($flag)
601 $this->_disableLoadDefaultDecorators = (bool) $flag;
602 return $this;
606 * Should we load the default decorators?
608 * @return bool
610 public function loadDefaultDecoratorsIsDisabled()
612 return $this->_disableLoadDefaultDecorators;
616 * Load default decorators
618 * @return void
620 public function loadDefaultDecorators()
622 if ($this->loadDefaultDecoratorsIsDisabled()) {
623 return;
626 $decorators = $this->getDecorators();
627 if (empty($decorators)) {
628 $this->addDecorator('FormElements')
629 ->addDecorator('HtmlTag', array('tag' => 'dl'))
630 ->addDecorator('Fieldset')
631 ->addDecorator('DtDdWrapper');
636 * Instantiate a decorator based on class name or class name fragment
638 * @param string $name
639 * @param null|array $options
640 * @return Zend_Form_Decorator_Interface
642 protected function _getDecorator($name, $options = null)
644 $class = $this->getPluginLoader()->load($name);
645 if (null === $options) {
646 $decorator = new $class;
647 } else {
648 $decorator = new $class($options);
651 return $decorator;
655 * Add a decorator for rendering the group
657 * @param string|Zend_Form_Decorator_Interface $decorator
658 * @param array|Zend_Config $options Options with which to initialize decorator
659 * @return Zend_Form_DisplayGroup
661 public function addDecorator($decorator, $options = null)
663 if ($decorator instanceof Zend_Form_Decorator_Interface) {
664 $name = get_class($decorator);
665 } elseif (is_string($decorator)) {
666 $name = $decorator;
667 $decorator = array(
668 'decorator' => $name,
669 'options' => $options,
671 } elseif (is_array($decorator)) {
672 foreach ($decorator as $name => $spec) {
673 break;
675 if (is_numeric($name)) {
676 require_once 'Zend/Form/Exception.php';
677 throw new Zend_Form_Exception('Invalid alias provided to addDecorator; must be alphanumeric string');
679 if (is_string($spec)) {
680 $decorator = array(
681 'decorator' => $spec,
682 'options' => $options,
684 } elseif ($spec instanceof Zend_Form_Decorator_Interface) {
685 $decorator = $spec;
687 } else {
688 require_once 'Zend/Form/Exception.php';
689 throw new Zend_Form_Exception('Invalid decorator provided to addDecorator; must be string or Zend_Form_Decorator_Interface');
692 $this->_decorators[$name] = $decorator;
694 return $this;
698 * Add many decorators at once
700 * @param array $decorators
701 * @return Zend_Form_DisplayGroup
703 public function addDecorators(array $decorators)
705 foreach ($decorators as $decoratorInfo) {
706 if (is_string($decoratorInfo)) {
707 $this->addDecorator($decoratorInfo);
708 } elseif ($decoratorInfo instanceof Zend_Form_Decorator_Interface) {
709 $this->addDecorator($decoratorInfo);
710 } elseif (is_array($decoratorInfo)) {
711 $argc = count($decoratorInfo);
712 $options = array();
713 if (isset($decoratorInfo['decorator'])) {
714 $decorator = $decoratorInfo['decorator'];
715 if (isset($decoratorInfo['options'])) {
716 $options = $decoratorInfo['options'];
718 $this->addDecorator($decorator, $options);
719 } else {
720 switch (true) {
721 case (0 == $argc):
722 break;
723 case (1 <= $argc):
724 $decorator = array_shift($decoratorInfo);
725 case (2 <= $argc):
726 $options = array_shift($decoratorInfo);
727 default:
728 $this->addDecorator($decorator, $options);
729 break;
732 } else {
733 require_once 'Zend/Form/Exception.php';
734 throw new Zend_Form_Exception('Invalid decorator passed to addDecorators()');
738 return $this;
742 * Overwrite all decorators
744 * @param array $decorators
745 * @return Zend_Form_DisplayGroup
747 public function setDecorators(array $decorators)
749 $this->clearDecorators();
750 return $this->addDecorators($decorators);
754 * Retrieve a registered decorator
756 * @param string $name
757 * @return false|Zend_Form_Decorator_Abstract
759 public function getDecorator($name)
761 if (!isset($this->_decorators[$name])) {
762 $len = strlen($name);
763 foreach ($this->_decorators as $localName => $decorator) {
764 if ($len > strlen($localName)) {
765 continue;
768 if (0 === substr_compare($localName, $name, -$len, $len, true)) {
769 if (is_array($decorator)) {
770 return $this->_loadDecorator($decorator, $localName);
772 return $decorator;
775 return false;
778 if (is_array($this->_decorators[$name])) {
779 return $this->_loadDecorator($this->_decorators[$name], $name);
782 return $this->_decorators[$name];
786 * Retrieve all decorators
788 * @return array
790 public function getDecorators()
792 foreach ($this->_decorators as $key => $value) {
793 if (is_array($value)) {
794 $this->_loadDecorator($value, $key);
797 return $this->_decorators;
801 * Remove a single decorator
803 * @param string $name
804 * @return bool
806 public function removeDecorator($name)
808 $decorator = $this->getDecorator($name);
809 if ($decorator) {
810 if (array_key_exists($name, $this->_decorators)) {
811 unset($this->_decorators[$name]);
812 } else {
813 $class = get_class($decorator);
814 unset($this->_decorators[$class]);
816 return true;
819 return false;
823 * Clear all decorators
825 * @return Zend_Form_DisplayGroup
827 public function clearDecorators()
829 $this->_decorators = array();
830 return $this;
834 * Set view
836 * @param Zend_View_Interface $view
837 * @return Zend_Form_DisplayGroup
839 public function setView(Zend_View_Interface $view = null)
841 $this->_view = $view;
842 return $this;
846 * Retrieve view
848 * @return Zend_View_Interface
850 public function getView()
852 if (null === $this->_view) {
853 require_once 'Zend/Controller/Action/HelperBroker.php';
854 $viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
855 $this->setView($viewRenderer->view);
858 return $this->_view;
862 * Render display group
864 * @return string
866 public function render(Zend_View_Interface $view = null)
868 if (null !== $view) {
869 $this->setView($view);
871 $content = '';
872 foreach ($this->getDecorators() as $decorator) {
873 $decorator->setElement($this);
874 $content = $decorator->render($content);
876 return $content;
880 * String representation of group
882 * @return string
884 public function __toString()
886 try {
887 $return = $this->render();
888 return $return;
889 } catch (Exception $e) {
890 trigger_error($e->getMessage(), E_USER_WARNING);
891 return '';
896 * Set translator object
898 * @param Zend_Translate|Zend_Translate_Adapter|null $translator
899 * @return Zend_Form_DisplayGroup
901 public function setTranslator($translator = null)
903 if ((null === $translator) || ($translator instanceof Zend_Translate_Adapter)) {
904 $this->_translator = $translator;
905 } elseif ($translator instanceof Zend_Translate) {
906 $this->_translator = $translator->getAdapter();
907 } else {
908 require_once 'Zend/Form/Exception.php';
909 throw new Zend_Form_Exception('Invalid translator specified');
911 return $this;
915 * Retrieve translator object
917 * @return Zend_Translate_Adapter|null
919 public function getTranslator()
921 if ($this->translatorIsDisabled()) {
922 return null;
925 if (null === $this->_translator) {
926 require_once 'Zend/Form.php';
927 return Zend_Form::getDefaultTranslator();
930 return $this->_translator;
934 * Indicate whether or not translation should be disabled
936 * @param bool $flag
937 * @return Zend_Form_DisplayGroup
939 public function setDisableTranslator($flag)
941 $this->_translatorDisabled = (bool) $flag;
942 return $this;
946 * Is translation disabled?
948 * @return bool
950 public function translatorIsDisabled()
952 return $this->_translatorDisabled;
956 * Overloading: allow rendering specific decorators
958 * Call renderDecoratorName() to render a specific decorator.
960 * @param string $method
961 * @param array $args
962 * @return string
963 * @throws Zend_Form_Exception for invalid decorator or invalid method call
965 public function __call($method, $args)
967 if ('render' == substr($method, 0, 6)) {
968 $decoratorName = substr($method, 6);
969 if (false !== ($decorator = $this->getDecorator($decoratorName))) {
970 $decorator->setElement($this);
971 $seed = '';
972 if (0 < count($args)) {
973 $seed = array_shift($args);
975 return $decorator->render($seed);
978 require_once 'Zend/Form/Exception.php';
979 throw new Zend_Form_Exception(sprintf('Decorator by name %s does not exist', $decoratorName));
982 require_once 'Zend/Form/Exception.php';
983 throw new Zend_Form_Exception(sprintf('Method %s does not exist', $method));
986 // Interfaces: Iterator, Countable
989 * Current element
991 * @return Zend_Form_Element
993 public function current()
995 $this->_sort();
996 current($this->_elementOrder);
997 $key = key($this->_elementOrder);
998 return $this->getElement($key);
1002 * Current element
1004 * @return string
1006 public function key()
1008 $this->_sort();
1009 return key($this->_elementOrder);
1013 * Move pointer to next element
1015 * @return void
1017 public function next()
1019 $this->_sort();
1020 next($this->_elementOrder);
1024 * Move pointer to beginning of element loop
1026 * @return void
1028 public function rewind()
1030 $this->_sort();
1031 reset($this->_elementOrder);
1035 * Determine if current element/subform/display group is valid
1037 * @return bool
1039 public function valid()
1041 $this->_sort();
1042 return (current($this->_elementOrder) !== false);
1046 * Count of elements/subforms that are iterable
1048 * @return int
1050 public function count()
1052 return count($this->_elements);
1056 * Sort items according to their order
1058 * @return void
1060 protected function _sort()
1062 if ($this->_groupUpdated || !is_array($this->_elementOrder)) {
1063 $elementOrder = array();
1064 foreach ($this->getElements() as $key => $element) {
1065 $elementOrder[$key] = $element->getOrder();
1068 $items = array();
1069 $index = 0;
1070 foreach ($elementOrder as $key => $order) {
1071 if (null === $order) {
1072 while (array_search($index, $elementOrder, true)) {
1073 ++$index;
1075 $items[$index] = $key;
1076 ++$index;
1077 } else {
1078 $items[$order] = $key;
1082 $items = array_flip($items);
1083 asort($items);
1084 $this->_elementOrder = $items;
1085 $this->_groupUpdated = false;
1090 * Lazy-load a decorator
1092 * @param array $decorator Decorator type and options
1093 * @param mixed $name Decorator name or alias
1094 * @return Zend_Form_Decorator_Interface
1096 protected function _loadDecorator(array $decorator, $name)
1098 $sameName = false;
1099 if ($name == $decorator['decorator']) {
1100 $sameName = true;
1103 $instance = $this->_getDecorator($decorator['decorator'], $decorator['options']);
1104 if ($sameName) {
1105 $newName = get_class($instance);
1106 $decoratorNames = array_keys($this->_decorators);
1107 $order = array_flip($decoratorNames);
1108 $order[$newName] = $order[$name];
1109 $decoratorsExchange = array();
1110 unset($order[$name]);
1111 asort($order);
1112 foreach ($order as $key => $index) {
1113 if ($key == $newName) {
1114 $decoratorsExchange[$key] = $instance;
1115 continue;
1117 $decoratorsExchange[$key] = $this->_decorators[$key];
1119 $this->_decorators = $decoratorsExchange;
1120 } else {
1121 $this->_decorators[$name] = $instance;
1124 return $instance;