public function call($group, $hook, $parameters = null, $action = null) { if (!isset($action)) { $action = 'execute'; } if (!isset($this->hooks[$this->site][$group][$hook][$action])) { $this->register($group, $hook, $action); } $calls = []; if (isset($this->hooks[$this->site][$group][$hook][$action])) { $calls = $this->hooks[$this->site][$group][$hook][$action]; } if (isset($this->watches[$this->site][$group][$hook][$action])) { $calls = array_merge($calls, $this->watches[$this->site][$group][$hook][$action]); } $result = []; foreach ($calls as $code) { $bait = null; if (is_string($code)) { $class = Apps::getModuleClass($code, 'Hooks'); $obj = new $class(); $bait = $obj->{$action}($parameters); } else { $ref = new \ReflectionFunction($code); if ($ref->isClosure()) { $bait = $code($parameters); } } if (!empty($bait)) { $result[] = $bait; } } return $result; }
/** * @return self */ public static function from($from) : self { if (is_string($from) && strpos($from, '::')) { $from = new \ReflectionMethod($from); } elseif (is_array($from)) { $from = new \ReflectionMethod($from[0], $from[1]); } elseif (!$from instanceof \ReflectionFunctionAbstract) { $from = new \ReflectionFunction($from); } $method = new static(); $method->name = $from->isClosure() ? NULL : $from->getName(); foreach ($from->getParameters() as $param) { $method->parameters[$param->getName()] = Parameter::from($param); } if ($from instanceof \ReflectionMethod) { $method->static = $from->isStatic(); $method->visibility = $from->isPrivate() ? 'private' : ($from->isProtected() ? 'protected' : NULL); $method->final = $from->isFinal(); $method->abstract = $from->isAbstract() && !$from->getDeclaringClass()->isInterface(); $method->body = $from->isAbstract() ? FALSE : ''; } $method->returnReference = $from->returnsReference(); $method->variadic = PHP_VERSION_ID >= 50600 && $from->isVariadic(); $method->comment = $from->getDocComment() ? preg_replace('#^\\s*\\* ?#m', '', trim($from->getDocComment(), "/* \r\n\t")) : NULL; if (PHP_VERSION_ID >= 70000 && $from->hasReturnType()) { $returnType = $from->getReturnType(); $method->returnType = $returnType->isBuiltin() ? (string) $returnType : '\\' . $returnType; } return $method; }
/** * @param \ReflectionFunction $reflection * * @throws \InvalidArgumentException */ public function __construct(\ReflectionFunction $reflection) { if (!$reflection->isClosure()) { throw new \InvalidArgumentException('You must provide the reflection of a closure.'); } $this->reflection = $reflection; }
protected function invokeClosure($targetValue) { if (is_callable($this->condition)) { $reflection = new \ReflectionFunction($this->condition); if (!$reflection->isClosure()) { throw new Exceptions\NotCallable("Specified condition is not closure, can't proceed"); } return $reflection->invokeArgs(array($targetValue)); } return false; }
private function checkIfIsClosureOrCode($function) { if (is_string($function)) { return; } if (!is_callable($function) || !is_object($function)) { throw new RegisteringInvalidClosureException(); } $rf = new \ReflectionFunction($function); if (!$rf->isClosure()) { throw new RegisteringInvalidClosureException(); } }
/** * @param array|\Closure $function * @param string $column * * @return $this|bool * @throws \BadFunctionCallException * @throws \InvalidArgumentException * @throws \LengthException */ public function addHook($function, $column) { //check for closure if (false === is_array($function)) { $functionReflected = new \ReflectionFunction($function); if ($functionReflected->isClosure()) { $this->hooks[$column] = $function; return true; } } else { if (2 !== count($function)) { throw new \LengthException('Exactly two parameters required!'); } if (false === is_callable($function)) { throw new \BadFunctionCallException(sprintf('Function %s in class %s is non callable!', $function[1], $function[0])); } $this->hooks[$column] = [$function[0], $function[1]]; } return $this; }
<?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());
/** * Renders the footer row. * * @param string $html The string to which it footer should be appended. * This should of course be the already (almost finished) table. * * @return string The $html argument with the table appended. */ protected function renderFooter($html) { $hasFooter = false; $footer = '<tr>'; $emptyCount = 1; foreach ($this->columns as $column) { // Do only something if we have a footer. if (isset($column['footerData'])) { $hasFooter = true; // Render the empty cells before. if ($emptyCount > 0) { $footer .= '<td colspan="' . $emptyCount . '"></td>'; $emptyCount = 0; } $dataContainer = $column['footerData']; if (is_string($dataContainer)) { // Just show the static string $footer .= '<td>' . $dataContainer . "</td>"; } else { $rf = new \ReflectionFunction($dataContainer); if ($rf->isClosure()) { // Call the closure and get the result $value = $dataContainer($this->getData(), $this); $footer .= "<td>" . $value . "</td>"; } } } else { // Let's remember how many empty cell there was. $emptyCount++; } } // Render empty cells (if we have) if ($emptyCount > 0) { $footer .= '<td colspan="' . $emptyCount . '"></td>'; } $footer .= "</tr>"; if ($hasFooter) { $html .= $footer; } return $html; }
public function parseUrl(Url $url = null) { if ($url) { $this->url = $url; // override existing } if (!$this->url instanceof Url) { throw new ConfigException('No Url instance supplied for parser.'); } $pathComponents = $this->url->pathComponents; // Iterate through each and convert to class or method name foreach ($pathComponents as &$pathComponent) { $pathComponent = str_replace('-', '_', ucfirst($pathComponent)); } $projectControllers = $this->project->ns . '\\Controllers\\'; // Attempt 1: Look for Routes class in project and call routeResolver method $method = self::ROUTE_RESOLVER; $controller = $this->project->ns . '\\Routes'; if (method_exists($controller, $method)) { // Call the project routeResolver method $route = call_user_func(array(new $controller($this->project), $method), $this->url); // If we get a class name back, look for another routeResolver method within if (is_string($route) && strpos($route, '::') === false && class_exists($projectControllers . $route) && method_exists($projectControllers . $route, $method)) { $savedRoute = $route; $routeController = $projectControllers . $route; $controllerClass = new $routeController($this->project); // Call routeResolver in the controller class $route = call_user_func(array($controllerClass, $method), $this->url); // If I get a partial string result, assume it's a method response, otherwise prepare for fallback if (is_string($route) && strpos($route, '::') === false && is_callable(array($controllerClass, $route))) { return $this->invokeClassMethod($controllerClass, $route); } else { $pathComponents[0] = $savedRoute; } } // If we get a string back in format $controller::$method, look for the method // If the return class method starts with "\" char, look outside the project controller tree if (is_string($route) && strpos($route, '::') !== false) { list($controller, $method) = explode('::', ($route[0] != '\\' ? $projectControllers : '') . $route); if (class_exists($controller) && is_callable($controller . '::' . $method, true)) { return $this->invokeClassMethod(new $controller($this->project), $method); } } // Otherwise, if we get a closure back, call it if (is_callable($route)) { if (is_array($route) && count($route) == 2) { return $this->invokeClassMethod($route[0], $route[1]); } else { $reflection = new \ReflectionFunction($route); if ($reflection->isClosure()) { return $this->invokeFunction($route); } } } } // Attempt 2: pointing to a controller with a routeResolver method $path = $pathComponents; $method = self::ROUTE_RESOLVER; $controller = $projectControllers . (empty($path) ? 'Index' : $path[0]); $controllerClass = class_exists($controller) ? new $controller($this->project) : null; if ($controllerClass && method_exists($controllerClass, $method)) { // Call routeResolver in the controller class $route = call_user_func(array($controllerClass, $method), $this->url); // If we get a string back in format $controller::$method, look for the method // If the return class method starts with "\" char, look outside the project controller tree if (is_string($route) && strpos($route, '::') !== false) { list($controller, $method) = explode('::', ($route[0] != '\\' ? $projectControllers : '') . $route); if (class_exists($controller) && is_callable($controller . '::' . $method, true)) { return $this->invokeClassMethod(new $controller($this->project), $method); } } // If we get a partial string result, assume it's a method response if (is_string($route) && strpos($route, '::') === false && is_callable(array($controllerClass, $route))) { return $this->invokeClassMethod($controllerClass, $route); } // Otherwise, if we get a closure back, call it if (is_callable($route)) { if (is_array($route) && count($route) == 2) { return $this->invokeClassMethod($route[0], $route[1]); } else { $reflection = new \ReflectionFunction($route); if ($reflection->isClosure()) { return $this->invokeFunction($route); } } } } // Attempt 3: pointing to a specific route* method within the controller if (count($pathComponents) > 1) { $path = $pathComponents; $controllerClass = array_shift($path); $methodName = array_shift($path); $method = $methodName != null ? 'route' . $methodName : self::ROUTE_DEFAULT; $controller = $this->findController($controllerClass); if ($controller) { $methodFound = $this->findMethod($controller, $method); if ($methodFound) { return $methodFound; } } } // Attempt 4: check for a controller with routeDefault method if (count($pathComponents) == 1) { $path = $pathComponents; $lookupName = array_shift($path); $method = self::ROUTE_DEFAULT; $controller = $this->findController($lookupName); if ($controller) { $methodFound = $this->findMethod($controller, $method); if ($methodFound) { return $methodFound; } } } // Attempt 5: look for a method in the Index controller $path = $pathComponents; $lookupName = array_shift($path); $method = $lookupName ? 'route' . $lookupName : self::ROUTE_DEFAULT; $controller = $this->findController('Index'); if ($controller) { $methodFound = $this->findMethod($controller, $method); if ($methodFound) { return $methodFound; } } // Can't determine route, so start fallback steps return $this->routeNotFound(); }
/** * @param $function * @param $column * @return $this|bool * @throws \BadFunctionCallException * @throws \InvalidArgumentException * @throws \LengthException */ public function addHook($function, $column) { //check for closure if (false === is_array($function)) { $f = new \ReflectionFunction($function); if ($f->isClosure()) { $this->hooks[$column] = $function; return true; } } else { if (2 !== count($function)) { throw new \LengthException('Exactly two parameters required!'); } if (!in_array($column, $this->columns)) { throw new \InvalidArgumentException(sprintf("Parameter column must be someone defined in setColumns function!\nRecived: %s\n Expected one of: %s", $function[1], implode(', ', $this->columns))); } if (!is_callable($function)) { throw new \BadFunctionCallException(sprintf('Function %s in class %s non exist!', $function[1], $function[0])); } $this->hooks[$column] = array($function[0], $function[1]); } return $this; }
public function validate($validationClosure) { try { $reflection = new \ReflectionFunction($validationClosure); } catch (\Exception $e) { throw new \Exception('Validate not called with Closure'); } if (!$reflection->isClosure()) { throw new \Exception('Validate not called with Closure'); } $this->validationClosure = $validationClosure; if (!$this->sessionCheck()) { throw new \Exception('NOT_LOGGED_IN'); } }
<?php $closure = function ($param) { return "this is a closure"; }; $rc = new ReflectionFunction($closure); var_dump($rc->isClosure());
protected function isClosure($value) { if (!is_callable($value)) { return false; } $reflection = new \ReflectionFunction($value); return (bool) $reflection->isClosure(); }
<?php function not_a_closure() { return 1; } $rf = new ReflectionFunction('not_a_closure'); var_dump($rf->isClosure()); var_dump($rf->isGenerator()); function is_a_generator() { (yield 1); (yield 2); } $rf = new ReflectionFunction('is_a_generator'); var_dump($rf->isClosure()); var_dump($rf->isGenerator()); $cl = function () { return 1; }; $rf = new ReflectionFunction($cl); var_dump($rf->isClosure()); var_dump($rf->isGenerator()); $cl = function () { (yield 1); (yield 2); }; $rf = new ReflectionFunction($cl); var_dump($rf->isClosure()); var_dump($rf->isGenerator());