/library/Zend/Filter/FilterChain.php

https://github.com/pborreli/zf2 · PHP · 227 lines · 117 code · 22 blank · 88 comment · 10 complexity · 8252bba512fe3ee6ee4010eae3d5709d MD5 · raw file

  1. <?php
  2. /**
  3. * Zend Framework (http://framework.zend.com/)
  4. *
  5. * @link http://github.com/zendframework/zf2 for the canonical source repository
  6. * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
  7. * @license http://framework.zend.com/license/new-bsd New BSD License
  8. * @package Zend_Filter
  9. */
  10. namespace Zend\Filter;
  11. use Countable;
  12. use Zend\Stdlib\PriorityQueue;
  13. /**
  14. * @category Zend
  15. * @package Zend_Filter
  16. */
  17. class FilterChain extends AbstractFilter implements Countable
  18. {
  19. /**
  20. * Default priority at which filters are added
  21. */
  22. const DEFAULT_PRIORITY = 1000;
  23. /**
  24. * @var FilterPluginManager
  25. */
  26. protected $plugins;
  27. /**
  28. * Filter chain
  29. *
  30. * @var PriorityQueue
  31. */
  32. protected $filters;
  33. /**
  34. * Initialize filter chain
  35. *
  36. */
  37. public function __construct($options = null)
  38. {
  39. $this->filters = new PriorityQueue();
  40. if (null !== $options) {
  41. $this->setOptions($options);
  42. }
  43. }
  44. public function setOptions($options)
  45. {
  46. if (!is_array($options) && !$options instanceof \Traversable) {
  47. throw new Exception\InvalidArgumentException(sprintf(
  48. 'Expected array or Traversable; received "%s"',
  49. (is_object($options) ? get_class($options) : gettype($options))
  50. ));
  51. }
  52. foreach ($options as $key => $value) {
  53. switch (strtolower($key)) {
  54. case 'callbacks':
  55. foreach ($value as $spec) {
  56. $callback = isset($spec['callback']) ? $spec['callback'] : false;
  57. $priority = isset($spec['priority']) ? $spec['priority'] : static::DEFAULT_PRIORITY;
  58. if ($callback) {
  59. $this->attach($callback, $priority);
  60. }
  61. }
  62. break;
  63. case 'filters':
  64. foreach ($value as $spec) {
  65. $name = isset($spec['name']) ? $spec['name'] : false;
  66. $options = isset($spec['options']) ? $spec['options'] : array();
  67. $priority = isset($spec['priority']) ? $spec['priority'] : static::DEFAULT_PRIORITY;
  68. if ($name) {
  69. $this->attachByName($name, $options, $priority);
  70. }
  71. }
  72. break;
  73. default:
  74. // ignore other options
  75. break;
  76. }
  77. }
  78. return $this;
  79. }
  80. /**
  81. * Return the count of attached filters
  82. *
  83. * @return int
  84. */
  85. public function count()
  86. {
  87. return count($this->filters);
  88. }
  89. /**
  90. * Get plugin manager instance
  91. *
  92. * @return FilterPluginManager
  93. */
  94. public function getPluginManager()
  95. {
  96. if (!$this->plugins) {
  97. $this->setPluginManager(new FilterPluginManager());
  98. }
  99. return $this->plugins;
  100. }
  101. /**
  102. * Set plugin manager instance
  103. *
  104. * @param FilterPluginManager $plugins
  105. * @return FilterChain
  106. */
  107. public function setPluginManager(FilterPluginManager $plugins)
  108. {
  109. $this->plugins = $plugins;
  110. return $this;
  111. }
  112. /**
  113. * Retrieve a filter plugin by name
  114. *
  115. * @param mixed $name
  116. * @param array $options
  117. * @return Filter
  118. */
  119. public function plugin($name, array $options = array())
  120. {
  121. $plugins = $this->getPluginManager();
  122. return $plugins->get($name, $options);
  123. }
  124. /**
  125. * Attach a filter to the chain
  126. *
  127. * @param callback|FilterInterface $callback A Filter implementation or valid PHP callback
  128. * @param int $priority Priority at which to enqueue filter; defaults to 1000 (higher executes earlier)
  129. * @return FilterChain
  130. */
  131. public function attach($callback, $priority = self::DEFAULT_PRIORITY)
  132. {
  133. if (!is_callable($callback)) {
  134. if (!$callback instanceof FilterInterface) {
  135. throw new Exception\InvalidArgumentException(sprintf(
  136. 'Expected a valid PHP callback; received "%s"',
  137. (is_object($callback) ? get_class($callback) : gettype($callback))
  138. ));
  139. }
  140. $callback = array($callback, 'filter');
  141. }
  142. $this->filters->insert($callback, $priority);
  143. return $this;
  144. }
  145. /**
  146. * Attach a filter to the chain using a short name
  147. *
  148. * Retrieves the filter from the attached plugin broker, and then calls attach()
  149. * with the retrieved instance.
  150. *
  151. * @param string $name
  152. * @param mixed $options
  153. * @param int $priority Priority at which to enqueue filter; defaults to 1000 (higher executes earlier)
  154. * @return FilterChain
  155. */
  156. public function attachByName($name, $options = array(), $priority = self::DEFAULT_PRIORITY)
  157. {
  158. if (!is_array($options)) {
  159. $options = (array) $options;
  160. } elseif (empty($options)) {
  161. $options = null;
  162. }
  163. $filter = $this->getPluginManager()->get($name, $options);
  164. return $this->attach($filter, $priority);
  165. }
  166. /**
  167. * Merge the filter chain with the one given in parameter
  168. *
  169. * @param FilterChain $filterChain
  170. * @return FilterChain
  171. */
  172. public function merge(FilterChain $filterChain)
  173. {
  174. foreach ($filterChain->filters as $filter) {
  175. $this->attach($filter);
  176. }
  177. return $this;
  178. }
  179. /**
  180. * Get all the filters
  181. *
  182. * @return PriorityQueue
  183. */
  184. public function getFilters()
  185. {
  186. return $this->filters;
  187. }
  188. /**
  189. * Returns $value filtered through each filter in the chain
  190. *
  191. * Filters are run in the order in which they were added to the chain (FIFO)
  192. *
  193. * @param mixed $value
  194. * @return mixed
  195. */
  196. public function filter($value)
  197. {
  198. $chain = clone $this->filters;
  199. $valueFiltered = $value;
  200. foreach ($chain as $filter) {
  201. $valueFiltered = call_user_func($filter, $valueFiltered);
  202. }
  203. return $valueFiltered;
  204. }
  205. }