diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc index ab06260..ed3c729 100644 --- a/core/includes/bootstrap.inc +++ b/core/includes/bootstrap.inc @@ -3,6 +3,8 @@ use Symfony\Component\ClassLoader\UniversalClassLoader; use Symfony\Component\ClassLoader\ApcUniversalClassLoader; +use Drupal\Core\Request; + /** * @file * Functions that need to be loaded on every Drupal request. @@ -578,11 +580,11 @@ function conf_path($require_settings = TRUE, $reset = FALSE) { return $conf; } - $script_name = $_SERVER['SCRIPT_NAME']; + $script_name = request()->server->get('SCRIPT_NAME'); if (!$script_name) { - $script_name = $_SERVER['SCRIPT_FILENAME']; + $script_name = request()->server->get('SCRIPT_FILENAME'); } - $http_host = $_SERVER['HTTP_HOST']; + $http_host = request()->server->get('HTTP_HOST'); $conf = find_conf_path($http_host, $script_name, $require_settings); return $conf; } @@ -667,10 +669,10 @@ function drupal_override_server_variables($variables = array()) { if (isset($variables['url'])) { $url = parse_url($variables['url']); if (isset($url['host'])) { - $_SERVER['HTTP_HOST'] = $url['host']; + request()->server->set('HTTP_HOST', $url['host']); } if (isset($url['path'])) { - $_SERVER['SCRIPT_NAME'] = $url['path']; + request()->server->set('SCRIPT_NAME', $url['path']); } unset($variables['url']); } @@ -687,44 +689,40 @@ function drupal_override_server_variables($variables = array()) { 'HTTP_USER_AGENT' => NULL, ); // Replace elements of the $_SERVER array, as appropriate. - $_SERVER = $variables + $_SERVER + $defaults; + request()->server->replace($variables + request()->server->all() + $defaults); } /** * Initializes the PHP environment. */ +//@TODO - maybe make the $_SERVER/request()->server stuff be part of this +// function be in the Core\Drupal\Request function drupal_environment_initialize() { - if (!isset($_SERVER['HTTP_REFERER'])) { - $_SERVER['HTTP_REFERER'] = ''; + if (!request()->server->has('HTTP_REFERER')) { + request()->server->set('HTTP_REFERER',''); } - if (!isset($_SERVER['SERVER_PROTOCOL']) || ($_SERVER['SERVER_PROTOCOL'] != 'HTTP/1.0' && $_SERVER['SERVER_PROTOCOL'] != 'HTTP/1.1')) { - $_SERVER['SERVER_PROTOCOL'] = 'HTTP/1.0'; + if (!request()->server->has('SERVER_PROTOCOL') || (request()->server->get('SERVER_PROTOCOL') != 'HTTP/1.0' && request()->server->get('SERVER_PROTOCOL') != 'HTTP/1.1')) { + request()->server->set('SERVER_PROTOCOL', 'HTTP/1.0'); } - if (isset($_SERVER['HTTP_HOST'])) { + if (request()->server->has('HTTP_HOST')) { // As HTTP_HOST is user input, ensure it only contains characters allowed // in hostnames. See RFC 952 (and RFC 2181). // $_SERVER['HTTP_HOST'] is lowercased here per specifications. - $_SERVER['HTTP_HOST'] = strtolower($_SERVER['HTTP_HOST']); - if (!drupal_valid_http_host($_SERVER['HTTP_HOST'])) { + request()->server->set('HTTP_HOST', strtolower(request()->server->get('HTTP_HOST'))); + //@TODO drupal_valid_http_host function should probably be part of Core\Drupal\Request + if (!drupal_valid_http_host(request()->server->get('HTTP_HOST'))) { // HTTP_HOST is invalid, e.g. if containing slashes it may be an attack. - header($_SERVER['SERVER_PROTOCOL'] . ' 400 Bad Request'); + header(request()->server->get('SERVER_PROTOCOL') . ' 400 Bad Request'); exit; } } else { // Some pre-HTTP/1.1 clients will not send a Host header. Ensure the key is // defined for E_ALL compliance. - $_SERVER['HTTP_HOST'] = ''; + request()->server->set('HTTP_HOST', ''); } - // When clean URLs are enabled, emulate ?q=foo/bar using REQUEST_URI. It is - // not possible to append the query string using mod_rewrite without the B - // flag (this was added in Apache 2.2.8), because mod_rewrite unescapes the - // path before passing it on to PHP. This is a problem when the path contains - // e.g. "&" or "%" that have special meanings in URLs and must be encoded. - $_GET['q'] = request_path(); - // Enforce E_STRICT, but allow users to set levels not part of E_STRICT. error_reporting(E_STRICT | E_ALL | error_reporting()); @@ -755,6 +753,7 @@ function drupal_environment_initialize() { * @return * TRUE if only containing valid characters, or FALSE otherwise. */ +//@TODO - consider moving to Core\Drupal\Request function drupal_valid_http_host($host) { return preg_match('/^\[?(?:[a-zA-Z0-9-:\]_]+\.?)+$/', $host); } @@ -762,6 +761,12 @@ function drupal_valid_http_host($host) { /** * Sets the base URL, cookie domain, and session name from configuration. */ +//@TODO - it seems to me that we duplicate some work already done in request object here +// have to investigate what values from request could be used instead of some of the code here +// we just have to make sure to honour settings.php base url +// maybe by adding setBaseUrl method to \Core\Drupal\Request since request->baseUrl is protected +// look at why $cookie_domain is global - if sensible add to Drupal request object. +// Also we're starting to intersect on discussion of using symfony's session object function drupal_settings_initialize() { global $base_url, $base_path, $base_root; @@ -772,7 +777,7 @@ function drupal_settings_initialize() { if (file_exists(DRUPAL_ROOT . '/' . conf_path() . '/settings.php')) { include_once DRUPAL_ROOT . '/' . conf_path() . '/settings.php'; } - $is_https = isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on'; + $is_https = request()->isSecure(); if (isset($base_url)) { // Parse fixed base URL from settings.php. @@ -787,14 +792,13 @@ function drupal_settings_initialize() { } else { // Create base URL - $http_protocol = $is_https ? 'https' : 'http'; - $base_root = $http_protocol . '://' . $_SERVER['HTTP_HOST']; + $base_root = request()->getScheme() . '://' . request()->server->get('HTTP_HOST'); $base_url = $base_root; // $_SERVER['SCRIPT_NAME'] can, in contrast to $_SERVER['PHP_SELF'], not // be modified by a visitor. - if ($dir = rtrim(dirname($_SERVER['SCRIPT_NAME']), '\/')) { + if ($dir = rtrim(dirname(request()->server->get('SCRIPT_NAME')), '\/')) { // Remove "core" directory if present, allowing install.php, update.php, // cron.php and others to auto-detect a base path. $core_position = strrpos($dir, '/core'); @@ -824,8 +828,8 @@ function drupal_settings_initialize() { list( , $session_name) = explode('://', $base_url, 2); // HTTP_HOST can be modified by a visitor, but we already sanitized it // in drupal_settings_initialize(). - if (!empty($_SERVER['HTTP_HOST'])) { - $cookie_domain = $_SERVER['HTTP_HOST']; + if (request()->server->get('HTTP_HOST') != '') { + $cookie_domain = request()->server->get('HTTP_HOST'); // Strip leading periods, www., and port numbers from cookie domain. $cookie_domain = ltrim($cookie_domain, '.'); if (strpos($cookie_domain, 'www.') === 0) { @@ -1116,7 +1120,7 @@ function drupal_page_is_cacheable($allow_caching = NULL) { $allow_caching_static = $allow_caching; } - return $allow_caching_static && ($_SERVER['REQUEST_METHOD'] == 'GET' || $_SERVER['REQUEST_METHOD'] == 'HEAD') + return $allow_caching_static && (request()->getMethod() == 'GET' || request()->getMethod() == 'HEAD') && !drupal_is_cli(); } @@ -1278,7 +1282,7 @@ function drupal_send_headers($default_headers = array(), $only_default = FALSE) } foreach ($headers as $name_lower => $value) { if ($name_lower == 'status') { - header($_SERVER['SERVER_PROTOCOL'] . ' ' . $value); + header(request()->server->get('SERVER_PROTOCOL') . ' ' . $value); } // Skip headers that have been unset. elseif ($value) { @@ -1344,7 +1348,7 @@ function drupal_page_header() { function drupal_serve_page_from_cache(stdClass $cache) { // Negotiate whether to use compression. $page_compression = variable_get('page_compression', TRUE) && extension_loaded('zlib'); - $return_compressed = $page_compression && isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== FALSE; + $return_compressed = $page_compression && request()->server->has('HTTP_ACCEPT_ENCODING') && strpos(request()->server->get('HTTP_ACCEPT_ENCODING'), 'gzip') !== FALSE; // Get headers set in hook_boot(). Keys are lower-case. $hook_boot_headers = drupal_get_http_header(); @@ -1377,13 +1381,13 @@ function drupal_serve_page_from_cache(stdClass $cache) { header('Etag: ' . $etag); // See if the client has provided the required HTTP headers. - $if_modified_since = isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) : FALSE; - $if_none_match = isset($_SERVER['HTTP_IF_NONE_MATCH']) ? stripslashes($_SERVER['HTTP_IF_NONE_MATCH']) : FALSE; + $if_modified_since = request()->server->has('HTTP_IF_MODIFIED_SINCE') ? strtotime(request()->server->get('HTTP_IF_MODIFIED_SINCE')) : FALSE; + $if_none_match = request()->server->has('HTTP_IF_NONE_MATCH') ? stripslashes(request()->server->get('HTTP_IF_NONE_MATCH')) : FALSE; if ($if_modified_since && $if_none_match && $if_none_match == $etag // etag must match && $if_modified_since == $cache->created) { // if-modified-since must match - header($_SERVER['SERVER_PROTOCOL'] . ' 304 Not Modified'); + header(request()->server->get('SERVER_PROTOCOL') . ' 304 Not Modified'); drupal_send_headers($default_headers); return; } @@ -1654,19 +1658,20 @@ function drupal_validate_utf8($text) { * Because $_SERVER['REQUEST_URI'] is only available on Apache, we generate an * equivalent using other environment variables. */ +//@TODO - see if we even need this - request()->getRequestUri should return what we need function request_uri() { - if (isset($_SERVER['REQUEST_URI'])) { - $uri = $_SERVER['REQUEST_URI']; + if (request()->server->has('REQUEST_URI')) { + $uri = request()->server->get('REQUEST_URI'); } else { - if (isset($_SERVER['argv'])) { - $uri = $_SERVER['SCRIPT_NAME'] . '?' . $_SERVER['argv'][0]; + if (request()->server->has('argv')) { + $uri = request()->server->get('SCRIPT_NAME') . '?' . request()->server->get('argv[0]','',true); } - elseif (isset($_SERVER['QUERY_STRING'])) { - $uri = $_SERVER['SCRIPT_NAME'] . '?' . $_SERVER['QUERY_STRING']; + elseif (request()->server->has('QUERY_STRING')) { + $uri = request()->server->get('SCRIPT_NAME') . '?' . request()->server->get('QUERY_STRING'); } else { - $uri = $_SERVER['SCRIPT_NAME']; + $uri = request()->server->get('SCRIPT_NAME'); } } // Prevent multiple slashes to avoid cross site requests via the Form API. @@ -1759,8 +1764,8 @@ function watchdog($type, $message, $variables = array(), $severity = WATCHDOG_NO 'severity' => $severity, 'link' => $link, 'user' => $user, - 'request_uri' => $base_root . request_uri(), - 'referer' => isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '', + 'request_uri' => $base_root . request()->getRequestUri(), + 'referer' => request()->server->get('HTTP_REFERER', ''), 'ip' => ip_address(), 'timestamp' => REQUEST_TIME, ); @@ -1936,7 +1941,7 @@ function drupal_is_denied($ip) { function drupal_block_denied($ip) { // Deny access to blocked IP addresses - t() is not yet available. if (drupal_is_denied($ip)) { - header($_SERVER['SERVER_PROTOCOL'] . ' 403 Forbidden'); + header(request()->server->get('SERVER_PROTOCOL') . ' 403 Forbidden'); print 'Sorry, ' . check_plain(ip_address()) . ' has been banned.'; exit(); } @@ -1959,7 +1964,7 @@ function drupal_random_bytes($count) { // Initialize on the first call. The contents of $_SERVER includes a mix of // user-specific and system information that varies a little with each page. if (!isset($random_state)) { - $random_state = print_r($_SERVER, TRUE); + $random_state = print_r(request()->server->all(), TRUE); if (function_exists('getmypid')) { // Further initialize with the somewhat random PHP process ID. $random_state .= getmypid(); @@ -2287,19 +2292,9 @@ function _drupal_exception_handler($exception) { * Sets up the script environment and loads settings.php. */ function _drupal_bootstrap_configuration() { - // Set the Drupal custom error handler. - set_error_handler('_drupal_error_handler'); - set_exception_handler('_drupal_exception_handler'); - - drupal_environment_initialize(); - // Start a page timer: - timer_start('page'); - // Initialize the configuration, including variables from settings.php. - drupal_settings_initialize(); // Include and activate the class loader. $loader = drupal_classloader(); - // Register explicit vendor namespaces. $loader->registerNamespaces(array( // All Symfony-borrowed code lives in /core/vendor/Symfony. @@ -2315,6 +2310,17 @@ function _drupal_bootstrap_configuration() { // All Drupal-namespaced code in core lives in /core/lib/Drupal. 'Drupal' => DRUPAL_ROOT . '/core/lib', )); + + // Set the Drupal custom error handler. + set_error_handler('_drupal_error_handler'); + set_exception_handler('_drupal_exception_handler'); + + drupal_environment_initialize(); + // Start a page timer: + timer_start('page'); + // Initialize the configuration, including variables from settings.php. + drupal_settings_initialize(); + } /** @@ -2482,7 +2488,7 @@ function drupal_valid_test_ua() { return $test_prefix; } - if (isset($_SERVER['HTTP_USER_AGENT']) && preg_match("/^(simpletest\d+);(.+);(.+);(.+)$/", $_SERVER['HTTP_USER_AGENT'], $matches)) { + if (request()->server->has('HTTP_USER_AGENT') && preg_match("/^(simpletest\d+);(.+);(.+);(.+)$/", request()->server->get('HTTP_USER_AGENT'), $matches)) { list(, $prefix, $time, $salt, $hmac) = $matches; $check_string = $prefix . ';' . $time . ';' . $salt; // We use the salt from settings.php to make the HMAC key, since @@ -2758,157 +2764,65 @@ function language_default() { } /** + * Returns the request object for the current request. + * + * @return Drupal\Core\Request + * The request object for this request as populated from the PHP superglobals. + */ +function request() { + $request = &drupal_static(__FUNCTION__); + if (empty($request)) { + $request = Request::createFromGlobals(); + } + return $request; +} + +/** * Returns the requested URL path of the page being viewed. * - * Examples: - * - http://example.com/node/306 returns "node/306". - * - http://example.com/drupalfolder/node/306 returns "node/306" while - * base_path() returns "/drupalfolder/". - * - http://example.com/path/alias (which is a path alias for node/306) returns - * "path/alias" as opposed to the internal path. - * - http://example.com/index.php returns an empty string (meaning: front page). - * - http://example.com/index.php?page=1 returns an empty string. + * @deprecated + * Do not use this function. It is provided for temporary backward + * compatibility only. Instead, use the request object directly. * * @return * The requested Drupal URL path. * - * @see current_path() + * @see Drupal\Core\Request::requestPath() */ function request_path() { - static $path; - - if (isset($path)) { - return $path; - } - - if (isset($_GET['q'])) { - // This is a request with a ?q=foo/bar query string. $_GET['q'] is - // overwritten in drupal_path_initialize(), but request_path() is called - // very early in the bootstrap process, so the original value is saved in - // $path and returned in later calls. - $path = $_GET['q']; - } - elseif (isset($_SERVER['REQUEST_URI'])) { - // This request is either a clean URL, or 'index.php', or nonsense. - // Extract the path from REQUEST_URI. - $request_path = strtok($_SERVER['REQUEST_URI'], '?'); - $base_path_len = strlen(rtrim(dirname($_SERVER['SCRIPT_NAME']), '\/')); - // Unescape and strip $base_path prefix, leaving q without a leading slash. - $path = substr(urldecode($request_path), $base_path_len + 1); - // If the path equals the script filename, either because 'index.php' was - // explicitly provided in the URL, or because the server added it to - // $_SERVER['REQUEST_URI'] even when it wasn't provided in the URL (some - // versions of Microsoft IIS do this), the front page should be served. - if ($path == basename($_SERVER['PHP_SELF'])) { - $path = ''; - } - } - else { - // This is the front page. - $path = ''; - } - - // Under certain conditions Apache's RewriteRule directive prepends the value - // assigned to $_GET['q'] with a slash. Moreover we can always have a trailing - // slash in place, hence we need to normalize $_GET['q']. - $path = trim($path, '/'); - - return $path; + return request()->requestPath(); } /** * Returns a component of the current Drupal path. * - * When viewing a page at the path "admin/structure/types", for example, arg(0) - * returns "admin", arg(1) returns "structure", and arg(2) returns "types". - * - * Avoid use of this function where possible, as resulting code is hard to - * read. In menu callback functions, attempt to use named arguments. See the - * explanation in menu.inc for how to construct callbacks that take arguments. - * When attempting to use this function to load an element from the current - * path, e.g. loading the node on a node page, use menu_get_object() instead. - * - * @param $index - * The index of the component, where each component is separated by a '/' - * (forward-slash), and where the first component has an index of 0 (zero). - * @param $path - * A path to break into components. Defaults to the path of the current page. + * @deprecated + * Do not use this function. It is provided for temporary backward + * compatibility only. Instead, use the request object directly. * * @return * The component specified by $index, or NULL if the specified component was - * not found. If called without arguments, it returns an array containing all - * the components of the current path. + * not found. */ function arg($index = NULL, $path = NULL) { - // Even though $arguments doesn't need to be resettable for any functional - // reasons (the result of explode() does not depend on any run-time - // information), it should be resettable anyway in case a module needs to - // free up the memory used by it. - // Use the advanced drupal_static() pattern, since this is called very often. - static $drupal_static_fast; - if (!isset($drupal_static_fast)) { - $drupal_static_fast['arguments'] = &drupal_static(__FUNCTION__); - } - $arguments = &$drupal_static_fast['arguments']; - - if (!isset($path)) { - $path = $_GET['q']; - } - if (!isset($arguments[$path])) { - $arguments[$path] = explode('/', $path); - } - if (!isset($index)) { - return $arguments[$path]; - } - if (isset($arguments[$path][$index])) { - return $arguments[$path][$index]; - } + return request()->pathElement($index); } /** * Returns the IP address of the client machine. * - * If Drupal is behind a reverse proxy, we use the X-Forwarded-For header - * instead of $_SERVER['REMOTE_ADDR'], which would be the IP address of - * the proxy server, and not the client's. The actual header name can be - * configured by the reverse_proxy_header variable. + * @deprecated + * Do not use this function. It is provided for temporary backward + * compatibility only. Instead, use the request object directly. * * @return * IP address of client machine, adjusted for reverse proxy and/or cluster * environments. + * + * @see Symfony\Component\HttpFoundation\Request::getClientIp() */ function ip_address() { - $ip_address = &drupal_static(__FUNCTION__); - - if (!isset($ip_address)) { - $ip_address = $_SERVER['REMOTE_ADDR']; - - if (variable_get('reverse_proxy', 0)) { - $reverse_proxy_header = variable_get('reverse_proxy_header', 'HTTP_X_FORWARDED_FOR'); - if (!empty($_SERVER[$reverse_proxy_header])) { - // If an array of known reverse proxy IPs is provided, then trust - // the XFF header if request really comes from one of them. - $reverse_proxy_addresses = variable_get('reverse_proxy_addresses', array()); - - // Turn XFF header into an array. - $forwarded = explode(',', $_SERVER[$reverse_proxy_header]); - - // Trim the forwarded IPs; they may have been delimited by commas and spaces. - $forwarded = array_map('trim', $forwarded); - - // Tack direct client IP onto end of forwarded array. - $forwarded[] = $ip_address; - - // Eliminate all trusted IPs. - $untrusted = array_diff($forwarded, $reverse_proxy_addresses); - - // The right-most IP is the most specific we can trust. - $ip_address = array_pop($untrusted); - } - } - } - - return $ip_address; + return request()->getClientIp(variable_get('reverse_proxy', 0)); } /** @@ -2958,7 +2872,7 @@ class SchemaCache extends DrupalCacheArray { */ public function __construct() { // Cache by request method. - parent::__construct('schema:runtime:' . ($_SERVER['REQUEST_METHOD'] == 'GET'), 'cache'); + parent::__construct('schema:runtime:' . (request()->server->get('REQUEST_METHOD') == 'GET'), 'cache'); } /** @@ -3392,7 +3306,7 @@ function drupal_static_reset($name = NULL) { * Detects whether the current script is running in a command-line environment. */ function drupal_is_cli() { - return (!isset($_SERVER['SERVER_SOFTWARE']) && (php_sapi_name() == 'cli' || (is_numeric($_SERVER['argc']) && $_SERVER['argc'] > 0))); + return (!request()->server->has('SERVER_SOFTWARE') && (php_sapi_name() == 'cli' || (is_numeric(request()->server->get('argc')) && request()->server->get('argc') > 0))); } /** diff --git a/core/includes/common.inc b/core/includes/common.inc index 9c65647..56bb81e 100644 --- a/core/includes/common.inc +++ b/core/includes/common.inc @@ -2344,7 +2344,7 @@ function l($text, $path, array $options = array()) { ); // Append active class. - if (($path == $_GET['q'] || ($path == '' && drupal_is_front_page())) && + if (($path == request()->systemPath() || ($path == '' && drupal_is_front_page())) && (empty($options['language']) || $options['language']->langcode == $language_url->langcode)) { $options['attributes']['class'][] = 'active'; } diff --git a/core/includes/form.inc b/core/includes/form.inc index 85bffc6..6dea16c 100644 --- a/core/includes/form.inc +++ b/core/includes/form.inc @@ -1238,7 +1238,7 @@ function drupal_redirect_form($form_state) { $function($form_state['redirect']); } } - drupal_goto($_GET['q']); + drupal_goto(request()->systemPath()); } } diff --git a/core/includes/locale.inc b/core/includes/locale.inc index ab11d31..49355a4 100644 --- a/core/includes/locale.inc +++ b/core/includes/locale.inc @@ -272,7 +272,12 @@ function locale_language_from_url($languages) { case LANGUAGE_NEGOTIATION_URL_PREFIX: // $_GET['q'] might not be available at this time, because // path initialization runs after the language bootstrap phase. - list($language, $_GET['q']) = language_url_split_prefix(isset($_GET['q']) ? $_GET['q'] : NULL, $languages); + $path = request()->systemPath(); + list($language, $path) = language_url_split_prefix($path, $languages); + if (empty($path)) { + $path = variable_get('site_frontpage', 'user'); + } + request()->setSystemPath($path); if ($language !== FALSE) { $language_url = $language->langcode; } diff --git a/core/includes/menu.inc b/core/includes/menu.inc index 0ab3d8c..85c6ed9 100644 --- a/core/includes/menu.inc +++ b/core/includes/menu.inc @@ -434,7 +434,7 @@ function menu_set_item($path, $router_item) { function menu_get_item($path = NULL, $router_item = NULL) { $router_items = &drupal_static(__FUNCTION__); if (!isset($path)) { - $path = $_GET['q']; + $path = request()->systemPath(); } if (isset($router_item)) { $router_items[$path] = $router_item; @@ -445,7 +445,7 @@ function menu_get_item($path = NULL, $router_item = NULL) { if (variable_get('menu_rebuild_needed', FALSE) || !variable_get('menu_masks', array())) { menu_rebuild(); } - $original_map = arg(NULL, $path); + $original_map = explode('/', $path); $parts = array_slice($original_map, 0, MENU_MAX_PARTS); $ancestors = menu_get_ancestors($parts); @@ -491,7 +491,7 @@ function menu_execute_active_handler($path = NULL, $deliver = TRUE) { // Allow other modules to change the site status but not the path because that // would not change the global variable. hook_url_inbound_alter() can be used // to change the path. Code later will not use the $read_only_path variable. - $read_only_path = !empty($path) ? $path : $_GET['q']; + $read_only_path = !empty($path) ? $path : request()->systemPath(); drupal_alter('menu_site_status', $page_callback_result, $read_only_path); // Only continue if the site status is not set. @@ -1697,7 +1697,7 @@ function menu_get_active_help() { return ''; } - $arg = drupal_help_arg(arg(NULL)); + $arg = drupal_help_arg(explode('/', request()->systemPath())); foreach (module_implements('help') as $module) { $function = $module . '_help'; @@ -2291,7 +2291,7 @@ function menu_get_active_menu_names() { * A Drupal path - not a path alias. */ function menu_set_active_item($path) { - $_GET['q'] = $path; + request()->setSystemPath($path); } /** diff --git a/core/includes/path.inc b/core/includes/path.inc index b49d42b..cb1af95 100644 --- a/core/includes/path.inc +++ b/core/includes/path.inc @@ -13,12 +13,7 @@ * Initialize the $_GET['q'] variable to the proper normal path. */ function drupal_path_initialize() { - // Ensure $_GET['q'] is set before calling drupal_normal_path(), to support - // path caching with hook_url_inbound_alter(). - if (empty($_GET['q'])) { - $_GET['q'] = variable_get('site_frontpage', 'user'); - } - $_GET['q'] = drupal_get_normal_path($_GET['q']); + request()->setSystemPath(drupal_get_normal_path(request()->systemPath())); } /** @@ -235,7 +230,7 @@ function drupal_cache_system_paths() { function drupal_get_path_alias($path = NULL, $langcode = NULL) { // If no path is specified, use the current page's path. if ($path == NULL) { - $path = $_GET['q']; + $path = request()->systemPath(); } $result = $path; if ($alias = drupal_lookup_path('alias', $path, $langcode)) { @@ -292,7 +287,7 @@ function drupal_is_front_page() { if (!isset($is_front_page)) { // As drupal_path_initialize updates $_GET['q'] with the 'site_frontpage' path, // we can check it against the 'site_frontpage' variable. - $is_front_page = ($_GET['q'] == variable_get('site_frontpage', 'user')); + $is_front_page = (request()->systemPath() == variable_get('site_frontpage', 'user')); } return $is_front_page; @@ -349,10 +344,14 @@ function drupal_match_path($path, $patterns) { * @return * The current Drupal URL path. * + * @deprecated + * Do not use this function. It is provided for temporary backward + * compatibility only. Instead, use the request object directly. + * * @see request_path() */ function current_path() { - return $_GET['q']; + return request()->systemPath(); } /** diff --git a/core/includes/theme.inc b/core/includes/theme.inc index 9ce9289..6469931 100644 --- a/core/includes/theme.inc +++ b/core/includes/theme.inc @@ -1727,7 +1727,7 @@ function theme_links($variables) { // Handle links. if (isset($link['href'])) { - $is_current_path = ($link['href'] == $_GET['q'] || ($link['href'] == '' && drupal_is_front_page())); + $is_current_path = ($link['href'] == request()->systemPath() || ($link['href'] == '' && drupal_is_front_page())); $is_current_language = (empty($link['language']) || $link['language']->langcode == $language_url->langcode); if ($is_current_path && $is_current_language) { $class[] = 'active'; @@ -2479,7 +2479,7 @@ function template_preprocess_html(&$variables) { } // Populate the body classes. - if ($suggestions = theme_get_suggestions(arg(), 'page', '-')) { + if ($suggestions = theme_get_suggestions(request()->pathElements(), 'page', '-')) { foreach ($suggestions as $suggestion) { if ($suggestion != 'page-front') { // Add current suggestion to page classes to make it possible to theme @@ -2527,7 +2527,7 @@ function template_preprocess_html(&$variables) { $variables['head_title'] = implode(' | ', $head_title); // Populate the page template suggestions. - if ($suggestions = theme_get_suggestions(arg(), 'html')) { + if ($suggestions = theme_get_suggestions(request()->pathElements(), 'html')) { $variables['theme_hook_suggestions'] = $suggestions; } } @@ -2539,9 +2539,6 @@ function template_preprocess_html(&$variables) { * inside "modules/system/page.tpl.php". Look in there for the full list of * variables. * - * Uses the arg() function to generate a series of page template suggestions - * based on the current path. - * * Any changes to variables in this preprocessor should also be changed inside * template_preprocess_maintenance_page() to keep all of them consistent. * @@ -2586,7 +2583,7 @@ function template_preprocess_page(&$variables) { } // Populate the page template suggestions. - if ($suggestions = theme_get_suggestions(arg(), 'page')) { + if ($suggestions = theme_get_suggestions(request()->pathElements(), 'page')) { $variables['theme_hook_suggestions'] = $suggestions; } } @@ -2655,7 +2652,7 @@ function template_process_html(&$variables) { * base the additional suggestions on the path of the current page. * * @param $args - * An array of path arguments, such as from function arg(). + * An array of path arguments. * @param $base * A string identifying the base 'thing' from which more specific suggestions * are derived. For example, 'page' or 'html'. diff --git a/core/modules/locale/locale.module b/core/modules/locale/locale.module index d50684e..2f8b754 100644 --- a/core/modules/locale/locale.module +++ b/core/modules/locale/locale.module @@ -893,7 +893,7 @@ function locale_block_info() { */ function locale_block_view($type) { if (language_multilingual()) { - $path = drupal_is_front_page() ? '' : $_GET['q']; + $path = drupal_is_front_page() ? '' : request()->systemPath(); $links = language_negotiation_get_switch_links($type, $path); if (isset($links->links)) { diff --git a/core/modules/locale/locale.test b/core/modules/locale/locale.test index 42a0fbd..d66a546 100644 --- a/core/modules/locale/locale.test +++ b/core/modules/locale/locale.test @@ -2333,7 +2333,7 @@ class LocaleUILanguageNegotiationTest extends DrupalWebTestCase { } /** - * Tests url() when separate domains are used for multiple languages. + * Test if the url function returns the right url when using different domains for different languages. */ function testLanguageDomain() { // Add the Italian language. diff --git a/core/modules/simpletest/simpletest.info b/core/modules/simpletest/simpletest.info index d518a76..549fef5 100644 --- a/core/modules/simpletest/simpletest.info +++ b/core/modules/simpletest/simpletest.info @@ -30,6 +30,7 @@ files[] = tests/pager.test files[] = tests/password.test files[] = tests/path.test files[] = tests/registry.test +files[] = tests/request.test files[] = tests/schema.test files[] = tests/session.test files[] = tests/symfony.test diff --git a/core/modules/simpletest/tests/bootstrap.test b/core/modules/simpletest/tests/bootstrap.test index 13fdf07..607e21b 100644 --- a/core/modules/simpletest/tests/bootstrap.test +++ b/core/modules/simpletest/tests/bootstrap.test @@ -494,16 +494,15 @@ class BootstrapOverrideServerVariablesTestCase extends DrupalUnitTestCase { foreach ($tests as $url => $expected_server_values) { // Remember the original value of $_SERVER, since the function call below // will modify it. - $original_server = $_SERVER; + $original_server = request()->server->all(); // Call drupal_override_server_variables() and ensure that all expected // $_SERVER variables were modified correctly. drupal_override_server_variables(array('url' => $url)); foreach ($expected_server_values as $key => $value) { - $this->assertIdentical($_SERVER[$key], $value); + $this->assertIdentical(request()->server->get($key), $value); } // Restore the original value of $_SERVER. - $_SERVER = $original_server; + request()->server->replace($original_server); } } } - diff --git a/core/modules/simpletest/tests/form_test.module b/core/modules/simpletest/tests/form_test.module index e1e2435..28ba566 100644 --- a/core/modules/simpletest/tests/form_test.module +++ b/core/modules/simpletest/tests/form_test.module @@ -1526,7 +1526,7 @@ function form_test_clicked_button($form, &$form_state) { // 'image_button', and a 'button' with #access=FALSE. This enables form.test // to test a variety of combinations. $i=0; - $args = array_slice(arg(), 2); + $args = array_slice(request()->pathElements(), 2); foreach ($args as $arg) { $name = 'button' . ++$i; // 's', 'b', or 'i' in the argument define the button type wanted. diff --git a/core/modules/simpletest/tests/menu.test b/core/modules/simpletest/tests/menu.test index 5a173b1..5630ff4 100644 --- a/core/modules/simpletest/tests/menu.test +++ b/core/modules/simpletest/tests/menu.test @@ -236,15 +236,15 @@ class MenuRouterTestCase extends DrupalWebTestCase { /** * Test that an authenticated user hitting 'user/login' gets redirected to - * 'user' and 'user/register' gets redirected to the user edit page. + * 'user/uid' and 'user/register' gets redirected to the user edit page. */ function testAuthUserUserLogin() { $loggedInUser = $this->drupalCreateUser(array()); $this->drupalLogin($loggedInUser); $this->DrupalGet('user/login'); - // Check that we got to 'user'. - $this->assertTrue($this->url == url('user', array('absolute' => TRUE)), t("Logged-in user redirected to q=user on accessing q=user/login")); + // Check that we got to 'user/uid'. + $this->assertTrue($this->url == url('user/' . $this->loggedInUser->uid, array('absolute' => TRUE)), t("Logged-in user redirected to q=user/" . $this->loggedInUser->uid . " on accessing q=user/login")); // user/register should redirect to user/UID/edit. $this->DrupalGet('user/register'); diff --git a/core/modules/simpletest/tests/theme.test b/core/modules/simpletest/tests/theme.test index cf75885..8fd2dc6 100644 --- a/core/modules/simpletest/tests/theme.test +++ b/core/modules/simpletest/tests/theme.test @@ -296,7 +296,7 @@ class ThemeFunctionsTestCase extends DrupalWebTestCase { // Required to verify the "active" class in expected links below, and // because the current path is different when running tests manually via // simpletest.module ('batch') and via the testing framework (''). - $_GET['q'] = variable_get('site_frontpage', 'user'); + request()->setSystemPath(variable_get('site_frontpage', 'user')); // Verify that a list of links is properly rendered. $variables = array(); diff --git a/core/modules/system/system.admin.inc b/core/modules/system/system.admin.inc index d28ecfb..00c4c41 100644 --- a/core/modules/system/system.admin.inc +++ b/core/modules/system/system.admin.inc @@ -428,13 +428,15 @@ function system_theme_settings($form, &$form_state, $key = '') { $form['logo'] = array( '#type' => 'fieldset', '#title' => t('Logo image settings'), + '#description' => t('If toggled on, the following logo will be displayed.'), '#attributes' => array('class' => array('theme-settings-bottom')), ); $form['logo']['default_logo'] = array( '#type' => 'checkbox', - '#title' => t('Use the default logo supplied by the theme'), + '#title' => t('Use the default logo'), '#default_value' => theme_get_setting('default_logo', $key), '#tree' => FALSE, + '#description' => t('Check here if you want the theme to use the logo supplied with it.') ); $form['logo']['settings'] = array( '#type' => 'container', @@ -445,10 +447,17 @@ function system_theme_settings($form, &$form_state, $key = '') { ), ), ); + $logo_path = theme_get_setting('logo_path', $key); + // If $logo_path is a public:// URI, display the path relative to the files + // directory; stream wrappers are not end-user friendly. + if (file_uri_scheme($logo_path) == 'public') { + $logo_path = file_uri_target($logo_path); + } $form['logo']['settings']['logo_path'] = array( '#type' => 'textfield', '#title' => t('Path to custom logo'), - '#default_value' => theme_get_setting('logo_path', $key), + '#default_value' => $logo_path, + '#description' => t('The path to the file you would like to use as your logo file instead of the default logo.'), ); $form['logo']['settings']['logo_upload'] = array( '#type' => 'file', @@ -466,8 +475,9 @@ function system_theme_settings($form, &$form_state, $key = '') { ); $form['favicon']['default_favicon'] = array( '#type' => 'checkbox', - '#title' => t('Use the default shortcut icon supplied by the theme'), + '#title' => t('Use the default shortcut icon.'), '#default_value' => theme_get_setting('default_favicon', $key), + '#description' => t('Check here if you want the theme to use the default shortcut icon.') ); $form['favicon']['settings'] = array( '#type' => 'container', @@ -478,10 +488,17 @@ function system_theme_settings($form, &$form_state, $key = '') { ), ), ); + $favicon_path = theme_get_setting('favicon_path', $key); + // If $favicon_path is a public:// URI, display the path relative to the + // files directory; stream wrappers are not end-user friendly. + if (file_uri_scheme($favicon_path) == 'public') { + $favicon_path = file_uri_target($favicon_path); + } $form['favicon']['settings']['favicon_path'] = array( '#type' => 'textfield', '#title' => t('Path to custom icon'), - '#default_value' => theme_get_setting('favicon_path', $key), + '#default_value' => $favicon_path, + '#description' => t('The path to the image file you would like to use as your custom shortcut icon.') ); $form['favicon']['settings']['favicon_upload'] = array( '#type' => 'file', @@ -490,40 +507,6 @@ function system_theme_settings($form, &$form_state, $key = '') { ); } - // Inject human-friendly values and form element descriptions for logo and - // favicon. - foreach (array('logo' => 'logo.png', 'favicon' => 'favicon.ico') as $type => $default) { - if (isset($form[$type]['settings'][$type . '_path'])) { - $element = &$form[$type]['settings'][$type . '_path']; - - // If path is a public:// URI, display the path relative to the files - // directory; stream wrappers are not end-user friendly. - $original_path = $element['#default_value']; - $friendly_path = NULL; - if (file_uri_scheme($original_path) == 'public') { - $friendly_path = file_uri_target($original_path); - $element['#default_value'] = $friendly_path; - } - - // Prepare local file path for description. - if ($original_path && isset($friendly_path)) { - $local_file = strtr($original_path, array('public:/' => variable_get('file_public_path', conf_path() . '/files'))); - } - elseif ($key) { - $local_file = drupal_get_path('theme', $key) . '/' . $default; - } - else { - $local_file = path_to_theme() . '/' . $default; - } - - $element['#description'] = t('Examples: @implicit-public-file (for a file in the public filesystem), @explicit-file, or @local-file.', array( - '@implicit-public-file' => isset($friendly_path) ? $friendly_path : $default, - '@explicit-file' => file_uri_scheme($original_path) !== FALSE ? $original_path : 'public://' . $default, - '@local-file' => $local_file, - )); - } - } - if ($key) { // Call engine-specific settings. $function = $themes[$key]->prefix . '_engine_settings'; @@ -651,20 +634,13 @@ function system_theme_settings_validate($form, &$form_state) { * the path could not be validated. */ function _system_theme_settings_validate_path($path) { - // Absolute local file paths are invalid. - if (drupal_realpath($path) == $path) { - return FALSE; - } - // A path relative to the Drupal root or a fully qualified URI is valid. - if (is_file($path)) { + if (drupal_realpath($path)) { + // The path is relative to the Drupal root, or is a valid URI. return $path; } - // Prepend 'public://' for relative file paths within public filesystem. - if (file_uri_scheme($path) === FALSE) { - $path = 'public://' . $path; - } - if (is_file($path)) { - return $path; + $uri = 'public://' . $path; + if (file_exists($uri)) { + return $uri; } return FALSE; } diff --git a/core/modules/system/system.test b/core/modules/system/system.test index 3a9adcb..cd309c8 100644 --- a/core/modules/system/system.test +++ b/core/modules/system/system.test @@ -1587,8 +1587,6 @@ class SystemMainContentFallback extends DrupalWebTestCase { * Tests for the theme interface functionality. */ class SystemThemeFunctionalTest extends DrupalWebTestCase { - protected $profile = 'testing'; - public static function getInfo() { return array( 'name' => 'Theme interface functionality', @@ -1598,9 +1596,7 @@ class SystemThemeFunctionalTest extends DrupalWebTestCase { } function setUp() { - parent::setUp(array('node', 'block')); - - $this->drupalCreateContentType(array('type' => 'page', 'name' => 'Basic page')); + parent::setUp(); $this->admin_user = $this->drupalCreateUser(array('access administration pages', 'view the administration theme', 'administer themes', 'bypass node access', 'administer blocks')); $this->drupalLogin($this->admin_user); @@ -1613,127 +1609,26 @@ class SystemThemeFunctionalTest extends DrupalWebTestCase { function testThemeSettings() { // Specify a filesystem path to be used for the logo. $file = current($this->drupalGetTestFiles('image')); - $file_relative = strtr($file->uri, array('public:/' => variable_get('file_public_path', conf_path() . '/files'))); - $default_theme_path = 'core/themes/stark'; - - $supported_paths = array( - // Raw stream wrapper URI. - $file->uri => array( - 'form' => file_uri_target($file->uri), - 'src' => file_create_url($file->uri), - ), - // Relative path within the public filesystem. - file_uri_target($file->uri) => array( - 'form' => file_uri_target($file->uri), - 'src' => file_create_url($file->uri), - ), - // Relative path to a public file. - $file_relative => array( - 'form' => $file_relative, - 'src' => file_create_url($file->uri), - ), - // Relative path to an arbitrary file. - 'core/misc/druplicon.png' => array( - 'form' => 'core/misc/druplicon.png', - 'src' => $GLOBALS['base_url'] . '/' . 'core/misc/druplicon.png', - ), - // Relative path to a file in a theme. - $default_theme_path . '/logo.png' => array( - 'form' => $default_theme_path . '/logo.png', - 'src' => $GLOBALS['base_url'] . '/' . $default_theme_path . '/logo.png', - ), - ); - foreach ($supported_paths as $input => $expected) { - $edit = array( - 'default_logo' => FALSE, - 'logo_path' => $input, - ); - $this->drupalPost('admin/appearance/settings', $edit, t('Save configuration')); - $this->assertNoText('The custom logo path is invalid.'); - $this->assertFieldByName('logo_path', $expected['form']); - - // Verify logo path examples. - $elements = $this->xpath('//div[contains(@class, :item)]/div[@class=:description]/code', array( - ':item' => 'form-item-logo-path', - ':description' => 'description', - )); - // Expected default values (if all else fails). - $implicit_public_file = 'logo.png'; - $explicit_file = 'public://logo.png'; - $local_file = $default_theme_path . '/logo.png'; - // Adjust for fully qualified stream wrapper URI in public filesystem. - if (file_uri_scheme($input) == 'public') { - $implicit_public_file = file_uri_target($input); - $explicit_file = $input; - $local_file = strtr($input, array('public:/' => variable_get('file_public_path', conf_path() . '/files'))); - } - // Adjust for fully qualified stream wrapper URI elsewhere. - elseif (file_uri_scheme($input) !== FALSE) { - $explicit_file = $input; - } - // Adjust for relative path within public filesystem. - elseif ($input == file_uri_target($file->uri)) { - $implicit_public_file = $input; - $explicit_file = 'public://' . $input; - $local_file = variable_get('file_public_path', conf_path() . '/files') . '/' . $input; - } - $this->assertEqual((string) $elements[0], $implicit_public_file); - $this->assertEqual((string) $elements[1], $explicit_file); - $this->assertEqual((string) $elements[2], $local_file); - - // Verify the actual 'src' attribute of the logo being output. - $this->drupalGet(''); - $elements = $this->xpath('//*[@id=:id]/img', array(':id' => 'logo')); - $this->assertEqual((string) $elements[0]['src'], $expected['src']); - } - - $unsupported_paths = array( - // Stream wrapper URI to non-existing file. - 'public://whatever.png', - 'private://whatever.png', - 'temporary://whatever.png', - // Bogus stream wrapper URIs. - 'public:/whatever.png', - '://whatever.png', - ':whatever.png', - 'public://', - // Relative path within the public filesystem to non-existing file. - 'whatever.png', - // Relative path to non-existing file in public filesystem. - variable_get('file_public_path', conf_path() . '/files') . '/whatever.png', - // Semi-absolute path to non-existing file in public filesystem. - '/' . variable_get('file_public_path', conf_path() . '/files') . '/whatever.png', - // Relative path to arbitrary non-existing file. - 'core/misc/whatever.png', - // Semi-absolute path to arbitrary non-existing file. - '/core/misc/whatever.png', - // Absolute paths to any local file (even if it exists). - drupal_realpath($file->uri), + $fullpath = drupal_realpath($file->uri); + $edit = array( + 'default_logo' => FALSE, + 'logo_path' => $fullpath, ); - $this->drupalGet('admin/appearance/settings'); - foreach ($unsupported_paths as $path) { - $edit = array( - 'default_logo' => FALSE, - 'logo_path' => $path, - ); - $this->drupalPost(NULL, $edit, t('Save configuration')); - $this->assertText('The custom logo path is invalid.'); - } + $this->drupalPost('admin/appearance/settings', $edit, t('Save configuration')); + $this->drupalGet('node'); + $this->assertRaw($fullpath, t('Logo path successfully changed.')); // Upload a file to use for the logo. + $file = current($this->drupalGetTestFiles('image')); $edit = array( 'default_logo' => FALSE, 'logo_path' => '', 'files[logo_upload]' => drupal_realpath($file->uri), ); - $this->drupalPost('admin/appearance/settings', $edit, t('Save configuration')); - - $fields = $this->xpath($this->constructFieldXpath('name', 'logo_path')); - $uploaded_filename = 'public://' . $fields[0]['value']; - - $this->drupalGet(''); - $elements = $this->xpath('//*[@id=:id]/img', array(':id' => 'logo')); - $this->assertEqual($elements[0]['src'], file_create_url($uploaded_filename)); + $options = array(); + $this->drupalPost('admin/appearance/settings', $edit, t('Save configuration'), $options); + $this->drupalGet('node'); + $this->assertRaw($file->name, t('Logo file successfully uploaded.')); } /** @@ -1792,20 +1687,20 @@ class SystemThemeFunctionalTest extends DrupalWebTestCase { * Test switching the default theme. */ function testSwitchDefaultTheme() { - // Enable Bartik and set it as the default theme. - theme_enable(array('bartik')); + // Enable "stark" and set it as the default theme. + theme_enable(array('stark')); $this->drupalGet('admin/appearance'); - $this->clickLink(t('Set default')); - $this->assertEqual(variable_get('theme_default', ''), 'bartik'); + $this->clickLink(t('Set default'), 1); + $this->assertTrue(variable_get('theme_default', '') == 'stark', t('Site default theme switched successfully.')); // Test the default theme on the secondary links (blocks admin page). $this->drupalGet('admin/structure/block'); - $this->assertText('Bartik(' . t('active tab') . ')', t('Default local task on blocks admin page is the default theme.')); - // Switch back to Stark and test again to test that the menu cache is cleared. + $this->assertText('Stark(' . t('active tab') . ')', t('Default local task on blocks admin page is the default theme.')); + // Switch back to Bartik and test again to test that the menu cache is cleared. $this->drupalGet('admin/appearance'); $this->clickLink(t('Set default'), 0); $this->drupalGet('admin/structure/block'); - $this->assertText('Stark(' . t('active tab') . ')', t('Default local task on blocks admin page has changed.')); + $this->assertText('Bartik(' . t('active tab') . ')', t('Default local task on blocks admin page has changed.')); } } diff --git a/core/modules/user/user.pages.inc b/core/modules/user/user.pages.inc index 8239c53..f020d75 100644 --- a/core/modules/user/user.pages.inc +++ b/core/modules/user/user.pages.inc @@ -504,8 +504,7 @@ function user_cancel_confirm($account, $timestamp = 0, $hashed_pass = '') { function user_page() { global $user; if ($user->uid) { - menu_set_active_item('user/' . $user->uid); - return menu_execute_active_handler(NULL, FALSE); + drupal_goto('user/' . $user->uid); } else { return drupal_get_form('user_login');