PriorityStack.php 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  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_Controller
  17. * @subpackage Zend_Controller_Action
  18. * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. * @version $Id$
  21. */
  22. /**
  23. * @category Zend
  24. * @package Zend_Controller
  25. * @subpackage Zend_Controller_Action
  26. * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
  27. * @license http://framework.zend.com/license/new-bsd New BSD License
  28. */
  29. class Zend_Controller_Action_HelperBroker_PriorityStack implements IteratorAggregate, ArrayAccess, Countable
  30. {
  31. protected $_helpersByPriority = array();
  32. protected $_helpersByNameRef = array();
  33. protected $_nextDefaultPriority = 1;
  34. /**
  35. * Magic property overloading for returning helper by name
  36. *
  37. * @param string $helperName The helper name
  38. * @return Zend_Controller_Action_Helper_Abstract
  39. */
  40. public function __get($helperName)
  41. {
  42. if (!array_key_exists($helperName, $this->_helpersByNameRef)) {
  43. return false;
  44. }
  45. return $this->_helpersByNameRef[$helperName];
  46. }
  47. /**
  48. * Magic property overloading for returning if helper is set by name
  49. *
  50. * @param string $helperName The helper name
  51. * @return Zend_Controller_Action_Helper_Abstract
  52. */
  53. public function __isset($helperName)
  54. {
  55. return array_key_exists($helperName, $this->_helpersByNameRef);
  56. }
  57. /**
  58. * Magic property overloading for unsetting if helper is exists by name
  59. *
  60. * @param string $helperName The helper name
  61. * @return Zend_Controller_Action_Helper_Abstract
  62. */
  63. public function __unset($helperName)
  64. {
  65. return $this->offsetUnset($helperName);
  66. }
  67. /**
  68. * push helper onto the stack
  69. *
  70. * @param Zend_Controller_Action_Helper_Abstract $helper
  71. * @return Zend_Controller_Action_HelperBroker_PriorityStack
  72. */
  73. public function push(Zend_Controller_Action_Helper_Abstract $helper)
  74. {
  75. $this->offsetSet($this->getNextFreeHigherPriority(), $helper);
  76. return $this;
  77. }
  78. /**
  79. * Return something iterable
  80. *
  81. * @return array
  82. */
  83. public function getIterator()
  84. {
  85. return new ArrayObject($this->_helpersByPriority);
  86. }
  87. /**
  88. * offsetExists()
  89. *
  90. * @param int|string $priorityOrHelperName
  91. * @return Zend_Controller_Action_HelperBroker_PriorityStack
  92. */
  93. public function offsetExists($priorityOrHelperName)
  94. {
  95. if (is_string($priorityOrHelperName)) {
  96. return array_key_exists($priorityOrHelperName, $this->_helpersByNameRef);
  97. } else {
  98. return array_key_exists($priorityOrHelperName, $this->_helpersByPriority);
  99. }
  100. }
  101. /**
  102. * offsetGet()
  103. *
  104. * @param int|string $priorityOrHelperName
  105. * @return Zend_Controller_Action_HelperBroker_PriorityStack
  106. */
  107. public function offsetGet($priorityOrHelperName)
  108. {
  109. if (!$this->offsetExists($priorityOrHelperName)) {
  110. require_once 'Zend/Controller/Action/Exception.php';
  111. throw new Zend_Controller_Action_Exception('A helper with priority ' . $priorityOrHelperName . ' does not exist.');
  112. }
  113. if (is_string($priorityOrHelperName)) {
  114. return $this->_helpersByNameRef[$priorityOrHelperName];
  115. } else {
  116. return $this->_helpersByPriority[$priorityOrHelperName];
  117. }
  118. }
  119. /**
  120. * offsetSet()
  121. *
  122. * @param int $priority
  123. * @param Zend_Controller_Action_Helper_Abstract $helper
  124. * @return Zend_Controller_Action_HelperBroker_PriorityStack
  125. */
  126. public function offsetSet($priority, $helper)
  127. {
  128. $priority = (int) $priority;
  129. if (!$helper instanceof Zend_Controller_Action_Helper_Abstract) {
  130. require_once 'Zend/Controller/Action/Exception.php';
  131. throw new Zend_Controller_Action_Exception('$helper must extend Zend_Controller_Action_Helper_Abstract.');
  132. }
  133. if (array_key_exists($helper->getName(), $this->_helpersByNameRef)) {
  134. // remove any object with the same name to retain BC compailitbility
  135. // @todo At ZF 2.0 time throw an exception here.
  136. $this->offsetUnset($helper->getName());
  137. }
  138. if (array_key_exists($priority, $this->_helpersByPriority)) {
  139. $priority = $this->getNextFreeHigherPriority($priority); // ensures LIFO
  140. trigger_error("A helper with the same priority already exists, reassigning to $priority", E_USER_WARNING);
  141. }
  142. $this->_helpersByPriority[$priority] = $helper;
  143. $this->_helpersByNameRef[$helper->getName()] = $helper;
  144. if ($priority == ($nextFreeDefault = $this->getNextFreeHigherPriority($this->_nextDefaultPriority))) {
  145. $this->_nextDefaultPriority = $nextFreeDefault;
  146. }
  147. krsort($this->_helpersByPriority); // always make sure priority and LIFO are both enforced
  148. return $this;
  149. }
  150. /**
  151. * offsetUnset()
  152. *
  153. * @param int|string $priorityOrHelperName Priority integer or the helper name
  154. * @return Zend_Controller_Action_HelperBroker_PriorityStack
  155. */
  156. public function offsetUnset($priorityOrHelperName)
  157. {
  158. if (!$this->offsetExists($priorityOrHelperName)) {
  159. require_once 'Zend/Controller/Action/Exception.php';
  160. throw new Zend_Controller_Action_Exception('A helper with priority or name ' . $priorityOrHelperName . ' does not exist.');
  161. }
  162. if (is_string($priorityOrHelperName)) {
  163. $helperName = $priorityOrHelperName;
  164. $helper = $this->_helpersByNameRef[$helperName];
  165. $priority = array_search($helper, $this->_helpersByPriority, true);
  166. } else {
  167. $priority = $priorityOrHelperName;
  168. $helperName = $this->_helpersByPriority[$priorityOrHelperName]->getName();
  169. }
  170. unset($this->_helpersByNameRef[$helperName]);
  171. unset($this->_helpersByPriority[$priority]);
  172. return $this;
  173. }
  174. /**
  175. * return the count of helpers
  176. *
  177. * @return int
  178. */
  179. public function count()
  180. {
  181. return count($this->_helpersByPriority);
  182. }
  183. /**
  184. * Find the next free higher priority. If an index is given, it will
  185. * find the next free highest priority after it.
  186. *
  187. * @param int $indexPriority OPTIONAL
  188. * @return int
  189. */
  190. public function getNextFreeHigherPriority($indexPriority = null)
  191. {
  192. if ($indexPriority == null) {
  193. $indexPriority = $this->_nextDefaultPriority;
  194. }
  195. $priorities = array_keys($this->_helpersByPriority);
  196. while (in_array($indexPriority, $priorities)) {
  197. $indexPriority++;
  198. }
  199. return $indexPriority;
  200. }
  201. /**
  202. * Find the next free lower priority. If an index is given, it will
  203. * find the next free lower priority before it.
  204. *
  205. * @param int $indexPriority
  206. * @return int
  207. */
  208. public function getNextFreeLowerPriority($indexPriority = null)
  209. {
  210. if ($indexPriority == null) {
  211. $indexPriority = $this->_nextDefaultPriority;
  212. }
  213. $priorities = array_keys($this->_helpersByPriority);
  214. while (in_array($indexPriority, $priorities)) {
  215. $indexPriority--;
  216. }
  217. return $indexPriority;
  218. }
  219. /**
  220. * return the highest priority
  221. *
  222. * @return int
  223. */
  224. public function getHighestPriority()
  225. {
  226. return max(array_keys($this->_helpersByPriority));
  227. }
  228. /**
  229. * return the lowest priority
  230. *
  231. * @return int
  232. */
  233. public function getLowestPriority()
  234. {
  235. return min(array_keys($this->_helpersByPriority));
  236. }
  237. /**
  238. * return the helpers referenced by name
  239. *
  240. * @return array
  241. */
  242. public function getHelpersByName()
  243. {
  244. return $this->_helpersByNameRef;
  245. }
  246. }