diff --git a/core/includes/batch.inc b/core/includes/batch.inc
index d1902e0..fe34cc6 100644
--- a/core/includes/batch.inc
+++ b/core/includes/batch.inc
@@ -156,7 +156,9 @@ function _batch_progress_page() {
$batch['url_options']['query']['id'] = $batch['id'];
$batch['url_options']['query']['op'] = $new_op;
- $url = _url($batch['url'], $batch['url_options']);
+ // Normally, the batch is from from the batch route, except in the case of
+ // some special cases, like the installer.
+ $url = Url::fromPath($batch['url'], $batch['url_options'])->toString();
$build = array(
'#theme' => 'progress_bar',
diff --git a/core/includes/form.inc b/core/includes/form.inc
index 69c970f..57af95d 100644
--- a/core/includes/form.inc
+++ b/core/includes/form.inc
@@ -793,7 +793,7 @@ function batch_process($redirect = NULL, $url = 'batch', $redirect_callback = NU
if ($batch['progressive']) {
// Now that we have a batch id, we can generate the redirection link in
// the generic error message.
- $batch['error_message'] = t('Please continue to the error page', array('@error_url' => _url($url, array('query' => array('id' => $batch['id'], 'op' => 'finished')))));
+ $batch['error_message'] = t('Please continue to the error page', array('@error_url' => Url::fromPath($url, array('query' => array('id' => $batch['id'], 'op' => 'finished')))->toString()));
// Clear the way for the redirection to the batch processing page, by
// saving and unsetting the 'destination', if there is any.
@@ -821,7 +821,7 @@ function batch_process($redirect = NULL, $url = 'batch', $redirect_callback = NU
}
else {
$options['absolute'] = TRUE;
- return new RedirectResponse(_url($batch['url'], $options));
+ return new RedirectResponse(Url::fromPath($batch['url'], $options)->toString());
}
}
else {
diff --git a/core/lib/Drupal/Core/Render/Element/RenderElement.php b/core/lib/Drupal/Core/Render/Element/RenderElement.php
index c0c982a..b6b3ebe 100644
--- a/core/lib/Drupal/Core/Render/Element/RenderElement.php
+++ b/core/lib/Drupal/Core/Render/Element/RenderElement.php
@@ -292,7 +292,7 @@ public static function preRenderAjaxForm($element) {
}
// Change progress path to a full URL.
if (isset($settings['progress']['path'])) {
- $settings['progress']['url'] = _url($settings['progress']['path']);
+ $settings['progress']['url'] = Url::fromPath($settings['progress']['path'])->toString();
unset($settings['progress']['path']);
}
diff --git a/core/lib/Drupal/Core/Url.php b/core/lib/Drupal/Core/Url.php
index 999f447..2637ced 100644
--- a/core/lib/Drupal/Core/Url.php
+++ b/core/lib/Drupal/Core/Url.php
@@ -8,6 +8,7 @@
namespace Drupal\Core;
use Drupal\Component\Utility\String;
+use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\DependencyInjection\DependencySerializationTrait;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Routing\UrlGeneratorInterface;
@@ -236,6 +237,59 @@ public static function fromUri($uri, $options = array()) {
}
/**
+ * Creates a new Url object for a path, which may be a Drupal route, an
+ * unroutable local path, or an external URL.
+ *
+ * This method is to be used for generating URLs where the exact source or
+ * type of the path is unknown, such as one coming from user input. In
+ * general, this method should be avoided in favor of Url::fromRoute() or
+ * Url::fromUri().
+ *
+ * SECURITY NOTE: Drupal route checking will bypass the access check, as
+ * the logic will revert to generating an unroutable Url object if the
+ * path validator is used with the access check.
+ *
+ * @param string $path
+ * The path to be converted.
+ * @param array $options
+ * (optional) An associative array of additional URL options, with the
+ * following elements:
+ * - 'query': An array of query key/value-pairs (without any URL-encoding)
+ * to append to the URL. Merged with the parameters array.
+ * - '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.
+ * - 'language': An optional language object used to look up the alias
+ * for the URL. If $options['language'] is omitted, it defaults to the
+ * current language for the language type 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.
+ *
+ * @return \Drupal\Core\Url
+ * A new Url object for the path.
+ *
+ * @see static::fromRoute()
+ * @see static::fromUri()
+ */
+ public static function fromPath($path, $options = array()) {
+ if (UrlHelper::isExternal($path) && UrlHelper::isValid($path)) {
+ return static::fromUri($path, $options);
+ }
+
+ $url = \Drupal::pathValidator()->getUrlIfValidWithoutAccessCheck($path);
+ if ($url === FALSE) {
+ return static::fromUri('base://' . $path, $options);
+ }
+
+ $url->setOptions($options);
+
+ return $url;
+ }
+
+ /**
* Returns the Url object matching a request.
*
* SECURITY NOTE: The request path is not checked to be valid and accessible