PriorityStack.php 8.5 KB

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