/** * Converts the request path to a system path. * * @param Symfony\Component\HttpKernel\Event\GetResponseEvent $event * The Event to process. */ public function onKernelRequestConvertPath(GetResponseEvent $event) { $request = $event->getRequest(); $path = trim($request->getPathInfo(), '/'); $path = $this->pathProcessor->processInbound($path, $request); $this->currentPath->setPath('/' . $path, $request); // Set the cache key on the alias manager cache decorator. if ($event->getRequestType() == HttpKernelInterface::MASTER_REQUEST) { $this->aliasManager->setCacheKey($path); } }
/** * Test the getArgument() method. * * @see \Drupal\views\Plugin\views\argument_default\Raw::getArgument() */ public function testGetArgument() { $view = $this->getMockBuilder('Drupal\\views\\ViewExecutable')->disableOriginalConstructor()->getMock(); $display_plugin = $this->getMockBuilder('Drupal\\views\\Plugin\\views\\display\\DisplayPluginBase')->disableOriginalConstructor()->getMock(); $current_path = new CurrentPathStack(new RequestStack()); $request = new Request(); $current_path->setPath('/test/example', $request); $view->expects($this->any())->method('getRequest')->will($this->returnValue($request)); $alias_manager = $this->getMock('Drupal\\Core\\Path\\AliasManagerInterface'); $alias_manager->expects($this->never())->method('getAliasByPath'); // Don't use aliases. $raw = new Raw(array(), 'raw', array(), $alias_manager, $current_path); $options = array('use_alias' => FALSE, 'index' => 0); $raw->init($view, $display_plugin, $options); $this->assertEquals('test', $raw->getArgument()); $raw = new Raw(array(), 'raw', array(), $alias_manager, $current_path); $options = array('use_alias' => FALSE, 'index' => 1); $raw->init($view, $display_plugin, $options); $this->assertEquals('example', $raw->getArgument()); // Setup an alias manager with a path alias. $alias_manager = $this->getMock('Drupal\\Core\\Path\\AliasManagerInterface'); $alias_manager->expects($this->any())->method('getAliasByPath')->with($this->equalTo('test/example'))->will($this->returnValue('other/example')); $raw = new Raw(array(), 'raw', array(), $alias_manager, $current_path); $options = array('use_alias' => TRUE, 'index' => 0); $raw->init($view, $display_plugin, $options); $this->assertEquals('other', $raw->getArgument()); $raw = new Raw(array(), 'raw', array(), $alias_manager, $current_path); $options = array('use_alias' => TRUE, 'index' => 1); $raw->init($view, $display_plugin, $options); $this->assertEquals('example', $raw->getArgument()); }
/** * Tests the request path condition. */ public function testConditions() { // Get the request path condition and test and configure it to check against // different patterns and requests. $pages = "/my/pass/page\r\n/my/pass/page2\r\n/foo"; $request = Request::create('/my/pass/page2'); $this->requestStack->push($request); /* @var \Drupal\system\Plugin\Condition\RequestPath $condition */ $condition = $this->pluginManager->createInstance('request_path'); $condition->setConfig('pages', $pages); $this->aliasManager->addAlias('/my/pass/page2', '/my/pass/page2'); $this->assertTrue($condition->execute(), 'The request path matches a standard path'); $this->assertEqual($condition->summary(), 'Return true on the following pages: /my/pass/page, /my/pass/page2, /foo', 'The condition summary matches for a standard path'); // Test an aliased path. $this->currentPath->setPath('/my/aliased/page', $request); $this->requestStack->pop(); $this->requestStack->push($request); $this->aliasManager->addAlias('/my/aliased/page', '/my/pass/page'); $this->assertTrue($condition->execute(), 'The request path matches an aliased path'); $this->assertEqual($condition->summary(), 'Return true on the following pages: /my/pass/page, /my/pass/page2, /foo', 'The condition summary matches for an aliased path'); // Test a wildcard path. $this->aliasManager->addAlias('/my/pass/page3', '/my/pass/page3'); $this->currentPath->setPath('/my/pass/page3', $request); $this->requestStack->pop(); $this->requestStack->push($request); $condition->setConfig('pages', '/my/pass/*'); $this->assertTrue($condition->evaluate(), 'The system_path my/pass/page3 passes for wildcard paths.'); $this->assertEqual($condition->summary(), 'Return true on the following pages: /my/pass/*', 'The condition summary matches for a wildcard path'); // Test a missing path. $this->requestStack->pop(); $this->requestStack->push($request); $this->currentPath->setPath('/my/fail/page4', $request); $condition->setConfig('pages', '/my/pass/*'); $this->aliasManager->addAlias('/my/fail/page4', '/my/fail/page4'); $this->assertFalse($condition->evaluate(), 'The system_path /my/pass/page4 fails for a missing path.'); // Test a path of '/'. $this->aliasManager->addAlias('/', '/my/pass/page3'); $this->currentPath->setPath('/', $request); $this->requestStack->pop(); $this->requestStack->push($request); $this->assertTrue($condition->evaluate(), 'The system_path my/pass/page3 passes for wildcard paths.'); $this->assertEqual($condition->summary(), 'Return true on the following pages: /my/pass/*', 'The condition summary matches for a wildcard path'); }
/** * Ensures a path set on the current path services overrides the request one. */ function testCurrentPath() { $connection = Database::getConnection(); $provider = new RouteProvider($connection, $this->state, $this->currentPath, 'test_routes'); $this->fixtures->createTables($connection); $dumper = new MatcherDumper($connection, $this->state, 'test_routes'); $dumper->addRoutes($this->fixtures->sampleRouteCollection()); $dumper->dump(); $request = Request::create('/path/one', 'GET'); $this->currentPath->setPath('/path/two', $request); $routes_by_pattern = $provider->getRoutesByPattern('/path/two'); $routes = $provider->getRouteCollectionForRequest($request); $this->assertEqual(array_keys($routes_by_pattern->all()), array_keys($routes->all()), 'Ensure the expected routes are found.'); foreach ($routes as $route) { $this->assertEqual($route->getPath(), '/path/two', 'Found path has correct pattern'); } }
/** * Finds routes that may potentially match the request. * * This may return a mixed list of class instances, but all routes returned * must extend the core symfony route. The classes may also implement * RouteObjectInterface to link to a content document. * * This method may not throw an exception based on implementation specific * restrictions on the url. That case is considered a not found - returning * an empty array. Exceptions are only used to abort the whole request in * case something is seriously broken, like the storage backend being down. * * Note that implementations may not implement an optimal matching * algorithm, simply a reasonable first pass. That allows for potentially * very large route sets to be filtered down to likely candidates, which * may then be filtered in memory more completely. * * @param Request $request A request against which to match. * * @return \Symfony\Component\Routing\RouteCollection with all urls that * could potentially match $request. Empty collection if nothing can * match. */ public function getRouteCollectionForRequest(Request $request) { // Cache both the system path as well as route parameters and matching // routes. $cid = 'route:' . $request->getPathInfo() . ':' . $request->getQueryString(); if ($cached = $this->cache->get($cid)) { $this->currentPath->setPath($cached->data['path'], $request); $request->query->replace($cached->data['query']); return $cached->data['routes']; } else { // Just trim on the right side. $path = $request->getPathInfo(); $path = $path === '/' ? $path : rtrim($request->getPathInfo(), '/'); $path = $this->pathProcessor->processInbound($path, $request); $this->currentPath->setPath($path, $request); // Incoming path processors may also set query parameters. $query_parameters = $request->query->all(); $routes = $this->getRoutesByPath(rtrim($path, '/')); $cache_value = ['path' => $path, 'query' => $query_parameters, 'routes' => $routes]; $this->cache->set($cid, $cache_value, CacheBackendInterface::CACHE_PERMANENT, ['route_match']); return $routes; } }
/** * Loads and renders a view via AJAX. * * @param \Symfony\Component\HttpFoundation\Request $request * The current request object. * * @return \Drupal\views\Ajax\ViewAjaxResponse * The view response as ajax response. * * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException * Thrown when the view was not found. */ public function ajaxView(Request $request) { $name = $request->request->get('view_name'); $display_id = $request->request->get('view_display_id'); if (isset($name) && isset($display_id)) { $args = $request->request->get('view_args'); $args = isset($args) && $args !== '' ? explode('/', $args) : array(); // Arguments can be empty, make sure they are passed on as NULL so that // argument validation is not triggered. $args = array_map(function ($arg) { return $arg == '' ? NULL : $arg; }, $args); $path = $request->request->get('view_path'); $dom_id = $request->request->get('view_dom_id'); $dom_id = isset($dom_id) ? preg_replace('/[^a-zA-Z0-9_-]+/', '-', $dom_id) : NULL; $pager_element = $request->request->get('pager_element'); $pager_element = isset($pager_element) ? intval($pager_element) : NULL; $response = new ViewAjaxResponse(); // Remove all of this stuff from the query of the request so it doesn't // end up in pagers and tablesort URLs. foreach (array('view_name', 'view_display_id', 'view_args', 'view_path', 'view_dom_id', 'pager_element', 'view_base_path', AjaxResponseSubscriber::AJAX_REQUEST_PARAMETER) as $key) { $request->query->remove($key); $request->request->remove($key); } // Load the view. if (!($entity = $this->storage->load($name))) { throw new NotFoundHttpException(); } $view = $this->executableFactory->get($entity); if ($view && $view->access($display_id)) { $response->setView($view); // Fix the current path for paging. if (!empty($path)) { $this->currentPath->setPath('/' . $path, $request); } // Add all POST data, because AJAX is always a post and many things, // such as tablesorts, exposed filters and paging assume GET. $request_all = $request->request->all(); $query_all = $request->query->all(); $request->query->replace($request_all + $query_all); // Overwrite the destination. // @see the redirect.destination service. $origin_destination = $path; // Remove some special parameters you never want to have part of the // destination query. $used_query_parameters = $request->query->all(); // @todo Remove this parsing once these are removed from the request in // https://www.drupal.org/node/2504709. unset($used_query_parameters[FormBuilderInterface::AJAX_FORM_REQUEST], $used_query_parameters[MainContentViewSubscriber::WRAPPER_FORMAT], $used_query_parameters['ajax_page_state']); $query = UrlHelper::buildQuery($used_query_parameters); if ($query != '') { $origin_destination .= '?' . $query; } $this->redirectDestination->set($origin_destination); // Override the display's pager_element with the one actually used. if (isset($pager_element)) { $response->addCommand(new ScrollTopCommand(".js-view-dom-id-{$dom_id}")); $view->displayHandlers->get($display_id)->setOption('pager_element', $pager_element); } // Reuse the same DOM id so it matches that in drupalSettings. $view->dom_id = $dom_id; $context = new RenderContext(); $preview = $this->renderer->executeInRenderContext($context, function () use($view, $display_id, $args) { return $view->preview($display_id, $args); }); if (!$context->isEmpty()) { $bubbleable_metadata = $context->pop(); BubbleableMetadata::createFromRenderArray($preview)->merge($bubbleable_metadata)->applyTo($preview); } $response->addCommand(new ReplaceCommand(".js-view-dom-id-{$dom_id}", $preview)); return $response; } else { throw new AccessDeniedHttpException(); } } else { throw new NotFoundHttpException(); } }
/** * Loads and renders a view via AJAX. * * @param \Symfony\Component\HttpFoundation\Request $request * The current request object. * * @return \Drupal\views\Ajax\ViewAjaxResponse * The view response as ajax response. * * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException * Thrown when the view was not found. */ public function ajaxView(Request $request) { $name = $request->request->get('view_name'); $display_id = $request->request->get('view_display_id'); if (isset($name) && isset($display_id)) { $args = $request->request->get('view_args'); $args = isset($args) && $args !== '' ? explode('/', $args) : array(); // Arguments can be empty, make sure they are passed on as NULL so that // argument validation is not triggered. $args = array_map(function ($arg) { return $arg == '' ? NULL : $arg; }, $args); $path = $request->request->get('view_path'); $dom_id = $request->request->get('view_dom_id'); $dom_id = isset($dom_id) ? preg_replace('/[^a-zA-Z0-9_-]+/', '-', $dom_id) : NULL; $pager_element = $request->request->get('pager_element'); $pager_element = isset($pager_element) ? intval($pager_element) : NULL; $response = new ViewAjaxResponse(); // Remove all of this stuff from the query of the request so it doesn't // end up in pagers and tablesort URLs. foreach (array('view_name', 'view_display_id', 'view_args', 'view_path', 'view_dom_id', 'pager_element', 'view_base_path', 'ajax_html_ids') as $key) { $request->query->remove($key); $request->request->remove($key); } // Load the view. if (!($entity = $this->storage->load($name))) { throw new NotFoundHttpException(); } $view = $this->executableFactory->get($entity); if ($view && $view->access($display_id)) { $response->setView($view); // Fix the current path for paging. if (!empty($path)) { $this->currentPath->setPath('/' . $path, $request); } // Add all POST data, because AJAX is always a post and many things, // such as tablesorts, exposed filters and paging assume GET. $request_all = $request->request->all(); $query_all = $request->query->all(); $request->query->replace($request_all + $query_all); // Overwrite the destination. // @see the redirect.destination service. $origin_destination = $path; $query = UrlHelper::buildQuery($request->query->all()); if ($query != '') { $origin_destination .= '?' . $query; } $this->redirectDestination->set($origin_destination); // Override the display's pager_element with the one actually used. if (isset($pager_element)) { $response->addCommand(new ScrollTopCommand(".view-dom-id-{$dom_id}")); $view->displayHandlers->get($display_id)->setOption('pager_element', $pager_element); } // Reuse the same DOM id so it matches that in drupalSettings. $view->dom_id = $dom_id; if ($preview = $view->preview($display_id, $args)) { $response->addCommand(new ReplaceCommand(".view-dom-id-{$dom_id}", $this->renderer->render($preview))); $response->setAttachments($preview['#attached']); } return $response; } else { throw new AccessDeniedHttpException(); } } else { throw new NotFoundHttpException(); } }