Issue #2955685 by Wim Leers, dawehner, mpdonadio, alexpott, borisson_: Unrouted URLs cannot have have overridden query or fragments

8.6.x
Alex Pott 2018-05-18 11:13:12 +01:00
parent d9a566139a
commit a7fdfb6469
No known key found for this signature in database
GPG Key ID: 31905460D4A69276
4 changed files with 23 additions and 13 deletions

View File

@ -2,6 +2,7 @@
namespace Drupal\Core\Utility;
use Drupal\Component\Utility\NestedArray;
use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\GeneratedUrl;
use Drupal\Core\PathProcessor\OutboundPathProcessorInterface;
@ -69,13 +70,18 @@ class UnroutedUrlAssembler implements UnroutedUrlAssemblerInterface {
*/
protected function buildExternalUrl($uri, array $options = [], $collect_bubbleable_metadata = FALSE) {
$this->addOptionDefaults($options);
// Split off the fragment.
if (strpos($uri, '#') !== FALSE) {
list($uri, $old_fragment) = explode('#', $uri, 2);
// If $options contains no fragment, take it over from the path.
if (isset($old_fragment) && !$options['fragment']) {
$options['fragment'] = '#' . $old_fragment;
}
// Split off the query & fragment.
$parsed = UrlHelper::parse($uri);
$uri = $parsed['path'];
$parsed += ['query' => []];
$options += ['query' => []];
$options['query'] = NestedArray::mergeDeep($parsed['query'], $options['query']);
ksort($options['query']);
if ($parsed['fragment'] && !$options['fragment']) {
$options['fragment'] = '#' . $parsed['fragment'];
}
if (isset($options['https'])) {
@ -88,7 +94,7 @@ class UnroutedUrlAssembler implements UnroutedUrlAssemblerInterface {
}
// Append the query.
if ($options['query']) {
$uri .= (strpos($uri, '?') !== FALSE ? '&' : '?') . UrlHelper::buildQuery($options['query']);
$uri .= '?' . UrlHelper::buildQuery($options['query']);
}
// Reassemble.
$url = $uri . $options['fragment'];

View File

@ -42,7 +42,7 @@ class LinkFieldRdfaTest extends FieldRdfaTestBase {
*/
public function testAllFormattersExternal() {
// Set up test values.
$this->testValue = 'http://test.me/foo/bar/neque/porro/quisquam/est/qui-dolorem?foo/bar/neque/porro/quisquam/est/qui-dolorem';
$this->testValue = 'http://test.me/foo/bar/neque/porro/quisquam/est/qui-dolorem?path=foo/bar/neque/porro/quisquam/est/qui-dolorem';
$this->entity = EntityTest::create([]);
$this->entity->{$this->fieldName}->uri = $this->testValue;

View File

@ -306,15 +306,15 @@ class UrlTest extends BrowserTestBase {
// Verify external URL can be extended with a query string.
$url = $test_url;
$query = [$this->randomMachineName(5) => $this->randomMachineName(5)];
$query = ['awesome' => 'drupal'];
$result = Url::fromUri($url, ['query' => $query])->toString();
$this->assertEqual($url . '?' . http_build_query($query, '', '&'), $result, 'External URL can be extended with a query string in $options.');
$this->assertSame('https://www.drupal.org/?awesome=drupal', $result);
// Verify query string can be extended in an external URL.
$url = $test_url . '?drupal=awesome';
$query = [$this->randomMachineName(5) => $this->randomMachineName(5)];
$query = ['awesome' => 'drupal'];
$result = Url::fromUri($url, ['query' => $query])->toString();
$this->assertEqual($url . '&' . http_build_query($query, '', '&'), $result);
$this->assertEqual('https://www.drupal.org/?awesome=drupal&drupal=awesome', $result);
}
}

View File

@ -96,6 +96,10 @@ class UnroutedUrlAssemblerTest extends UnitTestCase {
['http://example.com/test', ['https' => TRUE], 'https://example.com/test'],
['https://example.com/test', ['https' => FALSE], 'http://example.com/test'],
['https://example.com/test?foo=1#bar', [], 'https://example.com/test?foo=1#bar'],
'override-query' => ['https://example.com/test?foo=1#bar', ['query' => ['foo' => 2]], 'https://example.com/test?foo=2#bar'],
'override-query-merge' => ['https://example.com/test?foo=1#bar', ['query' => ['bar' => 2]], 'https://example.com/test?bar=2&foo=1#bar'],
'override-deep-query-merge' => ['https://example.com/test?foo=1#bar', ['query' => ['bar' => ['baz' => 'foo']]], 'https://example.com/test?bar%5Bbaz%5D=foo&foo=1#bar'],
'override-fragment' => ['https://example.com/test?foo=1#bar', ['fragment' => 'baz'], 'https://example.com/test?foo=1#baz'],
['//www.drupal.org', [], '//www.drupal.org'],
];
}