diff -r 2251fb41dbc7 -r 1e110b03ae96 web/lib/Zend/Stdlib/CallbackHandler.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/lib/Zend/Stdlib/CallbackHandler.php Sun Apr 21 21:54:24 2013 +0200 @@ -0,0 +1,301 @@ +metadata = $metadata; + $this->registerCallback($callback); + } + + /** + * Error handler + * + * Used by registerCallback() when calling is_callable() to capture engine warnings. + * + * @param int $errno + * @param string $errstr + * @return void + */ + public function errorHandler($errno, $errstr) + { + $this->error = true; + } + + /** + * Registers the callback provided in the constructor + * + * If you have pecl/weakref {@see http://pecl.php.net/weakref} installed, + * this method provides additional behavior. + * + * If a callback is a functor, or an array callback composing an object + * instance, this method will pass the object to a WeakRef instance prior + * to registering the callback. + * + * @param Callable $callback + * @return void + */ + protected function registerCallback($callback) + { + set_error_handler(array($this, 'errorHandler'), E_STRICT); + $callable = is_callable($callback); + restore_error_handler(); + if (!$callable || $this->error) { + require_once 'Zend/Stdlib/Exception/InvalidCallbackException.php'; + throw new Zend_Stdlib_Exception_InvalidCallbackException('Invalid callback provided; not callable'); + } + + // If pecl/weakref is not installed, simply store the callback and return + if (!class_exists('WeakRef')) { + $this->callback = $callback; + return; + } + + // If WeakRef exists, we want to use it. + + // If we have a non-closure object, pass it to WeakRef, and then + // register it. + if (is_object($callback) && !$callback instanceof Closure) { + $this->callback = new WeakRef($callback); + return; + } + + // If we have a string or closure, register as-is + if (!is_array($callback)) { + $this->callback = $callback; + return; + } + + list($target, $method) = $callback; + + // If we have an array callback, and the first argument is not an + // object, register as-is + if (!is_object($target)) { + $this->callback = $callback; + return; + } + + // We have an array callback with an object as the first argument; + // pass it to WeakRef, and then register the new callback + $target = new WeakRef($target); + $this->callback = array($target, $method); + } + + /** + * Retrieve registered callback + * + * @return Callable + */ + public function getCallback() + { + $callback = $this->callback; + + // String callbacks -- simply return + if (is_string($callback)) { + return $callback; + } + + // WeakRef callbacks -- pull it out of the object and return it + if ($callback instanceof WeakRef) { + return $callback->get(); + } + + // Non-WeakRef object callback -- return it + if (is_object($callback)) { + return $callback; + } + + // Array callback with WeakRef object -- retrieve the object first, and + // then return + list($target, $method) = $callback; + if ($target instanceof WeakRef) { + return array($target->get(), $method); + } + + // Otherwise, return it + return $callback; + } + + /** + * Invoke handler + * + * @param array $args Arguments to pass to callback + * @return mixed + */ + public function call(array $args = array()) + { + $callback = $this->getCallback(); + + $isPhp54 = version_compare(PHP_VERSION, '5.4.0rc1', '>='); + + if ($isPhp54 && is_string($callback)) { + $this->validateStringCallbackFor54($callback); + } + + // Minor performance tweak; use call_user_func() until > 3 arguments + // reached + switch (count($args)) { + case 0: + if ($isPhp54) { + return $callback(); + } + return call_user_func($callback); + case 1: + if ($isPhp54) { + return $callback(array_shift($args)); + } + return call_user_func($callback, array_shift($args)); + case 2: + $arg1 = array_shift($args); + $arg2 = array_shift($args); + if ($isPhp54) { + return $callback($arg1, $arg2); + } + return call_user_func($callback, $arg1, $arg2); + case 3: + $arg1 = array_shift($args); + $arg2 = array_shift($args); + $arg3 = array_shift($args); + if ($isPhp54) { + return $callback($arg1, $arg2, $arg3); + } + return call_user_func($callback, $arg1, $arg2, $arg3); + default: + return call_user_func_array($callback, $args); + } + } + + /** + * Invoke as functor + * + * @return mixed + */ + public function __invoke() + { + return $this->call(func_get_args()); + } + + /** + * Get all callback metadata + * + * @return array + */ + public function getMetadata() + { + return $this->metadata; + } + + /** + * Retrieve a single metadatum + * + * @param string $name + * @return mixed + */ + public function getMetadatum($name) + { + if (array_key_exists($name, $this->metadata)) { + return $this->metadata[$name]; + } + return null; + } + + /** + * Validate a static method call + * + * Validates that a static method call in PHP 5.4 will actually work + * + * @param string $callback + * @return true + * @throws Zend_Stdlib_Exception_InvalidCallbackException if invalid + */ + protected function validateStringCallbackFor54($callback) + { + if (!strstr($callback, '::')) { + return true; + } + + list($class, $method) = explode('::', $callback, 2); + + if (!class_exists($class)) { + require_once 'Zend/Stdlib/Exception/InvalidCallbackException.php'; + throw new Zend_Stdlib_Exception_InvalidCallbackException(sprintf( + 'Static method call "%s" refers to a class that does not exist', + $callback + )); + } + + $r = new ReflectionClass($class); + if (!$r->hasMethod($method)) { + require_once 'Zend/Stdlib/Exception/InvalidCallbackException.php'; + throw new Zend_Stdlib_Exception_InvalidCallbackException(sprintf( + 'Static method call "%s" refers to a method that does not exist', + $callback + )); + } + $m = $r->getMethod($method); + if (!$m->isStatic()) { + require_once 'Zend/Stdlib/Exception/InvalidCallbackException.php'; + throw new Zend_Stdlib_Exception_InvalidCallbackException(sprintf( + 'Static method call "%s" refers to a method that is not static', + $callback + )); + } + + return true; + } +}