diff --git a/core/lib/Drupal/Core/Form/ConfirmFormHelper.php b/core/lib/Drupal/Core/Form/ConfirmFormHelper.php index 30e2c8d..73ba98e 100644 --- a/core/lib/Drupal/Core/Form/ConfirmFormHelper.php +++ b/core/lib/Drupal/Core/Form/ConfirmFormHelper.php @@ -34,7 +34,7 @@ public static function buildCancelLink(ConfirmFormInterface $form, Request $requ // If a destination is specified, that serves as the cancel link. if ($query->has('destination')) { $options = UrlHelper::parse($query->get('destination')); - $url = Url::fromUserEnteredPath($options['path'], $options); + $url = Url::fromUri('user-path://' . $options['path'], $options); } // Check for a route-based cancel link. else { diff --git a/core/lib/Drupal/Core/Url.php b/core/lib/Drupal/Core/Url.php index 823921b..62d6eb8 100644 --- a/core/lib/Drupal/Core/Url.php +++ b/core/lib/Drupal/Core/Url.php @@ -172,44 +172,6 @@ public static function fromRoute($route_name, $route_parameters = array(), $opti } /** - * Creates a new Url object for a user-entered path. - * - * This method should be used for generating URLs where the exact route is - * unknown. This should almost never be necessary, except when dealing with - * user input, which are paths, or possibly external URLs. - * - * In general, this method should be avoided except when processing user input - * in favor of Url::fromRoute() for Drupal routes, and Url::fromUri() for - * external paths, or paths not controlled by Drupal (e.g. text files). - * - * Note: You can call access() on the returned object to do access checking. - * - * @param string $path - * The path to be converted. The path may include query arguments and a - * fragment. - * @param array $options - * (optional) Additional options used for the url. - * - * @return \Drupal\Core\Url - * A Url object. - * - * @see static::fromUri() - * @see static::fromRoute() - */ - public static function fromUserEnteredPath($path, array $options = []) { - if ($scheme = parse_url($path, PHP_URL_SCHEME)) { - $url = static::fromUri($path, $options); - } - else { - $url = \Drupal::pathValidator() - ->getUrlIfValidWithoutAccessCheck($path) ?: Url::fromUri('base://' . $path); - // Allow to specify additional or override options from the path. - $url->setOptions($options + $url->getOptions()); - } - return $url; - } - - /** * Creates a new URL object from a route match. * * @param \Drupal\Core\Routing\RouteMatchInterface $route_match @@ -235,8 +197,11 @@ public static function fromRouteMatch(RouteMatchInterface $route_match) { * generated by Drupal), use Url::fromRoute(). * * @param string $uri - * The URI of the external resource including the scheme. For Drupal paths - * that are not handled by the routing system, use base:// for the scheme. + * The URI of the external resource including the scheme. For user input + * that may correspond to a Drupal route, use user-path:// for the scheme. + * For paths that are known not to be handled by the Drupal routing system + * (such as static files), use base:// for the scheme to get a link + * relative to the Drupal base path (like the HTML element). * @param array $options * (optional) An associative array of additional URL options, with the * following elements: @@ -254,8 +219,14 @@ public static function fromRouteMatch(RouteMatchInterface $route_match) { * defined, the current scheme is used, so the user stays on HTTP or HTTPS * respectively. TRUE enforces HTTPS and FALSE enforces HTTP. * + * Note: the user-path:// scheme should be avoided except when processing actual + * user input that may or may not correspond to a Drupal route. Normally use + * Url::fromRoute() for code linking to any any Drupal page. + * + * You can call access() on the returned object to do access checking. + * * @return \Drupal\Core\Url - * A new Url object for an unrouted (non-Drupal) URL. + * A new Url object. * * @throws \InvalidArgumentException * Thrown when the passed in path has no scheme. @@ -263,12 +234,21 @@ public static function fromRouteMatch(RouteMatchInterface $route_match) { * @see static::fromRoute() */ public static function fromUri($uri, $options = array()) { - if (!parse_url($uri, PHP_URL_SCHEME)) { - throw new \InvalidArgumentException(String::format('The URI "@uri" is invalid. You must use a valid URI scheme. Use base:// for a path, e.g., to a Drupal file that needs the base path. Do not use this for internal paths controlled by Drupal.', ['@uri' => $uri])); + $scheme = parse_url($uri, PHP_URL_SCHEME); + if (!$scheme) { + throw new \InvalidArgumentException(String::format('The URI "@uri" is invalid. You must use a valid URI scheme. Use base:// for a path, e.g., to a Drupal file that needs the base path. Do not use this for internal paths controlled by Drupal. Use user-path:// for user input without a scheme.', ['@uri' => $uri])); + } + if ($scheme == 'user-path'){ + $path = substr($uri, 12); + $url = \Drupal::pathValidator() + ->getUrlIfValidWithoutAccessCheck($path) ?: Url::fromUri('base://' . $path); + // Allow to specify additional or override options from the path. + $url->setOptions($options + $url->getOptions()); + } + else { + $url = new static($uri, array(), $options); + $url->setUnrouted(); } - - $url = new static($uri, array(), $options); - $url->setUnrouted(); return $url; } @@ -590,7 +570,11 @@ public function getInternalPath() { * Returns TRUE if the user has access to the url, otherwise FALSE. */ public function access(AccountInterface $account = NULL) { - return $this->accessManager()->checkNamedRoute($this->getRouteName(), $this->getRouteParameters(), $account); + if ($this->isRouted()) { + return $this->accessManager() + ->checkNamedRoute($this->getRouteName(), $this->getRouteParameters(), $account); + } + return TRUE; } /** diff --git a/core/modules/dblog/src/Controller/DbLogController.php b/core/modules/dblog/src/Controller/DbLogController.php index 9a838ae..732816c 100644 --- a/core/modules/dblog/src/Controller/DbLogController.php +++ b/core/modules/dblog/src/Controller/DbLogController.php @@ -255,11 +255,11 @@ public function eventDetails($event_id) { ), array( array('data' => $this->t('Location'), 'header' => TRUE), - $this->l($dblog->location, $dblog->location ? Url::fromUserEnteredPath($dblog->location) : Url::fromRoute('')), + $this->l($dblog->location, $dblog->location ? Url::fromUri('user-path://' . $dblog->location) : Url::fromRoute('')), ), array( array('data' => $this->t('Referrer'), 'header' => TRUE), - $this->l($dblog->referer, $dblog->referer ? Url::fromUserEnteredPath($dblog->location) : Url::fromRoute('')), + $this->l($dblog->referer, $dblog->referer ? Url::fromUri('user-path://' . $dblog->location) : Url::fromRoute('')), ), array( array('data' => $this->t('Message'), 'header' => TRUE), diff --git a/core/modules/field_ui/src/FieldUI.php b/core/modules/field_ui/src/FieldUI.php index 1b577ab..6ea2aa6 100644 --- a/core/modules/field_ui/src/FieldUI.php +++ b/core/modules/field_ui/src/FieldUI.php @@ -61,9 +61,7 @@ public static function getNextDestination(array $destinations) { $options['query']['destinations'] = $destinations; } // Redirect to any given path within the same domain. - // @todo Use Url::fromPath() once https://www.drupal.org/node/2351379 is - // resolved. - $next_destination = Url::fromUserEnteredPath($options['path']); + $next_destination = Url::fromUri('user-path://' . $options['path']); } return $next_destination; } diff --git a/core/modules/menu_ui/src/Tests/MenuTest.php b/core/modules/menu_ui/src/Tests/MenuTest.php index 531ff5b..c57dec4 100644 --- a/core/modules/menu_ui/src/Tests/MenuTest.php +++ b/core/modules/menu_ui/src/Tests/MenuTest.php @@ -115,8 +115,8 @@ function testMenu() { // Verify delete link exists and reset link does not exist. $this->drupalGet('admin/structure/menu/manage/' . $this->menu->id()); - $this->assertLinkByHref('admin/structure/menu/item/' . $this->items[0]->id() . '/delete'); - $this->assertNoLinkByHref(Url::fromUserEnteredPath('admin/structure/menu/link/' . $this->items[0]->getPluginId() . '/reset')->toString()); + $this->assertLinkByHref(Url::fromRoute('entity.menu_link_content.delete_form', $this->items[0]->id())->toString()); + $this->assertNoLinkByHref(Url::fromRoute('menu_ui.link_reset', $this->items[0]->getPluginId())->toString()); // Check delete and reset access. $this->drupalGet('admin/structure/menu/item/' . $this->items[0]->id() . '/delete'); $this->assertResponse(200); diff --git a/core/modules/views_ui/src/ViewListBuilder.php b/core/modules/views_ui/src/ViewListBuilder.php index 29b74b8..b318a3c 100644 --- a/core/modules/views_ui/src/ViewListBuilder.php +++ b/core/modules/views_ui/src/ViewListBuilder.php @@ -265,7 +265,7 @@ protected function getDisplayPaths(EntityInterface $view) { if ($view->status() && strpos($path, '%') === FALSE) { // @todo Use the method on the executable when // https://www.drupal.org/node/2364157 is available. - $all_paths[] = \Drupal::l('/' . $path, Url::fromUserEnteredPath($path)); + $all_paths[] = \Drupal::l('/' . $path, Url::fromUri('user-path://' . $path)); } else { $all_paths[] = String::checkPlain('/' . $path); diff --git a/core/modules/views_ui/src/ViewUI.php b/core/modules/views_ui/src/ViewUI.php index 0e10ac7..a42fb24 100644 --- a/core/modules/views_ui/src/ViewUI.php +++ b/core/modules/views_ui/src/ViewUI.php @@ -702,7 +702,7 @@ public function renderPreview($display_id, $args = array()) { Xss::filterAdmin($this->executable->getTitle()), ); if (isset($path)) { - $path = \Drupal::l($path, Url::fromUserEnteredPath($path)); + $path = \Drupal::l($path, Url::fromUri('user-path://' . $path)); } else { $path = t('This display has no path.'); diff --git a/core/tests/Drupal/Tests/Core/UrlTest.php b/core/tests/Drupal/Tests/Core/UrlTest.php index 49d4ca9..a08fe59 100644 --- a/core/tests/Drupal/Tests/Core/UrlTest.php +++ b/core/tests/Drupal/Tests/Core/UrlTest.php @@ -170,24 +170,24 @@ public function testFromRouteFront() { } /** - * Tests fromUserEnteredPath() method with an invalid route. + * Tests fromUri() method with a user-entered path not matching any route. * - * @covers ::fromUserEnteredPath + * @covers ::fromUri */ public function testFromRoutedPathWithInvalidRoute() { $this->pathValidator->expects($this->once()) ->method('getUrlIfValidWithoutAccessCheck') ->with('invalid-path') ->willReturn(FALSE); - $url = Url::fromUserEnteredPath('invalid-path'); + $url = Url::fromUri('user-path://invalid-path'); $this->assertSame(FALSE, $url->isRouted()); $this->assertSame('base://invalid-path', $url->getUri()); } /** - * Tests fromUserEnteredPath() method with a valid route. + * Tests fromUri() method with user-entered path matching a valid route. * - * @covers ::fromUserEnteredPath + * @covers ::fromUri */ public function testFromRoutedPathWithValidRoute() { $url = Url::fromRoute('test_route'); @@ -195,7 +195,7 @@ public function testFromRoutedPathWithValidRoute() { ->method('getUrlIfValidWithoutAccessCheck') ->with('valid-path') ->willReturn($url); - $result_url = Url::fromUserEnteredPath('valid-path'); + $result_url = Url::fromUri('user-path://valid-path'); $this->assertSame($url, $result_url); }