/** * @param Request $request */ public function match(Request $request) { // Initialize the context that is also used by the generator (assuming matcher and generator share the same // context instance). $this->context->fromRequest($request); if ($request->attributes->has('_controller')) { // Routing is already done. return; } // Add attributes based on the request (routing). try { // Matching a request is more powerful than matching a URL path + context, so try that first. if ($this->matcher instanceof RequestMatcherInterface) { $parameters = $this->matcher->matchRequest($request); } else { $parameters = $this->matcher->match($request->getPathInfo()); } if (null !== $this->logger) { $this->logger->info(sprintf('Matched route "%s" (parameters: %s)', $parameters['_route'], $this->parametersToString($parameters))); } $request->attributes->add($parameters); unset($parameters['_route']); unset($parameters['_controller']); $request->attributes->set('_route_params', $parameters); } catch (ResourceNotFoundException $e) { $message = sprintf('No route found for "%s %s"', $request->getMethod(), $request->getPathInfo()); throw new NotFoundHttpException($message, $e); } catch (MethodNotAllowedException $e) { $message = sprintf('No route found for "%s %s": Method Not Allowed (Allow: %s)', $request->getMethod(), $request->getPathInfo(), strtoupper(implode(', ', $e->getAllowedMethods()))); throw new MethodNotAllowedException($e->getAllowedMethods(), $message); } }
/** * Constructor. * * RequestStack will become required in 3.0. * * @param UrlMatcherInterface|RequestMatcherInterface $matcher The Url or Request matcher * @param RequestStack $requestStack A RequestStack instance * @param RequestContext|null $context The RequestContext (can be null when $matcher implements RequestContextAwareInterface) * @param LoggerInterface|null $logger The logger * * @throws \InvalidArgumentException */ public function __construct($matcher, $requestStack = null, $context = null, $logger = null) { if ($requestStack instanceof RequestContext || $context instanceof LoggerInterface || $logger instanceof RequestStack) { $tmp = $requestStack; $requestStack = $logger; $logger = $context; $context = $tmp; @trigger_error('The ' . __METHOD__ . ' method now requires a RequestStack to be given as second argument as ' . __CLASS__ . '::setRequest method will not be supported anymore in 3.0.', E_USER_DEPRECATED); } elseif (!$requestStack instanceof RequestStack) { @trigger_error('The ' . __METHOD__ . ' method now requires a RequestStack instance as ' . __CLASS__ . '::setRequest method will not be supported anymore in 3.0.', E_USER_DEPRECATED); } if (null !== $requestStack && !$requestStack instanceof RequestStack) { throw new \InvalidArgumentException('RequestStack instance expected.'); } if (null !== $context && !$context instanceof RequestContext) { throw new \InvalidArgumentException('RequestContext instance expected.'); } if (null !== $logger && !$logger instanceof LoggerInterface) { throw new \InvalidArgumentException('Logger must implement LoggerInterface.'); } if (!$matcher instanceof UrlMatcherInterface && !$matcher instanceof RequestMatcherInterface) { throw new \InvalidArgumentException('Matcher must either implement UrlMatcherInterface or RequestMatcherInterface.'); } if (null === $context && !$matcher instanceof RequestContextAwareInterface) { throw new \InvalidArgumentException('You must either pass a RequestContext or the matcher must implement RequestContextAwareInterface.'); } $this->matcher = $matcher; $this->context = $context ?: $matcher->getContext(); $this->requestStack = $requestStack; $this->logger = $logger; }
public function __construct(Profiler $profiler = null, \Twig_Environment $twig, UrlMatcherInterface $matcher = null, RouteCollection $routes = null) { $this->profiler = $profiler; $this->twig = $twig; $this->matcher = $matcher; $this->routes = null === $routes && $matcher instanceof RouterInterface ? $matcher->getRouteCollection() : $routes; }
/** * {@inheritdoc} * @throws \UnexpectedValueException If a controller is not \Ratchet\Http\HttpServerInterface */ public function onOpen(ConnectionInterface $conn, RequestInterface $request = null) { if (null === $request) { throw new \UnexpectedValueException('$request can not be null'); } $context = $this->_matcher->getContext(); $context->setMethod($request->getMethod()); $context->setHost($request->getHost()); try { $route = $this->_matcher->match($request->getPath()); } catch (MethodNotAllowedException $nae) { return $this->close($conn, 403); } catch (ResourceNotFoundException $nfe) { return $this->close($conn, 404); } if (is_string($route['_controller']) && class_exists($route['_controller'])) { $route['_controller'] = new $route['_controller'](); } if (!$route['_controller'] instanceof HttpServerInterface) { throw new \UnexpectedValueException('All routes must implement Ratchet\\Http\\HttpServerInterface'); } $parameters = array(); foreach ($route as $key => $value) { if (is_string($key) && '_' !== substr($key, 0, 1)) { $parameters[$key] = $value; } } $url = Url::factory($request->getPath()); $url->setQuery($parameters); $request->setUrl($url); $conn->controller = $route['_controller']; $conn->controller->onOpen($conn, $request); }
function it_throws_an_exception_if_neither_create_nor_update_key_word_has_been_found(Session $session, SymfonyPageInterface $createPage, SymfonyPageInterface $updatePage, UrlMatcherInterface $urlMatcher) { $session->getCurrentUrl()->willReturn('https://sylius.com/resource/show'); $urlMatcher->match('/resource/show')->willReturn(['_route' => 'sylius_resource_show']); $createPage->getRouteName()->willReturn('sylius_resource_create'); $updatePage->getRouteName()->willReturn('sylius_resource_update'); $this->shouldThrow(\LogicException::class)->during('getCurrentPageWithForm', [[$createPage, $updatePage]]); }
/** * {@inheritdoc} * * @throws \LogicException */ public function getCurrentPageWithForm(array $pages) { $routeParameters = $this->urlMatcher->match(parse_url($this->session->getCurrentUrl(), PHP_URL_PATH)); Assert::allIsInstanceOf($pages, SymfonyPageInterface::class); foreach ($pages as $page) { if ($routeParameters['_route'] === $page->getRouteName()) { return $page; } } throw new \LogicException('Route name could not be matched to provided pages.'); }
/** * {@inheritdoc} * * @throws \LogicException */ public function getCurrentPageWithForm(CreatePageInterface $createPage, UpdatePageInterface $updatePage) { $routeParameters = $this->urlMatcher->match($this->session->getCurrentUrl()); if (false !== strpos($routeParameters['_route'], 'create')) { return $createPage; } if (false !== strpos($routeParameters['_route'], 'update')) { return $updatePage; } throw new \LogicException('Route name does not have any of "update" or "create" keyword, so matcher was unable to match proper page.'); }
/** * Constructor. * * @param UrlMatcherInterface|RequestMatcherInterface $matcher The Url or Request matcher * @param RequestContext|null $context The RequestContext (can be null when $matcher implements RequestContextAwareInterface) * @param LoggerInterface|null $logger The logger * * @throws \InvalidArgumentException */ public function __construct($matcher, RequestContext $context = null, LoggerInterface $logger = null) { if (!$matcher instanceof UrlMatcherInterface && !$matcher instanceof RequestMatcherInterface) { throw new \InvalidArgumentException('Matcher must either implement UrlMatcherInterface or RequestMatcherInterface.'); } if (null === $context && !$matcher instanceof RequestContextAwareInterface) { throw new \InvalidArgumentException('You must either pass a RequestContext or the matcher must implement RequestContextAwareInterface.'); } $this->matcher = $matcher; $this->context = $context ?: $matcher->getContext(); $this->logger = $logger; }
/** * {@inheritdoc} */ protected function setUp() { $this->configFactory = $this->getConfigFactoryStub(['system.site' => ['page.403' => '/access-denied-page', 'page.404' => '/not-found-page']]); $this->kernel = $this->getMock('Symfony\\Component\\HttpKernel\\HttpKernelInterface'); $this->logger = $this->getMock('Psr\\Log\\LoggerInterface'); $this->redirectDestination = $this->getMock('\\Drupal\\Core\\Routing\\RedirectDestinationInterface'); $this->redirectDestination->expects($this->any())->method('getAsArray')->willReturn(['destination' => 'test']); $this->accessUnawareRouter = $this->getMock('Symfony\\Component\\Routing\\Matcher\\UrlMatcherInterface'); $this->accessUnawareRouter->expects($this->any())->method('match')->willReturn(['_controller' => 'mocked']); $this->customPageSubscriber = new CustomPageExceptionHtmlSubscriber($this->configFactory, $this->kernel, $this->logger, $this->redirectDestination, $this->accessUnawareRouter); // You can't create an exception in PHP without throwing it. Store the // current error_log, and disable it temporarily. $this->errorLog = ini_set('error_log', file_exists('/dev/null') ? '/dev/null' : 'nul'); }
/** * Gets the UrlMatcher instance associated with this Router. * * @return UrlMatcherInterface A UrlMatcherInterface instance */ public function getMatcher() { if (null !== $this->matcher) { return $this->matcher; } if (null === $this->options['cache_dir'] || null === $this->options['matcher_cache_class']) { $this->matcher = new $this->options['matcher_class']($this->getRouteCollection(), $this->context); if (method_exists($this->matcher, 'addExpressionLanguageProvider')) { foreach ($this->expressionLanguageProviders as $provider) { $this->matcher->addExpressionLanguageProvider($provider); } } return $this->matcher; } $class = $this->options['matcher_cache_class']; $baseClass = $this->options['matcher_base_class']; $expressionLanguageProviders = $this->expressionLanguageProviders; $that = $this; // required for PHP 5.3 where "$this" cannot be use()d in anonymous functions. Change in Symfony 3.0. $cache = $this->getConfigCacheFactory()->cache($this->options['cache_dir'] . '/' . $class . '.php', function (ConfigCacheInterface $cache) use($that, $class, $baseClass, $expressionLanguageProviders) { $dumper = $that->getMatcherDumperInstance(); if (method_exists($dumper, 'addExpressionLanguageProvider')) { foreach ($expressionLanguageProviders as $provider) { $dumper->addExpressionLanguageProvider($provider); } } $options = array('class' => $class, 'base_class' => $baseClass); $cache->write($dumper->dump($options), $that->getRouteCollection()->getResources()); }); require_once $cache->getPath(); return $this->matcher = new $class($this->context); }
/** * Constructor. * * RequestStack will become required in 3.0. * * @param UrlMatcherInterface|RequestMatcherInterface $matcher The Url or Request matcher * @param RequestContext|null $context The RequestContext (can be null when $matcher implements RequestContextAwareInterface) * @param LoggerInterface|null $logger The logger * @param RequestStack|null $requestStack A RequestStack instance * * @throws \InvalidArgumentException */ public function __construct($matcher, RequestContext $context = null, LoggerInterface $logger = null, RequestStack $requestStack = null) { if (!$matcher instanceof UrlMatcherInterface && !$matcher instanceof RequestMatcherInterface) { throw new \InvalidArgumentException('Matcher must either implement UrlMatcherInterface or RequestMatcherInterface.'); } if (null === $context && !$matcher instanceof RequestContextAwareInterface) { throw new \InvalidArgumentException('You must either pass a RequestContext or the matcher must implement RequestContextAwareInterface.'); } if (!$requestStack instanceof RequestStack) { @trigger_error('The ' . __METHOD__ . ' method now requires a RequestStack instance as ' . __CLASS__ . '::setRequest method will not be supported anymore in 3.0.', E_USER_DEPRECATED); } $this->matcher = $matcher; $this->context = $context ?: $matcher->getContext(); $this->requestStack = $requestStack; $this->logger = $logger; }
/** * Gets the UrlMatcher instance associated with this Router. * * @return UrlMatcherInterface A UrlMatcherInterface instance */ public function getMatcher() { if (null !== $this->matcher) { return $this->matcher; } if (null === $this->options['cache_dir'] || null === $this->options['matcher_cache_class']) { $this->matcher = new $this->options['matcher_class']($this->getRouteCollection(), $this->context); if (method_exists($this->matcher, 'addExpressionLanguageProvider')) { foreach ($this->expressionLanguageProviders as $provider) { $this->matcher->addExpressionLanguageProvider($provider); } } return $this->matcher; } $class = $this->options['matcher_cache_class']; $cache = new ConfigCache($this->options['cache_dir'] . '/' . $class . '.php', $this->options['debug']); if (!$cache->isFresh()) { $dumper = $this->getMatcherDumperInstance(); if (method_exists($dumper, 'addExpressionLanguageProvider')) { foreach ($this->expressionLanguageProviders as $provider) { $dumper->addExpressionLanguageProvider($provider); } } $options = array('class' => $class, 'base_class' => $this->options['matcher_base_class']); $cache->write($dumper->dump($options), $this->getRouteCollection()->getResources()); } require_once $cache; return $this->matcher = new $class($this->context); }
/** * Checks whether the given path is an administrative one. * * @param \Symfony\Component\HttpFoundation\Request $request * The request object. * * @return bool * TRUE if the path is administrative, FALSE otherwise. */ protected function isAdminPath(Request $request) { $result = FALSE; if ($request && $this->adminContext) { // If called from an event subscriber, the request may not have the route // object yet (it is still being built), so use the router to look up // based on the path. $route_match = $this->stackedRouteMatch->getRouteMatchFromRequest($request); if ($route_match && !($route_object = $route_match->getRouteObject())) { try { // Process the path as an inbound path. This will remove any language // prefixes and other path components that inbound processing would // clear out, so we can attempt to load the route clearly. $path = $this->pathProcessorManager->processInbound(urldecode(rtrim($request->getPathInfo(), '/')), $request); $attributes = $this->router->match($path); } catch (ResourceNotFoundException $e) { return FALSE; } catch (AccessDeniedHttpException $e) { return FALSE; } $route_object = $attributes[RouteObjectInterface::ROUTE_OBJECT]; } $result = $this->adminContext->isAdminRoute($route_object); } return $result; }
/** * @override * @inheritDoc */ public function handleMessage(IoConnectionInterface $conn, IoMessageInterface $message) { if (!$message instanceof HttpRequestInterface) { $conn->controller->handleMessage($conn, $message); return; } if (($header = $message->getHeaderLine('Origin')) !== '') { $origin = parse_url($header, PHP_URL_HOST) ?: $header; if ($origin !== '' && $this->isBlocked($origin)) { return $this->close($conn, 403); } } $context = $this->matcher->getContext(); $context->setMethod($message->getMethod()); $context->setHost($message->getUri()->getHost()); $route = []; try { $route = $this->matcher->match($message->getUri()->getPath()); } catch (Error $ex) { return $this->close($conn, 500); } catch (MethodNotAllowedException $nae) { return $this->close($conn, 403); } catch (ResourceNotFoundException $nfe) { return $this->close($conn, 404); } $conn->controller = $route['_controller']; try { $conn->controller->handleConnect($conn); $conn->controller->handleMessage($conn, $message); } catch (Error $ex) { $conn->controller->handleError($conn, $ex); } catch (Exception $ex) { $conn->controller->handleError($conn, $ex); } }
/** * Tests the isValid() method with a not existing path. * * @covers ::isValid */ public function testIsValidWithNotExistingPath() { $this->account->expects($this->once())->method('hasPermission')->with('link to any page')->willReturn(FALSE); $this->accessUnawareRouter->expects($this->never())->method('match'); $this->accessAwareRouter->expects($this->once())->method('match')->with('/not-existing-path')->willThrowException(new ResourceNotFoundException()); $this->pathProcessor->expects($this->once())->method('processInbound')->willReturnArgument(0); $this->assertFalse($this->pathValidator->isValid('not-existing-path')); }
public function setUp() { $this->urlMatcher = $this->getMockForAbstractClass(UrlMatcherInterface::class); $this->resourceTransformer = $this->getMockForAbstractClass(TransformerInterface::class); $this->kernel = $this->getMockForAbstractClass(HttpKernelInterface::class); $this->context = $this->getMockBuilder(RequestContext::class)->disableOriginalConstructor()->getMock(); $this->urlMatcher->method('getContext')->willReturn($this->context); }
/** * Tests the getUrlIfValidWithoutAccessCheck() method. * * @covers ::getUrlIfValidWithoutAccessCheck */ public function testGetUrlIfValidWithoutAccessCheck() { $this->account->expects($this->never())->method('hasPermission')->with('link to any page'); $this->accessAwareRouter->expects($this->never())->method('match'); $this->accessUnawareRouter->expects($this->once())->method('match')->with('/test-path')->willReturn([RouteObjectInterface::ROUTE_NAME => 'test_route', '_raw_variables' => new ParameterBag(['key' => 'value'])]); $this->pathProcessor->expects($this->once())->method('processInbound')->willReturnArgument(0); $url = $this->pathValidator->getUrlIfValidWithoutAccessCheck('test-path'); $this->assertInstanceOf('Drupal\\Core\\Url', $url); $this->assertEquals('test_route', $url->getRouteName()); $this->assertEquals(['key' => 'value'], $url->getRouteParameters()); }
/** * @return RequestMatcherInterface|UrlMatcherInterface */ public function getMatcher() { /* we may not set the context in DynamicRouter::setContext as this * would lead to symfony cache warmup problems. * a request matcher does not need the request context separately as it * can get it from the request. */ if ($this->matcher instanceof RequestContextAwareInterface) { $this->matcher->setContext($this->getContext()); } return $this->matcher; }
/** * {@inheritdoc} */ protected function setUp() { $this->configFactory = $this->getConfigFactoryStub(['system.site' => ['page.403' => '/access-denied-page', 'page.404' => '/not-found-page']]); $this->kernel = $this->getMock('Symfony\\Component\\HttpKernel\\HttpKernelInterface'); $this->logger = $this->getMock('Psr\\Log\\LoggerInterface'); $this->redirectDestination = $this->getMock('\\Drupal\\Core\\Routing\\RedirectDestinationInterface'); $this->redirectDestination->expects($this->any())->method('getAsArray')->willReturn(['destination' => 'test']); $this->accessUnawareRouter = $this->getMock('Symfony\\Component\\Routing\\Matcher\\UrlMatcherInterface'); $this->accessUnawareRouter->expects($this->any())->method('match')->willReturn(['_controller' => 'mocked']); $this->accessManager = $this->getMock('Drupal\\Core\\Access\\AccessManagerInterface'); $this->accessManager->expects($this->any())->method('checkNamedRoute')->willReturn(AccessResult::allowed()->addCacheTags(['foo', 'bar'])); $this->customPageSubscriber = new CustomPageExceptionHtmlSubscriber($this->configFactory, $this->kernel, $this->logger, $this->redirectDestination, $this->accessUnawareRouter, $this->accessManager); $path_validator = $this->getMock('Drupal\\Core\\Path\\PathValidatorInterface'); $path_validator->expects($this->any())->method('getUrlIfValidWithoutAccessCheck')->willReturn(Url::fromRoute('foo', ['foo' => 'bar'])); $container = new ContainerBuilder(); $container->set('path.validator', $path_validator); \Drupal::setContainer($container); // You can't create an exception in PHP without throwing it. Store the // current error_log, and disable it temporarily. $this->errorLog = ini_set('error_log', file_exists('/dev/null') ? '/dev/null' : 'nul'); }
/** * Checks whether the given path is an administrative one. * * @param \Symfony\Component\HttpFoundation\Request $request * The request object. * * @return bool * TRUE if the path is administrative, FALSE otherwise. */ public function isAdminPath(Request $request) { $result = FALSE; if ($request && $this->adminContext) { // If called from an event subscriber, the request may not the route info // yet, so use the router to look up the path first. if (!($route_object = $request->attributes->get(RouteObjectInterface::ROUTE_OBJECT))) { $attributes = $this->router->match('/' . urldecode(trim($request->getPathInfo(), '/'))); $route_object = $attributes[RouteObjectInterface::ROUTE_OBJECT]; } $result = $this->adminContext->isAdminRoute($route_object); } return $result; }
/** * Verify if the given path is a valid route. * * Taken from menu_execute_active_handler(). * * @param string $path * A string containing a relative path. * * @return bool * TRUE if the path already exists. */ public function isRoute($path) { if (is_file(DRUPAL_ROOT . '/' . $path) || is_dir(DRUPAL_ROOT . '/' . $path)) { // Do not allow existing files or directories to get assigned an automatic // alias. Note that we do not need to use is_link() to check for symbolic // links since this returns TRUE for either is_file() or is_dir() already. return TRUE; } try { $this->urlMatcher->match('/' . $path); return TRUE; } catch (ResourceNotFoundException $e) { return FALSE; } }
/** * {@inheritdoc} * @throws \UnexpectedValueException If a controller is not \Ratchet\Http\HttpServerInterface */ public function onOpen(ConnectionInterface $conn, RequestInterface $request = null) { if (null === $request) { throw new \UnexpectedValueException('$request can not be null'); } $context = $this->_matcher->getContext(); $context->setMethod($request->getMethod()); $context->setHost($request->getHost()); try { $route = $this->_matcher->match($request->getPath()); } catch (MethodNotAllowedException $nae) { return $this->close($conn, 403); } catch (ResourceNotFoundException $nfe) { return $this->close($conn, 404); } if (is_string($route['_controller']) && class_exists($route['_controller'])) { $route['_controller'] = new $route['_controller'](); } if (!$route['_controller'] instanceof HttpServerInterface) { throw new \UnexpectedValueException('All routes must implement Ratchet\\Http\\HttpServerInterface'); } $conn->controller = $route['_controller']; $conn->controller->onOpen($conn, $request); }
public function onKernelRequest(KernelEvent $event) { if (strtoupper($event->getRequest()->getMethod()) !== 'LINK' && strtoupper($event->getRequest()->getMethod()) !== 'UNLINK') { return; } if (!$event->getRequest()->headers->has('link')) { throw new BadRequestHttpException('Please specify at least one Link.'); } $requestMethod = $this->urlMatcher->getContext()->getMethod(); $this->urlMatcher->getContext()->setMethod('GET'); $links = []; /* * Due to limitations, multiple same-name headers are sent as comma * separated values. * * This breaks those headers into Link headers following the format * http://tools.ietf.org/html/rfc2068#section-19.6.2.4 */ foreach (explode(',', $event->getRequest()->headers->get('link')) as $header) { $header = trim($header); $link = new LinkHeader($header); try { if ($urlParameters = $this->urlMatcher->match($link->getValue())) { $link->setUrlParameters($urlParameters); } } catch (ResourceNotFoundException $exception) { } try { $link->setResource($this->resourceTransformer->getResourceProxy($link->getValue())); } catch (InvalidArgumentException $e) { } $links[] = $link; } $this->urlMatcher->getContext()->setMethod($requestMethod); $event->getRequest()->attributes->set('links', $links); }
/** * Makes a subrequest to retrieve the default error page. * * @param \Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event * The event to process. * @param string $url * The path/url to which to make a subrequest for this error message. * @param int $status_code * The status code for the error being handled. */ protected function makeSubrequest(GetResponseForExceptionEvent $event, $url, $status_code) { $request = $event->getRequest(); $exception = $event->getException(); try { // Reuse the exact same request (so keep the same URL, keep the access // result, the exception, et cetera) but override the routing information. // This means that aside from routing, this is identical to the master // request. This allows us to generate a response that is executed on // behalf of the master request, i.e. for the original URL. This is what // allows us to e.g. generate a 404 response for the original URL; if we // would execute a subrequest with the 404 route's URL, then it'd be // generated for *that* URL, not the *original* URL. $sub_request = clone $request; // The routing to the 404 page should be done as GET request because it is // restricted to GET and POST requests only. Otherwise a DELETE request // would for example trigger a method not allowed exception. $request_context = clone $this->accessUnawareRouter->getContext(); $request_context->setMethod('GET'); $this->accessUnawareRouter->setContext($request_context); $sub_request->attributes->add($this->accessUnawareRouter->match($url)); // Add to query (GET) or request (POST) parameters: // - 'destination' (to ensure e.g. the login form in a 403 response // redirects to the original URL) // - '_exception_statuscode' $parameters = $sub_request->isMethod('GET') ? $sub_request->query : $sub_request->request; $parameters->add($this->redirectDestination->getAsArray() + ['_exception_statuscode' => $status_code]); $response = $this->httpKernel->handle($sub_request, HttpKernelInterface::SUB_REQUEST); // Only 2xx responses should have their status code overridden; any // other status code should be passed on: redirects (3xx), error (5xx)… // @see https://www.drupal.org/node/2603788#comment-10504916 if ($response->isSuccessful()) { $response->setStatusCode($status_code); } // Persist any special HTTP headers that were set on the exception. if ($exception instanceof HttpExceptionInterface) { $response->headers->add($exception->getHeaders()); } $event->setResponse($response); } catch (\Exception $e) { // If an error happened in the subrequest we can't do much else. Instead, // just log it. The DefaultExceptionSubscriber will catch the original // exception and handle it normally. $error = Error::decodeException($e); $this->logger->log($error['severity_level'], '%type: @message in %function (line %line of %file).', $error); } }
/** * Tests onHandleException with a GET request. */ public function testHandleWithGetRequest() { $request = Request::create('/test', 'GET', array('name' => 'druplicon', 'pass' => '12345')); $request->attributes->set(AccessAwareRouterInterface::ACCESS_RESULT, AccessResult::forbidden()->addCacheTags(['druplicon'])); $request_context = new RequestContext(); $request_context->fromRequest($request); $this->accessUnawareRouter->expects($this->any())->method('getContext')->willReturn($request_context); $this->kernel->expects($this->once())->method('handle')->will($this->returnCallback(function (Request $request) { return new Response($request->getMethod() . ' ' . UrlHelper::buildQuery($request->query->all())); })); $event = new GetResponseForExceptionEvent($this->kernel, $request, 'foo', new NotFoundHttpException('foo')); $this->customPageSubscriber->onException($event); $response = $event->getResponse(); $result = $response->getContent() . " " . UrlHelper::buildQuery($request->request->all()); $this->assertEquals('GET name=druplicon&pass=12345&destination=test&_exception_statuscode=404 ', $result); $this->assertEquals(AccessResult::forbidden()->addCacheTags(['druplicon', 'foo', 'bar']), $request->attributes->get(AccessAwareRouterInterface::ACCESS_RESULT)); }
/** * Verify if the given path is a valid route. * * @param string $path * A string containing a relative path. * * @return bool * TRUE if the path already exists. * * @throws \InvalidArgumentException */ public function isRoute($path) { if (is_file(DRUPAL_ROOT . '/' . $path) || is_dir(DRUPAL_ROOT . '/' . $path)) { // Do not allow existing files or directories to get assigned an automatic // alias. Note that we do not need to use is_link() to check for symbolic // links since this returns TRUE for either is_file() or is_dir() already. return TRUE; } try { $route = $this->urlMatcher->match($path); if ($route['_route'] == $this->lastRouteName) { throw new \InvalidArgumentException('The given alias pattern (' . $path . ') always matches the route ' . $this->lastRouteName); } $this->lastRouteName = $route['_route']; return TRUE; } catch (ResourceNotFoundException $e) { $this->lastRouteName = NULL; return FALSE; } }
/** * @param string $pathinfo * * @return array */ public function match($pathinfo) { return $this->matcher->match($pathinfo); }
/** * @param GetResponseEvent $event * * @return array */ public function onKernelRequest(GetResponseEvent $event, $eventName, EventDispatcherInterface $dispatcher) { if (!$event->getRequest()->headers->has('link')) { return; } $links = []; $header = $event->getRequest()->headers->get('link'); /* * Due to limitations, multiple same-name headers are sent as comma * separated values. * * This breaks those headers into Link headers following the format * http://tools.ietf.org/html/rfc2068#section-19.6.2.4 */ while (preg_match('/^((?:[^"]|"[^"]*")*?),/', $header, $matches)) { $header = trim(substr($header, strlen($matches[0]))); $links[] = $matches[1]; } if ($header) { $links[] = $header; } $requestMethod = $this->urlMatcher->getContext()->getMethod(); // The controller resolver needs a request to resolve the controller. $stubRequest = new Request(); foreach ($links as $idx => $link) { // Force the GET method to avoid the use of the previous method (LINK/UNLINK) $this->urlMatcher->getContext()->setMethod('GET'); $linkParams = explode(';', trim($link)); $resourceType = null; if (count($linkParams) > 1) { $resourceType = trim(preg_replace('/<|>/', '', $linkParams[1])); $resourceType = str_replace('"', '', str_replace('rel=', '', $resourceType)); } $resource = array_shift($linkParams); $resource = preg_replace('/<|>/', '', $resource); // Assume that no resource is specified here if there is no path separator, because urlMatcher will return homepage if (strpos($resource, '/') === false) { continue; } $tempRequest = Request::create($resource); try { $route = $this->urlMatcher->match($tempRequest->getRequestUri()); } catch (\Exception $e) { // If we don't have a matching route we return the original Link header continue; } $stubRequest->attributes->replace($route); $stubRequest->server = $event->getRequest()->server; if (false === ($controller = $this->resolver->getController($stubRequest))) { continue; } $subEvent = new FilterControllerEvent($event->getKernel(), $controller, $stubRequest, HttpKernelInterface::SUB_REQUEST); $kernelSubEvent = new GetResponseEvent($event->getKernel(), $stubRequest, HttpKernelInterface::SUB_REQUEST); $dispatcher->dispatch(KernelEvents::REQUEST, $kernelSubEvent); $dispatcher->dispatch(KernelEvents::CONTROLLER, $subEvent); $controller = $subEvent->getController(); $arguments = $this->resolver->getArguments($stubRequest, $controller); if (!isset($arguments[0])) { continue; } $arguments[0]->attributes->set('_link_request', true); try { $result = call_user_func_array($controller, $arguments); // Our api returns objects for single resources if (!is_object($result)) { continue; } $links[$idx] = ['object' => $result, 'resourceType' => $resourceType]; } catch (\Exception $e) { $links[$idx] = ['object' => $e, 'resourceType' => 'exception']; continue; } } $event->getRequest()->attributes->set('links', $links); $this->urlMatcher->getContext()->setMethod($requestMethod); return $links; }
public function onKernelRequest(GetResponseEvent $event) { if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) { return; } if (!$event->getRequest()->headers->has('link')) { return; } $links = array(); $header = $event->getRequest()->headers->get('link'); /* * Due to limitations, multiple same-name headers are sent as comma * separated values. * * This breaks those headers into Link headers following the format * http://tools.ietf.org/html/rfc2068#section-19.6.2.4 */ while (preg_match('/^((?:[^"]|"[^"]*")*?),/', $header, $matches)) { $header = trim(substr($header, strlen($matches[0]))); $links[] = $matches[1]; } if ($header) { $links[] = $header; } $requestMethod = $this->urlMatcher->getContext()->getMethod(); // Force the GET method to avoid the use of the // previous method (LINK/UNLINK) $this->urlMatcher->getContext()->setMethod('GET'); // The controller resolver needs a request to resolve the controller. $stubRequest = new Request(); foreach ($links as $idx => $link) { $linkHeader = $this->parseLinkHeader($link); $resource = $this->parseResource($linkHeader, $event->getRequest()); try { $route = $this->urlMatcher->match($resource); } catch (\Exception $e) { // If we don't have a matching route we return // the original Link header continue; } $stubRequest->attributes->replace($route); if (false === ($controller = $this->resolver->getController($stubRequest))) { continue; } // Make sure @ParamConverter and some other annotations are called $subEvent = new FilterControllerEvent($event->getKernel(), $controller, $stubRequest, HttpKernelInterface::SUB_REQUEST); $event->getDispatcher()->dispatch(KernelEvents::CONTROLLER, $subEvent); $controller = $subEvent->getController(); $arguments = $this->resolver->getArguments($stubRequest, $controller); try { $result = call_user_func_array($controller, $arguments); $value = is_array($result) ? current($result) : $result; if ($linkHeader->hasRel()) { unset($links[$idx]); $links[$linkHeader->getRel()][] = $value; } else { $links[$idx] = $value; } } catch (\Exception $e) { continue; } } $event->getRequest()->attributes->set('links', $links); $this->urlMatcher->getContext()->setMethod($requestMethod); }
/** * @param FilterControllerEvent $event A FilterControllerEvent instance */ public function onKernelController(FilterControllerEvent $event) { if (!$event->getRequest()->headers->has('link')) { return; } $links = array(); $header = $event->getRequest()->headers->get('link'); /* * Due to limitations, multiple same-name headers are sent as comma * separated values. * * This breaks those headers into Link headers following the format * http://tools.ietf.org/html/rfc2068#section-19.6.2.4 */ while (preg_match('/^((?:[^"]|"[^"]*")*?),/', $header, $matches)) { $header = trim(substr($header, strlen($matches[0]))); $links[] = $matches[1]; } if ($header) { $links[] = $header; } $requestMethod = $this->urlMatcher->getContext()->getMethod(); // Force the GET method to avoid the use of the // previous method (LINK/UNLINK) $this->urlMatcher->getContext()->setMethod('GET'); // The controller resolver needs a request to resolve the controller. $stubRequest = new Request(); foreach ($links as $idx => $link) { $linkParams = explode(';', trim($link)); $resource = array_shift($linkParams); $resource = preg_replace('/<|>/', '', $resource); if (preg_match('#^/|https?://#', $resource) === 0) { $resource = '/' . $resource; } try { $route = $this->urlMatcher->match($resource); } catch (\Exception $e) { // If we don't have a matching route we return // the original Link header continue; } $stubRequest->attributes->replace($route); if (false === ($controller = $this->resolver->getController($stubRequest))) { continue; } try { $stubEvent = new FilterControllerEvent($this->httpKernel, $controller, $stubRequest, HttpKernelInterface::SUB_REQUEST); $this->eventDispatcher->dispatch(KernelEvents::CONTROLLER, $stubEvent); $arguments = $this->resolver->getArguments($stubRequest, $controller); $result = call_user_func_array($controller, $arguments); // By convention the controller action must return an array if (!is_array($result)) { continue; } // The key of first item is discarded $links[$idx] = current($result); } catch (\Exception $e) { continue; } } $event->getRequest()->attributes->set('link', $links); $this->urlMatcher->getContext()->setMethod($requestMethod); }