/** * @param mixed class, object, callable * @param string method * @return \Closure */ public static function closure($callable, $m = NULL) { if ($m !== NULL) { $callable = array($callable, $m); } elseif (is_string($callable) && count($tmp = explode('::', $callable)) === 2) { $callable = $tmp; } elseif ($callable instanceof \Closure) { return $callable; } elseif (is_object($callable)) { $callable = array($callable, '__invoke'); } if (PHP_VERSION_ID >= 50400) { if (is_string($callable) && function_exists($callable)) { $r = new \ReflectionFunction($callable); return $r->getClosure(); } elseif (is_array($callable) && method_exists($callable[0], $callable[1])) { $r = new \ReflectionMethod($callable[0], $callable[1]); return $r->getClosure($callable[0]); } } self::check($callable); $_callable_ = $callable; return function () use($_callable_) { return call_user_func_array($_callable_, func_get_args()); }; }
/** * Constructor * * @param string $name * @param function $fn */ public function __construct($name, $fn) { $this->fn = $fn; $this->name = $name; if (!Preview::is_php53()) { $ref = new \ReflectionFunction($fn); $this->fn = $ref->getClosure(); } }
/** * Casts the given callable to Closure * @param callable $callable * @return \Closure * @throws \InvalidArgumentException */ protected function castToClosure($callable) { if (!is_callable($callable)) { throw new \InvalidArgumentException('Argument 1 must be callable, ' . gettype($callable) . ' given.'); } $result = null; if (is_object($callable)) { if ($callable instanceof \Closure) { $result = $callable; } else { if (method_exists($callable, '__invoke')) { $r = new \ReflectionObject($callable); $result = $r->getMethod('__invoke')->getClosure($callable); } } } else { try { $r = new \ReflectionMethod($callable); $result = $r->getClosure(); } catch (\Exception $e) { try { $r = new \ReflectionFunction($callable); $result = $r->getClosure(); } catch (\Exception $e) { if (is_array($callable)) { $r = new \ReflectionObject($callable[0]); $result = $r->getMethod($callable[1])->getClosure($callable[0]); } } } } if ($result === null) { throw new \InvalidArgumentException('Unsupported callable given.'); } return $result; }
/** * Returns the function/method as closure. * * @return \Closure */ public function getClosure() { if (PHP_VERSION_ID >= 50400) { return parent::getClosure(); } else { $that = $this; return function () use($that) { return $that->invokeArgs(func_get_args()); }; } }
/** * {@inheritDoc} */ public function getClosure() { $this->initializeInternalReflection(); return parent::getClosure(); }
public function getClosure() { return PHP_VERSION_ID < 50400 ? Nette\Utils\Callback::closure($this->value) : parent::getClosure(); }
<?php /* Prototype : public mixed ReflectionFunction::getClosure() * Description: Returns a dynamically created closure for the function * Source code: ext/reflection/php_reflection.c * Alias to functions: */ echo "*** Testing ReflectionFunction::getClosure() : error conditions ***\n"; function foo() { var_dump("Inside foo function"); } $func = new ReflectionFunction('foo'); $closure = $func->getClosure('bar'); ?> ===DONE===
/** * Gets the closure instance. * * @return \Closure */ public function getClosure() { return $this->reflection->getClosure(); }
<?php /* Prototype : public mixed ReflectionFunction::getClosure() * Description: Returns a dynamically created closure for the function * Source code: ext/reflection/php_reflection.c * Alias to functions: */ echo "*** Testing ReflectionFunction::getClosure() : basic functionality ***\n"; function foo() { var_dump("Inside foo function"); } function bar($arg) { var_dump("Arg is " . $arg); } $func = new ReflectionFunction('foo'); $closure = $func->getClosure(); $closure(); $func = new ReflectionFunction('bar'); $closure = $func->getClosure(); $closure('succeeded'); ?> ===DONE===
{ return $a + 2; } $foo = function ($a) { return $a + 3; }; $bar = new Bar(10); // Dynamic methods $rf = new ReflectionMethod($bar, 'baz'); var_dump($rf->getClosure() === NULL); var_dump(call_user_func($rf->getClosure($bar), 1)); $rf = new ReflectionMethod('Bar', 'baz'); var_dump($rf->getClosure() === NULL); var_dump(call_user_func($rf->getClosure($bar), 1)); $rf = new ReflectionMethod('Bar::baz'); var_dump($rf->getClosure() === NULL); var_dump(call_user_func($rf->getClosure($bar), 1)); // Static methods $rf = new ReflectionMethod($bar, 'foo'); var_dump(call_user_func($rf->getClosure(), 1)); $rf = new ReflectionMethod('Bar', 'foo'); var_dump(call_user_func($rf->getClosure(), 1)); $rf = new ReflectionMethod('Bar::foo'); var_dump(call_user_func($rf->getClosure(), 1)); // Function $rf = new ReflectionFunction('foo'); var_dump(call_user_func($rf->getClosure(), 1)); // Closure $rf = new ReflectionFunction($foo); var_dump(call_user_func($rf->getClosure(), 1));
<?php $closure = function () { echo "Invoked!\n"; }; $method = new ReflectionFunction($closure); $closure2 = $method->getClosure(); $closure2(); $closure2->__invoke(); unset($closure); $closure2(); $closure2->__invoke(); $closure = function () { echo "Invoked!\n"; }; $method = new ReflectionMethod($closure, '__invoke'); $closure2 = $method->getClosure($closure); $closure2(); $closure2->__invoke(); unset($closure); $closure2(); $closure2->__invoke(); ?> ===DONE===
/** * Load config from file. * * @param string $file config file path * @return object Configuration object. */ public function load_from_file($file) { $options = (require_once $file); if (!is_array($options)) { $options = array(); } $this->update($options); if (!Preview::is_php53()) { // PHP 5.4 and above will automatically // bind current $this (if any) to closure. // For example, if we call load_from_file method // the hooks defined in config file will be bound to // the current configuration object($this). // So we unbind hook closure. $hooks = array("before_hook", "after_hook", "before_each_hook", "after_each_hook"); foreach ($hooks as $hook) { if ($this->{$hook}) { $ref = new \ReflectionFunction($this->{$hook}); $this->{$hook} = $ref->getClosure(); } } } }
/** * constructor * * @param string $title * @param function $fn */ public function __construct($title, $fn) { $this->context = new \stdClass(); $this->title = $title; $this->pending = !isset($fn); $this->timer = new Timer(); $this->fn = $fn; if ($fn) { $ref = new \ReflectionFunction($fn); $this->filename = $ref->getFileName(); $this->startline = $ref->getStartLine(); $this->endline = $ref->getEndLine(); if (!Preview::is_php53()) { $this->fn = $ref->getClosure(); } } }
/** * Converts any valid PHP callable into a Closure. Requires PHP 5.4.0+. * * The ramifications of this are many, but basically it means that any function * or method can be converted into a Closure, bound to another scope, and * executed easily. Works properly even with private methods. * * - On success, returns a Closure corresponding to the provided callable. * - If the parameter is not callable, issues an E_USER_WARNING and returns a * Closure which only returns null. * - In the event of a strange or unrecoverable situation (e.g. providing a * non-static method without an object), an UnexpectedValueException is * thrown. * * @author Matthew Lanigan <*****@*****.**> * @copyright (c) 2012, Matthew Lanigan * @license http://www.opensource.org/licenses/mit-license.php MIT License * @link https://gist.github.com/2773168 Official closurize() gist * @param callable $callable * @return \Closure * @throws \UnexpectedValueException */ function closurize($callable) { if ($callable instanceof \Closure) { return $callable; } $is_callable = function ($callable) { return \is_callable($callable); }; $error = function () { $debug = \debug_backtrace(\DEBUG_BACKTRACE_PROVIDE_OBJECT, 2); $fmt = 'Parameter 1 for closurize() must be callable ' . 'in %s on line %d (issued at %s on line %d)'; $error = \sprintf($fmt, $debug[1]['file'], $debug[1]['line'], $debug[0]['file'], $debug[0]['line']); \trigger_error($error, \E_USER_WARNING); return function () { return null; }; }; $object = null; $class = null; $debug = \debug_backtrace(\DEBUG_BACKTRACE_PROVIDE_OBJECT, 2); if (isset($debug[1]['object']) && \is_object($debug[1]['object'])) { $object = $debug[1]['object']; $class = $debug[1]['class']; $is_callable = $is_callable->bindTo($object, $object); } if (!$is_callable($callable)) { if (isset($callable[0]) && is_object($callable[0])) { $is_callable = $is_callable->bindTo($callable[0], $callable[0]); } else { if (isset($callable[0]) && \class_exists($callable[0])) { $is_callable = $is_callable->bindTo(null, $callable[0]); } } if (!$is_callable($callable)) { return $error(); } } if (\is_string($callable) && \strpos($callable, '::') === false) { $ref = new \ReflectionFunction($callable); return $ref->getClosure(); } else { if (\is_string($callable)) { $callable = \explode('::', $callable); } } if (!\is_array($callable)) { throw new \UnexpectedValueException('Callable is not string, array, ' . 'or Closure'); } if (\is_object($callable[0])) { $ref = new \ReflectionMethod($callable[0], $callable[1]); return $ref->getClosure($callable[0]); } if (!\is_string($callable[0])) { throw new \UnexpectedValueException('Callable class is not string ' . 'or object'); } switch ($callable[0]) { case 'self': if (!\is_object($object) && \is_null($class)) { return $error(); } $self = function () { return \get_class(); }; $self = $self->bindTo($object, $class); $ref = new \ReflectionMethod($self(), $callable[1]); $callable[0] = $object; break; case 'static': if (!\is_object($object)) { return $error(); } $static = function () { return \get_called_class(); }; $static = $static->bindTo($object, $class); $ref = new \ReflectionMethod($static(), $callable[1]); $callable[0] = $object; break; case 'parent': if (!\is_object($object)) { return $error(); } $parent = function () { return \get_parent_class(); }; $parent = $parent->bindTo($object, $class); $ref = new \ReflectionMethod($parent(), $callable[1]); $callable[0] = $object; break; default: $ref = new \ReflectionMethod($callable[0], $callable[1]); break; } if (!$ref->isStatic() && \is_object($callable[0])) { return $ref->getClosure($callable[0]); } else { if (!$ref->isStatic()) { throw new \UnexpectedValueException('Callable method is not static, ' . 'but no calling object available'); } } return $ref->getClosure(); }