public static function wrap($callable)
    {
        $parts          = explode('::', static::represent($callable));
        if (count($parts) == 1) {
            // We wrapped a function.
            $reflector = new \ReflectionFunction($callable);
        } else {
            if (!is_array($callable)) {
                // We wrapped a Closure or some invokable object.
                $callable = array($callable, $parts[1]);
            }
            $reflector = new \ReflectionMethod($callable[0], $callable[1]);
        }

        // References are lost, unless __invoke()'s signature also requires them.
        // We must also make sure default values are preserved.
        $args = array();
        foreach ($reflector->getParameters() as $argReflect) {
            $arg = '';
            if ($argReflect->isPassedByReference()) {
                $arg .= '&';
            }
            $arg .= '$a' . count($args);
            if ($argReflect->isOptional()) {
                $arg .= '=' . var_export($argReflect->getDefaultValue(), true);
            } else {
                $arg .= '=null';
            }
            $args[] = $arg;
        }

        $args   = implode(',', $args);
        $class  = 'Wrapped_' . sha1($args);
        if (!class_exists("\\Erebot\\CallableWrapper\\$class", false)) {
            $tpl = "
                namespace Erebot\\CallableWrapper {
                    class $class extends \\Erebot\\CallableWrapper
                    {
                        public function __invoke($args)
                        {
                            // HACK: we use debug_backtrace() to get (and pass along)
                            // references for call_user_func_array().

                            // Starting with PHP 5.4.0, it is possible to limit
                            // the number of stack frames returned.
                            if (version_compare(PHP_VERSION, '5.4', '>='))
                                \$bt = debug_backtrace(0, 1);
                            // Starting with PHP 5.3.6, the first argument
                            // to debug_backtrace() is a bitmask of options.
                            else if (version_compare(PHP_VERSION, '5.3.6', '>='))
                                \$bt = debug_backtrace(0);
                            else
                                \$bt = debug_backtrace(FALSE);

                            if (isset(\$bt[0]['args']))
                                \$args =& \$bt[0]['args'];
                            else
                                \$args = array();
                            return call_user_func_array(\$this->callable, \$args);
                        }
                    }
                }
            ";
            eval($tpl);
        }
        $class = "\\Erebot\\CallableWrapper\\$class";
        return new $class($callable);
    }
public static function wrap($callable)
    {
        $parts          = explode('::', static::represent($callable));
        if (count($parts) == 1) {
            // We wrapped a function.
            $reflector = new \ReflectionFunction($callable);
        } else {
            if (!is_array($callable)) {
                // We wrapped a Closure or some invokable object.
                $callable = array($callable, $parts[1]);
            }
            $reflector = new \ReflectionMethod($callable[0], $callable[1]);
        }

        // References are lost, unless __invoke()'s signature also requires them.
        // We must also make sure default values are preserved.
        $args = array();
        foreach ($reflector->getParameters() as $argReflect) {
            $arg = '';
            if ($argReflect->isPassedByReference()) {
                $arg .= '&';
            }
            $arg .= '$a' . count($args);
            if ($argReflect->isOptional()) {
                $arg .= '=' . var_export($argReflect->getDefaultValue(), true);
            } else {
                $arg .= '=null';
            }
            $args[] = $arg;
        }

        $args   = implode(',', $args);
        $class  = 'Wrapped_' . sha1($args);
        if (!class_exists("\\Erebot\\CallableWrapper\\$class", false)) {
            $tpl = "
                namespace Erebot\\CallableWrapper {
                    class $class extends \\Erebot\\CallableWrapper
                    {
                        public function __invoke($args)
                        {
                            // HACK: we use debug_backtrace() to get (and pass along)
                            // references for call_user_func_array().

                            // Starting with PHP 5.4.0, it is possible to limit
                            // the number of stack frames returned.
                            if (version_compare(PHP_VERSION, '5.4', '>='))
                                \$bt = debug_backtrace(0, 1);
                            // Starting with PHP 5.3.6, the first argument
                            // to debug_backtrace() is a bitmask of options.
                            else if (version_compare(PHP_VERSION, '5.3.6', '>='))
                                \$bt = debug_backtrace(0);
                            else
                                \$bt = debug_backtrace(FALSE);

                            if (isset(\$bt[0]['args']))
                                \$args =& \$bt[0]['args'];
                            else
                                \$args = array();
                            return call_user_func_array(\$this->callable, \$args);
                        }
                    }
                }
            ";
            eval($tpl);
        }
        $class = "\\Erebot\\CallableWrapper\\$class";
        return new $class($callable);
    }
public static function wrap ( $ callable ) { $ parts = explode ( '::' , static :: represent ( $ callable ) ) ; if ( count ( $ parts ) == 1 ) { // We wrapped a function. $ reflector = new \ ReflectionFunction ( $ callable ) ; } else { if ( ! is_array ( $ callable ) ) { // We wrapped a Closure or some invokable object. $ callable = array ( $ callable , $ parts [ 1 ] ) ; } $ reflector = new \ ReflectionMethod ( $ callable [ 0 ] , $ callable [ 1 ] ) ; } // References are lost, unless __invoke()'s signature also requires them. // We must also make sure default values are preserved. $ args = array ( ) ; foreach ( $ reflector -> getParameters ( ) as $ argReflect ) { $ arg = '' ; if ( $ argReflect -> isPassedByReference ( ) ) { $ arg .= '&' ; } $ arg .= '$a' . count ( $ args ) ; if ( $ argReflect -> isOptional ( ) ) { $ arg .= '=' . var_export ( $ argReflect -> getDefaultValue ( ) , true ) ; } else { $ arg .= '=null' ; } $ args [ ] = $ arg ; } $ args = implode ( ',' , $ args ) ; $ class = 'Wrapped_' . sha1 ( $ args ) ; if ( ! class_exists ( "\\Erebot\\CallableWrapper\\$class" , false ) ) { $ tpl = "
                namespace Erebot\\CallableWrapper {
                    class $class extends \\Erebot\\CallableWrapper
                    {
                        public function __invoke($args)
                        {
                            // HACK: we use debug_backtrace() to get (and pass along)
                            // references for call_user_func_array().

                            // Starting with PHP 5.4.0, it is possible to limit
                            // the number of stack frames returned.
                            if (version_compare(PHP_VERSION, '5.4', '>='))
                                \$bt = debug_backtrace(0, 1);
                            // Starting with PHP 5.3.6, the first argument
                            // to debug_backtrace() is a bitmask of options.
                            else if (version_compare(PHP_VERSION, '5.3.6', '>='))
                                \$bt = debug_backtrace(0);
                            else
                                \$bt = debug_backtrace(FALSE);

                            if (isset(\$bt[0]['args']))
                                \$args =& \$bt[0]['args'];
                            else
                                \$args = array();
                            return call_user_func_array(\$this->callable, \$args);
                        }
                    }
                }
            " ; eval ( $ tpl ) ; } $ class = "\\Erebot\\CallableWrapper\\$class" ; return new $ class ( $ callable ) ; }
Wraps an existing callable piece of code.

\param mixed $callable
Callable piece of code to wrap.

\retval Erebot::CallableInterface
An object of a class implementing the
Erebot::CallableInterface is returned.
The precise type of the object will usually vary
between calls as new types are created on-the-fly
if needed.
Wraps an existing callable piece of code .