diff --git a/core/includes/common.inc b/core/includes/common.inc index a78bc06..3036a2c 100644 --- a/core/includes/common.inc +++ b/core/includes/common.inc @@ -6,6 +6,7 @@ use Symfony\Component\Yaml\Parser; use Drupal\Component\PhpStorage\PhpStorageFactory; use Drupal\Component\Utility\NestedArray; +use Drupal\Component\Utility\PathUtils; use Drupal\Core\Cache\CacheBackendInterface; use Drupal\Core\Datetime\DrupalDateTime; use Drupal\Core\Database\Database; @@ -476,12 +477,12 @@ function drupal_get_query_array($query) { /** * Parses an array into a valid, rawurlencoded query string. * - * @see \Drupal\Core\Routing\PathBasedGeneratorInterface::httpBuildQuery() + * @see \Drupal\Component\Utility\PathUtils::httpBuildQuery() * @see drupal_get_query_parameters() * @ingroup php_wrappers */ function drupal_http_build_query(array $query, $parent = '') { - return Drupal::service('router.generator')->httpBuildQuery($query, $parent); + return PathUtils::httpBuildQuery($query, $parent); } /** @@ -512,7 +513,7 @@ function drupal_get_destination() { } else { $path = current_path(); - $query = drupal_http_build_query(drupal_get_query_parameters()); + $query = PathUtils::httpBuildQuery(drupal_get_query_parameters()); if ($query != '') { $path .= '?' . $query; } @@ -1181,11 +1182,12 @@ function valid_number_step($value, $step, $offset = 0.0) { * Drupal\Core\Template\Attribute, or another function that will call * check_plain() separately. * - * @see \Drupal\Core\Routing\PathBasedGeneratorInterface::stripDisallowedProtocols() + * @see \Drupal\Component\Utility\PathUtils::stripDisallowedProtocols() * @see check_url() */ function drupal_strip_dangerous_protocols($uri) { - return Drupal::service('router.generator')->stripDisallowedProtocols($uri); + $allowed_protocols = array_flip(config('system.filter')->get('protocols') ?: array('http', 'https')); + return PathUtils::stripDisallowedProtocols($uri, $allowed_protocols); } /** @@ -1206,7 +1208,7 @@ function drupal_strip_dangerous_protocols($uri) { * @see drupal_strip_dangerous_protocols() */ function check_url($uri) { - return check_plain(Drupal::service('router.generator')->stripDisallowedProtocols($uri)); + return check_plain(drupal_strip_dangerous_protocols($uri)); } /** @@ -1485,7 +1487,7 @@ function filter_xss_bad_protocol($string, $decode = TRUE) { $string = decode_entities($string); } - return check_plain(Drupal::service('router.generator')->stripDisallowedProtocols($string)); + return check_plain(drupal_strip_dangerous_protocols($string)); } /** @@ -1923,7 +1925,15 @@ function datetime_default_format_type() { * @see \Drupal\Core\Routing\PathBasedGeneratorInterface::generateFromPath(). */ function url($path = NULL, array $options = array()) { - return Drupal::service('router.generator')->generateFromPath($path, $options); + $generator = Drupal::service('router.generator'); + if (!$generator->serverVariablesInitialized) { + global $base_url, $base_path, $script_path; + $generator->setBasePath($base_path); + $generator->setBaseUrl($base_url . '/'); + $generator->setScriptPath($script_path); + $generator->serverVariablesInitialized = TRUE; + } + return $generator->generateFromPath($path, $options); } diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc index c6d8eec..b428967 100644 --- a/core/includes/install.core.inc +++ b/core/includes/install.core.inc @@ -374,8 +374,7 @@ function install_begin_request(&$install_state) { )) ->addMethodCall('setUserAgent', array('Drupal (+http://drupal.org/)')); - $container->register('router.generator', 'Drupal\Core\Routing\NullGenerator') - ->addArgument(new Reference('config.factory')); + $container->register('router.generator', 'Drupal\Core\Routing\NullGenerator'); Drupal::setContainer($container); } diff --git a/core/lib/Drupal/Component/Utility/PathUtils.php b/core/lib/Drupal/Component/Utility/PathUtils.php new file mode 100644 index 0000000..e9d40bc --- /dev/null +++ b/core/lib/Drupal/Component/Utility/PathUtils.php @@ -0,0 +1,94 @@ + 0) { + // We found a colon, possibly a protocol. Verify. + $protocol = substr($uri, 0, $colonpos); + // If a colon is preceded by a slash, question mark or hash, it cannot + // possibly be part of the URL scheme. This must be a relative URL, which + // inherits the (safe) protocol of the base document. + if (preg_match('![/?#]!', $protocol)) { + break; + } + // Check if this is a disallowed protocol. Per RFC2616, section 3.2.3 + // (URI Comparison) scheme comparison must be case-insensitive. + if (!isset($protocols[strtolower($protocol)])) { + $uri = substr($uri, $colonpos + 1); + } + } + } while ($before != $uri); + + return $uri; + } + + /** + * Parses an array into a valid, rawurlencoded query string. + * + * This differs from http_build_query() as we need to rawurlencode() (instead of + * urlencode()) all query parameters. + * + * @param $query + * The query parameter array to be processed, e.g. $_GET. + * @param $parent + * Internal use only. Used to build the $query array key for nested items. + * + * @return + * A rawurlencoded string which can be used as or appended to the URL query + * string. + * + * @see drupal_get_query_parameters() + * @ingroup php_wrappers + */ + public static function httpBuildQuery(array $query, $parent = '') { + $params = array(); + + foreach ($query as $key => $value) { + $key = ($parent ? $parent . '[' . rawurlencode($key) . ']' : rawurlencode($key)); + + // Recurse into children. + if (is_array($value)) { + $params[] = static::httpBuildQuery($value, $key); + } + // If a query parameter value is NULL, only append its key. + elseif (!isset($value)) { + $params[] = $key; + } + else { + // For better readability of paths in query strings, we decode slashes. + $params[] = $key . '=' . str_replace('%2F', '/', rawurlencode($value)); + } + } + + return implode('&', $params); + } + +} diff --git a/core/lib/Drupal/Core/CoreBundle.php b/core/lib/Drupal/Core/CoreBundle.php index 6b93d79..8206aa3 100644 --- a/core/lib/Drupal/Core/CoreBundle.php +++ b/core/lib/Drupal/Core/CoreBundle.php @@ -282,7 +282,6 @@ public function build(ContainerBuilder $container) { $container->register('path_subscriber', 'Drupal\Core\EventSubscriber\PathSubscriber') ->addArgument(new Reference('path.alias_manager.cached')) ->addArgument(new Reference('path_processor_manager')) - ->addArgument(new Reference('router.generator')) ->addTag('event_subscriber'); $container->register('legacy_request_subscriber', 'Drupal\Core\EventSubscriber\LegacyRequestSubscriber') ->addTag('event_subscriber'); @@ -378,7 +377,8 @@ protected function registerRouting(ContainerBuilder $container) { ->addArgument(new Reference('router.route_provider')) ->addArgument(new Reference('path_processor_manager')) ->addArgument(NULL) - ->addArgument(new Reference('config.factory')); + ->addArgument(new Reference('config.factory')) + ->addMethodCall('setRequest', array(new Reference('request', ContainerInterface::NULL_ON_INVALID_REFERENCE, false))); $container->register('router.dynamic', 'Symfony\Cmf\Component\Routing\DynamicRouter') ->addArgument(new Reference('router.request_context')) ->addArgument(new Reference('router.matcher')) diff --git a/core/lib/Drupal/Core/EventSubscriber/PathSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/PathSubscriber.php index 34fab09..669db82 100644 --- a/core/lib/Drupal/Core/EventSubscriber/PathSubscriber.php +++ b/core/lib/Drupal/Core/EventSubscriber/PathSubscriber.php @@ -25,10 +25,9 @@ class PathSubscriber extends PathListenerBase implements EventSubscriberInterfac protected $pathProcessor; protected $generator; - public function __construct(AliasManagerCacheDecorator $alias_manager, InboundPathProcessorInterface $path_processor, PathBasedGeneratorInterface $generator) { + public function __construct(AliasManagerCacheDecorator $alias_manager, InboundPathProcessorInterface $path_processor) { $this->aliasManager = $alias_manager; $this->pathProcessor = $path_processor; - $this->generator = $generator; } /** @@ -45,7 +44,6 @@ public function onKernelRequestConvertPath(GetResponseEvent $event) { if ($event->getRequestType() == HttpKernelInterface::MASTER_REQUEST) { $this->aliasManager->setCacheKey($path); } - $this->generator->setRequest($request); } /** diff --git a/core/lib/Drupal/Core/Routing/NullGenerator.php b/core/lib/Drupal/Core/Routing/NullGenerator.php index 9a4c127..5be674e 100644 --- a/core/lib/Drupal/Core/Routing/NullGenerator.php +++ b/core/lib/Drupal/Core/Routing/NullGenerator.php @@ -17,18 +17,13 @@ */ class NullGenerator extends UrlGenerator { - /** - * A config factory for retrieving required config settings. - * - * @var \Drupal\Core\Config\ConfigFactory - */ - protected $config; + public $serverVariablesInitialized = TRUE; /** * Override the parent constructor. */ - public function __construct(ConfigFactory $config) { - $this->config = $config; + public function __construct() { + $this->allowedProtocols = array_flip(array('http', 'https')); } /** diff --git a/core/lib/Drupal/Core/Routing/PathBasedGeneratorInterface.php b/core/lib/Drupal/Core/Routing/PathBasedGeneratorInterface.php index e497295..53b7d63 100644 --- a/core/lib/Drupal/Core/Routing/PathBasedGeneratorInterface.php +++ b/core/lib/Drupal/Core/Routing/PathBasedGeneratorInterface.php @@ -82,38 +82,27 @@ public function generateFromPath($path = NULL, $options = array()); public function setRequest(Request $request); /** - * Parses an array into a valid, rawurlencoded query string. + * Sets the baseUrl property. * - * This differs from http_build_query() as we need to rawurlencode() (instead of - * urlencode()) all query parameters. - * - * @param $query - * The query parameter array to be processed, e.g. $_GET. - * @param $parent - * Internal use only. Used to build the $query array key for nested items. - * - * @return - * A rawurlencoded string which can be used as or appended to the URL query - * string. - * - * @see drupal_get_query_parameters() - * @ingroup php_wrappers + * @var string $url + * The base url to use for url generation. */ - public function httpBuildQuery(array $query, $parent = ''); + public function setBaseUrl($url); /** - * Strips dangerous protocols (e.g. 'javascript:') from a URI. - * - * @param $uri - * A plain-text URI that might contain dangerous protocols. + * Sets the basePath property. * - * @return - * A plain-text URI stripped of dangerous protocols. As with all plain-text - * strings, this return value must not be output to an HTML page without - * check_plain() being called on it. However, it can be passed to functions - * expecting plain-text strings. + * @var string $path + * The base path to use for url generation. + */ + public function setBasePath($path); + + /** + * Sets the scriptPath property. * + * @var string $path + * The script path to use for url generation. */ - public function stripDisallowedProtocols($uri); + public function setScriptPath($path); } diff --git a/core/lib/Drupal/Core/Routing/UrlGenerator.php b/core/lib/Drupal/Core/Routing/UrlGenerator.php index fb30fa9..00d6ff9 100644 --- a/core/lib/Drupal/Core/Routing/UrlGenerator.php +++ b/core/lib/Drupal/Core/Routing/UrlGenerator.php @@ -16,6 +16,8 @@ use Drupal\Core\Config\ConfigFactory; use Drupal\Core\PathProcessor\OutboundPathProcessorInterface; +use Drupal\Component\Utility\PathUtils; + /** * A Generator creates URL strings based on a specified route. */ @@ -36,13 +38,6 @@ class UrlGenerator extends ProviderBasedGenerator implements PathBasedGeneratorI protected $pathProcessor; /** - * A config factory for retrieving required config settings. - * - * @var \Drupal\Core\Config\ConfigFactory - */ - protected $config; - - /** * The base path to use for urls. * * @var string @@ -57,32 +52,25 @@ class UrlGenerator extends ProviderBasedGenerator implements PathBasedGeneratorI protected $baseUrl; /** - * The base url to use for urls, using 'http' as the scheme. - * - * @var string - */ - protected $baseSecureUrl; - - /** - * The base url to use for urls, using 'https' as the scheme. + * The script path to use for urls. * * @var string */ - protected $baseInsecureUrl; + protected $scriptPath; /** - * The script path to use for urls. + * The allowed protocols for generated URLs. * - * @var string + * @var array */ - protected $scriptPath; + protected $allowedProtocols; /** * Whether or not the server properties needed for url generation have been set. * * @var bool */ - protected $serverPropertiesInitialized = FALSE; + public $serverVariablesInitialized = FALSE; /** * Constructs a new generator object. @@ -98,17 +86,7 @@ public function __construct(RouteProviderInterface $provider, OutboundPathProces parent::__construct($provider, $logger); $this->pathProcessor = $path_processor; - $this->config = $config; - } - - /** - * Implements Symfony\Component\Routing\Generator\UrlGeneratorInterface::generate(). - */ - public function generate($name, $parameters = array(), $absolute = FALSE) { - $path = parent::generate($name, $parameters, $absolute); - $path = $this->processPath($path); - - return $path; + $this->allowedProtocols = array_flip($config->get('system.filter')->get('protocols')); } /** @@ -116,18 +94,32 @@ public function generate($name, $parameters = array(), $absolute = FALSE) { */ public function setRequest(Request $request) { $this->request = $request; + // Set some properties, based on the request, that are used during url + // generation. $this->basePath = $request->getBasePath() . '/'; $this->baseUrl = $request->getSchemeAndHttpHost() . $this->basePath; - $this->baseSecureUrl = str_replace('http://', 'https://', $this->baseUrl); - $this->baseInsecureUrl = str_replace('https://', 'http://', $this->baseUrl); $this->scriptPath = ''; $base_path_with_script = $request->getBaseUrl(); - $script_name = $this->request->getScriptName(); + $script_name = $request->getScriptName(); if (!empty($base_path_with_script) && strpos($base_path_with_script, $script_name) !== FALSE) { $length = strlen($this->basePath); $this->scriptPath = ltrim(substr($script_name, $length), '/') . '/'; } - $this->serverPropertiesInitialized = TRUE; + $this->serverVariablesInitialized = TRUE; + } + + public function getRequest(Request $request) { + return $this->request; + } + + /** + * Implements Symfony\Component\Routing\Generator\UrlGeneratorInterface::generate(). + */ + public function generate($name, $parameters = array(), $absolute = FALSE) { + $path = parent::generate($name, $parameters, $absolute); + $path = $this->processPath($path); + + return $path; } /** @@ -135,10 +127,6 @@ public function setRequest(Request $request) { */ public function generateFromPath($path = NULL, $options = array()) { - if (!$this->serverPropertiesInitialized) { - $this->setServerPropertiesWithoutRequest(); - } - // Merge in defaults. $options += array( 'fragment' => '', @@ -154,7 +142,7 @@ public function generateFromPath($path = NULL, $options = array()) { // that would require another function call, and performance inside url() is // critical. $colonpos = strpos($path, ':'); - $options['external'] = ($colonpos !== FALSE && !preg_match('![/?#]!', substr($path, 0, $colonpos)) && $this->stripDisallowedProtocols($path) == $path); + $options['external'] = ($colonpos !== FALSE && !preg_match('![/?#]!', substr($path, 0, $colonpos)) && PathUtils::stripDisallowedProtocols($path, $this->allowedProtocols) == $path); } if (isset($options['fragment']) && $options['fragment'] !== '') { @@ -172,7 +160,7 @@ public function generateFromPath($path = NULL, $options = array()) { } // Append the query. if ($options['query']) { - $path .= (strpos($path, '?') !== FALSE ? '&' : '?') . $this->httpBuildQuery($options['query']); + $path .= (strpos($path, '?') !== FALSE ? '&' : '?') . PathUtils::httpBuildQuery($options['query']); } if (isset($options['https']) && variable_get('https', FALSE)) { if ($options['https'] === TRUE) { @@ -196,11 +184,11 @@ public function generateFromPath($path = NULL, $options = array()) { if (!isset($options['base_url'])) { if (isset($options['https']) && variable_get('https', FALSE)) { if ($options['https'] === TRUE) { - $options['base_url'] = $this->baseSecureUrl; + $options['base_url'] = str_replace('http://', 'https://', $this->baseUrl); $options['absolute'] = TRUE; } elseif ($options['https'] === FALSE) { - $options['base_url'] = $this->baseInsecureUrl; + $options['base_url'] = str_replace('https://', 'http://', $this->baseUrl); $options['absolute'] = TRUE; } } @@ -215,69 +203,29 @@ public function generateFromPath($path = NULL, $options = array()) { $prefix = empty($path) ? rtrim($options['prefix'], '/') : $options['prefix']; $path = str_replace('%2F', '/', rawurlencode($prefix . $path)); - $query = $options['query'] ? ('?' . $this->httpBuildQuery($options['query'])) : ''; + $query = $options['query'] ? ('?' . PathUtils::httpBuildQuery($options['query'])) : ''; return $base . $options['script'] . $path . $query . $options['fragment']; } /** - * Implements \Drupal\Core\Routing\PathBasedGeneratorInterface::stripDisallowedProtocols(). + * Implements \Drupal\Core\Routing\PathBasedGeneratorInterface::setBaseUrl(). */ - public function stripDisallowedProtocols($uri) { - if (!isset($this->allowed_protocols)) { - // filter_xss_admin() is called by the installer and update.php, in which - // case the configuration may not exist (yet). Provide a minimal default set - // of allowed protocols for these cases. - $this->allowed_protocols = array_flip($this->config->get('system.filter')->get('protocols') ?: array('http', 'https')); - } - - // Iteratively remove any invalid protocol found. - do { - $before = $uri; - $colonpos = strpos($uri, ':'); - if ($colonpos > 0) { - // We found a colon, possibly a protocol. Verify. - $protocol = substr($uri, 0, $colonpos); - // If a colon is preceded by a slash, question mark or hash, it cannot - // possibly be part of the URL scheme. This must be a relative URL, which - // inherits the (safe) protocol of the base document. - if (preg_match('![/?#]!', $protocol)) { - break; - } - // Check if this is a disallowed protocol. Per RFC2616, section 3.2.3 - // (URI Comparison) scheme comparison must be case-insensitive. - if (!isset($this->allowed_protocols[strtolower($protocol)])) { - $uri = substr($uri, $colonpos + 1); - } - } - } while ($before != $uri); - - return $uri; + public function setBaseUrl($url) { + $this->baseUrl = $url; } /** - * Implements \Drupal\Core\Routing\PathBasedGeneratorInterface::httpBuildQuery(). + * Implements \Drupal\Core\Routing\PathBasedGeneratorInterface::setBasePath(). */ - public function httpBuildQuery(array $query, $parent = '') { - $params = array(); - - foreach ($query as $key => $value) { - $key = ($parent ? $parent . '[' . rawurlencode($key) . ']' : rawurlencode($key)); - - // Recurse into children. - if (is_array($value)) { - $params[] = $this->httpBuildQuery($value, $key); - } - // If a query parameter value is NULL, only append its key. - elseif (!isset($value)) { - $params[] = $key; - } - else { - // For better readability of paths in query strings, we decode slashes. - $params[] = $key . '=' . str_replace('%2F', '/', rawurlencode($value)); - } - } + public function setBasePath($path) { + $this->basePath = $path; + } - return implode('&', $params); + /** + * Implements \Drupal\Core\Routing\PathBasedGeneratorInterface::setScriptPath(). + */ + public function setScriptPath($path) { + $this->scriptPath = $path; } /** @@ -300,21 +248,5 @@ protected function processPath($path, &$options = array()) { return $path; } - /** - * Sets various server-related properties using globals. - * - * @todo Remove this once we've eliminated all calls to the generateFromPath() - * method that happen without a request object having been set. - * - */ - protected function setServerPropertiesWithoutRequest() { - global $base_url, $base_path, $script_path; - $this->basePath = $base_path; - $this->baseUrl = $base_url . '/'; - $this->baseSecureUrl = str_replace('http://', 'https://', $base_url); - $this->baseInsecureUrl = str_replace('https://', 'http://', $base_url); - $this->scriptPath = $script_path; - $this->serverPropertiesInitialized = TRUE; - } } diff --git a/core/modules/system/lib/Drupal/system/Tests/Common/UrlTest.php b/core/modules/system/lib/Drupal/system/Tests/Common/UrlTest.php index 994d864..66cd090 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Common/UrlTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Common/UrlTest.php @@ -172,53 +172,6 @@ function testDrupalParseUrl() { } /** - * Tests url() functionality. - * - * Tests url() with/without query, with/without fragment, absolute on/off and - * asserts all that works when clean URLs are on and off. - */ - function testUrl() { - $clean_url_settings = array( - 'clean' => '', - 'unclean' => 'index.php/', - ); - $generator = $this->container->get('router.generator'); - foreach ($clean_url_settings as $clean_url_setting => $script_path) { - $clean_urls = $clean_url_setting == 'clean'; - $request = $this->prepareRequestForGenerator($clean_urls); - $base_url = $request->getSchemeAndHttpHost() . $request->getBasePath(); - foreach (array(FALSE, TRUE) as $absolute) { - // Get the expected start of the path string. - $base = ($absolute ? $base_url . '/' : $request->getBasePath() . '/') . $script_path; - $absolute_string = $absolute ? 'absolute' : NULL; - $url = $base . 'node/123'; - $result = $generator->generateFromPath('node/123', array('absolute' => $absolute)); - $this->assertEqual($url, $result, "$url == $result"); - - $url = $base . 'node/123#foo'; - $result = $generator->generateFromPath('node/123', array('fragment' => 'foo', 'absolute' => $absolute)); - $this->assertEqual($url, $result, "$url == $result"); - - $url = $base . 'node/123?foo'; - $result = $generator->generateFromPath('node/123', array('query' => array('foo' => NULL), 'absolute' => $absolute)); - $this->assertEqual($url, $result, "$url == $result"); - - $url = $base . 'node/123?foo=bar&bar=baz'; - $result = $generator->generateFromPath('node/123', array('query' => array('foo' => 'bar', 'bar' => 'baz'), 'absolute' => $absolute)); - $this->assertEqual($url, $result, "$url == $result"); - - $url = $base . 'node/123?foo#bar'; - $result = $generator->generateFromPath('node/123', array('query' => array('foo' => NULL), 'fragment' => 'bar', 'absolute' => $absolute)); - $this->assertEqual($url, $result, "$url == $result"); - - $url = $base; - $result = $generator->generateFromPath('', array('absolute' => $absolute)); - $this->assertEqual($url, $result, "$url == $result"); - } - } - } - - /** * Tests external URL handling. */ function testExternalUrls() { diff --git a/core/modules/system/lib/Drupal/system/Tests/Routing/UrlGeneratorTest.php b/core/modules/system/lib/Drupal/system/Tests/Routing/UrlGeneratorTest.php deleted file mode 100644 index 37bc483..0000000 --- a/core/modules/system/lib/Drupal/system/Tests/Routing/UrlGeneratorTest.php +++ /dev/null @@ -1,85 +0,0 @@ - 'UrlGenerator', - 'description' => 'Confirm that the UrlGenerator is functioning properly.', - 'group' => 'Routing', - ); - } - - function setUp() { - parent::setUp(); - - $routes = new RouteCollection(); - $routes->add('test_1', new Route('/test/one')); - $routes->add('test_2', new Route('/test/two/{narf}')); - $provider = new MockRouteProvider($routes); - - $this->aliasManager = new MockAliasManager(); - $this->aliasManager->addAlias('test/one', 'hello/world'); - - $context = new RequestContext(); - $context->fromRequest(Request::create('/some/path')); - - $processor = new PathProcessorAlias($this->aliasManager); - $processor_manager = new PathProcessorManager(); - $processor_manager->addOutbound($processor, 1000); - $config_context_factory = new ConfigContextFactory(new EventDispatcher()); - $config = new ConfigFactory(new NullStorage(), $config_context_factory->get()); - $generator = new UrlGenerator($provider, $processor_manager, NULL, $config); - $generator->setContext($context); - - $this->generator = $generator; - } - - /** - * Confirms that generated routes will have aliased paths. - */ - public function testAliasGeneration() { - $url = $this->generator->generate('test_1'); - - $this->assertEqual($url, '/hello/world', 'Correct URL generated including alias.'); - } - - /** - * Confirms that generated routes will have aliased paths. - */ - public function testAliasGenerationWithParameters() { - $this->aliasManager->addAlias('test/two/5', 'goodbye/cruel/world'); - $url = $this->generator->generate('test_2', array('narf' => '5')); - $this->assertEqual($url, '/goodbye/cruel/world', 'Correct URL generated including alias and parameters.'); - } - -} diff --git a/core/tests/Drupal/Tests/Core/Routing/UrlGeneratorTest.php b/core/tests/Drupal/Tests/Core/Routing/UrlGeneratorTest.php new file mode 100644 index 0000000..82a1acc --- /dev/null +++ b/core/tests/Drupal/Tests/Core/Routing/UrlGeneratorTest.php @@ -0,0 +1,178 @@ + 'UrlGenerator', + 'description' => 'Confirm that the UrlGenerator is functioning properly.', + 'group' => 'Routing', + ); + } + + function setUp() { + parent::setUp(); + + $routes = new RouteCollection(); + $first_route = new Route('/test/one'); + $second_route = new Route('/test/two/{narf}'); + $routes->add('test_1', $first_route); + $routes->add('test_2', $second_route); + + // Create a route provider stub. + $provider = $this->getMockBuilder('Drupal\Core\Routing\RouteProvider') + ->disableOriginalConstructor() + ->getMock(); + $route_name_return_map = array( + array('test_1', array(), $first_route), + array('test_2', array('narf' => '5'), $second_route), + ); + $provider->expects($this->any()) + ->method('getRouteByName') + ->will($this->returnValueMap($route_name_return_map)); + $routes_names_return_map = array( + array(array('test_1'), array(), array($first_route)), + array(array('test_2'), array('narf' => '5'), array($second_route)), + ); + $provider->expects($this->any()) + ->method('getRoutesByNames') + ->will($this->returnValueMap($routes_names_return_map)); + + // Create an alias manager stub. + $alias_manager = $this->getMockBuilder('Drupal\Core\Path\AliasManager') + ->disableOriginalConstructor() + ->getMock(); + $alias_map = array( + array('test/one', NULL, 'hello/world'), + array('test/two/5', NULL, 'goodbye/cruel/world'), + array('node/123', NULL, 'node/123'), + ); + $alias_manager->expects($this->any()) + ->method('getPathAlias') + ->will($this->returnValueMap($alias_map)); + + $this->aliasManager = $alias_manager; + + $context = new RequestContext(); + $context->fromRequest(Request::create('/some/path')); + + $processor = new PathProcessorAlias($this->aliasManager); + $processor_manager = new PathProcessorManager(); + $processor_manager->addOutbound($processor, 1000); + + // Create a mock config factory for the system.filter config object required + // by the generator. + $config_object = $this->getMockBuilder('Drupal\Core\Config\Config') + ->disableOriginalConstructor() + ->getMock(); + $map = array( + array('protocols', array('http', 'https')) + ); + $config_object->expects($this->any()) + ->method('get') + ->will($this->returnValueMap($map)); + + $config_factory = $this->getMockBuilder('Drupal\Core\Config\ConfigFactory') + ->disableOriginalConstructor() + ->getMock(); + $map = array( + array('system.filter', $config_object), + ); + $config_factory->expects($this->any()) + ->method('get') + ->will($this->returnValueMap($map)); + + $generator = new UrlGenerator($provider, $processor_manager, NULL, $config_factory); + $generator->setContext($context); + + $this->generator = $generator; + } + + /** + * Confirms that generated routes will have aliased paths. + */ + public function testAliasGeneration() { + $url = $this->generator->generate('test_1'); + $this->assertEquals('/hello/world', $url); + } + + /** + * Confirms that generated routes will have aliased paths. + */ + public function testAliasGenerationWithParameters() { + + //$this->aliasManager->addAlias('test/two/5', 'goodbye/cruel/world'); + $url = $this->generator->generate('test_2', array('narf' => '5')); + $this->assertEquals($url, '/goodbye/cruel/world', 'Correct URL generated including alias and parameters.'); + } + + public function testPathBasedURLGeneration() { + $base_path = '/subdir'; + $base_url = 'http://www.example.com' . $base_path; + $this->generator->setBasePath($base_path . '/'); + $this->generator->setBaseUrl($base_url . '/'); + foreach (array('', 'index.php/') as $script_path) { + $this->generator->setScriptPath($script_path); + foreach (array(FALSE, TRUE) as $absolute) { + // Get the expected start of the path string. + $base = ($absolute ? $base_url . '/' : $base_path . '/') . $script_path; + $absolute_string = $absolute ? 'absolute' : NULL; + $url = $base . 'node/123'; + $result = $this->generator->generateFromPath('node/123', array('absolute' => $absolute)); + $this->assertEquals($url, $result, "$url == $result"); + + $url = $base . 'node/123#foo'; + $result = $this->generator->generateFromPath('node/123', array('fragment' => 'foo', 'absolute' => $absolute)); + $this->assertEquals($url, $result, "$url == $result"); + + $url = $base . 'node/123?foo'; + $result = $this->generator->generateFromPath('node/123', array('query' => array('foo' => NULL), 'absolute' => $absolute)); + $this->assertEquals($url, $result, "$url == $result"); + + $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"); + + $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"); + + $url = $base; + $result = $this->generator->generateFromPath('', array('absolute' => $absolute)); + $this->assertEquals($url, $result, "$url == $result"); + } + } + } + +}