/** * Resolve the dispatch call. * * @param array $rule Rule. * @param \Hoa\Router $router Router. * @param \Hoa\View\Viewable $view View. * @return mixed * @throws \Hoa\Dispatcher\Exception */ protected function resolve(array $rule, Router $router, View\Viewable $view = null) { $called = null; $variables =& $rule[Router::RULE_VARIABLES]; $call = isset($variables['_call']) ? $variables['_call'] : $rule[Router::RULE_CALL]; $able = isset($variables['_able']) ? $variables['_able'] : $rule[Router::RULE_ABLE]; $rtv = [$router, $this, $view]; $arguments = []; $reflection = null; $async = $router->isAsynchronous(); $class = $call; $method = $able; if (false === $async) { $_class = 'synchronous.call'; $_method = 'synchronous.able'; } else { $_class = 'asynchronous.call'; $_method = 'asynchronous.able'; } $this->_parameters->setKeyword('call', $class); $this->_parameters->setKeyword('able', $method); $class = $this->_parameters->getFormattedParameter($_class); $method = $this->_parameters->getFormattedParameter($_method); try { $class = dnew($class, $rtv); } catch (\Exception $e) { throw new Exception('Class %s is not found ' . '(method: %s, asynchronous: %s).', 0, [$class, strtoupper($variables['_method']), true === $async ? 'true' : 'false'], $e); } $kitname = $this->getKitName(); if (!empty($kitname) && !isset($variables['_this']) || !(isset($variables['_this']) && $variables['_this'] instanceof $kitname)) { $variables['_this'] = dnew($kitname, $rtv); $variables['_this']->construct(); } if (!method_exists($class, $method)) { throw new Exception('Method %s does not exist on the class %s ' . '(method: %s, asynchronous: %s).', 1, [$method, get_class($class), strtoupper($variables['_method']), true === $async ? 'true' : 'false']); } $called = $class; $reflection = new \ReflectionMethod($class, $method); foreach ($reflection->getParameters() as $parameter) { $name = strtolower($parameter->getName()); if (true === array_key_exists($name, $variables)) { $arguments[$name] = $variables[$name]; continue; } if (false === $parameter->isOptional()) { throw new Exception('The method %s on the class %s needs a value for ' . 'the parameter $%s and this value does not exist.', 2, [$method, get_class($class), $name]); } } return $reflection->invokeArgs($called, $arguments); }
/** * Resolve the dispatch call. * * @param array $rule Rule. * @param \Hoa\Router $router Router. * @param \Hoa\View\Viewable $view View. * @return mixed * @throws \Hoa\Dispatcher\Exception */ protected function resolve(array $rule, Router $router, View\Viewable $view = null) { $called = null; $variables =& $rule[Router::RULE_VARIABLES]; $call = isset($variables['controller']) ? $variables['controller'] : (isset($variables['_call']) ? $variables['_call'] : $rule[Router::RULE_CALL]); $able = isset($variables['action']) ? $variables['action'] : (isset($variables['_able']) ? $variables['_able'] : $rule[Router::RULE_ABLE]); $rtv = [$router, $this, $view]; $arguments = []; $reflection = null; if ($call instanceof \Closure) { $kitname = $this->getKitName(); if (!empty($kitname)) { $kit = dnew($this->getKitName(), $rtv); if (!$kit instanceof Kit) { throw new Exception('Your kit %s must extend Hoa\\Dispatcher\\Kit.', 0, $kitname); } $variables['_this'] = $kit; } $called = $call; $reflection = new \ReflectionMethod($call, '__invoke'); foreach ($reflection->getParameters() as $parameter) { $name = strtolower($parameter->getName()); if (true === array_key_exists($name, $variables)) { $arguments[$name] = $variables[$name]; continue; } if (false === $parameter->isOptional()) { throw new Exception('The closured action for the rule with pattern %s needs ' . 'a value for the parameter $%s and this value does not ' . 'exist.', 1, [$rule[Router::RULE_PATTERN], $name]); } } } elseif (is_string($call) && null === $able) { $kitname = $this->getKitName(); if (!empty($kitname)) { $kit = dnew($this->getKitName(), $rtv); if (!$kit instanceof Kit) { throw new Exception('Your kit %s must extend Hoa\\Dispatcher\\Kit.', 2, $kitname); } $variables['_this'] = $kit; } $reflection = new \ReflectionFunction($call); foreach ($reflection->getParameters() as $parameter) { $name = strtolower($parameter->getName()); if (true === array_key_exists($name, $variables)) { $arguments[$name] = $variables[$name]; continue; } if (false === $parameter->isOptional()) { throw new Exception('The functional action for the rule with pattern %s needs ' . 'a value for the parameter $%s and this value does not ' . 'exist.', 3, [$rule[Router::RULE_PATTERN], $name]); } } } else { $async = $router->isAsynchronous(); $controller = $call; $action = $able; if (!is_object($call)) { if (false === $async) { $_controller = 'synchronous.call'; $_action = 'synchronous.able'; } else { $_controller = 'asynchronous.call'; $_action = 'asynchronous.able'; } $this->_parameters->setKeyword('call', $controller); $this->_parameters->setKeyword('able', $action); $controller = $this->_parameters->getFormattedParameter($_controller); $action = $this->_parameters->getFormattedParameter($_action); try { $controller = dnew($controller, $rtv); } catch (\Exception $e) { throw new Exception('Controller %s is not found ' . '(method: %s, asynchronous: %s).', 4, [$controller, strtoupper($router->getMethod()), true === $async ? 'true' : 'false'], $e); } $kitname = $this->getKitName(); if (!empty($kitname)) { $variables['_this'] = dnew($kitname, $rtv); } if (method_exists($controller, 'construct')) { $controller->construct(); } } if (!method_exists($controller, $action)) { throw new Exception('Action %s does not exist on the controller %s ' . '(method: %s, asynchronous: %s).', 5, [$action, get_class($controller), strtoupper($router->getMethod()), true === $async ? 'true' : 'false']); } $called = $controller; $reflection = new \ReflectionMethod($controller, $action); foreach ($reflection->getParameters() as $parameter) { $name = strtolower($parameter->getName()); if (true === array_key_exists($name, $variables)) { $arguments[$name] = $variables[$name]; continue; } if (false === $parameter->isOptional()) { throw new Exception('The action %s on the controller %s needs a value for ' . 'the parameter $%s and this value does not exist.', 6, [$action, get_class($controller), $name]); } } } if ($reflection instanceof \ReflectionFunction) { $return = $reflection->invokeArgs($arguments); } elseif ($reflection instanceof \ReflectionMethod) { $return = $reflection->invokeArgs($called, $arguments); } return $return; }
protected function route(Router $router, $uri, array $extraVariables = []) { $router->route($uri); $theRule =& $router->getTheRule(); $theRule[$router::RULE_VARIABLES]['test'] = $this; foreach ($extraVariables as $name => $value) { $theRule[$router::RULE_VARIABLES][$name] = $value; } return $router; }
/** * Dispatch a router rule. * * @param \Hoa\Router $router Router. * @param \Hoa\View\Viewable $view View. * @return mixed * @throws \Hoa\Controller\Exception */ public function dispatch(Router $router, View\Viewable $view = null) { $rule = $router->getTheRule(); if (null === $rule) { $router->route(); $rule = $router->getTheRule(); } if (null === $view) { $view = $this->_currentView; } else { $this->_currentView = $view; } $parameters = $this->_parameters; $this->_parameters = clone $this->_parameters; foreach ($rule[Router::RULE_VARIABLES] as $key => $value) { $this->_parameters->setParameter('variables.' . $key, $value); } $out = $this->resolve($rule, $router, $view); unset($this->_parameters); $this->_parameters = $parameters; return $out; }