/** * handle the http user request * * @param \Alchemy\Application $app * @param \Alchemy\Component\Http\Request $request user http request * @return \Alchemy\Component\Http\JsonResponse|\Alchemy\Component\Http\Response */ public function handle(Request $request, Application $app = null) { $this->request = $request; try { // init services providers /** @var \Alchemy\Service\ServiceProviderInterface $providers */ $providers = $app->getServiceProviders(); foreach ($providers as $provider) { $provider->init($app); } /* * "EVENT" KernelEvents::REQUEST using GetResponse Event * * This event can be used by an application to filter a request before * ever all kernel logic being executed, listeners for this event should * be registered outside framework logic (should be on application logic). */ if ($this->dispatcher->hasListeners(KernelEvents::REQUEST)) { $event = new GetResponseEvent($this, $request, $app); $this->dispatcher->dispatch(KernelEvents::REQUEST, $event); if ($event->hasResponse()) { //var_dump($event->getResponse()); die("ee"); $event = new FilterResponseEvent($this, $request, $event->getResponse()); $this->dispatcher->dispatch(KernelEvents::RESPONSE, $event); return $event->getResponse(); } } /* * try match the url request with a defined route. * it any route match the current url a ResourceNotFoundException * will be thrown. */ $params = $this->mapper->match($request); $uriParams = $params["params"]; // prepare request params. $params = $this->prepareRequestParams(array($params["mapped"], $request->query->all(), $request->request->all())); // add prepared params to request as attributes. $request->attributes->add($params); // resolve controller try { $controller = $this->resolver->getController($request); } catch (\Exception $exception) { /* * Detailed exception types are only for development environments * if the current is a non dev environment just overrides the current exception with * a ResourceNotFoundException exception */ if ($this->config->get('env.type') !== 'dev') { $exception = new ResourceNotFoundException($request->getPathInfo()); } throw $exception; } if (!$controller) { throw new ResourceNotFoundException($request->getPathInfo()); } // setting default annotations namespace $this->annotationReader->setDefaultNamespace('\\Alchemy\\Annotation\\'); // seeting annotation reader target $this->annotationReader->setTarget($params['_controllerClass'], $params['_controllerMethod']); $arguments = $this->resolver->getArguments($app, $request, $controller); //"EVENT" FILTER_CONTROLLER if ($this->dispatcher->hasListeners(KernelEvents::FILTER_CONTROLLER)) { $event = new FilterControllerEvent($this, $controller, $request); $this->dispatcher->dispatch(KernelEvents::FILTER_CONTROLLER, $event); // getting controller; this can be the same or other filtered controller $controller = $event->getController(); } //"EVENT" BEFORE_CONTROLLER if ($this->dispatcher->hasListeners(KernelEvents::BEFORE_CONTROLLER)) { $event = new ControllerEvent($this, $controller, $arguments, $request); $this->dispatcher->dispatch(KernelEvents::BEFORE_CONTROLLER, $event); } // Execute controller action $response = call_user_func_array($controller, $arguments); // check returned value by method is a array if (is_array($response)) { // set controller view data object foreach ($response as $key => $value) { $controller[0]->view->{$key} = $value; } } // getting controller's data. $controllerData = (array) $controller[0]->view; if (!($response instanceof Response || $response instanceof JsonResponse)) { if ($this->annotationReader->getAnnotation('JsonResponse')) { $controllerData = $response; $response = new JsonResponse(); $response->setData($controllerData); } else { $response = new Response(); } } //"EVENT" AFTER_CONTROLLER if ($this->dispatcher->hasListeners(KernelEvents::AFTER_CONTROLLER)) { if (!isset($event) || !$event instanceof ControllerEvent) { $event = new ControllerEvent($this, $controller, $arguments, $request); } $event->setResponse($response); $this->dispatcher->dispatch(KernelEvents::AFTER_CONTROLLER, $event); } // handling view $view = $this->handleView($params['_controllerClass'], $params['_controllerMethod'], $controllerData, $this->annotationReader->getAnnotation('View')); // handling meta ui if ($this->annotationReader->getAnnotation('ServeUi')) { $view = $this->handleMetaUi($controllerData, $this->annotationReader->getAnnotation('ServeUi'), $view, $request); } // if there is a view adapter instance, get its contents and set to response content if (!empty($view)) { foreach ($uriParams as $keyParam => $valParam) { $view->assign($keyParam, $valParam); } //"EVENT" VIEW dispatch all KernelEvents::VIEW events if ($this->dispatcher->hasListeners(KernelEvents::VIEW)) { $event = new ViewEvent($this, $view, $request, $this->annotationReader, $app); $this->dispatcher->dispatch(KernelEvents::VIEW, $event); $view = $event->getView(); } $response->setContent($view->getOutput()); } } catch (ResourceNotFoundException $e) { $exceptionHandler = new Exception\Handler(); if ($request->isXmlHttpRequest()) { $response = new JsonResponse(); $response->setData(array('success' => false, 'message' => $e->getMessage())); } else { $response = new Response($exceptionHandler->getOutput($e), 404); } } catch (\Exception $e) { // echo $e->getMessage(); // echo "<br><pre>"; // echo $e->getTraceAsString(); // die; $exceptionHandler = new Exception\Handler(); if ($request->isXmlHttpRequest()) { $response = new JsonResponse(); $response->setData(array('success' => false, 'message' => $e->getMessage())); } else { $response = new Response($exceptionHandler->getOutput($e), 500); } } if ($this->annotationReader->hasTarget()) { $responseAnnotation = $this->annotationReader->getAnnotation('Response'); } else { $responseAnnotation = null; } // dispatch a response event $this->dispatcher->dispatch(KernelEvents::RESPONSE, new FilterResponseEvent($this, $request, $response, $responseAnnotation)); return $response; }
/** * Test routes */ public function testMapping2() { $mapper = new Mapper(new \Alchemy\Component\Yaml\Yaml()); $mapper->loadFrom(self::$rootDir . "/Tests/fixtures/routes3.yaml"); $result = $mapper->match('/user_role/assign'); $expected = array("params" => array('_controller' => 'user_role', '_action' => 'assign'), "mapped" => array("_controller" => 'Sandbox\\Controller\\UserRoleController', "_action" => 'assignAction')); $this->assertEquals($expected, $result); $result = $mapper->match('/tool/leap_year/1998'); $expected = array("_controller" => 'SomeOther\\Module\\UserTools', "_action" => 'leapYear', "year" => 1998); $this->assertEquals($expected, $result); // $result = $mapper->match('/admin/setup/group/profile'); // $expected = array( // "_controller" => 'Sandbox\Utils\groupTest', // "_action" => 'do_update_profile', // "year" => 1998 // ); // $this->assertEquals($expected, $result); }
protected function loadMapperFromYaml($app, $file) { $mapper = new Mapper(); $routesList = $app['yaml']->load($file); foreach ($routesList as $rname => $rconf) { $defaults = isset($rconf['defaults']) ? $rconf['defaults'] : array(); $requirements = isset($rconf['requirements']) ? $rconf['requirements'] : array(); $type = isset($rconf['type']) ? $rconf['type'] : ''; $resourcePath = isset($rconf['resourcePath']) ? $rconf['resourcePath'] : ''; if (!array_key_exists('pattern', $rconf)) { throw new \InvalidArgumentException(sprintf('Runtime Error: Route pattern for "%s" route is missing.', $rname)); } $mapper->connect($rname, new Route($rconf['pattern'], $defaults, $requirements, $type, $resourcePath)); } return $mapper; }