You are here

class CallbackHandler in Zircon Profile 8

Same name and namespace in other branches
  1. 8.0 vendor/zendframework/zend-stdlib/src/CallbackHandler.php \Zend\Stdlib\CallbackHandler

CallbackHandler

A handler for an event, event, filterchain, etc. Abstracts PHP callbacks, primarily to allow for lazy-loading and ensuring availability of default arguments (currying).

Hierarchy

Expanded class hierarchy of CallbackHandler

File

vendor/zendframework/zend-stdlib/src/CallbackHandler.php, line 21

Namespace

Zend\Stdlib
View source
class CallbackHandler {

  /**
   * @var string|array|callable PHP callback to invoke
   */
  protected $callback;

  /**
   * Callback metadata, if any
   * @var array
   */
  protected $metadata;

  /**
   * Constructor
   *
   * @param  string|array|object|callable $callback PHP callback
   * @param  array                        $metadata  Callback metadata
   */
  public function __construct($callback, array $metadata = []) {
    $this->metadata = $metadata;
    $this
      ->registerCallback($callback);
  }

  /**
   * Registers the callback provided in the constructor
   *
   * @param  callable $callback
   * @throws Exception\InvalidCallbackException
   * @return void
   */
  protected function registerCallback($callback) {
    if (!is_callable($callback)) {
      throw new Exception\InvalidCallbackException('Invalid callback provided; not callable');
    }
    $this->callback = $callback;
  }

  /**
   * Retrieve registered callback
   *
   * @return callable
   */
  public function getCallback() {
    return $this->callback;
  }

  /**
   * Invoke handler
   *
   * @param  array $args Arguments to pass to callback
   * @return mixed
   */
  public function call(array $args = []) {
    $callback = $this
      ->getCallback();
    $argCount = count($args);
    if (is_string($callback)) {
      $result = $this
        ->validateStringCallbackFor54($callback);
      if ($result !== true && $argCount <= 3) {
        $callback = $result;

        // Minor performance tweak, if the callback gets called more
        // than once
        $this->callback = $result;
      }
    }

    // Minor performance tweak; use call_user_func() until > 3 arguments
    // reached
    switch ($argCount) {
      case 0:
        return $callback();
      case 1:
        return $callback(array_shift($args));
      case 2:
        $arg1 = array_shift($args);
        $arg2 = array_shift($args);
        return $callback($arg1, $arg2);
      case 3:
        $arg1 = array_shift($args);
        $arg2 = array_shift($args);
        $arg3 = array_shift($args);
        return $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;
  }

  /**
   * Validate a static method call
   *
   *
   * @param  string $callback
   * @return true|array
   * @throws Exception\InvalidCallbackException if invalid
   */
  protected function validateStringCallbackFor54($callback) {
    if (!strstr($callback, '::')) {
      return true;
    }
    list($class, $method) = explode('::', $callback, 2);
    if (!class_exists($class)) {
      throw new Exception\InvalidCallbackException(sprintf('Static method call "%s" refers to a class that does not exist', $callback));
    }
    $r = new ReflectionClass($class);
    if (!$r
      ->hasMethod($method)) {
      throw new Exception\InvalidCallbackException(sprintf('Static method call "%s" refers to a method that does not exist', $callback));
    }
    $m = $r
      ->getMethod($method);
    if (!$m
      ->isStatic()) {
      throw new Exception\InvalidCallbackException(sprintf('Static method call "%s" refers to a method that is not static', $callback));
    }

    // returning a non boolean value may not be nice for a validate method,
    // but that allows the usage of a static string callback without using
    // the call_user_func function.
    return [
      $class,
      $method,
    ];
  }

}

Members

Namesort descending Modifiers Type Description Overrides
CallbackHandler::$callback protected property
CallbackHandler::$metadata protected property Callback metadata, if any
CallbackHandler::call public function Invoke handler
CallbackHandler::getCallback public function Retrieve registered callback
CallbackHandler::getMetadata public function Get all callback metadata
CallbackHandler::getMetadatum public function Retrieve a single metadatum
CallbackHandler::registerCallback protected function Registers the callback provided in the constructor
CallbackHandler::validateStringCallbackFor54 protected function Validate a static method call
CallbackHandler::__construct public function Constructor
CallbackHandler::__invoke public function Invoke as functor