3 * Zend Framework (http://framework.zend.com/)
5 * @link http://github.com/zendframework/zf2 for the canonical source repository
6 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
7 * @license http://framework.zend.com/license/new-bsd New BSD License
10 namespace Zend\Stdlib
;
17 * A handler for an event, event, filterchain, etc. Abstracts PHP callbacks,
18 * primarily to allow for lazy-loading and ensuring availability of default
19 * arguments (currying).
24 * @var string|array|callable PHP callback to invoke
29 * Callback metadata, if any
35 * PHP version is greater as 5.4rc1?
38 protected static $isPhp54;
43 * @param string|array|object|callable $callback PHP callback
44 * @param array $metadata Callback metadata
46 public function __construct($callback, array $metadata = array())
48 $this->metadata
= $metadata;
49 $this->registerCallback($callback);
53 * Registers the callback provided in the constructor
55 * @param callable $callback
56 * @throws Exception\InvalidCallbackException
59 protected function registerCallback($callback)
61 if (!is_callable($callback)) {
62 throw new Exception\
InvalidCallbackException('Invalid callback provided; not callable');
65 $this->callback
= $callback;
69 * Retrieve registered callback
73 public function getCallback()
75 return $this->callback
;
81 * @param array $args Arguments to pass to callback
84 public function call(array $args = array())
86 $callback = $this->getCallback();
88 // Minor performance tweak, if the callback gets called more than once
89 if (!isset(static::$isPhp54)) {
90 static::$isPhp54 = version_compare(PHP_VERSION
, '5.4.0rc1', '>=');
93 $argCount = count($args);
95 if (static::$isPhp54 && is_string($callback)) {
96 $result = $this->validateStringCallbackFor54($callback);
98 if ($result !== true && $argCount <= 3) {
100 // Minor performance tweak, if the callback gets called more
102 $this->callback
= $result;
106 // Minor performance tweak; use call_user_func() until > 3 arguments
110 if (static::$isPhp54) {
113 return call_user_func($callback);
115 if (static::$isPhp54) {
116 return $callback(array_shift($args));
118 return call_user_func($callback, array_shift($args));
120 $arg1 = array_shift($args);
121 $arg2 = array_shift($args);
122 if (static::$isPhp54) {
123 return $callback($arg1, $arg2);
125 return call_user_func($callback, $arg1, $arg2);
127 $arg1 = array_shift($args);
128 $arg2 = array_shift($args);
129 $arg3 = array_shift($args);
130 if (static::$isPhp54) {
131 return $callback($arg1, $arg2, $arg3);
133 return call_user_func($callback, $arg1, $arg2, $arg3);
135 return call_user_func_array($callback, $args);
144 public function __invoke()
146 return $this->call(func_get_args());
150 * Get all callback metadata
154 public function getMetadata()
156 return $this->metadata
;
160 * Retrieve a single metadatum
162 * @param string $name
165 public function getMetadatum($name)
167 if (array_key_exists($name, $this->metadata
)) {
168 return $this->metadata
[$name];
174 * Validate a static method call
176 * Validates that a static method call in PHP 5.4 will actually work
178 * @param string $callback
180 * @throws Exception\InvalidCallbackException if invalid
182 protected function validateStringCallbackFor54($callback)
184 if (!strstr($callback, '::')) {
188 list($class, $method) = explode('::', $callback, 2);
190 if (!class_exists($class)) {
191 throw new Exception\
InvalidCallbackException(sprintf(
192 'Static method call "%s" refers to a class that does not exist',
197 $r = new ReflectionClass($class);
198 if (!$r->hasMethod($method)) {
199 throw new Exception\
InvalidCallbackException(sprintf(
200 'Static method call "%s" refers to a method that does not exist',
204 $m = $r->getMethod($method);
205 if (!$m->isStatic()) {
206 throw new Exception\
InvalidCallbackException(sprintf(
207 'Static method call "%s" refers to a method that is not static',
212 // returning a non boolean value may not be nice for a validate method,
213 // but that allows the usage of a static string callback without using
214 // the call_user_func function.
215 return array($class, $method);