Commit b8251f61 authored by xjm's avatar xjm

Issue #2575869 by pwolanin, Wim Leers, JeroenT, dawehner, YesCT: Remove all...

Issue #2575869 by pwolanin, Wim Leers, JeroenT, dawehner, YesCT: Remove all remaining usage of deprecated UrlGeneratorInterface::generateFromPath() and delete it
parent ab90199b
......@@ -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:
......
......@@ -11,7 +11,7 @@
use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\Routing\LocalRedirectResponse;
use Drupal\Core\Routing\RequestContext;
use Drupal\Core\Routing\UrlGeneratorInterface;
use Drupal\Core\Utility\UnroutedUrlAssemblerInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
......@@ -25,22 +25,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;
}
......@@ -117,19 +117,18 @@ protected function getDestinationAsAbsoluteUrl($destination, $scheme_and_host) {
$destination = $scheme_and_host . $destination;
}
else {
// 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.
// Legacy destination query parameters can be internal paths that have
// not yet been converted to URLs.
$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;
......
......@@ -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) {
......
......@@ -22,7 +22,7 @@ interface OutboundPathProcessorInterface {
* 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
......
......@@ -114,17 +114,6 @@ public function generateFromRoute($name, $parameters = array(), $options = array
return $collect_bubbleable_metadata ? $generated_url : $generated_url->getGeneratedUrl();
}
/**
* {@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}
*/
......
......@@ -369,116 +369,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.
*/
......
......@@ -16,86 +16,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 '<front>'. 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 '<front>' 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.
*
......
......@@ -115,11 +115,6 @@ protected function buildLocalUrl($uri, array $options = [], $collect_bubbleable_
// https://www.drupal.org/node/2417459
$uri = substr($uri, 5);
// Strip leading slashes from internal paths to prevent them becoming
// external URLs without protocol. /example.com should not be turned into
// //example.com.
$uri = ltrim($uri, '/');
// Allow (outbound) path processing, if needed. A valid use case is the path
// alias overview form:
// @see \Drupal\path\Controller\PathController::adminOverview().
......@@ -128,6 +123,10 @@ protected function buildLocalUrl($uri, array $options = [], $collect_bubbleable_
// want to include e.g. the request language in the processing.
$uri = $this->pathProcessor->processOutbound($uri, $options, NULL, $generated_url);
}
// Strip leading slashes from internal paths to prevent them becoming
// external URLs without protocol. /example.com should not be turned into
// //example.com.
$uri = ltrim($uri, '/');
// Add any subdirectory where Drupal is installed.
$current_base_path = $request->getBasePath() . '/';
......@@ -177,8 +176,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) {
......
......@@ -7,12 +7,13 @@
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\Utility\UnroutedUrlAssemblerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
......@@ -37,11 +38,11 @@ class GotoAction extends ConfigurableActionBase implements ContainerFactoryPlugi
protected $dispatcher;
/**
* 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 new DeleteNode object.
......@@ -54,29 +55,47 @@ class GotoAction extends ConfigurableActionBase implements ContainerFactoryPlugi
* The plugin implementation definition.
* @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $dispatcher
* The tempstore factory.
* @param \Drupal\Core\Routing\UrlGeneratorInterface $url_generator
* The url generator service.
* @param \Drupal\Core\Utility\UnroutedUrlAssemblerInterface $url_assembler
* The unrouted URL assembler service.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, EventDispatcherInterface $dispatcher, UrlGeneratorInterface $url_generator) {
public function __construct(array $configuration, $plugin_id, $plugin_definition, EventDispatcherInterface $dispatcher, UnroutedUrlAssemblerInterface $url_assembler) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->dispatcher = $dispatcher;
$this->urlGenerator = $url_generator;
$this->unroutedUrlAssembler = $url_assembler;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static($configuration, $plugin_id, $plugin_definition, $container->get('event_dispatcher'), $container->get('url_generator'));
return new static($configuration, $plugin_id, $plugin_definition, $container->get('event_dispatcher'), $container->get('unrouted_url_assembler'));
}
/**
* {@inheritdoc}
*/
public function execute($object = NULL) {
$url = $this->urlGenerator
->generateFromPath($this->configuration['url'], array('absolute' => TRUE));
$url = $this->configuration['url'];
// Leave external URLs unchanged, and assemble others as absolute URLs
// relative to the site's base URL.
if (!UrlHelper::isExternal($url)) {
$parts = UrlHelper::parse($url);
// @todo '<front>' is valid input for BC reasons, may be removed by
// https://www.drupal.org/node/2421941
if ($parts['path'] === '<front>') {
$parts['path'] = '';
}
$uri = 'base:' . $parts['path'];
$options = [
'query' => $parts['query'],
'fragment' => $parts['fragment'],
'absolute' => TRUE,
];
// Treat this as if it's user input of a path relative to the site's
// base URL.
$url = $this->unroutedUrlAssembler->assemble($uri, $options);
}
$response = new RedirectResponse($url);
$listener = function($event) use ($response) {
$event->setResponse($response);
......@@ -101,7 +120,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,
);
......
......@@ -36,13 +36,6 @@ public function generate($name, $parameters = array(), $referenceType = self::AB
throw new \Exception();
}
/**
* {@inheritdoc}
*/
public function generateFromPath($path = NULL, $options = array(), $collect_bubbleable_metadata = FALSE) {
throw new \Exception();
}
/**
* {@inheritdoc}
*/
......
......@@ -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;
......@@ -404,7 +406,14 @@ 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 {
// This is needed for language prefixing.
$options['path_processing'] = TRUE;
$url = Url::fromUri('base:/' . $path, $options)->toString();
}
}
else {
$url = $this->getAbsoluteUrl($path);
......
......@@ -2684,12 +2684,18 @@ 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 === '<front>' ? 'base:/' : 'base:/' . $path;
// This is needed for language prefixing.
$options['path_processing'] = TRUE;
$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 +2956,19 @@ 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);
$force_internal = isset($options['external']) && $options['external'] == FALSE;
if (!$force_internal && UrlHelper::isExternal($path)) {
return Url::fromUri($path, $options)->toString();
}
else {
$uri = $path === '<front>' ? 'base:/' : 'base:/' . $path;
// Path processing is needed for language prefixing. Skip it when a
// path that may look like an external URL is being used as internal.
$options['path_processing'] = !$force_internal;
return Url::fromUri($uri, $options)
->setAbsolute()
->toString();
}
}
else {
return $this->getAbsoluteUrl($path);
......
......@@ -34,7 +34,7 @@ public function testGoTo() {
$this->drupalLogin($account);
// Visit a Drupal page that requires login.
$this->drupalGet('/test-page');
$this->drupalGet('test-page');
$this->assertSession()->statusCodeEquals(200);
// Test page contains some text.
......@@ -46,7 +46,7 @@ public function testGoTo() {
*/
public function testForm() {
// Ensure the proper response code for a _form route.
$this->drupalGet('/form-test/object-builder');
$this->drupalGet('form-test/object-builder');
$this->assertSession()->statusCodeEquals(200);
// Ensure the form and text field exist.
......
......@@ -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);
......
......@@ -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;
......@@ -33,6 +33,13 @@ class RedirectResponseSubscriberTest extends UnitTestCase {
*/
protected $requestContext;
/**
* The mocked request context.
*
* @var \Drupal\Core\Utility\UnroutedUrlAssemblerInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $urlAssembler;
/**
* {@inheritdoc}
*/
......@@ -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();