/** * @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()); }; }
/** * Execute command * * @return int|mixed * @throws \Exception */ public function exec() { $args = func_get_args(); if (!$this->cmd) { throw new FWException('no cmd provided', 1); } $build = new ProcessBuilder(); $pro = $build->setPrefix($this->cmd)->setArguments($args)->getProcess(); $pro->setTimeout($this->timeout); $rm = new \ReflectionMethod($this, 'output'); $func = $rm->getClosure($this); $re = 0; if ($this->async) { $pro->start($func); } else { try { $pro->mustRun($func); $this->out = $pro->getOutput(); $re = $this->out; } catch (ProcessFailedException $e) { getLog()->error($e->getMessage()); $re = 1; } } return $re; }
public function __construct(LoggerInterface $logger) { $build = new \ReflectionMethod($this, 'buildCallback'); $run = new \ReflectionMethod($this, 'runCallback'); $this->buildCallback = $build->getClosure($this); $this->runCallback = $run->getClosure($this); $this->logger = $logger; }
public function method($controller_root, $method) { $controller = $this->controller; $class = $this->class; $controller_model_name = $controller_root . '\\' . $class; $func = new \ReflectionMethod($controller_model_name, $method); $Closure = $func->getClosure(new $controller_model_name()); $controller->{$class}()->Methods[$method] = $Closure->bindTo($controller->{$class}(), $controller->{$class}()); return $controller->{$class}()->Methods[$method]; }
function execute($class_name, $method_name, $instance) { try { $ref = new ReflectionMethod($class_name, $method_name); $method = $ref->getClosure($instance); var_dump($method()); } catch (Exception $e) { $c = get_class($e); echo "{$c}: {$e->getMessage()}\n"; } }
public function __construct() { if (PHP_VERSION_ID >= 50400) { if (is_int($code = http_response_code())) { $this->code = $code; } } if (PHP_VERSION_ID >= 50401) { // PHP bug #61106 $rm = new \ReflectionMethod('Nette\\Http\\Helpers::removeDuplicateCookies'); header_register_callback($rm->getClosure()); // requires closure due PHP bug #66375 } }
/** * Extracts the named method from the supplied object and attaches * it to the skeleton instance * * @param object $object * @param string $methodName * @param string $newMethodName - optional: attach the method under a new name * @throws InvalidObjectException When the $object param isn't actually an object * @throws InvalidMethodException When the named method is not callable * @return \Vanqard\Frankenbuilder\Builder fluent interface */ public function addMethod($object, $methodName, $newMethodName = null) { if (!is_object($object)) { throw new InvalidObjectException('First parameter must be an object instance'); } if (!is_callable(array($object, $methodName))) { throw new InvalidMethodException('The named method must be callable on the supplied object'); } $methodInstance = new \ReflectionMethod($object, $methodName); $limb = $methodInstance->getClosure($object); $limbName = !is_null($newMethodName) ? $newMethodName : $methodName; $this->addToSkeleton($limbName, $limb); return $this; }
/** * Call a action of controller * * @access public * @param MVC $mvc MVC Application object * @param string $method Method or Function of the Class Controller * @param string $fileView String of the view file * @return array Response array * @throws \LogicException */ public final function call(MVC $mvc, $method, $fileView = null) { if (!method_exists($this, $method)) { throw new \LogicException(sprintf('Method "s" don\'t exists.', $method)); } # Replace the view object $this->view = $mvc->view(); # Arguments of method $arguments = array(); # Create a reflection method $reflectionMethod = new \ReflectionMethod(get_class($this), $method); $reflectionParams = $reflectionMethod->getParameters(); foreach ($reflectionParams as $param) { if ($paramClass = $param->getClass()) { $className = $paramClass->name; if ($className === 'MVC\\MVC' || $className === '\\MVC\\MVC') { $arguments[] = $mvc; } elseif ($className === 'MVC\\Server\\HttpRequest' || $className === '\\MVC\\Server\\HttpRequest') { $arguments[] = $mvc->request(); } } else { foreach ($mvc->request()->params as $keyReqParam => $valueReqParam) { if ($param->name === $keyReqParam) { $arguments[] = $valueReqParam; break; } } } } $response = call_user_func_array($reflectionMethod->getClosure($this), $arguments); if (empty($response)) { throw new \LogicException('Response null returned.'); } if (is_string($response)) { $this->response['body'] = $response; } elseif ($mvc->request()->isAjax()) { $this->response['body'] = $this->renderJson($response); } elseif (is_array($response)) { if (!$fileView) { throw new \LogicException('File view is null.'); } $class = explode("\\", get_called_class()); $classname = end($class); // Class without Controller $classname = str_replace('Controller', '', $classname); $file = $classname . "/{$fileView}"; $this->response['body'] = $this->renderHtml($file, $response); } return $this->response; }
public static function loadTable($name, $db_name = db_name) { if (isset(self::$tables[$db_name][$name])) { return self::$tables[$db_name][$name]; } $blackList = array("index", "foreign", "unique"); $sName = "\\database\\{$db_name}\\{$name}"; if (class_exists($sName)) { $table_load = new $sName(); foreach ($table_load as $key => $value) { if (!preg_grep("/^{$key}\$/", $blackList)) { $keys = array_keys($value); $values = array_values($value); $array = array(); foreach ($keys as $k => $v) { if (is_int($v)) { $keys[$k] = $values[$k]; $values[$k] = true; } } if (method_exists($table_load, $key)) { $options = new \lib\sql\options(); $func = new \ReflectionMethod($sName, $key); $Closure = $func->getClosure($table_load); $options->{$key} = \Closure::bind($Closure, $options); $options->table = $table_load; $options->tableName = $table_load; $options->fieldName = $key; $values[] = $options; $keys[] = 'closure'; } $array = array_combine($keys, $values); $table_load->{$key} = (object) $array; } } foreach ($table_load as $key => $value) { if (method_exists($table_load, $key)) { if (isset($table_load->{$key}->closure)) { $closure = $table_load->{$key}->closure; call_user_func($closure->{$key}); } } } self::$tables[$db_name][$name] = $table_load; return $table_load; } return null; }
public function testExpandClasses() { $r = new \ReflectionClass(AddClassesToCachePass::class); $pass = $r->newInstanceWithoutConstructor(); $r = new \ReflectionMethod(AddClassesToCachePass::class, 'expandClasses'); $expand = $r->getClosure($pass); $this->assertSame('Foo', $expand(array('Foo'), array())[0]); $this->assertSame('Foo', $expand(array('\\Foo'), array())[0]); $this->assertSame('Foo', $expand(array('Foo'), array('\\Foo'))[0]); $this->assertSame('Foo', $expand(array('Foo'), array('Foo'))[0]); $this->assertSame('Foo', $expand(array('\\Foo'), array('\\Foo\\Bar'))[0]); $this->assertSame('Foo', $expand(array('Foo'), array('\\Foo\\Bar'))[0]); $this->assertSame('Foo', $expand(array('\\Foo'), array('\\Foo\\Bar\\Acme'))[0]); $this->assertSame('Foo\\Bar', $expand(array('Foo\\'), array('\\Foo\\Bar'))[0]); $this->assertSame('Foo\\Bar\\Acme', $expand(array('Foo\\'), array('\\Foo\\Bar\\Acme'))[0]); $this->assertEmpty($expand(array('Foo\\'), array('\\Foo'))); $this->assertSame('Acme\\Foo\\Bar', $expand(array('**\\Foo\\'), array('\\Acme\\Foo\\Bar'))[0]); $this->assertEmpty($expand(array('**\\Foo\\'), array('\\Foo\\Bar'))); $this->assertEmpty($expand(array('**\\Foo\\'), array('\\Acme\\Foo'))); $this->assertEmpty($expand(array('**\\Foo\\'), array('\\Foo'))); $this->assertSame('Acme\\Foo', $expand(array('**\\Foo'), array('\\Acme\\Foo'))[0]); $this->assertEmpty($expand(array('**\\Foo'), array('\\Acme\\Foo\\AcmeBundle'))); $this->assertEmpty($expand(array('**\\Foo'), array('\\Acme\\FooBar\\AcmeBundle'))); $this->assertSame('Foo\\Acme\\Bar', $expand(array('Foo\\*\\Bar'), array('\\Foo\\Acme\\Bar'))[0]); $this->assertEmpty($expand(array('Foo\\*\\Bar'), array('\\Foo\\Acme\\Bundle\\Bar'))); $this->assertSame('Foo\\Acme\\Bar', $expand(array('Foo\\**\\Bar'), array('\\Foo\\Acme\\Bar'))[0]); $this->assertSame('Foo\\Acme\\Bundle\\Bar', $expand(array('Foo\\**\\Bar'), array('\\Foo\\Acme\\Bundle\\Bar'))[0]); $this->assertSame('Acme\\Bar', $expand(array('*\\Bar'), array('\\Acme\\Bar'))[0]); $this->assertEmpty($expand(array('*\\Bar'), array('\\Bar'))); $this->assertEmpty($expand(array('*\\Bar'), array('\\Foo\\Acme\\Bar'))); $this->assertSame('Foo\\Acme\\Bar', $expand(array('**\\Bar'), array('\\Foo\\Acme\\Bar'))[0]); $this->assertSame('Foo\\Acme\\Bundle\\Bar', $expand(array('**\\Bar'), array('\\Foo\\Acme\\Bundle\\Bar'))[0]); $this->assertEmpty($expand(array('**\\Bar'), array('\\Bar'))); $this->assertSame('Foo\\Bar', $expand(array('Foo\\*'), array('\\Foo\\Bar'))[0]); $this->assertEmpty($expand(array('Foo\\*'), array('\\Foo\\Acme\\Bar'))); $this->assertSame('Foo\\Bar', $expand(array('Foo\\**'), array('\\Foo\\Bar'))[0]); $this->assertSame('Foo\\Acme\\Bar', $expand(array('Foo\\**'), array('\\Foo\\Acme\\Bar'))[0]); $this->assertSame(array('Foo\\Bar'), $expand(array('Foo\\*'), array('Foo\\Bar', 'Foo\\BarTest'))); $this->assertSame(array('Foo\\Bar', 'Foo\\BarTest'), $expand(array('Foo\\*', 'Foo\\*Test'), array('Foo\\Bar', 'Foo\\BarTest'))); $this->assertSame('Acme\\FooBundle\\Controller\\DefaultController', $expand(array('**Bundle\\Controller\\'), array('\\Acme\\FooBundle\\Controller\\DefaultController'))[0]); $this->assertSame('FooBundle\\Controller\\DefaultController', $expand(array('**Bundle\\Controller\\'), array('\\FooBundle\\Controller\\DefaultController'))[0]); $this->assertSame('Acme\\FooBundle\\Controller\\Bar\\DefaultController', $expand(array('**Bundle\\Controller\\'), array('\\Acme\\FooBundle\\Controller\\Bar\\DefaultController'))[0]); $this->assertSame('Bundle\\Controller\\Bar\\DefaultController', $expand(array('**Bundle\\Controller\\'), array('\\Bundle\\Controller\\Bar\\DefaultController'))[0]); $this->assertSame('Acme\\Bundle\\Controller\\Bar\\DefaultController', $expand(array('**Bundle\\Controller\\'), array('\\Acme\\Bundle\\Controller\\Bar\\DefaultController'))[0]); $this->assertSame('Foo\\Bar', $expand(array('Foo\\Bar'), array())[0]); $this->assertSame('Foo\\Acme\\Bar', $expand(array('Foo\\**'), array('\\Foo\\Acme\\Bar'))[0]); }
/** * Add routes to an App from this class by inferring details from PHPDoc @url and @method properties * @param App $app */ public function load(App $app) { $class = get_called_class(); $methods = get_class_methods($class); foreach ($methods as $class_method) { $method_props = []; $rm = new \ReflectionMethod($this, $class_method); $phpdoc = preg_split('/\\r\\n|\\n|\\r/', preg_replace('%^\\s*/?\\*+((?<=\\*)/|[ \\t]*)%m', '', $rm->getDocComment())); foreach ($phpdoc as $docline) { if (preg_match('#^@(url|method)\\s+(\\S+)$#', $docline, $matches)) { $method_props[$matches[1]] = $matches[2]; } } if (isset($method_props['url'])) { $route = $app->route($class . '::' . $class_method, $method_props['url'], $rm->getClosure($this)); if (isset($method_props['method'])) { $route->via($method_props['method']); } } } }
/** * 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. * * @param object $object Object * * @return \Closure */ public function getClosure($object) { if (PHP_VERSION >= 50400) { return parent::getClosure(); } else { $that = $this; return function () use($object, $that) { return $that->invokeArgs($object, func_get_args()); }; } }
/** * @return Closure */ public function getClosure() { if ($this->closure instanceof \Closure) { return $this->closure; } $reflect = new \ReflectionMethod($this->closure); return $reflect->getClosure(); }
function yolisp($swag, array &$env = []) { static $OP_CACHE = []; // HAH! Take that Zend! if (!$swag instanceof cons) { // implicitly quote non-strings if (!is_string($swag)) { return $swag; } // lookup in environment if (array_key_exists($swag, $env)) { return $env[$swag]; } else { if (isset($OP_CACHE[$swag])) { return $OP_CACHE[$swag]; } else { if (array_key_exists($swag, DEFAULT_ENV)) { $callable = DEFAULT_ENV[$swag]; if (is_array($callable)) { return $OP_CACHE[$swag] = (new \ReflectionMethod(...$callable))->getClosure(); } else { if (is_string($callable)) { return $OP_CACHE[$swag] = (new \ReflectionFunction($callable))->getClosure(); } else { return $callable; } } } else { if (function_exists($swag)) { return $OP_CACHE[$swag] = (new \ReflectionFunction($swag))->getClosure(); // we do class lookup after function lookup because everyone knows functional programming is superior // what did you expect? this is yolisp, not yojava } else { if (class_exists($swag)) { return $swag; } else { if (array_key_exists($swag, OPS)) { $format = OPS[$swag]; $ops = substr_count($format, '$'); $ops += $optional_ops = substr_count($format, '?'); if ($ops === 0) { throw new \Exception("Invalid operator format string: \"{$format}\""); } $param_names = []; for ($i = 0; $i < $ops; $i++) { $param_names[] = '$op' . $i; } $param_list = ''; for ($i = 0; $i < $ops; $i++) { if ($i !== 0) { $param_list .= ', '; } $param_list .= $param_names[$i]; if ($i >= $ops - $optional_ops) { $param_list .= ' = NULL'; } } $parts = explode(' ', $format); if ($optional_ops) { $optionless_expr = ''; $i = 0; foreach ($parts as $part) { if ($part === '?') { $optionless_expr .= ' '; } else { if ($part === '$') { $optionless_expr .= ' ' . $param_names[$i]; $i++; } else { $optionless_expr .= ' ' . $part; } } } } $expr = ''; $i = 0; foreach ($parts as $part) { if ($part === '?' || $part === '$') { $expr .= ' ' . $param_names[$i]; $i++; } else { $expr .= ' ' . $part; } } if ($optional_ops) { $body = "if (func_num_args() < {$ops}) { return {$optionless_expr}; } else { return {$expr}; }"; } else { $body = "return {$expr};"; } // And people said eval() and create_function() were evil! return $OP_CACHE[$swag] = create_function($param_list, $body); } else { throw new \Exception("Could not find {$swag} in environment"); } } } } } } } $eval = function ($swag) use(&$env) { return yolisp($swag, $env); }; $command = cons::car($swag); $args = cons::cdr($swag); switch ($command) { case 'quote': return cons::car($args); case 'lambda': $arg_names = x(cons::car($args)); $body = cons::car(cons::cdr($args)); return function (...$args) use($arg_names, $body, &$env) { $new_env = $env; // copies rather than references foreach ($arg_names as $i => $arg_name) { $new_env[$arg_name] = $args[$i]; } return yolisp($body, $new_env); }; case 'let': $pairs = cons::car($args); $body = cons::car(cons::cdr($args)); $new_env = $env; // copies rather than references while (!is_null($pairs)) { $pair = cons::car($pairs); // (name value) 2-element list $new_env[cons::car($pair)] = yolisp(cons::car(cons::cdr($pair)), $new_env); $pairs = cons::cdr($pairs); } return yolisp($body, $new_env); case 'if': $expr = cons::car($args); $results = cons::cdr($args); $on_true = cons::car($results); $on_false = cons::car(cons::cdr($results)); if ($eval($expr)) { return $eval($on_true); } else { return $eval($on_false); } break; // -> and :: aren't normal ops as property name is implicitly quoted // -> and :: aren't normal ops as property name is implicitly quoted case '->': case '::': $obj = $eval(cons::car($args)); $prop = cons::car(cons::cdr($args)); if (property_exists($obj, $prop)) { if ($command === '->') { return $obj->{$prop}; } else { // this is really ugly syntax for a variable static property access // luckily yolo users don't need to deal with it return $obj::${$prop}; } // PHP has separate symbol tables for methods and properties // NOT IN YOLISP! } else { if (method_exists($obj, $prop)) { $method = new \ReflectionMethod($obj, $prop); if ($command === '->') { return $method->getClosure($obj); } else { return $method->getClosure(); } } else { throw new \Exception("No property/method {$command}{$prop} in {$obj}"); } } break; case 'new': $class = cons::car($args); $constructor_args = cons::cdr($args); $class_name = $eval($class); $evaluated_args = array_map($eval, x($constructor_args)); return new $class_name(...$evaluated_args); default: $func = $eval($command); $evaluated_args = array_map($eval, x($args)); return $func(...$evaluated_args); } }
public function getClosure($object = NULL) { return PHP_VERSION_ID < 50400 ? Nette\Utils\Callback::closure($object ?: parent::getDeclaringClass()->getName(), $this->getName()) : parent::getClosure($object); }
<?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===
/** * __get() implementation. * @param object * @param string property name * @return mixed property value * @throws MemberAccessException if the property is not defined. */ public static function &get($_this, $name) { $class = get_class($_this); $uname = ucfirst($name); $methods =& self::getMethods($class); if ($name === '') { throw new MemberAccessException("Cannot read a class '{$class}' property without name."); } elseif (isset($methods[$m = 'get' . $uname]) || isset($methods[$m = 'is' . $uname])) { // property getter if ($methods[$m] === 0) { $rm = new \ReflectionMethod($class, $m); $methods[$m] = $rm->returnsReference(); } if ($methods[$m] === TRUE) { return $_this->{$m}(); } else { $val = $_this->{$m}(); return $val; } } elseif (isset($methods[$name])) { // public method as closure getter if (PHP_VERSION_ID >= 50400) { $rm = new \ReflectionMethod($class, $name); $val = $rm->getClosure($_this); } else { $val = Nette\Utils\Callback::closure($_this, $name); } return $val; } else { // strict class $type = isset($methods['set' . $uname]) ? 'a write-only' : 'an undeclared'; throw new MemberAccessException("Cannot read {$type} property {$class}::\${$name}."); } }
/** * Возвращает замыкания на метод * @param $name имя метода, для которого надо получить замыкание * @return callable */ protected function getMethod($name) { $method = new \ReflectionMethod(get_class($this), $name); return $method->getClosure($this); }
function foo($a) { 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));
/** * {@inheritDoc} */ public function getClosure($object) { $this->initializeInternalReflection(); return parent::getClosure($object); }
<?php class MyClass { public function method() { } } $object = new MyClass(); $reflector = new \ReflectionMethod($object, 'method'); $closure = $reflector->getClosure($object); $closureReflector = new \ReflectionFunction($closure); var_dump($closureReflector->isClosure());
/** * 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(); }
/** * Invokes a method of an object/class, optionally on the context of another class. * * @param callable $ref A callable reference; either [className,methodName] or [classInstance,methodName]. * @param null $self [optional] The object on which context the call will be performed (this will set $this in * the method). * @param mixed ...$args Extra arguments to be prepended to `$fn` on each call. * @return mixed The method's return value. */ function call_method($ref, $self = null) { if (!is_array($ref) || count($ref) != 2) { throw new InvalidArgumentException("Argument must be an array with 2 elements"); } $args = array_slice(func_get_args(), 2); $m = new \ReflectionMethod($ref[0], $ref[1]); if ($m->isStatic()) { return call_user_func_array($ref, $args); } $f = $m->getClosure($ref[0]); if ($self) { $f = $f->bindTo($self, $self); } return call_user_func_array($f, $args); }
/** * Returns the method as a closure * * @return callable * @since 0.1.0 */ public function getClosure() { return parent::getClosure($this->instance); }
/** * Run the aplication * * @access public * @return void */ public function run(HttpRequest $request = null) { if (!$this->container->getSetting('debug')) { error_reporting(0); } else { error_reporting(E_ALL); } if (!$request) { $request = $this->container->getRequest(); } try { $parsed = $this->container->getRouter()->parse($request, $this->container->getRoutes()); if ($parsed['found'] || $this->container->hasRoute('notFound')) { if (is_string($parsed['action'])) { # Extract class controller and method list($controller, $method) = explode('::', $parsed['action']); # initialize arguments $arguments = array(); # Create a reflection method $reflectionMethod = new \ReflectionMethod($controller, $method); $reflectionParams = $reflectionMethod->getParameters(); # Create arguments foreach ($reflectionParams as $param) { if ($paramClass = $param->getClass()) { $className = $paramClass->name; if ($className === 'MVC\\MVC' || $className === '\\MVC\\MVC') { $arguments[] = $this; } elseif ($className === 'MVC\\Server\\HttpRequest' || $className === '\\MVC\\Server\\HttpRequest') { $arguments[] = $request; } } else { foreach ($parsed['params'] as $keyRouteParam => $valueRouteParam) { if ($param->name === $keyRouteParam) { $arguments[] = $valueRouteParam; break; } } } } $response = call_user_func_array($reflectionMethod->getClosure(new $controller()), $arguments); if (is_array($response) && !isset($response['body'])) { throw new \LogicException("Invalid response array. Array response haven't body. Expected array('body' => 'string')"); } elseif (is_string($response)) { $response = array('body' => $response); } } elseif (is_callable($parsed['action'])) { $this->container->getRequest()->params = $parsed['params']; $response = call_user_func_array($parsed['action'], array_values($parsed['params'])); } else { throw new \LogicException('Route haven\'t action.'); } if ($this->container->hasProvider('monolog')) { $this->container->providers['monolog']->addInfo($response, $parsed); } $this->container->getResponse()->render($response); } else { if ($this->container->getSetting('debug')) { throw new \LogicException(sprintf('Route or Resource "%s" not found.', $request->url)); } $this->defaultNotFound(); } } catch (\Exception $e) { Error::run($e); } }