diff --git a/core/core.services.yml b/core/core.services.yml index 0d6eb2e..e39252d 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -1077,7 +1077,7 @@ services: - { name: event_subscriber } redirect_response_subscriber: class: Drupal\Core\EventSubscriber\RedirectResponseSubscriber - arguments: ['@url_generator', '@router.request_context'] + arguments: ['@unrouted_url_assembler', '@router.request_context'] tags: - { name: event_subscriber } redirect_leading_slashes_subscriber: diff --git a/core/lib/Drupal/Core/EventSubscriber/RedirectResponseSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/RedirectResponseSubscriber.php index efaf5c8..ee571e1 100644 --- a/core/lib/Drupal/Core/EventSubscriber/RedirectResponseSubscriber.php +++ b/core/lib/Drupal/Core/EventSubscriber/RedirectResponseSubscriber.php @@ -11,7 +11,8 @@ use Drupal\Component\Utility\UrlHelper; use Drupal\Core\Routing\LocalRedirectResponse; use Drupal\Core\Routing\RequestContext; -use Drupal\Core\Routing\UrlGeneratorInterface; +use Drupal\Core\Url; +use Drupal\Core\Utility\UnroutedUrlAssemblerInterface; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; @@ -25,22 +26,22 @@ class RedirectResponseSubscriber implements EventSubscriberInterface { /** - * The url generator service. + * The unrouted URL assembler service. * - * @var \Drupal\Core\Routing\UrlGeneratorInterface + * @var \Drupal\Core\Utility\UnroutedUrlAssemblerInterface */ - protected $urlGenerator; + protected $unroutedUrlAssembler; /** * Constructs a RedirectResponseSubscriber object. * - * @param \Drupal\Core\Routing\UrlGeneratorInterface $url_generator - * The url generator service. + * @param \Drupal\Core\Utility\UnroutedUrlAssemblerInterface $url_assembler + * The unrouted URL assembler service. * @param \Drupal\Core\Routing\RequestContext $request_context * The request context. */ - public function __construct(UrlGeneratorInterface $url_generator, RequestContext $request_context) { - $this->urlGenerator = $url_generator; + public function __construct(UnroutedUrlAssemblerInterface $url_assembler, RequestContext $request_context) { + $this->unroutedUrlAssembler = $url_assembler; $this->requestContext = $request_context; } @@ -120,16 +121,16 @@ protected function getDestinationAsAbsoluteUrl($destination, $scheme_and_host) { // Legacy destination query parameters can be relative paths that have // not yet been converted to URLs (outbound path processors and other // URL handling still needs to be performed). - // @todo As generateFromPath() is deprecated, remove this in - // https://www.drupal.org/node/2418219. $destination = UrlHelper::parse($destination); - $path = $destination['path']; + $uri = 'base:' . $destination['path']; $options = [ 'query' => $destination['query'], 'fragment' => $destination['fragment'], 'absolute' => TRUE, ]; - $destination = $this->urlGenerator->generateFromPath($path, $options); + // Treat this as if it's user input of a path relative to the site's + // base URL. + $destination = $this->unroutedUrlAssembler->assemble($uri, $options); } } return $destination; diff --git a/core/lib/Drupal/Core/Menu/menu.api.php b/core/lib/Drupal/Core/Menu/menu.api.php index defec19..b37fa61 100644 --- a/core/lib/Drupal/Core/Menu/menu.api.php +++ b/core/lib/Drupal/Core/Menu/menu.api.php @@ -452,7 +452,7 @@ function hook_system_breadcrumb_alter(\Drupal\Core\Breadcrumb\Breadcrumb &$bread * URL. * - url: The \Drupal\Core\Url object. * - options: An associative array of additional options that will be passed - * to either \Drupal\Core\Routing\UrlGenerator::generateFromPath() or + * to either \Drupal\Core\Utility\UnroutedUrlAssembler::assemble() or * \Drupal\Core\Routing\UrlGenerator::generateFromRoute() to generate the * href attribute for this link, and also used when generating the link. * Defaults to an empty array. It may contain the following elements: @@ -469,7 +469,7 @@ function hook_system_breadcrumb_alter(\Drupal\Core\Breadcrumb\Breadcrumb &$bread * to work as an argument for the constructor of the class * Drupal\Core\Template\Attribute($options['attributes']). * - * @see \Drupal\Core\Routing\UrlGenerator::generateFromPath() + * @see \Drupal\Core\Utility\UnroutedUrlAssembler::assemble() * @see \Drupal\Core\Routing\UrlGenerator::generateFromRoute() */ function hook_link_alter(&$variables) { diff --git a/core/lib/Drupal/Core/PathProcessor/OutboundPathProcessorInterface.php b/core/lib/Drupal/Core/PathProcessor/OutboundPathProcessorInterface.php index b350112..59f2d0c 100644 --- a/core/lib/Drupal/Core/PathProcessor/OutboundPathProcessorInterface.php +++ b/core/lib/Drupal/Core/PathProcessor/OutboundPathProcessorInterface.php @@ -22,7 +22,7 @@ * The path to process, with a leading slash. * @param array $options * An array of options such as would be passed to the generator's - * generateFromPath() method. + * generateFromRoute() method. * @param \Symfony\Component\HttpFoundation\Request $request * The HttpRequest object representing the current request. * @param \Drupal\Core\Render\BubbleableMetadata $bubbleable_metadata diff --git a/core/lib/Drupal/Core/Render/MetadataBubblingUrlGenerator.php b/core/lib/Drupal/Core/Render/MetadataBubblingUrlGenerator.php index 3a4535e..940c0e1 100644 --- a/core/lib/Drupal/Core/Render/MetadataBubblingUrlGenerator.php +++ b/core/lib/Drupal/Core/Render/MetadataBubblingUrlGenerator.php @@ -117,17 +117,6 @@ public function generateFromRoute($name, $parameters = array(), $options = array /** * {@inheritdoc} */ - public function generateFromPath($path = NULL, $options = array(), $collect_bubbleable_metadata = FALSE) { - $generated_url = $this->urlGenerator->generateFromPath($path, $options, TRUE); - if (!$collect_bubbleable_metadata) { - $this->bubble($generated_url, $options); - } - return $collect_bubbleable_metadata ? $generated_url : $generated_url->getGeneratedUrl(); - } - - /** - * {@inheritdoc} - */ public function supports($name) { return $this->urlGenerator->supports($name); } diff --git a/core/lib/Drupal/Core/Routing/UrlGenerator.php b/core/lib/Drupal/Core/Routing/UrlGenerator.php index d990e40..cf6607a 100644 --- a/core/lib/Drupal/Core/Routing/UrlGenerator.php +++ b/core/lib/Drupal/Core/Routing/UrlGenerator.php @@ -370,116 +370,6 @@ public function generateFromRoute($name, $parameters = array(), $options = array } /** - * {@inheritdoc} - */ - public function generateFromPath($path = NULL, $options = array(), $collect_bubbleable_metadata = FALSE) { - $generated_url = $collect_bubbleable_metadata ? new GeneratedUrl() : NULL; - - $request = $this->requestStack->getCurrentRequest(); - $current_base_path = $request->getBasePath() . '/'; - $current_base_url = $request->getSchemeAndHttpHost() . $current_base_path; - $current_script_path = ''; - $base_path_with_script = $request->getBaseUrl(); - if (!empty($base_path_with_script)) { - $script_name = $request->getScriptName(); - if (strpos($base_path_with_script, $script_name) !== FALSE) { - $current_script_path = ltrim(substr($script_name, strlen($current_base_path)), '/') . '/'; - } - } - - // Merge in defaults. - $options += array( - 'fragment' => '', - 'query' => array(), - 'absolute' => FALSE, - 'prefix' => '', - ); - - // A duplicate of the code from - // \Drupal\Component\Utility\UrlHelper::isExternal() to avoid needing - // another function call, since performance inside url() is critical. - if (!isset($options['external'])) { - $colonpos = strpos($path, ':'); - // Avoid calling drupal_strip_dangerous_protocols() if there is any slash - // (/), hash (#) or question_mark (?) before the colon (:) occurrence - - // if any - as this would clearly mean it is not a URL. If the path starts - // with 2 slashes then it is always considered an external URL without an - // explicit protocol part. - $options['external'] = (strpos($path, '//') === 0) - || ($colonpos !== FALSE - && !preg_match('![/?#]!', substr($path, 0, $colonpos)) - && UrlHelper::stripDangerousProtocols($path) == $path); - } - - if (isset($options['fragment']) && $options['fragment'] !== '') { - $options['fragment'] = '#' . $options['fragment']; - } - - if ($options['external']) { - // Split off the fragment. - if (strpos($path, '#') !== FALSE) { - list($path, $old_fragment) = explode('#', $path, 2); - // If $options contains no fragment, take it over from the path. - if (isset($old_fragment) && !$options['fragment']) { - $options['fragment'] = '#' . $old_fragment; - } - } - // Append the query. - if ($options['query']) { - $path .= (strpos($path, '?') !== FALSE ? '&' : '?') . UrlHelper::buildQuery($options['query']); - } - if (isset($options['https'])) { - if ($options['https'] === TRUE) { - $path = str_replace('http://', 'https://', $path); - } - elseif ($options['https'] === FALSE) { - $path = str_replace('https://', 'http://', $path); - } - } - // Reassemble. - $url = $path . $options['fragment']; - return $collect_bubbleable_metadata ? $generated_url->setGeneratedUrl($url) : $url; - } - else { - $path = ltrim($this->processPath('/' . $path, $options, $generated_url), '/'); - } - - if (!isset($options['script'])) { - $options['script'] = $current_script_path; - } - // The base_url might be rewritten from the language rewrite in domain mode. - if (!isset($options['base_url'])) { - if (isset($options['https'])) { - if ($options['https'] === TRUE) { - $options['base_url'] = str_replace('http://', 'https://', $current_base_url); - $options['absolute'] = TRUE; - } - elseif ($options['https'] === FALSE) { - $options['base_url'] = str_replace('https://', 'http://', $current_base_url); - $options['absolute'] = TRUE; - } - } - else { - $options['base_url'] = $current_base_url; - } - } - elseif (rtrim($options['base_url'], '/') == $options['base_url']) { - $options['base_url'] .= '/'; - } - $base = $options['absolute'] ? $options['base_url'] : $current_base_path; - $prefix = empty($path) ? rtrim($options['prefix'], '/') : $options['prefix']; - - if ($options['absolute'] && $collect_bubbleable_metadata) { - $generated_url->addCacheContexts(['url.site']); - } - - $path = str_replace('%2F', '/', rawurlencode($prefix . $path)); - $query = $options['query'] ? ('?' . UrlHelper::buildQuery($options['query'])) : ''; - $url = $base . $options['script'] . $path . $query . $options['fragment']; - return $collect_bubbleable_metadata ? $generated_url->setGeneratedUrl($url) : $url; - } - - /** * Passes the path to a processor manager to allow alterations. */ protected function processPath($path, &$options = array(), BubbleableMetadata $bubbleable_metadata = NULL) { diff --git a/core/lib/Drupal/Core/Routing/UrlGeneratorInterface.php b/core/lib/Drupal/Core/Routing/UrlGeneratorInterface.php index 97868c3..0db116b 100644 --- a/core/lib/Drupal/Core/Routing/UrlGeneratorInterface.php +++ b/core/lib/Drupal/Core/Routing/UrlGeneratorInterface.php @@ -17,86 +17,6 @@ interface UrlGeneratorInterface extends VersatileGeneratorInterface { /** - * Generates an internal or external URL. - * - * @param string $path - * (optional) The internal path or external URL being linked to, such as - * "node/34" or "http://example.com/foo". The default value is equivalent to - * passing in ''. A few notes: - * - If you provide a full URL, it will be considered an external URL. - * - If you provide only the path (e.g. "node/34"), it will be - * considered an internal link. In this case, it should be a system URL, - * and it will be replaced with the alias, if one exists. Additional query - * arguments for internal paths must be supplied in $options['query'], not - * included in $path. - * - If you provide an internal path and $options['alias'] is set to TRUE, the - * path is assumed already to be the correct path alias, and the alias is - * not looked up. - * - The special string '' generates a link to the site's base URL. - * - If your external URL contains a query (e.g. http://example.com/foo?a=b), - * then you can either URL encode the query keys and values yourself and - * include them in $path, or use $options['query'] to let this method - * URL encode them. - * - * @param array $options - * (optional) An associative array of additional options, with the following - * elements: - * - 'query': An array of query key/value-pairs (without any URL-encoding) to - * append to the URL. - * - 'fragment': A fragment identifier (named anchor) to append to the URL. - * Do not include the leading '#' character. - * - 'absolute': Defaults to FALSE. Whether to force the output to be an - * absolute link (beginning with http:). Useful for links that will be - * displayed outside the site, such as in an RSS feed. - * - 'alias': Defaults to FALSE. Whether the given path is a URL alias - * already. - * - 'external': Whether the given path is an external URL. - * - 'language': An optional language object. If the path being linked to is - * internal to the site, $options['language'] is used to look up the alias - * for the URL. If $options['language'] is omitted, the language will be - * obtained from - * \Drupal::languageManager()->getCurrentLanguage(LanguageInterface::TYPE_URL). - * - 'https': Whether this URL should point to a secure location. If not - * defined, the current scheme is used, so the user stays on HTTP or HTTPS - * respectively. TRUE enforces HTTPS and FALSE enforces HTTP. - * - 'base_url': Only used internally by a path processor, for example, to - * modify the base URL when a language dependent URL requires so. - * - 'prefix': Only used internally, to modify the path when a language - * dependent URL requires so. - * - 'script': Added to the URL between the base path and the path prefix. - * Defaults to empty string when clean URLs are in effect, and to - * 'index.php/' when they are not. - * - 'entity_type': The entity type of the object that called the URL - * generator. Only set if the URL generator is invoked by - * \Drupal\Core\Entity\Entity::uri(). - * - 'entity': The entity object (such as a node) for which the URL is being - * generated. Only set if the URL generator is invoked by - * \Drupal\Core\Entity\Entity::uri(). - * @param bool $collect_bubbleable_metadata - * (optional) Defaults to FALSE. When TRUE, both the generated URL and its - * associated bubbleable metadata are returned. - * - * @return string|\Drupal\Core\GeneratedUrl - * A string containing a URL to the given path. - * When $collect_bubbleable_metadata is TRUE, a GeneratedUrl object is - * returned, containing the generated URL plus bubbleable metadata. - * - * @throws \Drupal\Core\Routing\GeneratorNotInitializedException. - * - * @deprecated in Drupal 8.0.x-dev and will be removed before Drupal 8.0.0. - * To generate URLs for Drupal routes (that is, most pages generated by - * Drupal), see UrlGeneratorInterface::generateFromRoute() instead. For - * non-routed local URIs relative to the base path (like robots.txt) see - * \Drupal\Core\Utility\UnroutedUrlAssembler. - * - * @see static::generateFromRoute() - * @see \Drupal\Core\Utility\UnroutedUrlAssembler - * @see \Drupal\Core\Url - * @see \Drupal\Core\GeneratedUrl - */ - public function generateFromPath($path = NULL, $options = array(), $collect_bubbleable_metadata = FALSE); - - /** * Gets the internal path (system path) of a route. * * @param string|\Symfony\Component\Routing\Route $name diff --git a/core/lib/Drupal/Core/Utility/UnroutedUrlAssembler.php b/core/lib/Drupal/Core/Utility/UnroutedUrlAssembler.php index 3c97c44..6522ec9 100644 --- a/core/lib/Drupal/Core/Utility/UnroutedUrlAssembler.php +++ b/core/lib/Drupal/Core/Utility/UnroutedUrlAssembler.php @@ -177,8 +177,7 @@ protected function addOptionDefaults(array &$options) { // If the current request was made with the script name (eg, index.php) in // it, then extract it, making sure the leading / is gone, and a trailing / - // is added, to allow simple string concatenation with other parts. This - // mirrors code from UrlGenerator::generateFromPath(). + // is added, to allow simple string concatenation with other parts. if (!empty($base_path_with_script)) { $script_name = $request->getScriptName(); if (strpos($base_path_with_script, $script_name) !== FALSE) { diff --git a/core/modules/action/src/Plugin/Action/GotoAction.php b/core/modules/action/src/Plugin/Action/GotoAction.php index 770f424..015634e 100644 --- a/core/modules/action/src/Plugin/Action/GotoAction.php +++ b/core/modules/action/src/Plugin/Action/GotoAction.php @@ -7,12 +7,14 @@ namespace Drupal\action\Plugin\Action; +use Drupal\Component\Utility\UrlHelper; use Drupal\Core\Access\AccessResult; use Drupal\Core\Action\ConfigurableActionBase; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\Core\Routing\UrlGeneratorInterface; use Drupal\Core\Session\AccountInterface; +use Drupal\Core\Url; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\HttpFoundation\RedirectResponse; @@ -75,8 +77,17 @@ public static function create(ContainerInterface $container, array $configuratio * {@inheritdoc} */ public function execute($object = NULL) { - $url = $this->urlGenerator - ->generateFromPath($this->configuration['url'], array('absolute' => TRUE)); + $uri = $this->configuration['url']; + // Leave external URLs unchanged, convert internal URLsto internal: URIs. + if (!UrlHelper::isExternal($uri)) { + // @todo '' is valid input for BC reasons, may be removed by + // https://www.drupal.org/node/2421941 + if ($uri === '') { + $uri = ''; + } + $uri = 'internal:/' . ltrim($uri, '/'); + } + $url = Url::fromUri($uri, array('absolute' => TRUE)); $response = new RedirectResponse($url); $listener = function($event) use ($response) { $event->setResponse($response); @@ -101,7 +112,7 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta $form['url'] = array( '#type' => 'textfield', '#title' => t('URL'), - '#description' => t('The URL to which the user should be redirected. This can be an internal URL like node/1234 or an external URL like @url.', array('@url' => 'http://example.com')), + '#description' => t('The URL to which the user should be redirected. This can be an internal URL like /node/1234 or an external URL like @url.', array('@url' => 'http://example.com')), '#default_value' => $this->configuration['url'], '#required' => TRUE, ); diff --git a/core/modules/help/tests/modules/help_test/src/SupernovaGenerator.php b/core/modules/help/tests/modules/help_test/src/SupernovaGenerator.php index 635ecaa..4904474 100644 --- a/core/modules/help/tests/modules/help_test/src/SupernovaGenerator.php +++ b/core/modules/help/tests/modules/help_test/src/SupernovaGenerator.php @@ -39,13 +39,6 @@ public function generate($name, $parameters = array(), $referenceType = self::AB /** * {@inheritdoc} */ - public function generateFromPath($path = NULL, $options = array(), $collect_bubbleable_metadata = FALSE) { - throw new \Exception(); - } - - /** - * {@inheritdoc} - */ public function getPathFromRoute($name, $parameters = array()) { throw new \Exception(); } diff --git a/core/modules/simpletest/src/BrowserTestBase.php b/core/modules/simpletest/src/BrowserTestBase.php index e5712c1..3b2d50c 100644 --- a/core/modules/simpletest/src/BrowserTestBase.php +++ b/core/modules/simpletest/src/BrowserTestBase.php @@ -13,6 +13,7 @@ use Behat\Mink\Mink; use Behat\Mink\Session; use Drupal\Component\Utility\SafeMarkup; +use Drupal\Component\Utility\UrlHelper; use Drupal\Core\Cache\Cache; use Drupal\Core\Database\ConnectionNotDefinedException; use Drupal\Core\Database\Database; @@ -23,6 +24,7 @@ use Drupal\Core\Site\Settings; use Drupal\Core\StreamWrapper\StreamWrapperInterface; use Drupal\Core\Test\TestRunnerKernel; +use Drupal\Core\Url; use Drupal\user\UserInterface; use Symfony\Component\HttpFoundation\Request; @@ -391,7 +393,7 @@ protected function prepareRequest() { * Retrieves a Drupal path or an absolute path. * * @param string $path - * Drupal path or URL to load into Mink controlled browser. + * Drupal path like /node or URL to load into Mink controlled browser. * @param array $options * (optional) Options to be forwarded to the url generator. * @@ -404,7 +406,12 @@ protected function drupalGet($path, array $options = array()) { // The URL generator service is not necessarily available yet; e.g., in // interactive installer tests. if ($this->container->has('url_generator')) { - $url = $this->container->get('url_generator')->generateFromPath($path, $options); + if (UrlHelper::isExternal($path)) { + $url = Url::fromUri($path, $options)->toString(); + } + else { + $url = Url::fromUri('internal:/' . ltrim($path, '/'), $options)->toString(); + } } else { $url = $this->getAbsoluteUrl($path); @@ -642,7 +649,7 @@ protected function drupalLogout() { // idea being if you were properly logged out you should be seeing a login // screen. $assert_session = $this->assertSession(); - $this->drupalGet('user/logout', array('query' => array('destination' => 'user'))); + $this->drupalGet('user/logout', array('query' => array('destination' => Url::fromUri('base:user')->toString()))); $assert_session->statusCodeEquals(200); $assert_session->fieldExists('name'); $assert_session->fieldExists('pass'); diff --git a/core/modules/simpletest/src/WebTestBase.php b/core/modules/simpletest/src/WebTestBase.php index f5c90cf..9ce2674 100644 --- a/core/modules/simpletest/src/WebTestBase.php +++ b/core/modules/simpletest/src/WebTestBase.php @@ -2684,12 +2684,16 @@ protected function drupalGetMails($filter = array()) { */ protected function assertUrl($path, array $options = array(), $message = '', $group = 'Other') { if ($path instanceof Url) { - $url = $path->setAbsolute()->toString(); + $url_obj = $path; + } + elseif (UrlHelper::isExternal($path)) { + $url_obj = Url::fromUri($path, $options); } else { - $options['absolute'] = TRUE; - $url = $this->container->get('url_generator')->generateFromPath($path, $options); + $uri = $path === '' ? 'internal:/' : 'internal:/' . $path; + $url_obj = Url::fromUri($uri, $options); } + $url = $url_obj->setAbsolute()->toString(); if (!$message) { $message = SafeMarkup::format('Expected @url matches current URL (@current_url).', array( '@url' => var_export($url, TRUE), @@ -2950,8 +2954,15 @@ protected function buildUrl($path, array $options = array()) { // The URL generator service is not necessarily available yet; e.g., in // interactive installer tests. else if ($this->container->has('url_generator')) { - $options['absolute'] = TRUE; - return $this->container->get('url_generator')->generateFromPath($path, $options); + if (UrlHelper::isExternal($path)) { + return Url::fromUri($path, $options)->toString(); + } + else { + $uri = $path === '' ? 'internal:/' : 'internal:/' . $path; + return Url::fromUri($uri, $options) + ->setAbsolute() + ->toString(); + } } else { return $this->getAbsoluteUrl($path); diff --git a/core/modules/system/src/Tests/ParamConverter/UpcastingTest.php b/core/modules/system/src/Tests/ParamConverter/UpcastingTest.php index f8ea8eb..3c6bc27 100644 --- a/core/modules/system/src/Tests/ParamConverter/UpcastingTest.php +++ b/core/modules/system/src/Tests/ParamConverter/UpcastingTest.php @@ -7,6 +7,7 @@ namespace Drupal\system\Tests\ParamConverter; +use Drupal\Core\Url; use Drupal\simpletest\WebTestBase; use Drupal\language\Entity\ConfigurableLanguage; @@ -78,9 +79,11 @@ public function testEntityLanguage() { $translation = $node->addTranslation('de'); $translation->setTitle('Deutscher Titel')->save(); - $this->drupalGet("/paramconverter_test/node/" . $node->id() . "/test_language"); + $url = Url::fromRoute('paramconverter_test.node_check_language', array('node' => $node->id())); + $this->drupalGet($url); $this->assertRaw("English label"); - $this->drupalGet("paramconverter_test/node/" . $node->id() . "/test_language", array('language' => $language)); + $url = Url::fromRoute('paramconverter_test.node_check_language', array('node' => $node->id()), array('language' => $language)); + $this->drupalGet($url); $this->assertRaw("Deutscher Titel"); } diff --git a/core/modules/system/src/Tests/Routing/DestinationTest.php b/core/modules/system/src/Tests/Routing/DestinationTest.php index a590d62..215e601 100644 --- a/core/modules/system/src/Tests/Routing/DestinationTest.php +++ b/core/modules/system/src/Tests/Routing/DestinationTest.php @@ -75,7 +75,7 @@ public function testDestination() { // Make sure that 404 pages do not populate $_GET['destination'] with // external URLs. \Drupal::configFactory()->getEditable('system.site')->set('page.404', 'system-test/get-destination')->save(); - $this->drupalGet('http://example.com', ['external' => FALSE]); + $this->drupalGet(Url::fromUri('base:/http://example.com')); $this->assertResponse(404); $this->assertIdentical(Url::fromRoute('')->toString(), $this->getRawContent(), 'External URL is not allowed on 404 pages.'); } diff --git a/core/modules/user/src/Tests/UserBlocksTest.php b/core/modules/user/src/Tests/UserBlocksTest.php index 3da2d46..99009d7 100644 --- a/core/modules/user/src/Tests/UserBlocksTest.php +++ b/core/modules/user/src/Tests/UserBlocksTest.php @@ -7,6 +7,7 @@ namespace Drupal\user\Tests; +use Drupal\Core\Url; use Drupal\simpletest\WebTestBase; /** @@ -89,7 +90,7 @@ function testUserLoginBlock() { // Check that the user login block is not vulnerable to information // disclosure to third party sites. $this->drupalLogout(); - $this->drupalPostForm('http://example.com/', $edit, t('Log in'), array('external' => FALSE)); + $this->drupalPostForm(Url::fromUri('base:/http://example.com/'), $edit, t('Log in')); // Check that we remain on the site after login. $this->assertUrl($user->url('canonical', ['absolute' => TRUE]), [], 'Redirected to user profile page after login from the frontpage'); } diff --git a/core/modules/views/src/Tests/Handler/FieldWebTest.php b/core/modules/views/src/Tests/Handler/FieldWebTest.php index 3f9a184..ddc9b50 100644 --- a/core/modules/views/src/Tests/Handler/FieldWebTest.php +++ b/core/modules/views/src/Tests/Handler/FieldWebTest.php @@ -11,6 +11,7 @@ use Drupal\Component\Utility\Unicode; use Drupal\Component\Utility\UrlHelper; use Drupal\Core\Render\RenderContext; +use Drupal\Core\Url; use Drupal\system\Tests\Cache\AssertPageCacheContextsAndTagsTrait; use Drupal\views\Views; @@ -262,7 +263,7 @@ public function testAlterUrl() { // @todo The route-based URL generator strips out NULL attributes. // $expected_result = \Drupal::url('entity.node.canonical', ['node' => '123'], ['query' => ['foo' => NULL], 'fragment' => 'bar', 'absolute' => $absolute]); - $expected_result = \Drupal::urlGenerator()->generateFromPath('node/123', array('query' => array('foo' => NULL), 'fragment' => 'bar', 'absolute' => $absolute)); + $expected_result = Url::fromUserInput('/node/123', array('query' => array('foo' => NULL), 'fragment' => 'bar', 'absolute' => $absolute))->toString(); $alter['path'] = 'node/123?foo#bar'; $result = $renderer->executeInRenderContext(new RenderContext(), function () use ($id_field, $row) { return $id_field->theme($row); diff --git a/core/tests/Drupal/Tests/Core/EventSubscriber/RedirectResponseSubscriberTest.php b/core/tests/Drupal/Tests/Core/EventSubscriber/RedirectResponseSubscriberTest.php index 193c25b..3a0aa79 100644 --- a/core/tests/Drupal/Tests/Core/EventSubscriber/RedirectResponseSubscriberTest.php +++ b/core/tests/Drupal/Tests/Core/EventSubscriber/RedirectResponseSubscriberTest.php @@ -8,8 +8,8 @@ namespace Drupal\Tests\Core\EventSubscriber; use Drupal\Core\EventSubscriber\RedirectResponseSubscriber; -use Drupal\Core\Routing\RequestContext; use Drupal\Core\Routing\TrustedRedirectResponse; +use Drupal\Core\Utility\UnroutedUrlAssemblerInterface; use Drupal\Tests\UnitTestCase; use Symfony\Component\DependencyInjection\Container; use Symfony\Component\EventDispatcher\EventDispatcher; @@ -34,6 +34,13 @@ class RedirectResponseSubscriberTest extends UnitTestCase { protected $requestContext; /** + * The mocked request context. + * + * @var \Drupal\Core\Utility\UnroutedUrlAssemblerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $urlAssembler; + + /** * {@inheritdoc} */ protected function setUp() { @@ -46,6 +53,17 @@ protected function setUp() { ->method('getCompleteBaseUrl') ->willReturn('http://example.com/drupal'); + $this->urlAssembler = $this->getMock(UnroutedUrlAssemblerInterface::class); + $this->urlAssembler + ->expects($this->any()) + ->method('assemble') + ->willReturnMap([ + ['base:test', ['query' => [], 'fragment' => '', 'absolute' => TRUE], FALSE, 'http://example.com/drupal/test'], + ['base:example.com', ['query' => [], 'fragment' => '', 'absolute' => TRUE], FALSE, 'http://example.com/drupal/example.com'], + ['base:example:com', ['query' => [], 'fragment' => '', 'absolute' => TRUE], FALSE, 'http://example.com/drupal/example:com'], + ['base:javascript:alert(0)', ['query' => [], 'fragment' => '', 'absolute' => TRUE], FALSE, 'http://example.com/drupal/javascript:alert(0)'], + ]); + $container = new Container(); $container->set('router.request_context', $this->requestContext); \Drupal::setContainer($container); @@ -66,27 +84,9 @@ public function testDestinationRedirect(Request $request, $expected) { $dispatcher = new EventDispatcher(); $kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'); $response = new RedirectResponse('http://example.com/drupal'); - $url_generator = $this->getMockBuilder('Drupal\Core\Routing\UrlGenerator') - ->disableOriginalConstructor() - ->setMethods(array('generateFromPath')) - ->getMock(); - - if ($expected) { - $url_generator - ->expects($this->any()) - ->method('generateFromPath') - ->willReturnMap([ - ['test', ['query' => [], 'fragment' => '', 'absolute' => TRUE], FALSE, 'http://example.com/drupal/test'], - ['example.com', ['query' => [], 'fragment' => '', 'absolute' => TRUE], FALSE, 'http://example.com/drupal/example.com'], - ['example:com', ['query' => [], 'fragment' => '', 'absolute' => TRUE], FALSE, 'http://example.com/drupal/example:com'], - ['javascript:alert(0)', ['query' => [], 'fragment' => '', 'absolute' => TRUE], FALSE, 'http://example.com/drupal/javascript:alert(0)'], - ['/test', ['query' => [], 'fragment' => '', 'absolute' => TRUE], FALSE, 'http://example.com/test'], - ]); - } - $request->headers->set('HOST', 'example.com'); - $listener = new RedirectResponseSubscriber($url_generator, $this->requestContext); + $listener = new RedirectResponseSubscriber($this->urlAssembler, $this->requestContext); $dispatcher->addListener(KernelEvents::RESPONSE, array($listener, 'checkRedirectUrl')); $event = new FilterResponseEvent($kernel, $request, HttpKernelInterface::SUB_REQUEST, $response); $dispatcher->dispatch(KernelEvents::RESPONSE, $event); @@ -127,32 +127,8 @@ public function testDestinationRedirectToExternalUrl($request, $expected) { $dispatcher = new EventDispatcher(); $kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'); $response = new RedirectResponse('http://other-example.com'); - $url_generator = $this->getMockBuilder('Drupal\Core\Routing\UrlGenerator') - ->disableOriginalConstructor() - ->setMethods(array('generateFromPath')) - ->getMock(); - $request_context = $this->getMockBuilder('Drupal\Core\Routing\RequestContext') - ->disableOriginalConstructor() - ->getMock(); - $request_context->expects($this->any()) - ->method('getCompleteBaseUrl') - ->willReturn('http://example.com/drupal'); - - if ($expected) { - $url_generator - ->expects($this->any()) - ->method('generateFromPath') - ->willReturnMap([ - ['test', ['query' => [], 'fragment' => '', 'absolute' => TRUE], FALSE, 'http://example.com/drupal/test'], - ['example.com', ['query' => [], 'fragment' => '', 'absolute' => TRUE], FALSE, 'http://example.com/drupal/example.com'], - ['example:com', ['query' => [], 'fragment' => '', 'absolute' => TRUE], FALSE, 'http://example.com/drupal/example:com'], - ['javascript:alert(0)', ['query' => [], 'fragment' => '', 'absolute' => TRUE], FALSE, 'http://example.com/drupal/javascript:alert(0)'], - ['/test', ['query' => [], 'fragment' => '', 'absolute' => TRUE], FALSE, 'http://example.com/test'], - ]); - } - - $listener = new RedirectResponseSubscriber($url_generator, $request_context); + $listener = new RedirectResponseSubscriber($this->urlAssembler, $this->requestContext); $dispatcher->addListener(KernelEvents::RESPONSE, array($listener, 'checkRedirectUrl')); $event = new FilterResponseEvent($kernel, $request, HttpKernelInterface::SUB_REQUEST, $response); $dispatcher->dispatch(KernelEvents::RESPONSE, $event); @@ -167,22 +143,10 @@ public function testRedirectWithOptInExternalUrl() { $dispatcher = new EventDispatcher(); $kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'); $response = new TrustedRedirectResponse('http://external-url.com'); - $url_generator = $this->getMockBuilder('Drupal\Core\Routing\UrlGenerator') - ->disableOriginalConstructor() - ->setMethods(array('generateFromPath')) - ->getMock(); - - $request_context = $this->getMockBuilder('Drupal\Core\Routing\RequestContext') - ->disableOriginalConstructor() - ->getMock(); - $request_context->expects($this->any()) - ->method('getCompleteBaseUrl') - ->willReturn('http://example.com/drupal'); - $request = Request::create(''); $request->headers->set('HOST', 'example.com'); - $listener = new RedirectResponseSubscriber($url_generator, $request_context); + $listener = new RedirectResponseSubscriber($this->urlAssembler, $this->requestContext); $dispatcher->addListener(KernelEvents::RESPONSE, array($listener, 'checkRedirectUrl')); $event = new FilterResponseEvent($kernel, $request, HttpKernelInterface::SUB_REQUEST, $response); $dispatcher->dispatch(KernelEvents::RESPONSE, $event); @@ -214,13 +178,8 @@ public function testDestinationRedirectWithInvalidUrl(Request $request) { $dispatcher = new EventDispatcher(); $kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'); $response = new RedirectResponse('http://example.com/drupal'); - $url_generator = $this->getMock('Drupal\Core\Routing\UrlGeneratorInterface'); - - $request_context = $this->getMockBuilder('Drupal\Core\Routing\RequestContext') - ->disableOriginalConstructor() - ->getMock(); - $listener = new RedirectResponseSubscriber($url_generator, $request_context); + $listener = new RedirectResponseSubscriber($this->urlAssembler, $this->requestContext); $dispatcher->addListener(KernelEvents::RESPONSE, array($listener, 'checkRedirectUrl')); $event = new FilterResponseEvent($kernel, $request, HttpKernelInterface::SUB_REQUEST, $response); $dispatcher->dispatch(KernelEvents::RESPONSE, $event); @@ -257,9 +216,7 @@ public function testSanitizeDestinationForGet($input, $output) { $request = new Request(); $request->query->set('destination', $input); - $url_generator = $this->getMock('Drupal\Core\Routing\UrlGeneratorInterface'); - $request_context = new RequestContext(); - $listener = new RedirectResponseSubscriber($url_generator, $request_context); + $listener = new RedirectResponseSubscriber($this->urlAssembler, $this->requestContext); $kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'); $event = new GetResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST); @@ -283,9 +240,7 @@ public function testSanitizeDestinationForPost($input, $output) { $request = new Request(); $request->request->set('destination', $input); - $url_generator = $this->getMock('Drupal\Core\Routing\UrlGeneratorInterface'); - $request_context = new RequestContext(); - $listener = new RedirectResponseSubscriber($url_generator, $request_context); + $listener = new RedirectResponseSubscriber($this->urlAssembler, $this->requestContext); $kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'); $event = new GetResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST); diff --git a/core/tests/Drupal/Tests/Core/Form/FormSubmitterTest.php b/core/tests/Drupal/Tests/Core/Form/FormSubmitterTest.php index 6be8a5a..b4a794e 100644 --- a/core/tests/Drupal/Tests/Core/Form/FormSubmitterTest.php +++ b/core/tests/Drupal/Tests/Core/Form/FormSubmitterTest.php @@ -9,7 +9,9 @@ use Drupal\Core\DependencyInjection\ContainerBuilder; use Drupal\Core\Form\FormState; +use Drupal\Core\Routing\UrlGeneratorInterface; use Drupal\Core\Url; +use Drupal\Core\Utility\UnroutedUrlAssemblerInterface; use Drupal\Tests\UnitTestCase; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; @@ -29,11 +31,19 @@ class FormSubmitterTest extends UnitTestCase { protected $urlGenerator; /** + * The mocked unrouted URL assembler. + * + * @var \PHPUnit_Framework_MockObject_MockObject|\Drupal\Core\Utility\UnroutedUrlAssemblerInterface + */ + protected $unroutedUrlAssembler; + + /** * {@inheritdoc} */ protected function setUp() { parent::setUp(); - $this->urlGenerator = $this->getMock('Drupal\Core\Routing\UrlGeneratorInterface'); + $this->urlGenerator = $this->getMock(UrlGeneratorInterface::class); + $this->unroutedUrlAssembler = $this->getMock(UnroutedUrlAssemblerInterface::class); } /** @@ -187,9 +197,13 @@ public function testRedirectWithResponseObject() { public function testRedirectWithoutResult() { $form_submitter = $this->getFormSubmitter(); $this->urlGenerator->expects($this->never()) - ->method('generateFromPath'); - $this->urlGenerator->expects($this->never()) ->method('generateFromRoute'); + $this->unroutedUrlAssembler->expects($this->never()) + ->method('assemble'); + $container = new ContainerBuilder(); + $container->set('url_generator', $this->urlGenerator); + $container->set('unrouted_url_assembler', $this->unroutedUrlAssembler); + \Drupal::setContainer($container); $form_state = $this->getMock('Drupal\Core\Form\FormStateInterface'); $form_state->expects($this->once()) ->method('getRedirect') diff --git a/core/tests/Drupal/Tests/Core/Routing/UrlGeneratorTest.php b/core/tests/Drupal/Tests/Core/Routing/UrlGeneratorTest.php index 6607cb5..4d91218 100644 --- a/core/tests/Drupal/Tests/Core/Routing/UrlGeneratorTest.php +++ b/core/tests/Drupal/Tests/Core/Routing/UrlGeneratorTest.php @@ -349,79 +349,6 @@ public function testUrlGenerationWithHttpsRequirement() { } /** - * Tests path-based URL generation. - */ - public function testPathBasedURLGeneration() { - $base_path = '/subdir'; - $base_url = 'http://www.example.com' . $base_path; - - foreach (array('', 'index.php/') as $script_path) { - foreach (array(FALSE, TRUE) as $absolute) { - // Setup a fake request which looks like a Drupal installed under the - // subdir "subdir" on the domain www.example.com. - // To reproduce the values install Drupal like that and use a debugger. - $server = [ - 'SCRIPT_NAME' => '/subdir/index.php', - 'SCRIPT_FILENAME' => $this->root . '/index.php', - 'SERVER_NAME' => 'http://www.example.com', - ]; - $request = Request::create('/subdir/' . $script_path, 'GET', [], [], [], $server); - $request->headers->set('host', ['www.example.com']); - $this->requestStack->push($request); - - // Determine the expected bubbleable metadata. - $expected_cacheability = (new BubbleableMetadata()) - ->setCacheContexts($absolute ? ['url.site'] : []) - ->setCacheMaxAge(Cache::PERMANENT); - - // Get the expected start of the path string. - $base = ($absolute ? $base_url . '/' : $base_path . '/') . $script_path; - $url = $base . 'node/123'; - $result = $this->generator->generateFromPath('node/123', array('absolute' => $absolute)); - $this->assertEquals($url, $result, "$url == $result"); - $generated_url = $this->generator->generateFromPath('node/123', array('absolute' => $absolute), TRUE); - $this->assertEquals($url, $generated_url->getGeneratedUrl(), "$url == $result"); - $this->assertEquals($expected_cacheability, BubbleableMetadata::createFromObject($generated_url)); - - $url = $base . 'node/123#foo'; - $result = $this->generator->generateFromPath('node/123', array('fragment' => 'foo', 'absolute' => $absolute)); - $this->assertEquals($url, $result, "$url == $result"); - $generated_url = $this->generator->generateFromPath('node/123', array('fragment' => 'foo', 'absolute' => $absolute), TRUE); - $this->assertEquals($url, $generated_url->getGeneratedUrl(), "$url == $result"); - $this->assertEquals($expected_cacheability, BubbleableMetadata::createFromObject($generated_url)); - - $url = $base . 'node/123?foo'; - $result = $this->generator->generateFromPath('node/123', array('query' => array('foo' => NULL), 'absolute' => $absolute)); - $this->assertEquals($url, $result, "$url == $result"); - $generated_url = $this->generator->generateFromPath('node/123', array('query' => array('foo' => NULL), 'absolute' => $absolute), TRUE); - $this->assertEquals($url, $generated_url->getGeneratedUrl(), "$url == $result"); - $this->assertEquals($expected_cacheability, BubbleableMetadata::createFromObject($generated_url)); - - $url = $base . 'node/123?foo=bar&bar=baz'; - $result = $this->generator->generateFromPath('node/123', array('query' => array('foo' => 'bar', 'bar' => 'baz'), 'absolute' => $absolute)); - $this->assertEquals($url, $result, "$url == $result"); - $generated_url = $this->generator->generateFromPath('node/123', array('query' => array('foo' => 'bar', 'bar' => 'baz'), 'absolute' => $absolute), TRUE); - $this->assertEquals($url, $generated_url->getGeneratedUrl(), "$url == $result"); - $this->assertEquals($expected_cacheability, BubbleableMetadata::createFromObject($generated_url)); - - $url = $base . 'node/123?foo#bar'; - $result = $this->generator->generateFromPath('node/123', array('query' => array('foo' => NULL), 'fragment' => 'bar', 'absolute' => $absolute)); - $this->assertEquals($url, $result, "$url == $result"); - $generated_url = $this->generator->generateFromPath('node/123', array('query' => array('foo' => NULL), 'fragment' => 'bar', 'absolute' => $absolute), TRUE); - $this->assertEquals($url, $generated_url->getGeneratedUrl(), "$url == $result"); - $this->assertEquals($expected_cacheability, BubbleableMetadata::createFromObject($generated_url)); - - $url = $base; - $result = $this->generator->generateFromPath('', array('absolute' => $absolute)); - $this->assertEquals($url, $result, "$url == $result"); - $generated_url = $this->generator->generateFromPath('', array('absolute' => $absolute), TRUE); - $this->assertEquals($url, $generated_url->getGeneratedUrl(), "$url == $result"); - $this->assertEquals($expected_cacheability, BubbleableMetadata::createFromObject($generated_url)); - } - } - } - - /** * Tests generating a relative URL with no path. * * @param array $options