2015-08-17 17:00:26 -07:00
< ? php
/**
* Zend Framework ( http :// framework . zend . com / )
*
* @ link http :// github . com / zendframework / zf2 for the canonical source repository
* @ copyright Copyright ( c ) 2005 - 2015 Zend Technologies USA Inc . ( http :// www . zend . com )
* @ license http :// framework . zend . com / license / new - bsd New BSD License
*/
namespace Zend\Stdlib ;
use ReflectionClass ;
/**
* 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 ) .
*/
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
*/
2015-10-08 11:40:12 -07:00
public function __construct ( $callback , array $metadata = [])
2015-08-17 17:00:26 -07:00
{
$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
*/
2015-10-08 11:40:12 -07:00
public function call ( array $args = [])
2015-08-17 17:00:26 -07:00
{
$callback = $this -> getCallback ();
$argCount = count ( $args );
2015-10-08 11:40:12 -07:00
if ( is_string ( $callback )) {
2015-08-17 17:00:26 -07:00
$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 :
2015-10-08 11:40:12 -07:00
return $callback ();
2015-08-17 17:00:26 -07:00
case 1 :
2015-10-08 11:40:12 -07:00
return $callback ( array_shift ( $args ));
2015-08-17 17:00:26 -07:00
case 2 :
$arg1 = array_shift ( $args );
$arg2 = array_shift ( $args );
2015-10-08 11:40:12 -07:00
return $callback ( $arg1 , $arg2 );
2015-08-17 17:00:26 -07:00
case 3 :
$arg1 = array_shift ( $args );
$arg2 = array_shift ( $args );
$arg3 = array_shift ( $args );
2015-10-08 11:40:12 -07:00
return $callback ( $arg1 , $arg2 , $arg3 );
2015-08-17 17:00:26 -07:00
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.
2015-10-08 11:40:12 -07:00
return [ $class , $method ];
2015-08-17 17:00:26 -07:00
}
}