diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc index 31b2aa1..0ef2d9d 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. @@ -718,13 +720,6 @@ function drupal_environment_initialize() { $_SERVER['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()); @@ -2292,8 +2287,8 @@ function _drupal_bootstrap_configuration() { // Register explicit vendor namespaces. $loader->registerNamespaces(array( - // All Symfony-borrowed code lives in /core/includes/Symfony. - 'Symfony' => DRUPAL_ROOT . '/core/includes', + // All Symfony-borrowed code lives in /core/vendor/Symfony. + 'Symfony' => DRUPAL_ROOT . '/core/vendor', )); // Register the Drupal namespace for classes in core as a fallback. // This allows to register additional namespaces within the Drupal namespace @@ -2302,8 +2297,8 @@ function _drupal_bootstrap_configuration() { // namespace match based on a string comparison. It further allows modules to // register/overload namespaces in Drupal core. $loader->registerNamespaceFallbacks(array( - // All Drupal-namespaced code in core lives in /core/includes/Drupal. - 'Drupal' => DRUPAL_ROOT . '/core/includes', + // All Drupal-namespaced code in core lives in /core/lib/Drupal. + 'Drupal' => DRUPAL_ROOT . '/core/lib', )); } @@ -2715,157 +2710,59 @@ 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 * * @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 * * @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 * * @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)); } /** @@ -3013,7 +2910,7 @@ function drupal_get_complete_schema($rebuild = FALSE) { */ function drupal_classloader() { // Include the Symfony ClassLoader for loading PSR-0-compatible classes. - require_once DRUPAL_ROOT . '/core/includes/Symfony/Component/ClassLoader/UniversalClassLoader.php'; + require_once DRUPAL_ROOT . '/core/vendor/Symfony/Component/ClassLoader/UniversalClassLoader.php'; // By default, use the UniversalClassLoader which is best for development, // as it does not break when code is moved on the file system. However, as it @@ -3025,7 +2922,7 @@ function drupal_classloader() { switch (variable_get('autoloader_mode', 'default')) { case 'apc': if (function_exists('apc_store')) { - require_once DRUPAL_ROOT . '/core/includes/Symfony/Component/ClassLoader/ApcUniversalClassLoader.php'; + require_once DRUPAL_ROOT . '/core/vendor/Symfony/Component/ClassLoader/ApcUniversalClassLoader.php'; $loader = new ApcUniversalClassLoader('drupal.' . $GLOBALS['drupal_hash_salt']); break; } diff --git a/core/includes/cache.inc b/core/includes/cache.inc index 48dbdd3..ab14bd4 100644 --- a/core/includes/cache.inc +++ b/core/includes/cache.inc @@ -8,20 +8,20 @@ /** * Instantiates and statically caches the correct class for a cache bin. * - * By default, this returns an instance of the Drupal\Cache\DatabaseBackend + * By default, this returns an instance of the Drupal\Core\Cache\DatabaseBackend * class. * - * Classes implementing Drupal\Cache\CacheBackendInterface can register themselves + * Classes implementing Drupal\Core\Cache\CacheBackendInterface can register themselves * both as a default implementation and for specific bins. * * @param $bin * The cache bin for which the cache object should be returned, defaults to * 'cache'. * - * @return Drupal\Cache\CacheBackendInterface + * @return Drupal\Core\Cache\CacheBackendInterface * The cache object associated with the specified bin. * - * @see Drupal\Cache\CacheBackendInterface + * @see Drupal\Core\Cache\CacheBackendInterface */ function cache($bin = 'cache') { // Temporary backwards compatibiltiy layer, allow old style prefixed cache @@ -34,7 +34,7 @@ function cache($bin = 'cache') { if (!isset($cache_objects[$bin])) { $class = variable_get('cache_class_' . $bin); if (!isset($class)) { - $class = variable_get('cache_default_class', 'Drupal\Cache\DatabaseBackend'); + $class = variable_get('cache_default_class', 'Drupal\Core\Cache\DatabaseBackend'); } $cache_objects[$bin] = new $class($bin); } diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc index 61f7891..b0df859 100644 --- a/core/includes/install.core.inc +++ b/core/includes/install.core.inc @@ -277,7 +277,7 @@ function install_begin_request(&$install_state) { // because any data put in the cache during the installer is inherently // suspect, due to the fact that Drupal is not fully set up yet. require_once DRUPAL_ROOT . '/core/includes/cache.inc'; - $conf['cache_default_class'] = 'Drupal\\Cache\\InstallBackend'; + $conf['cache_default_class'] = 'Drupal\Core\Cache\InstallBackend'; // Prepare for themed output. We need to run this at the beginning of the // page request to avoid a different theme accidentally getting set. (We also diff --git a/core/includes/menu.inc b/core/includes/menu.inc index 40f9bfe..d0a7c88 100644 --- a/core/includes/menu.inc +++ b/core/includes/menu.inc @@ -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); // Since there is no limit to the length of $path, use a hash to keep it // short yet unique. @@ -1705,7 +1705,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'; diff --git a/core/includes/path.inc b/core/includes/path.inc index 44bf3fe..0969d51 100644 --- a/core/includes/path.inc +++ b/core/includes/path.inc @@ -292,7 +292,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()->get('q') == variable_get('site_frontpage', 'user')); } return $is_front_page; diff --git a/core/includes/theme.inc b/core/includes/theme.inc index 40c4f35..9983a18 100644 --- a/core/includes/theme.inc +++ b/core/includes/theme.inc @@ -2332,7 +2332,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 @@ -2380,7 +2380,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; } } @@ -2392,9 +2392,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. * @@ -2439,7 +2436,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; } } @@ -2508,7 +2505,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/lib/Drupal/Component/README.txt b/core/lib/Drupal/Component/README.txt new file mode 100644 index 0000000..5b06318 --- /dev/null +++ b/core/lib/Drupal/Component/README.txt @@ -0,0 +1,8 @@ +Drupal Components are independent libraries that do not depend on the rest of +Drupal in order to function. Components MAY depend on other Components, but +that is discouraged. Components MAY NOT depend on any code that is not part of +PHP itself or another Drupal Component. + +Each Component should be in its own namespace, and should be as self-contained +as possible. It should be possible to split a Component off to its own +repository and use as a stand-alone library, independently of Drupal. diff --git a/core/includes/Drupal/Cache/CacheBackendInterface.php b/core/lib/Drupal/Core/Cache/CacheBackendInterface.php similarity index 99% rename from core/includes/Drupal/Cache/CacheBackendInterface.php rename to core/lib/Drupal/Core/Cache/CacheBackendInterface.php index 3cb3c46..6284047 100644 --- a/core/includes/Drupal/Cache/CacheBackendInterface.php +++ b/core/lib/Drupal/Core/Cache/CacheBackendInterface.php @@ -5,7 +5,7 @@ * Definition of CacheBackendInterface. */ -namespace Drupal\Cache; +namespace Drupal\Core\Cache; /** * Defines an interface for cache implementations. diff --git a/core/includes/Drupal/Cache/DatabaseBackend.php b/core/lib/Drupal/Core/Cache/DatabaseBackend.php similarity index 89% rename from core/includes/Drupal/Cache/DatabaseBackend.php rename to core/lib/Drupal/Core/Cache/DatabaseBackend.php index 5d9be14..37af13c 100644 --- a/core/includes/Drupal/Cache/DatabaseBackend.php +++ b/core/lib/Drupal/Core/Cache/DatabaseBackend.php @@ -5,7 +5,7 @@ * Definition of DatabaseBackend. */ -namespace Drupal\Cache; +namespace Drupal\Core\Cache; use Exception; @@ -23,7 +23,7 @@ class DatabaseBackend implements CacheBackendInterface { protected $bin; /** - * Implements Drupal\Cache\CacheBackendInterface::__construct(). + * Implements Drupal\Core\Cache\CacheBackendInterface::__construct(). */ function __construct($bin) { // All cache tables should be prefixed with 'cache_', except for the @@ -35,7 +35,7 @@ class DatabaseBackend implements CacheBackendInterface { } /** - * Implements Drupal\Cache\CacheBackendInterface::get(). + * Implements Drupal\Core\Cache\CacheBackendInterface::get(). */ function get($cid) { $cids = array($cid); @@ -44,7 +44,7 @@ class DatabaseBackend implements CacheBackendInterface { } /** - * Implements Drupal\Cache\CacheBackendInterface::getMultiple(). + * Implements Drupal\Core\Cache\CacheBackendInterface::getMultiple(). */ function getMultiple(&$cids) { try { @@ -114,7 +114,7 @@ class DatabaseBackend implements CacheBackendInterface { } /** - * Implements Drupal\Cache\CacheBackendInterface::set(). + * Implements Drupal\Core\Cache\CacheBackendInterface::set(). */ function set($cid, $data, $expire = CACHE_PERMANENT) { $fields = array( @@ -143,7 +143,7 @@ class DatabaseBackend implements CacheBackendInterface { } /** - * Implements Drupal\Cache\CacheBackendInterface::delete(). + * Implements Drupal\Core\Cache\CacheBackendInterface::delete(). */ function delete($cid) { db_delete($this->bin) @@ -152,7 +152,7 @@ class DatabaseBackend implements CacheBackendInterface { } /** - * Implements Drupal\Cache\CacheBackendInterface::deleteMultiple(). + * Implements Drupal\Core\Cache\CacheBackendInterface::deleteMultiple(). */ function deleteMultiple(Array $cids) { // Delete in chunks when a large array is passed. @@ -165,7 +165,7 @@ class DatabaseBackend implements CacheBackendInterface { } /** - * Implements Drupal\Cache\CacheBackendInterface::deletePrefix(). + * Implements Drupal\Core\Cache\CacheBackendInterface::deletePrefix(). */ function deletePrefix($prefix) { db_delete($this->bin) @@ -174,14 +174,14 @@ class DatabaseBackend implements CacheBackendInterface { } /** - * Implements Drupal\Cache\CacheBackendInterface::flush(). + * Implements Drupal\Core\Cache\CacheBackendInterface::flush(). */ function flush() { db_truncate($this->bin)->execute(); } /** - * Implements Drupal\Cache\CacheBackendInterface::expire(). + * Implements Drupal\Core\Cache\CacheBackendInterface::expire(). */ function expire() { if (variable_get('cache_lifetime', 0)) { @@ -216,7 +216,7 @@ class DatabaseBackend implements CacheBackendInterface { } /** - * Implements Drupal\Cache\CacheBackendInterface::garbageCollection(). + * Implements Drupal\Core\Cache\CacheBackendInterface::garbageCollection(). */ function garbageCollection() { global $user; @@ -236,7 +236,7 @@ class DatabaseBackend implements CacheBackendInterface { } /** - * Implements Drupal\Cache\CacheBackendInterface::isEmpty(). + * Implements Drupal\Core\Cache\CacheBackendInterface::isEmpty(). */ function isEmpty() { $this->garbageCollection(); diff --git a/core/includes/Drupal/Cache/InstallBackend.php b/core/lib/Drupal/Core/Cache/InstallBackend.php similarity index 80% rename from core/includes/Drupal/Cache/InstallBackend.php rename to core/lib/Drupal/Core/Cache/InstallBackend.php index f13ff98..8a1b177 100644 --- a/core/includes/Drupal/Cache/InstallBackend.php +++ b/core/lib/Drupal/Core/Cache/InstallBackend.php @@ -5,7 +5,7 @@ * Definition of InstallBackend. */ -namespace Drupal\Cache; +namespace Drupal\Core\Cache; use Exception; @@ -34,26 +34,26 @@ use Exception; class InstallBackend extends DatabaseBackend { /** - * Overrides Drupal\Cache\DatabaseBackend::get(). + * Overrides Drupal\Core\Cache\CacheBackendInterface::get(). */ function get($cid) { return FALSE; } /** - * Overrides Drupal\Cache\DatabaseBackend::getMultiple(). + * Overrides Drupal\Core\Cache\CacheBackendInterface::getMultiple(). */ function getMultiple(&$cids) { return array(); } /** - * Overrides Drupal\Cache\DatabaseBackend::set(). + * Overrides Drupal\Core\Cache\CacheBackendInterface::set(). */ function set($cid, $data, $expire = CACHE_PERMANENT) {} /** - * Implements Drupal\Cache\DatabaseBackend::delete(). + * Implements Drupal\Core\Cache\CacheBackendInterface::delete(). */ function delete($cid) { try { @@ -65,7 +65,7 @@ class InstallBackend extends DatabaseBackend { } /** - * Implements Drupal\Cache\DatabaseBackend::deleteMultiple(). + * Implements Drupal\Core\Cache\CacheBackendInterface::deleteMultiple(). */ function deleteMultiple(array $cids) { try { @@ -77,7 +77,7 @@ class InstallBackend extends DatabaseBackend { } /** - * Implements Drupal\Cache\DatabaseBackend::deletePrefix(). + * Implements Drupal\Core\Cache\CacheBackendInterface::deletePrefix(). */ function deletePrefix($prefix) { try { @@ -89,7 +89,7 @@ class InstallBackend extends DatabaseBackend { } /** - * Implements Drupal\Cache\DatabaseBackend::flush(). + * Implements Drupal\Core\Cache\CacheBackendInterface::flush(). */ function flush() { try { @@ -101,7 +101,7 @@ class InstallBackend extends DatabaseBackend { } /** - * Overrides Drupal\Cache\DatabaseBackend::isEmpty(). + * Overrides Drupal\Core\Cache\CacheBackendInterface::isEmpty(). */ function isEmpty() { return TRUE; diff --git a/core/includes/Drupal/Cache/NullBackend.php b/core/lib/Drupal/Core/Cache/NullBackend.php similarity index 59% rename from core/includes/Drupal/Cache/NullBackend.php rename to core/lib/Drupal/Core/Cache/NullBackend.php index 3ab731c..af83b96 100644 --- a/core/includes/Drupal/Cache/NullBackend.php +++ b/core/lib/Drupal/Core/Cache/NullBackend.php @@ -5,7 +5,7 @@ * Definition of NullBackend. */ -namespace Drupal\Cache; +namespace Drupal\Core\Cache; /** * Defines a stub cache implementation. @@ -21,61 +21,61 @@ namespace Drupal\Cache; class NullBackend implements CacheBackendInterface { /** - * Implements Drupal\Cache\CacheBackendInterface::__construct(). + * Implements Drupal\Core\Cache\CacheBackendInterface::__construct(). */ function __construct($bin) {} /** - * Implements Drupal\Cache\CacheBackendInterface::get(). + * Implements Drupal\Core\Cache\CacheBackendInterface::get(). */ function get($cid) { return FALSE; } /** - * Implements Drupal\Cache\CacheBackendInterface::getMultiple(). + * Implements Drupal\Core\Cache\CacheBackendInterface::getMultiple(). */ function getMultiple(&$cids) { return array(); } /** - * Implements Drupal\Cache\CacheBackendInterface::set(). + * Implements Drupal\Core\Cache\CacheBackendInterface::set(). */ function set($cid, $data, $expire = CACHE_PERMANENT) {} /** - * Implements Drupal\Cache\CacheBackendInterface::delete(). + * Implements Drupal\Core\Cache\CacheBackendInterface::delete(). */ function delete($cid) {} /** - * Implements Drupal\Cache\CacheBackendInterface::deleteMultiple(). + * Implements Drupal\Core\Cache\CacheBackendInterface::deleteMultiple(). */ function deleteMultiple(array $cids) {} /** - * Implements Drupal\Cache\CacheBackendInterface::deletePrefix(). + * Implements Drupal\Core\Cache\CacheBackendInterface::deletePrefix(). */ function deletePrefix($prefix) {} /** - * Implements Drupal\Cache\CacheBackendInterface::flush(). + * Implements Drupal\Core\Cache\CacheBackendInterface::flush(). */ function flush() {} /** - * Implements Drupal\Cache\CacheBackendInterface::expire(). + * Implements Drupal\Core\Cache\CacheBackendInterface::expire(). */ function expire() {} /** - * Implements Drupal\Cache\CacheBackendInterface::garbageCollection(). + * Implements Drupal\Core\Cache\CacheBackendInterface::garbageCollection(). */ function garbageCollection() {} /** - * Implements Drupal\Cache\CacheBackendInterface::isEmpty(). + * Implements Drupal\Core\Cache\CacheBackendInterface::isEmpty(). */ function isEmpty() { return TRUE; diff --git a/core/lib/Drupal/Core/README.txt b/core/lib/Drupal/Core/README.txt new file mode 100644 index 0000000..80cbf0e --- /dev/null +++ b/core/lib/Drupal/Core/README.txt @@ -0,0 +1,6 @@ +Code in the Drupal\Core namespace represents Drupal Subsystems provided by the +base system. These subsystems MAY depend on Drupal Components and other +Subsystems, but MAY NOT depend on any code in a module. + +Each Subsystem should be in its own namespace, and should be as self-contained +as possible. diff --git a/core/lib/Drupal/Core/Request.php b/core/lib/Drupal/Core/Request.php new file mode 100644 index 0000000..d514766 --- /dev/null +++ b/core/lib/Drupal/Core/Request.php @@ -0,0 +1,154 @@ +pathElements(); + return isset($elements[$index]) ? $elements[$index] : NULL; + } + + /** + * Returns the current path broken up into an array. + * + * @return array + * An array representing the elements of the path. + */ + public function pathElements() { + if (empty($this->pathElements)) { + $this->pathElements = explode('/', $this->systemPath()); + } + return $this->pathElements; + } + + /** + * 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. + * + * @return + * The requested URL path, as it came from the user agent. + */ + public function requestPath() { + if (empty($this->requestPath)) { + $raw_path = ''; + + $q = $this->query->get('q'); + + if (!empty($q)) { + // This is a request with a ?q=foo/bar query string. That trumps all other + // path locations. + $raw_path = $q; + } + else { + // This request is either a clean URL, or 'index.php', or nonsense. + // Extract the path from REQUEST_URI. + $request_uri = $this->getRequestUri(); + $request_path = strtok($request_uri, '?'); + $script_name = $this->getScriptName(); + $base_path_len = strlen(rtrim(dirname($script_name), '\/')); + // Unescape and strip $base_path prefix, leaving q without a leading slash. + $raw_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. + $php_self = $this->server->get('PHP_SELF'); + if ($raw_path == basename($php_self)) { + $raw_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']. + $this->requestPath = trim($raw_path, '/'); + } + + return $this->requestPath; + } + + /** + * Return the current 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 + * "node/306" as opposed to the path alias. + * + * This function is not available in hook_boot() so use Request::requestPath() + * instead. Be aware that requestPath() does not have aliases resolved. + * + * @return + * The current URL path, with aliases resolved. + */ + public function systemPath() { + if (empty($this->systemPath)) { + // @todo Temporary hack. Fix when path is an object. + require_once DRUPAL_ROOT . '/core/includes/path.inc'; + + $path = $this->requestPath(); + + if (empty($path)) { + // @todo Temporary hack. Fix when configuration is injectable. + $path = variable_get('site_frontpage', 'node'); + } + $this->systemPath = drupal_get_normal_path($path); + } + + return $this->systemPath; + } +} diff --git a/core/lib/README.txt b/core/lib/README.txt new file mode 100644 index 0000000..24b1f92 --- /dev/null +++ b/core/lib/README.txt @@ -0,0 +1,7 @@ +The core/lib directory is for classes provided by Drupal Core that are original +to Drupal. All Drupal-originated code must follow the PSR-0 naming convention +for classes and namespaces as documented here: + +https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md + +The vendor namespace for Drupal-originated code is "Drupal". diff --git a/core/modules/simpletest/simpletest.info b/core/modules/simpletest/simpletest.info index bbe65f0..8faf836 100644 --- a/core/modules/simpletest/simpletest.info +++ b/core/modules/simpletest/simpletest.info @@ -29,6 +29,7 @@ files[] = tests/module.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/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/request.test b/core/modules/simpletest/tests/request.test new file mode 100644 index 0000000..93e215d --- /dev/null +++ b/core/modules/simpletest/tests/request.test @@ -0,0 +1,92 @@ + 'Request', + 'description' => 'Tests for request information', + 'group' => 'Request', + ); + } + + public function setUp() { + parent::setUp(); + + require_once DRUPAL_ROOT . '/core/lib/Drupal/Core/Request.php'; + + // This unfortunately necessary because Drupal's registry throws a database + // exception when testing class_exist on non-existent classes in unit tests. + // This is the point of one of our tests so we have to remove the registry + // prior to running our tests. + spl_autoload_unregister('drupal_autoload_class'); + spl_autoload_unregister('drupal_autoload_interface'); + } + + public function tearDown() { + // Re-register drupal's autoload classes. See setUp for the reasoning. + spl_autoload_register('drupal_autoload_class'); + spl_autoload_register('drupal_autoload_interface'); + + parent::tearDown(); + } + + /** + * Test the request path logic. + */ + function testRequestPathFromPath() { + $request = Request::create('/' . $this->testPath); + + $this->assertEqual($request->requestPath(), $this->testPath, t('Correct request path derived from path.')); + } + + /** + * Test the request path logic. + */ + function testRequestPathFromQuery() { + $request = Request::create('index.php', 'GET', array('q' => $this->testPath)); + + $this->assertEqual($request->requestPath(), $this->testPath, t('Correct request path derived from arguments.')); + } + + /** + * Test the path fragment logic. + */ + function testPathFragment() { + $request = Request::create('/' . $this->testPath); + + $this->assertEqual($request->pathElement(0), 'foo', t('Correct first path element returned.')); + $this->assertEqual($request->pathElement(1), 'bar', t('Correct second path element returned.')); + $this->assertNull($request->pathElement(2), t('Null returned for non-existent path element.')); + } + + /** + * Test the path fragment logic. + */ + function testPathFragments() { + $request = Request::create('/' . $this->testPath); + + $elements = $request->pathElements(); + + $this->assertEqual($elements[0], 'foo', t('Correct first path element returned.')); + $this->assertEqual($elements[1], 'bar', t('Correct second path element returned.')); + $this->assertTrue(empty($elements[2]), t('Null returned for non-existent path element.')); + } + + + // System path cannot be unit tested, because it relies on the database. + // @TODO: Add a unit test here once the path logic becomes an object and can + // be mocked. + +} diff --git a/core/tests/README.txt b/core/tests/README.txt new file mode 100644 index 0000000..eaf3cae --- /dev/null +++ b/core/tests/README.txt @@ -0,0 +1,3 @@ +This directory contains test case code for Drupal core Components and Subsystems. +Test classes should mirror the namespace of the code being tested. Supporting +code for test classes is allowed. diff --git a/core/vendor/README.txt b/core/vendor/README.txt new file mode 100644 index 0000000..7968995 --- /dev/null +++ b/core/vendor/README.txt @@ -0,0 +1,6 @@ +3rd party libraries provided by Drupal core should be placed in this directory. +They should not be modified from their original form at any time. They should +be changed only to keep up to date with upstream projects. + +Code in this directory MAY be licensed under a GPL-compatible non-GPL license. If +so, it must be properly documented in COPYRIGHT.txt. diff --git a/core/includes/Symfony/Component/ClassLoader/ApcUniversalClassLoader.php b/core/vendor/Symfony/Component/ClassLoader/ApcUniversalClassLoader.php similarity index 100% rename from core/includes/Symfony/Component/ClassLoader/ApcUniversalClassLoader.php rename to core/vendor/Symfony/Component/ClassLoader/ApcUniversalClassLoader.php diff --git a/core/includes/Symfony/Component/ClassLoader/ClassCollectionLoader.php b/core/vendor/Symfony/Component/ClassLoader/ClassCollectionLoader.php similarity index 100% rename from core/includes/Symfony/Component/ClassLoader/ClassCollectionLoader.php rename to core/vendor/Symfony/Component/ClassLoader/ClassCollectionLoader.php diff --git a/core/includes/Symfony/Component/ClassLoader/DebugUniversalClassLoader.php b/core/vendor/Symfony/Component/ClassLoader/DebugUniversalClassLoader.php similarity index 100% rename from core/includes/Symfony/Component/ClassLoader/DebugUniversalClassLoader.php rename to core/vendor/Symfony/Component/ClassLoader/DebugUniversalClassLoader.php diff --git a/core/includes/Symfony/Component/ClassLoader/LICENSE b/core/vendor/Symfony/Component/ClassLoader/LICENSE similarity index 100% rename from core/includes/Symfony/Component/ClassLoader/LICENSE rename to core/vendor/Symfony/Component/ClassLoader/LICENSE diff --git a/core/includes/Symfony/Component/ClassLoader/MapClassLoader.php b/core/vendor/Symfony/Component/ClassLoader/MapClassLoader.php similarity index 100% rename from core/includes/Symfony/Component/ClassLoader/MapClassLoader.php rename to core/vendor/Symfony/Component/ClassLoader/MapClassLoader.php diff --git a/core/includes/Symfony/Component/ClassLoader/UniversalClassLoader.php b/core/vendor/Symfony/Component/ClassLoader/UniversalClassLoader.php similarity index 100% rename from core/includes/Symfony/Component/ClassLoader/UniversalClassLoader.php rename to core/vendor/Symfony/Component/ClassLoader/UniversalClassLoader.php diff --git a/core/includes/Symfony/Component/ClassLoader/composer.json b/core/vendor/Symfony/Component/ClassLoader/composer.json similarity index 100% rename from core/includes/Symfony/Component/ClassLoader/composer.json rename to core/vendor/Symfony/Component/ClassLoader/composer.json diff --git a/core/includes/Symfony/Component/HttpFoundation/ApacheRequest.php b/core/vendor/Symfony/Component/HttpFoundation/ApacheRequest.php similarity index 100% rename from core/includes/Symfony/Component/HttpFoundation/ApacheRequest.php rename to core/vendor/Symfony/Component/HttpFoundation/ApacheRequest.php diff --git a/core/includes/Symfony/Component/HttpFoundation/Cookie.php b/core/vendor/Symfony/Component/HttpFoundation/Cookie.php similarity index 100% rename from core/includes/Symfony/Component/HttpFoundation/Cookie.php rename to core/vendor/Symfony/Component/HttpFoundation/Cookie.php diff --git a/core/includes/Symfony/Component/HttpFoundation/File/Exception/AccessDeniedException.php b/core/vendor/Symfony/Component/HttpFoundation/File/Exception/AccessDeniedException.php similarity index 100% rename from core/includes/Symfony/Component/HttpFoundation/File/Exception/AccessDeniedException.php rename to core/vendor/Symfony/Component/HttpFoundation/File/Exception/AccessDeniedException.php diff --git a/core/includes/Symfony/Component/HttpFoundation/File/Exception/FileException.php b/core/vendor/Symfony/Component/HttpFoundation/File/Exception/FileException.php similarity index 100% rename from core/includes/Symfony/Component/HttpFoundation/File/Exception/FileException.php rename to core/vendor/Symfony/Component/HttpFoundation/File/Exception/FileException.php diff --git a/core/includes/Symfony/Component/HttpFoundation/File/Exception/FileNotFoundException.php b/core/vendor/Symfony/Component/HttpFoundation/File/Exception/FileNotFoundException.php similarity index 100% rename from core/includes/Symfony/Component/HttpFoundation/File/Exception/FileNotFoundException.php rename to core/vendor/Symfony/Component/HttpFoundation/File/Exception/FileNotFoundException.php diff --git a/core/includes/Symfony/Component/HttpFoundation/File/Exception/UnexpectedTypeException.php b/core/vendor/Symfony/Component/HttpFoundation/File/Exception/UnexpectedTypeException.php similarity index 100% rename from core/includes/Symfony/Component/HttpFoundation/File/Exception/UnexpectedTypeException.php rename to core/vendor/Symfony/Component/HttpFoundation/File/Exception/UnexpectedTypeException.php diff --git a/core/includes/Symfony/Component/HttpFoundation/File/Exception/UploadException.php b/core/vendor/Symfony/Component/HttpFoundation/File/Exception/UploadException.php similarity index 100% rename from core/includes/Symfony/Component/HttpFoundation/File/Exception/UploadException.php rename to core/vendor/Symfony/Component/HttpFoundation/File/Exception/UploadException.php diff --git a/core/includes/Symfony/Component/HttpFoundation/File/File.php b/core/vendor/Symfony/Component/HttpFoundation/File/File.php similarity index 100% rename from core/includes/Symfony/Component/HttpFoundation/File/File.php rename to core/vendor/Symfony/Component/HttpFoundation/File/File.php diff --git a/core/includes/Symfony/Component/HttpFoundation/File/MimeType/ContentTypeMimeTypeGuesser.php b/core/vendor/Symfony/Component/HttpFoundation/File/MimeType/ContentTypeMimeTypeGuesser.php similarity index 100% rename from core/includes/Symfony/Component/HttpFoundation/File/MimeType/ContentTypeMimeTypeGuesser.php rename to core/vendor/Symfony/Component/HttpFoundation/File/MimeType/ContentTypeMimeTypeGuesser.php diff --git a/core/includes/Symfony/Component/HttpFoundation/File/MimeType/FileBinaryMimeTypeGuesser.php b/core/vendor/Symfony/Component/HttpFoundation/File/MimeType/FileBinaryMimeTypeGuesser.php similarity index 100% rename from core/includes/Symfony/Component/HttpFoundation/File/MimeType/FileBinaryMimeTypeGuesser.php rename to core/vendor/Symfony/Component/HttpFoundation/File/MimeType/FileBinaryMimeTypeGuesser.php diff --git a/core/includes/Symfony/Component/HttpFoundation/File/MimeType/FileinfoMimeTypeGuesser.php b/core/vendor/Symfony/Component/HttpFoundation/File/MimeType/FileinfoMimeTypeGuesser.php similarity index 100% rename from core/includes/Symfony/Component/HttpFoundation/File/MimeType/FileinfoMimeTypeGuesser.php rename to core/vendor/Symfony/Component/HttpFoundation/File/MimeType/FileinfoMimeTypeGuesser.php diff --git a/core/includes/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesser.php b/core/vendor/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesser.php similarity index 100% rename from core/includes/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesser.php rename to core/vendor/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesser.php diff --git a/core/includes/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesserInterface.php b/core/vendor/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesserInterface.php similarity index 100% rename from core/includes/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesserInterface.php rename to core/vendor/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesserInterface.php diff --git a/core/includes/Symfony/Component/HttpFoundation/File/UploadedFile.php b/core/vendor/Symfony/Component/HttpFoundation/File/UploadedFile.php similarity index 100% rename from core/includes/Symfony/Component/HttpFoundation/File/UploadedFile.php rename to core/vendor/Symfony/Component/HttpFoundation/File/UploadedFile.php diff --git a/core/includes/Symfony/Component/HttpFoundation/FileBag.php b/core/vendor/Symfony/Component/HttpFoundation/FileBag.php similarity index 100% rename from core/includes/Symfony/Component/HttpFoundation/FileBag.php rename to core/vendor/Symfony/Component/HttpFoundation/FileBag.php diff --git a/core/includes/Symfony/Component/HttpFoundation/HeaderBag.php b/core/vendor/Symfony/Component/HttpFoundation/HeaderBag.php similarity index 100% rename from core/includes/Symfony/Component/HttpFoundation/HeaderBag.php rename to core/vendor/Symfony/Component/HttpFoundation/HeaderBag.php diff --git a/core/includes/Symfony/Component/HttpFoundation/LICENSE b/core/vendor/Symfony/Component/HttpFoundation/LICENSE similarity index 100% rename from core/includes/Symfony/Component/HttpFoundation/LICENSE rename to core/vendor/Symfony/Component/HttpFoundation/LICENSE diff --git a/core/includes/Symfony/Component/HttpFoundation/ParameterBag.php b/core/vendor/Symfony/Component/HttpFoundation/ParameterBag.php similarity index 100% rename from core/includes/Symfony/Component/HttpFoundation/ParameterBag.php rename to core/vendor/Symfony/Component/HttpFoundation/ParameterBag.php diff --git a/core/includes/Symfony/Component/HttpFoundation/RedirectResponse.php b/core/vendor/Symfony/Component/HttpFoundation/RedirectResponse.php similarity index 100% rename from core/includes/Symfony/Component/HttpFoundation/RedirectResponse.php rename to core/vendor/Symfony/Component/HttpFoundation/RedirectResponse.php diff --git a/core/includes/Symfony/Component/HttpFoundation/Request.php b/core/vendor/Symfony/Component/HttpFoundation/Request.php similarity index 100% rename from core/includes/Symfony/Component/HttpFoundation/Request.php rename to core/vendor/Symfony/Component/HttpFoundation/Request.php diff --git a/core/includes/Symfony/Component/HttpFoundation/RequestMatcher.php b/core/vendor/Symfony/Component/HttpFoundation/RequestMatcher.php similarity index 100% rename from core/includes/Symfony/Component/HttpFoundation/RequestMatcher.php rename to core/vendor/Symfony/Component/HttpFoundation/RequestMatcher.php diff --git a/core/includes/Symfony/Component/HttpFoundation/RequestMatcherInterface.php b/core/vendor/Symfony/Component/HttpFoundation/RequestMatcherInterface.php similarity index 100% rename from core/includes/Symfony/Component/HttpFoundation/RequestMatcherInterface.php rename to core/vendor/Symfony/Component/HttpFoundation/RequestMatcherInterface.php diff --git a/core/includes/Symfony/Component/HttpFoundation/Response.php b/core/vendor/Symfony/Component/HttpFoundation/Response.php similarity index 100% rename from core/includes/Symfony/Component/HttpFoundation/Response.php rename to core/vendor/Symfony/Component/HttpFoundation/Response.php diff --git a/core/includes/Symfony/Component/HttpFoundation/ResponseHeaderBag.php b/core/vendor/Symfony/Component/HttpFoundation/ResponseHeaderBag.php similarity index 100% rename from core/includes/Symfony/Component/HttpFoundation/ResponseHeaderBag.php rename to core/vendor/Symfony/Component/HttpFoundation/ResponseHeaderBag.php diff --git a/core/includes/Symfony/Component/HttpFoundation/ServerBag.php b/core/vendor/Symfony/Component/HttpFoundation/ServerBag.php similarity index 100% rename from core/includes/Symfony/Component/HttpFoundation/ServerBag.php rename to core/vendor/Symfony/Component/HttpFoundation/ServerBag.php diff --git a/core/includes/Symfony/Component/HttpFoundation/Session.php b/core/vendor/Symfony/Component/HttpFoundation/Session.php similarity index 100% rename from core/includes/Symfony/Component/HttpFoundation/Session.php rename to core/vendor/Symfony/Component/HttpFoundation/Session.php diff --git a/core/includes/Symfony/Component/HttpFoundation/SessionStorage/ArraySessionStorage.php b/core/vendor/Symfony/Component/HttpFoundation/SessionStorage/ArraySessionStorage.php similarity index 100% rename from core/includes/Symfony/Component/HttpFoundation/SessionStorage/ArraySessionStorage.php rename to core/vendor/Symfony/Component/HttpFoundation/SessionStorage/ArraySessionStorage.php diff --git a/core/includes/Symfony/Component/HttpFoundation/SessionStorage/FilesystemSessionStorage.php b/core/vendor/Symfony/Component/HttpFoundation/SessionStorage/FilesystemSessionStorage.php similarity index 100% rename from core/includes/Symfony/Component/HttpFoundation/SessionStorage/FilesystemSessionStorage.php rename to core/vendor/Symfony/Component/HttpFoundation/SessionStorage/FilesystemSessionStorage.php diff --git a/core/includes/Symfony/Component/HttpFoundation/SessionStorage/NativeSessionStorage.php b/core/vendor/Symfony/Component/HttpFoundation/SessionStorage/NativeSessionStorage.php similarity index 100% rename from core/includes/Symfony/Component/HttpFoundation/SessionStorage/NativeSessionStorage.php rename to core/vendor/Symfony/Component/HttpFoundation/SessionStorage/NativeSessionStorage.php diff --git a/core/includes/Symfony/Component/HttpFoundation/SessionStorage/PdoSessionStorage.php b/core/vendor/Symfony/Component/HttpFoundation/SessionStorage/PdoSessionStorage.php similarity index 100% rename from core/includes/Symfony/Component/HttpFoundation/SessionStorage/PdoSessionStorage.php rename to core/vendor/Symfony/Component/HttpFoundation/SessionStorage/PdoSessionStorage.php diff --git a/core/includes/Symfony/Component/HttpFoundation/SessionStorage/SessionStorageInterface.php b/core/vendor/Symfony/Component/HttpFoundation/SessionStorage/SessionStorageInterface.php similarity index 100% rename from core/includes/Symfony/Component/HttpFoundation/SessionStorage/SessionStorageInterface.php rename to core/vendor/Symfony/Component/HttpFoundation/SessionStorage/SessionStorageInterface.php diff --git a/core/includes/Symfony/Component/HttpFoundation/composer.json b/core/vendor/Symfony/Component/HttpFoundation/composer.json similarity index 100% rename from core/includes/Symfony/Component/HttpFoundation/composer.json rename to core/vendor/Symfony/Component/HttpFoundation/composer.json