Created
July 8, 2012 00:56
-
-
Save katbailey/3068825 to your computer and use it in GitHub Desktop.
Drupal 8 combined bundle and path alias patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc | |
index 0551e56..43f5f1b 100644 | |
--- a/core/includes/bootstrap.inc | |
+++ b/core/includes/bootstrap.inc | |
@@ -3,7 +3,8 @@ | |
use Drupal\Core\Database\Database; | |
use Symfony\Component\ClassLoader\UniversalClassLoader; | |
use Symfony\Component\ClassLoader\ApcUniversalClassLoader; | |
-use Drupal\Core\DependencyInjection\ContainerBuilder; | |
+use Symfony\Component\DependencyInjection\Container; | |
+use Symfony\Component\DependencyInjection\ContainerBuilder; | |
use Symfony\Component\HttpFoundation\Request; | |
use Drupal\Core\Language\Language; | |
@@ -2460,7 +2461,7 @@ function drupal_get_bootstrap_phase() { | |
* The instance of the Drupal Container used to set up and maintain object | |
* instances. | |
*/ | |
-function drupal_container(ContainerBuilder $reset = NULL) { | |
+function drupal_container(Container $reset = NULL) { | |
// We do not use drupal_static() here because we do not have a mechanism by | |
// which to reinitialize the stored objects, so a drupal_static_reset() call | |
// would leave Drupal in a nonfunctional state. | |
@@ -2469,7 +2470,14 @@ function drupal_container(ContainerBuilder $reset = NULL) { | |
$container = $reset; | |
} | |
elseif (!isset($container)) { | |
+ // This will only ever happen if an error has been thrown. Just build a new | |
+ // ContainerBuilder with only the language_interface service. | |
$container = new ContainerBuilder(); | |
+ | |
+ // An interface language always needs to be available for t() and other | |
+ // functions. This default is overridden by drupal_language_initialize() | |
+ // during language negotiation. | |
+ $container->register(LANGUAGE_TYPE_INTERFACE, 'Drupal\\Core\\Language\\Language'); | |
} | |
return $container; | |
} | |
@@ -2620,31 +2628,11 @@ function get_t() { | |
* @see Drupal\Core\Language\Language | |
*/ | |
function drupal_language_initialize() { | |
- $types = language_types_get_all(); | |
- $container = drupal_container(); | |
- | |
- // Ensure a language object is registered for each language type, whether the | |
- // site is multilingual or not. | |
if (language_multilingual()) { | |
- include_once DRUPAL_ROOT . '/core/includes/language.inc'; | |
- foreach ($types as $type) { | |
- $language = language_types_initialize($type); | |
- $container->set($type, NULL); | |
- $container->register($type, 'Drupal\\Core\\Language\\Language') | |
- ->addMethodCall('extend', array($language)); | |
- } | |
// Allow modules to react on language system initialization in multilingual | |
// environments. | |
bootstrap_invoke_all('language_init'); | |
} | |
- else { | |
- $default = language_default(); | |
- foreach ($types as $type) { | |
- $container->set($type, NULL); | |
- $container->register($type, 'Drupal\\Core\\Language\\Language') | |
- ->addMethodCall('extend', array($default)); | |
- } | |
- } | |
} | |
/** | |
diff --git a/core/includes/common.inc b/core/includes/common.inc | |
index 8b53cc6..9008849 100644 | |
--- a/core/includes/common.inc | |
+++ b/core/includes/common.inc | |
@@ -2176,7 +2176,7 @@ function url($path = NULL, array $options = array()) { | |
} | |
elseif (!empty($path) && !$options['alias']) { | |
$langcode = isset($options['language']) && isset($options['language']->langcode) ? $options['language']->langcode : ''; | |
- $alias = drupal_get_path_alias($original_path, $langcode); | |
+ $alias = drupal_container()->get('path_registry')->getPathAlias($original_path, $langcode); | |
if ($alias != $original_path) { | |
$path = $alias; | |
} | |
@@ -2499,7 +2499,7 @@ function drupal_deliver_html_page($page_callback_result) { | |
$_GET['destination'] = current_path(); | |
} | |
- $path = drupal_get_normal_path($site_config->get('page.404')); | |
+ $path = drupal_container()->get('path_registry')->getSystemPath($site_config->get('page.404')); | |
if ($path && $path != current_path()) { | |
// Custom 404 handler. Set the active item in case there are tabs to | |
// display, or other dependencies on the path. | |
@@ -2528,7 +2528,7 @@ function drupal_deliver_html_page($page_callback_result) { | |
$_GET['destination'] = current_path(); | |
} | |
- $path = drupal_get_normal_path($site_config->get('page.403')); | |
+ $path = drupal_container()->get('path_registry')->getSystemPath($site_config->get('page.403')); | |
if ($path && $path != current_path()) { | |
// Custom 403 handler. Set the active item in case there are tabs to | |
// display or other dependencies on the path. | |
@@ -5104,9 +5104,9 @@ function _drupal_bootstrap_code() { | |
} | |
/** | |
- * Temporary BC function for scripts not using HttpKernel. | |
+ * Temporary BC function for scripts not using DrupalKernel. | |
* | |
- * HttpKernel skips this and replicates it via event listeners. | |
+ * DrupalKernel skips this and replicates it via event listeners. | |
* | |
* @see Drupal\Core\EventSubscriber\PathSubscriber; | |
* @see Drupal\Core\EventSubscriber\LegacyRequestSubscriber; | |
@@ -5123,9 +5123,6 @@ function _drupal_bootstrap_full($skip = FALSE) { | |
// current_path(). | |
drupal_language_initialize(); | |
- // Initialize current_path() prior to invoking hook_init(). | |
- drupal_path_initialize(); | |
- | |
// Let all modules take action before the menu system handles the request. | |
// We do not want this while running update.php. | |
if (!defined('MAINTENANCE_MODE') || MAINTENANCE_MODE != 'update') { | |
diff --git a/core/includes/menu.inc b/core/includes/menu.inc | |
index 581a6ce..91ee47d 100644 | |
--- a/core/includes/menu.inc | |
+++ b/core/includes/menu.inc | |
@@ -2992,7 +2992,7 @@ function _menu_delete_item($item, $force = FALSE) { | |
* @param $item | |
* An associative array representing a menu link item, with elements: | |
* - link_path: (required) The path of the menu item, which should be | |
- * normalized first by calling drupal_get_normal_path() on it. | |
+ * normalized first by calling drupal_container()->get('path_registry')->getSystemPath() on it. | |
* - link_title: (required) Title to appear in menu for the link. | |
* - menu_name: (optional) The machine name of the menu for the link. | |
* Defaults to 'navigation'. | |
diff --git a/core/includes/path.inc b/core/includes/path.inc | |
index 62a58a6..9f37750 100644 | |
--- a/core/includes/path.inc | |
+++ b/core/includes/path.inc | |
@@ -1,8 +1,10 @@ | |
<?php | |
+use Drupal\Core\Path\DrupalPathRegistry; | |
+ | |
/** | |
* @file | |
- * Functions to handle paths in Drupal, including path aliasing. | |
+ * Functions to handle paths in Drupal. | |
* | |
* These functions are not loaded for cached pages, but modules that need | |
* to use them in hook_boot() or hook exit() can make them available, by | |
@@ -10,203 +12,12 @@ | |
*/ | |
/** | |
- * Initializes the current path to the proper normal path. | |
- */ | |
-function drupal_path_initialize() { | |
- // At this point, the current path is either the request path (due to | |
- // drupal_environment_initialize()) or some modified version of it due to | |
- // other bootstrap code (e.g., language negotiation), but it has not yet been | |
- // normalized by drupal_get_normal_path(). | |
- $path = _current_path(); | |
- | |
- // If on the front page, resolve to the front page path, including for calls | |
- // to current_path() while drupal_get_normal_path() is in progress. | |
- if (empty($path)) { | |
- $path = config('system.site')->get('page.front'); | |
- _current_path($path); | |
- } | |
- | |
- // Normalize the path. | |
- _current_path(drupal_get_normal_path($path)); | |
-} | |
- | |
-/** | |
- * Given an alias, return its Drupal system URL if one exists. Given a Drupal | |
- * system URL return one of its aliases if such a one exists. Otherwise, | |
- * return FALSE. | |
- * | |
- * @param $action | |
- * One of the following values: | |
- * - wipe: delete the alias cache. | |
- * - alias: return an alias for a given Drupal system path (if one exists). | |
- * - source: return the Drupal system URL for a path alias (if one exists). | |
- * @param $path | |
- * The path to investigate for corresponding aliases or system URLs. | |
- * @param $langcode | |
- * Optional language code to search the path with. Defaults to the page language. | |
- * If there's no path defined for that language it will search paths without | |
- * language. | |
- * | |
- * @return | |
- * Either a Drupal system path, an aliased path, or FALSE if no path was | |
- * found. | |
- */ | |
-function drupal_lookup_path($action, $path = '', $langcode = NULL) { | |
- // Use the advanced drupal_static() pattern, since this is called very often. | |
- static $drupal_static_fast; | |
- if (!isset($drupal_static_fast)) { | |
- $drupal_static_fast['cache'] = &drupal_static(__FUNCTION__); | |
- } | |
- $cache = &$drupal_static_fast['cache']; | |
- | |
- if (!isset($cache)) { | |
- $cache = array( | |
- 'map' => array(), | |
- 'no_source' => array(), | |
- 'whitelist' => NULL, | |
- 'system_paths' => array(), | |
- 'no_aliases' => array(), | |
- 'first_call' => TRUE, | |
- ); | |
- } | |
- | |
- // Retrieve the path alias whitelist. | |
- if (!isset($cache['whitelist'])) { | |
- $cache['whitelist'] = variable_get('path_alias_whitelist', NULL); | |
- if (!isset($cache['whitelist'])) { | |
- $cache['whitelist'] = drupal_path_alias_whitelist_rebuild(); | |
- } | |
- } | |
- | |
- // If no language is explicitly specified we default to the current URL | |
- // language. If we used a language different from the one conveyed by the | |
- // requested URL, we might end up being unable to check if there is a path | |
- // alias matching the URL path. | |
- $langcode = $langcode ? $langcode : drupal_container()->get(LANGUAGE_TYPE_URL)->langcode; | |
- | |
- if ($action == 'wipe') { | |
- $cache = array(); | |
- $cache['whitelist'] = drupal_path_alias_whitelist_rebuild(); | |
- } | |
- elseif ($cache['whitelist'] && $path != '') { | |
- if ($action == 'alias') { | |
- // During the first call to drupal_lookup_path() per language, load the | |
- // expected system paths for the page from cache. | |
- if (!empty($cache['first_call'])) { | |
- $cache['first_call'] = FALSE; | |
- | |
- $cache['map'][$langcode] = array(); | |
- // Load system paths from cache. | |
- $cid = current_path(); | |
- if ($cached = cache('path')->get($cid)) { | |
- $cache['system_paths'] = $cached->data; | |
- // Now fetch the aliases corresponding to these system paths. | |
- $args = array( | |
- ':system' => $cache['system_paths'], | |
- ':langcode' => $langcode, | |
- ':langcode_undetermined' => LANGUAGE_NOT_SPECIFIED, | |
- ); | |
- // Always get the language-specific alias before the language-neutral | |
- // one. For example 'de' is less than 'und' so the order needs to be | |
- // ASC, while 'xx-lolspeak' is more than 'und' so the order needs to | |
- // be DESC. We also order by pid ASC so that fetchAllKeyed() returns | |
- // the most recently created alias for each source. Subsequent queries | |
- // using fetchField() must use pid DESC to have the same effect. | |
- // For performance reasons, the query builder is not used here. | |
- if ($langcode == LANGUAGE_NOT_SPECIFIED) { | |
- // Prevent PDO from complaining about a token the query doesn't use. | |
- unset($args[':langcode']); | |
- $result = db_query('SELECT source, alias FROM {url_alias} WHERE source IN (:system) AND langcode = :langcode_undetermined ORDER BY pid ASC', $args); | |
- } | |
- elseif ($langcode < LANGUAGE_NOT_SPECIFIED) { | |
- $result = db_query('SELECT source, alias FROM {url_alias} WHERE source IN (:system) AND langcode IN (:langcode, :langcode_undetermined) ORDER BY langcode ASC, pid ASC', $args); | |
- } | |
- else { | |
- $result = db_query('SELECT source, alias FROM {url_alias} WHERE source IN (:system) AND langcode IN (:langcode, :langcode_undetermined) ORDER BY langcode DESC, pid ASC', $args); | |
- } | |
- $cache['map'][$langcode] = $result->fetchAllKeyed(); | |
- // Keep a record of paths with no alias to avoid querying twice. | |
- $cache['no_aliases'][$langcode] = array_flip(array_diff_key($cache['system_paths'], array_keys($cache['map'][$langcode]))); | |
- } | |
- } | |
- // If the alias has already been loaded, return it. | |
- if (isset($cache['map'][$langcode][$path])) { | |
- return $cache['map'][$langcode][$path]; | |
- } | |
- // Check the path whitelist, if the top_level part before the first / | |
- // is not in the list, then there is no need to do anything further, | |
- // it is not in the database. | |
- elseif (!isset($cache['whitelist'][strtok($path, '/')])) { | |
- return FALSE; | |
- } | |
- // For system paths which were not cached, query aliases individually. | |
- elseif (!isset($cache['no_aliases'][$langcode][$path])) { | |
- $args = array( | |
- ':source' => $path, | |
- ':langcode' => $langcode, | |
- ':langcode_undetermined' => LANGUAGE_NOT_SPECIFIED, | |
- ); | |
- // See the queries above. | |
- if ($langcode == LANGUAGE_NOT_SPECIFIED) { | |
- unset($args[':langcode']); | |
- $alias = db_query("SELECT alias FROM {url_alias} WHERE source = :source AND langcode = :langcode_undetermined ORDER BY pid DESC", $args)->fetchField(); | |
- } | |
- elseif ($langcode > LANGUAGE_NOT_SPECIFIED) { | |
- $alias = db_query("SELECT alias FROM {url_alias} WHERE source = :source AND langcode IN (:langcode, :langcode_undetermined) ORDER BY langcode DESC, pid DESC", $args)->fetchField(); | |
- } | |
- else { | |
- $alias = db_query("SELECT alias FROM {url_alias} WHERE source = :source AND langcode IN (:langcode, :langcode_undetermined) ORDER BY langcode ASC, pid DESC", $args)->fetchField(); | |
- } | |
- $cache['map'][$langcode][$path] = $alias; | |
- return $alias; | |
- } | |
- } | |
- // Check $no_source for this $path in case we've already determined that there | |
- // isn't a path that has this alias | |
- elseif ($action == 'source' && !isset($cache['no_source'][$langcode][$path])) { | |
- // Look for the value $path within the cached $map | |
- $source = FALSE; | |
- if (!isset($cache['map'][$langcode]) || !($source = array_search($path, $cache['map'][$langcode]))) { | |
- $args = array( | |
- ':alias' => $path, | |
- ':langcode' => $langcode, | |
- ':langcode_undetermined' => LANGUAGE_NOT_SPECIFIED, | |
- ); | |
- // See the queries above. | |
- if ($langcode == LANGUAGE_NOT_SPECIFIED) { | |
- unset($args[':langcode']); | |
- $result = db_query("SELECT source FROM {url_alias} WHERE alias = :alias AND langcode = :langcode_undetermined ORDER BY pid DESC", $args); | |
- } | |
- elseif ($langcode > LANGUAGE_NOT_SPECIFIED) { | |
- $result = db_query("SELECT source FROM {url_alias} WHERE alias = :alias AND langcode IN (:langcode, :langcode_undetermined) ORDER BY langcode DESC, pid DESC", $args); | |
- } | |
- else { | |
- $result = db_query("SELECT source FROM {url_alias} WHERE alias = :alias AND langcode IN (:langcode, :langcode_undetermined) ORDER BY langcode ASC, pid DESC", $args); | |
- } | |
- if ($source = $result->fetchField()) { | |
- $cache['map'][$langcode][$source] = $path; | |
- } | |
- else { | |
- // We can't record anything into $map because we do not have a valid | |
- // index and there is no need because we have not learned anything | |
- // about any Drupal path. Thus cache to $no_source. | |
- $cache['no_source'][$langcode][$path] = TRUE; | |
- } | |
- } | |
- return $source; | |
- } | |
- } | |
- | |
- return FALSE; | |
-} | |
- | |
-/** | |
* Cache system paths for a page. | |
* | |
* Cache an array of the system paths available on each page. We assume | |
* that aliases will be needed for the majority of these paths during | |
- * subsequent requests, and load them in a single query during | |
- * drupal_lookup_path(). | |
+ * subsequent requests, and load them in a single query during path alias | |
+ * lookup. | |
*/ | |
function drupal_cache_system_paths() { | |
// Check if the system paths for this page were loaded from cache in this | |
@@ -215,8 +26,8 @@ function drupal_cache_system_paths() { | |
if (empty($cache['system_paths']) && !empty($cache['map'])) { | |
// Generate a cache ID (cid) specifically for this page. | |
$cid = current_path(); | |
- // The static $map array used by drupal_lookup_path() includes all | |
- // system paths for the page request. | |
+ // The static $map array used by the alias lookup logic in path module | |
+ // includes all system paths for the page request. | |
if ($paths = current($cache['map'])) { | |
$data = array_keys($paths); | |
$expire = REQUEST_TIME + (60 * 60 * 24); | |
@@ -226,64 +37,6 @@ function drupal_cache_system_paths() { | |
} | |
/** | |
- * Given an internal Drupal path, return the alias set by the administrator. | |
- * | |
- * If no path is provided, the function will return the alias of the current | |
- * page. | |
- * | |
- * @param $path | |
- * An internal Drupal path. | |
- * @param $langcode | |
- * An optional language code to look up the path in. | |
- * | |
- * @return | |
- * An aliased path if one was found, or the original path if no alias was | |
- * found. | |
- */ | |
-function drupal_get_path_alias($path = NULL, $langcode = NULL) { | |
- // If no path is specified, use the current page's path. | |
- if ($path == NULL) { | |
- $path = current_path(); | |
- } | |
- $result = $path; | |
- if ($alias = drupal_lookup_path('alias', $path, $langcode)) { | |
- $result = $alias; | |
- } | |
- return $result; | |
-} | |
- | |
-/** | |
- * Given a path alias, return the internal path it represents. | |
- * | |
- * @param $path | |
- * A Drupal path alias. | |
- * @param $langcode | |
- * An optional language code to look up the path in. | |
- * | |
- * @return | |
- * The internal path represented by the alias, or the original alias if no | |
- * internal path was found. | |
- */ | |
-function drupal_get_normal_path($path, $langcode = NULL) { | |
- $original_path = $path; | |
- | |
- // Lookup the path alias first. | |
- if ($source = drupal_lookup_path('source', $path, $langcode)) { | |
- $path = $source; | |
- } | |
- | |
- // Allow other modules to alter the inbound URL. We cannot use drupal_alter() | |
- // here because we need to run hook_url_inbound_alter() in the reverse order | |
- // of hook_url_outbound_alter(). | |
- foreach (array_reverse(module_implements('url_inbound_alter')) as $module) { | |
- $function = $module . '_url_inbound_alter'; | |
- $function($path, $original_path, $langcode); | |
- } | |
- | |
- return $path; | |
-} | |
- | |
-/** | |
* Check if the current page is the front page. | |
* | |
* @return | |
@@ -362,125 +115,6 @@ function current_path() { | |
} | |
/** | |
- * Rebuild the path alias white list. | |
- * | |
- * @param $source | |
- * An optional system path for which an alias is being inserted. | |
- * | |
- * @return | |
- * An array containing a white list of path aliases. | |
- */ | |
-function drupal_path_alias_whitelist_rebuild($source = NULL) { | |
- // When paths are inserted, only rebuild the whitelist if the system path | |
- // has a top level component which is not already in the whitelist. | |
- if (!empty($source)) { | |
- $whitelist = variable_get('path_alias_whitelist', NULL); | |
- if (isset($whitelist[strtok($source, '/')])) { | |
- return $whitelist; | |
- } | |
- } | |
- // For each alias in the database, get the top level component of the system | |
- // path it corresponds to. This is the portion of the path before the first | |
- // '/', if present, otherwise the whole path itself. | |
- $whitelist = array(); | |
- $result = db_query("SELECT DISTINCT SUBSTRING_INDEX(source, '/', 1) AS path FROM {url_alias}"); | |
- foreach ($result as $row) { | |
- $whitelist[$row->path] = TRUE; | |
- } | |
- variable_set('path_alias_whitelist', $whitelist); | |
- return $whitelist; | |
-} | |
- | |
-/** | |
- * Fetch a specific URL alias from the database. | |
- * | |
- * @param $conditions | |
- * A string representing the source, a number representing the pid, or an | |
- * array of query conditions. | |
- * | |
- * @return | |
- * FALSE if no alias was found or an associative array containing the | |
- * following keys: | |
- * - source: The internal system path. | |
- * - alias: The URL alias. | |
- * - pid: Unique path alias identifier. | |
- * - langcode: The language code of the alias. | |
- */ | |
-function path_load($conditions) { | |
- if (is_numeric($conditions)) { | |
- $conditions = array('pid' => $conditions); | |
- } | |
- elseif (is_string($conditions)) { | |
- $conditions = array('source' => $conditions); | |
- } | |
- elseif (!is_array($conditions)) { | |
- return FALSE; | |
- } | |
- $select = db_select('url_alias'); | |
- foreach ($conditions as $field => $value) { | |
- $select->condition($field, $value); | |
- } | |
- return $select | |
- ->fields('url_alias') | |
- ->execute() | |
- ->fetchAssoc(); | |
-} | |
- | |
-/** | |
- * Save a path alias to the database. | |
- * | |
- * @param $path | |
- * An associative array containing the following keys: | |
- * - source: The internal system path. | |
- * - alias: The URL alias. | |
- * - pid: (optional) Unique path alias identifier. | |
- * - langcode: (optional) The language code of the alias. | |
- */ | |
-function path_save(&$path) { | |
- $path += array('langcode' => LANGUAGE_NOT_SPECIFIED); | |
- | |
- // Load the stored alias, if any. | |
- if (!empty($path['pid']) && !isset($path['original'])) { | |
- $path['original'] = path_load($path['pid']); | |
- } | |
- | |
- if (empty($path['pid'])) { | |
- drupal_write_record('url_alias', $path); | |
- module_invoke_all('path_insert', $path); | |
- } | |
- else { | |
- drupal_write_record('url_alias', $path, array('pid')); | |
- module_invoke_all('path_update', $path); | |
- } | |
- | |
- // Clear internal properties. | |
- unset($path['original']); | |
- | |
- // Clear the static alias cache. | |
- drupal_clear_path_cache($path['source']); | |
-} | |
- | |
-/** | |
- * Delete a URL alias. | |
- * | |
- * @param $criteria | |
- * A number representing the pid or an array of criteria. | |
- */ | |
-function path_delete($criteria) { | |
- if (!is_array($criteria)) { | |
- $criteria = array('pid' => $criteria); | |
- } | |
- $path = path_load($criteria); | |
- $query = db_delete('url_alias'); | |
- foreach ($criteria as $field => $value) { | |
- $query->condition($field, $value); | |
- } | |
- $query->execute(); | |
- module_invoke_all('path_delete', $path); | |
- drupal_clear_path_cache($path['source']); | |
-} | |
- | |
-/** | |
* Determine whether a path is in the administrative section of the site. | |
* | |
* By default, paths are considered to be non-administrative. If a path does not | |
@@ -580,14 +214,3 @@ function drupal_valid_path($path, $dynamic_allowed = FALSE) { | |
return $item && $item['access']; | |
} | |
-/** | |
- * Clear the path cache. | |
- * | |
- * @param $source | |
- * An optional system path for which an alias is being changed. | |
- */ | |
-function drupal_clear_path_cache($source = NULL) { | |
- // Clear the drupal_lookup_path() static cache. | |
- drupal_static_reset('drupal_lookup_path'); | |
- drupal_path_alias_whitelist_rebuild($source); | |
-} | |
diff --git a/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterKernelListenersPass.php b/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterKernelListenersPass.php | |
new file mode 100644 | |
index 0000000..291e54b | |
--- /dev/null | |
+++ b/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterKernelListenersPass.php | |
@@ -0,0 +1,36 @@ | |
+<?php | |
+ | |
+/** | |
+ * @file | |
+ * Definition of Drupal\Core\DependencyInjection\Compiler\RegisterKernelListenersPass. | |
+ */ | |
+ | |
+namespace Drupal\Core\DependencyInjection\Compiler; | |
+ | |
+use Symfony\Component\DependencyInjection\ContainerBuilder; | |
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; | |
+ | |
+class RegisterKernelListenersPass implements CompilerPassInterface | |
+{ | |
+ public function process(ContainerBuilder $container) | |
+ { | |
+ if (!$container->hasDefinition('dispatcher')) { | |
+ return; | |
+ } | |
+ | |
+ $definition = $container->getDefinition('dispatcher'); | |
+ | |
+ foreach ($container->findTaggedServiceIds('kernel.event_subscriber') as $id => $attributes) { | |
+ | |
+ // We must assume that the class value has been correcly filled, even if the service is created by a factory | |
+ $class = $container->getDefinition($id)->getClass(); | |
+ | |
+ $refClass = new \ReflectionClass($class); | |
+ $interface = 'Symfony\Component\EventDispatcher\EventSubscriberInterface'; | |
+ if (!$refClass->implementsInterface($interface)) { | |
+ throw new \InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, $interface)); | |
+ } | |
+ $definition->addMethodCall('addSubscriberService', array($id, $class)); | |
+ } | |
+ } | |
+} | |
diff --git a/core/lib/Drupal/Core/DependencyInjection/ContainerBuilder.php b/core/lib/Drupal/Core/DependencyInjection/ContainerBuilder.php | |
index a82f5b6..786a3a3 100644 | |
--- a/core/lib/Drupal/Core/DependencyInjection/ContainerBuilder.php | |
+++ b/core/lib/Drupal/Core/DependencyInjection/ContainerBuilder.php | |
@@ -7,113 +7,38 @@ | |
namespace Drupal\Core\DependencyInjection; | |
-use Drupal\Core\ContentNegotiation; | |
-use Drupal\Core\EventSubscriber\AccessSubscriber; | |
-use Drupal\Core\EventSubscriber\FinishResponseSubscriber; | |
-use Drupal\Core\EventSubscriber\LegacyControllerSubscriber; | |
-use Drupal\Core\EventSubscriber\LegacyRequestSubscriber; | |
-use Drupal\Core\EventSubscriber\MaintenanceModeSubscriber; | |
-use Drupal\Core\EventSubscriber\PathSubscriber; | |
-use Drupal\Core\EventSubscriber\RequestCloseSubscriber; | |
-use Drupal\Core\EventSubscriber\RouterListener; | |
-use Drupal\Core\EventSubscriber\ViewSubscriber; | |
-use Drupal\Core\ExceptionController; | |
-use Drupal\Core\LegacyUrlMatcher; | |
use Symfony\Component\DependencyInjection\ContainerBuilder as BaseContainerBuilder; | |
-use Symfony\Component\DependencyInjection\Reference; | |
-use Symfony\Component\EventDispatcher\EventDispatcher; | |
-use Symfony\Component\HttpKernel\EventListener\ExceptionListener; | |
+use Symfony\Component\DependencyInjection\Compiler\Compiler; | |
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; | |
+use Symfony\Component\DependencyInjection\Compiler\PassConfig; | |
+use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag; | |
/** | |
* Drupal's dependency injection container. | |
*/ | |
class ContainerBuilder extends BaseContainerBuilder { | |
- /** | |
- * Registers the base Drupal services for the dependency injection container. | |
- */ | |
- public function __construct() { | |
- parent::__construct(); | |
+ public function addCompilerPass(CompilerPassInterface $pass, $type = PassConfig::TYPE_BEFORE_OPTIMIZATION) | |
+ { | |
+ if (!isset($this->compiler) || null === $this->compiler) { | |
+ $this->compiler = new Compiler(); | |
+ } | |
+ | |
+ $this->compiler->addPass($pass, $type); | |
+ } | |
+ | |
+ public function compile() | |
+ { | |
+ if (null === $this->compiler) { | |
+ $this->compiler = new Compiler(); | |
+ } | |
+ | |
+ $this->compiler->compile($this); | |
+ $this->parameterBag->resolve(); | |
+ // TODO: The line below is commented out because there is code that calls | |
+ // the set() method on the container after it has been built - that method | |
+ // throws an exception if the container's parameters have been frozen. | |
+ //$this->parameterBag = new FrozenParameterBag($this->parameterBag->all()); | |
+ } | |
- // An interface language always needs to be available for t() and other | |
- // functions. This default is overridden by drupal_language_initialize() | |
- // during language negotiation. | |
- $this->register(LANGUAGE_TYPE_INTERFACE, 'Drupal\\Core\\Language\\Language'); | |
- | |
- // Register the default language content. | |
- $this->register(LANGUAGE_TYPE_CONTENT, 'Drupal\\Core\\Language\\Language'); | |
- | |
- // Register configuration storage dispatcher. | |
- $this->setParameter('config.storage.info', array( | |
- 'Drupal\Core\Config\DatabaseStorage' => array( | |
- 'connection' => 'default', | |
- 'target' => 'default', | |
- 'read' => TRUE, | |
- 'write' => TRUE, | |
- ), | |
- 'Drupal\Core\Config\FileStorage' => array( | |
- 'directory' => config_get_config_directory(), | |
- 'read' => TRUE, | |
- 'write' => FALSE, | |
- ), | |
- )); | |
- $this->register('config.storage.dispatcher', 'Drupal\Core\Config\StorageDispatcher') | |
- ->addArgument('%config.storage.info%'); | |
- | |
- // Register configuration object factory. | |
- $this->register('config.factory', 'Drupal\Core\Config\ConfigFactory') | |
- ->addArgument(new Reference('config.storage.dispatcher')); | |
- | |
- // Register the HTTP kernel services. | |
- $this->register('dispatcher', 'Symfony\Component\EventDispatcher\EventDispatcher') | |
- ->addArgument(new Reference('service_container')) | |
- ->setFactoryClass('Drupal\Core\DependencyInjection\ContainerBuilder') | |
- ->setFactoryMethod('getKernelEventDispatcher'); | |
- $this->register('resolver', 'Symfony\Component\HttpKernel\Controller\ControllerResolver'); | |
- $this->register('httpkernel', 'Symfony\Component\HttpKernel\HttpKernel') | |
- ->addArgument(new Reference('dispatcher')) | |
- ->addArgument(new Reference('resolver')); | |
- } | |
- | |
- /** | |
- * Creates an EventDispatcher for the HttpKernel. Factory method. | |
- * | |
- * @param Drupal\Core\DependencyInjection\ContainerBuilder $container | |
- * The dependency injection container that contains the HTTP kernel. | |
- * | |
- * @return Symfony\Component\EventDispatcher\EventDispatcher | |
- * An EventDispatcher with the default listeners attached to it. | |
- */ | |
- public static function getKernelEventDispatcher($container) { | |
- $dispatcher = new EventDispatcher(); | |
- | |
- $matcher = new LegacyUrlMatcher(); | |
- $dispatcher->addSubscriber(new RouterListener($matcher)); | |
- | |
- $negotiation = new ContentNegotiation(); | |
- | |
- // @todo Make this extensible rather than just hard coding some. | |
- // @todo Add a subscriber to handle other things, too, like our Ajax | |
- // replacement system. | |
- $dispatcher->addSubscriber(new ViewSubscriber($negotiation)); | |
- $dispatcher->addSubscriber(new AccessSubscriber()); | |
- $dispatcher->addSubscriber(new MaintenanceModeSubscriber()); | |
- $dispatcher->addSubscriber(new PathSubscriber()); | |
- $dispatcher->addSubscriber(new LegacyRequestSubscriber()); | |
- $dispatcher->addSubscriber(new LegacyControllerSubscriber()); | |
- $dispatcher->addSubscriber(new FinishResponseSubscriber()); | |
- $dispatcher->addSubscriber(new RequestCloseSubscriber()); | |
- | |
- // Some other form of error occured that wasn't handled by another kernel | |
- // listener. That could mean that it's a method/mime-type/error combination | |
- // that is not accounted for, or some other type of error. Either way, treat | |
- // it as a server-level error and return an HTTP 500. By default, this will | |
- // be an HTML-type response because that's a decent best guess if we don't | |
- // know otherwise. | |
- $exceptionController = new ExceptionController($negotiation); | |
- $exceptionController->setContainer($container); | |
- $dispatcher->addSubscriber(new ExceptionListener(array($exceptionController, 'execute'))); | |
- | |
- return $dispatcher; | |
- } | |
} | |
diff --git a/core/lib/Drupal/Core/DrupalBundle.php b/core/lib/Drupal/Core/DrupalBundle.php | |
new file mode 100644 | |
index 0000000..db28f5b | |
--- /dev/null | |
+++ b/core/lib/Drupal/Core/DrupalBundle.php | |
@@ -0,0 +1,218 @@ | |
+<?php | |
+ | |
+namespace Drupal\Core; | |
+ | |
+use Drupal\Core\DependencyInjection\Compiler\RegisterKernelListenersPass; | |
+use Symfony\Component\DependencyInjection\Definition; | |
+use Symfony\Component\DependencyInjection\ContainerBuilder; | |
+use Symfony\Component\DependencyInjection\Reference; | |
+use Symfony\Component\HttpKernel\Bundle\Bundle; | |
+use Symfony\Component\DependencyInjection\Compiler\PassConfig; | |
+ | |
+class DrupalBundle extends Bundle | |
+{ | |
+ public function build(ContainerBuilder $container) | |
+ { | |
+ $definitions = $this->getDefinitions(); | |
+ | |
+ foreach ($definitions as $id => $info) { | |
+ $info += array( | |
+ 'tags' => array(), | |
+ 'references' => array(), | |
+ 'parameters' => array(), | |
+ 'methods' => array(), | |
+ 'arguments' => array(), | |
+ ); | |
+ | |
+ $references = array(); | |
+ foreach ($info['references'] as $ref_id) { | |
+ $references[] = new Reference($ref_id); | |
+ } | |
+ | |
+ $definition = new Definition($info['class'], $references); | |
+ | |
+ foreach ($info['parameters'] as $key => $param) { | |
+ $container->setParameter($key, $param); | |
+ $definition->addArgument("%{$key}%"); | |
+ } | |
+ | |
+ if (isset($info['factory_class']) && isset($info['factory_method'])) { | |
+ $definition->setFactoryClass($info['factory_class']); | |
+ $definition->setFactoryMethod($info['factory_method']); | |
+ } | |
+ | |
+ foreach ($info['arguments'] as $argument) { | |
+ $definition->addArgument($argument); | |
+ } | |
+ | |
+ foreach($info['tags'] as $tag) { | |
+ $definition->addTag($tag); | |
+ } | |
+ | |
+ foreach ($info['methods'] as $method => $args) { | |
+ $definition->addMethodCall($method, $args); | |
+ } | |
+ | |
+ $container->setDefinition($id, $definition); | |
+ } | |
+ | |
+ $this->registerLanguageServices($container); | |
+ | |
+ // Add a compiler pass for registering event subscribers. | |
+ $container->addCompilerPass(new RegisterKernelListenersPass(), PassConfig::TYPE_AFTER_REMOVING); | |
+ } | |
+ | |
+ /** | |
+ * Returns an array of definitions for the services we want to register. | |
+ */ | |
+ function getDefinitions() { | |
+ return array( | |
+ // Register configuration storage dispatcher. | |
+ 'config.storage.dispatcher' => array( | |
+ 'class' => 'Drupal\Core\Config\StorageDispatcher', | |
+ 'parameters' => array( | |
+ 'conifg.storage.info' => array( | |
+ 'Drupal\Core\Config\DatabaseStorage' => array( | |
+ 'connection' => 'default', | |
+ 'target' => 'default', | |
+ 'read' => TRUE, | |
+ 'write' => TRUE, | |
+ ), | |
+ 'Drupal\Core\Config\FileStorage' => array( | |
+ 'directory' => config_get_config_directory(), | |
+ 'read' => TRUE, | |
+ 'write' => FALSE, | |
+ ), | |
+ ), | |
+ ), | |
+ ), | |
+ 'config.factory' => array( | |
+ 'class' => 'Drupal\Core\Config\ConfigFactory', | |
+ 'references' => array( | |
+ 'config.storage.dispatcher' | |
+ ) | |
+ ), | |
+ 'dispatcher' => array( | |
+ 'class' => 'Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher', | |
+ 'references' => array( | |
+ 'service_container', | |
+ ), | |
+ ), | |
+ 'resolver' => array( | |
+ 'class' => 'Symfony\Component\HttpKernel\Controller\ControllerResolver', | |
+ ), | |
+ 'http_kernel' => array( | |
+ 'class' => 'Symfony\Component\HttpKernel\HttpKernel', | |
+ 'references' => array( | |
+ 'dispatcher', 'resolver', | |
+ ) | |
+ ), | |
+ 'matcher' => array( | |
+ 'class' => 'Drupal\Core\LegacyUrlMatcher', | |
+ ), | |
+ 'router_listener' => array( | |
+ 'class' => 'Drupal\Core\EventSubscriber\RouterListener', | |
+ 'references' => array('matcher'), | |
+ 'tags' => array('kernel.event_subscriber') | |
+ ), | |
+ 'path_registry' => array( | |
+ 'class' => 'Drupal\Core\Path\PathRegistry' | |
+ ), | |
+ 'content_negotiation' => array( | |
+ 'class' => 'Drupal\Core\ContentNegotiation', | |
+ ), | |
+ 'view_subscriber' => array( | |
+ 'class' => 'Drupal\Core\EventSubscriber\ViewSubscriber', | |
+ 'references' => array('content_negotiation'), | |
+ 'tags' => array('kernel.event_subscriber') | |
+ ), | |
+ 'access_subscriber' => array( | |
+ 'class' => 'Drupal\Core\EventSubscriber\AccessSubscriber', | |
+ 'tags' => array('kernel.event_subscriber') | |
+ ), | |
+ 'maintenance_mode_subscriber' => array( | |
+ 'class' => 'Drupal\Core\EventSubscriber\MaintenanceModeSubscriber', | |
+ 'tags' => array('kernel.event_subscriber') | |
+ ), | |
+ 'path_subscriber' => array( | |
+ 'class' => 'Drupal\Core\EventSubscriber\PathSubscriber', | |
+ 'tags' => array('kernel.event_subscriber') | |
+ ), | |
+ 'legacy_request_subscriber' => array( | |
+ 'class' => 'Drupal\Core\EventSubscriber\LegacyRequestSubscriber', | |
+ 'tags' => array('kernel.event_subscriber') | |
+ ), | |
+ 'legacy_controller_subscriber' => array( | |
+ 'class' => 'Drupal\Core\EventSubscriber\LegacyControllerSubscriber', | |
+ 'tags' => array('kernel.event_subscriber') | |
+ ), | |
+ 'finish_response_subscriber' => array( | |
+ 'class' => 'Drupal\Core\EventSubscriber\FinishResponseSubscriber', | |
+ 'tags' => array('kernel.event_subscriber') | |
+ ), | |
+ 'request_close_subscriber' => array( | |
+ 'class' => 'Drupal\Core\EventSubscriber\RequestCloseSubscriber', | |
+ 'tags' => array('kernel.event_subscriber') | |
+ ), | |
+ 'exception_controller' => array( | |
+ 'class' => 'Drupal\Core\ExceptionController', | |
+ 'references' => array('content_negotiation'), | |
+ 'methods' => array('setContainer' => array('service_container')) | |
+ ), | |
+ 'exception_listener' => array( | |
+ 'class' => 'Symfony\Component\HttpKernel\EventListener\ExceptionListener', | |
+ 'references' => array('exception_controller'), | |
+ 'tags' => array('kernel.event_subscriber') | |
+ ), | |
+ 'database' => array( | |
+ 'class' => 'Drupal\Core\Database\Connection', | |
+ 'factory_class' => 'Drupal\Core\Database\Database', | |
+ 'factory_method' => 'getConnection', | |
+ 'arguments' => array('default'), | |
+ ), | |
+ 'database.slave' => array( | |
+ 'class' => 'Drupal\Core\Database\Connection', | |
+ 'factory_class' => 'Drupal\Core\Database\Database', | |
+ 'factory_method' => 'getConnection', | |
+ 'arguments' => array('slave'), | |
+ ), | |
+ ); | |
+ } | |
+ | |
+ /** | |
+ * Registers language-related services to the container. | |
+ */ | |
+ function registerLanguageServices($container) { | |
+ | |
+ $types = language_types_get_all(); | |
+ | |
+ // Ensure a language object is registered for each language type, whether the | |
+ // site is multilingual or not. | |
+ if (language_multilingual()) { | |
+ include_once DRUPAL_ROOT . '/core/includes/language.inc'; | |
+ foreach ($types as $type) { | |
+ $language = language_types_initialize($type); | |
+ // We cannot pass an object as a parameter to a method on a service. | |
+ $info = get_object_vars($language); | |
+ $container->set($type, NULL); | |
+ $container->register($type, 'Drupal\\Core\\Language\\Language') | |
+ ->addMethodCall('extend', array($info)); | |
+ } | |
+ } | |
+ else { | |
+ $info = variable_get('language_default', array( | |
+ 'langcode' => 'en', | |
+ 'name' => 'English', | |
+ 'direction' => 0, | |
+ 'weight' => 0, | |
+ 'locked' => 0, | |
+ )); | |
+ $info['default'] = TRUE; | |
+ foreach ($types as $type) { | |
+ $container->set($type, NULL); | |
+ $container->register($type, 'Drupal\\Core\\Language\\Language') | |
+ ->addMethodCall('extend', array($info)); | |
+ } | |
+ } | |
+ } | |
+} | |
\ No newline at end of file | |
diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php | |
new file mode 100644 | |
index 0000000..b38e950 | |
--- /dev/null | |
+++ b/core/lib/Drupal/Core/DrupalKernel.php | |
@@ -0,0 +1,90 @@ | |
+<?php | |
+ | |
+/** | |
+ * @file | |
+ * Definition of Drupal\Core\DrupalKernel. | |
+ */ | |
+ | |
+namespace Drupal\Core; | |
+ | |
+use Drupal\Core\DrupalBundle; | |
+use Symfony\Component\HttpKernel\Kernel; | |
+use Drupal\Core\DependencyInjection\ContainerBuilder; | |
+use Symfony\Component\Config\Loader\LoaderInterface; | |
+use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; | |
+ | |
+/** | |
+ * The DrupalKernel class is the core of Drupal itself. | |
+ */ | |
+class DrupalKernel extends Kernel { | |
+ | |
+ public function registerBundles() | |
+ { | |
+ $bundles = array( | |
+ new DrupalBundle(), | |
+ ); | |
+ | |
+ // Rather than bootstrapping to a higher phase prior to booting the Kernel, which | |
+ // would ensure these files are loaded already, we want to boot the Kernel as | |
+ // early as possible in the bootstrapping phase. | |
+ // TODO: Somehow remove the necessity of calling system_list() to find out which | |
+ // bundles exist. | |
+ require_once DRUPAL_ROOT . '/core/includes/cache.inc'; | |
+ require_once DRUPAL_ROOT . '/core/includes/module.inc'; | |
+ require_once DRUPAL_ROOT . '/core/includes/database.inc'; | |
+ | |
+ $modules = array_keys(system_list('module_enabled')); | |
+ foreach ($modules as $module) { | |
+ $class = "\Drupal\\{$module}\\{$module}Bundle"; | |
+ if (class_exists($class)) { | |
+ $bundles[] = new $class(); | |
+ } | |
+ } | |
+ return $bundles; | |
+ } | |
+ | |
+ | |
+ /** | |
+ * Initializes the service container. | |
+ */ | |
+ protected function initializeContainer() | |
+ { | |
+ $this->container = $this->buildContainer(); | |
+ $this->container->set('kernel', $this); | |
+ drupal_container($this->container); | |
+ } | |
+ | |
+ /** | |
+ * Builds the service container. | |
+ * | |
+ * @return ContainerBuilder The compiled service container | |
+ */ | |
+ protected function buildContainer() | |
+ { | |
+ $container = $this->getContainerBuilder(); | |
+ foreach ($this->bundles as $bundle) { | |
+ $bundle->build($container); | |
+ } | |
+ $container->compile(); | |
+ return $container; | |
+ } | |
+ | |
+ | |
+ /** | |
+ * Gets a new ContainerBuilder instance used to build the service container. | |
+ * | |
+ * @return ContainerBuilder | |
+ */ | |
+ protected function getContainerBuilder() | |
+ { | |
+ return new ContainerBuilder(new ParameterBag($this->getKernelParameters())); | |
+ } | |
+ | |
+ public function registerContainerConfiguration(LoaderInterface $loader) | |
+ { | |
+ // We have to define this method because it's not defined in the base class | |
+ // but is part of the KernelInterface interface. However, the LoaderInterface | |
+ // class is part of the config component, which we are not using, so this | |
+ // is badness :-/ | |
+ } | |
+} | |
diff --git a/core/lib/Drupal/Core/EventSubscriber/PathSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/PathSubscriber.php | |
index 2e1bece..9ee912f 100644 | |
--- a/core/lib/Drupal/Core/EventSubscriber/PathSubscriber.php | |
+++ b/core/lib/Drupal/Core/EventSubscriber/PathSubscriber.php | |
@@ -30,7 +30,7 @@ class PathSubscriber extends PathListenerBase implements EventSubscriberInterfac | |
$path = $this->extractPath($request); | |
- $path = drupal_get_normal_path($path); | |
+ $path = drupal_container()->get('path_registry')->getSystemPath($path); | |
$this->setPath($request, $path); | |
} | |
diff --git a/core/lib/Drupal/Core/ExceptionController.php b/core/lib/Drupal/Core/ExceptionController.php | |
index 7f71e28..931d88c 100644 | |
--- a/core/lib/Drupal/Core/ExceptionController.php | |
+++ b/core/lib/Drupal/Core/ExceptionController.php | |
@@ -82,7 +82,7 @@ class ExceptionController extends ContainerAware { | |
$system_path = $request->attributes->get('system_path'); | |
watchdog('access denied', $system_path, NULL, WATCHDOG_WARNING); | |
- $path = drupal_get_normal_path(config('system.site')->get('page.403')); | |
+ $path = drupal_container()->get('path_registry')->getSystemPath(config('system.site')->get('page.403')); | |
if ($path && $path != $system_path) { | |
// Keep old path for reference, and to allow forms to redirect to it. | |
if (!isset($_GET['destination'])) { | |
@@ -107,7 +107,7 @@ class ExceptionController extends ContainerAware { | |
drupal_static_reset('menu_set_active_trail'); | |
menu_reset_static_cache(); | |
- $response = $this->container->get('httpkernel')->handle($subrequest, HttpKernel::SUB_REQUEST); | |
+ $response = $this->container->get('http_kernel')->handle($subrequest, HttpKernel::SUB_REQUEST); | |
$response->setStatusCode(403, 'Access denied'); | |
} | |
else { | |
@@ -148,7 +148,7 @@ class ExceptionController extends ContainerAware { | |
$_GET['destination'] = $system_path; | |
} | |
- $path = drupal_get_normal_path(config('system.site')->get('page.404')); | |
+ $path = drupal_container()->get('path_registry')->getSystemPath(config('system.site')->get('page.404')); | |
if ($path && $path != $system_path) { | |
// @todo Um, how do I specify an override URL again? Totally not clear. Do | |
// that and sub-call the kernel rather than using meah(). | |
@@ -172,7 +172,7 @@ class ExceptionController extends ContainerAware { | |
drupal_static_reset('menu_set_active_trail'); | |
menu_reset_static_cache(); | |
- $response = $this->container->get('httpkernel')->handle($subrequest, HttpKernel::SUB_REQUEST); | |
+ $response = $this->container->get('http_kernel')->handle($subrequest, HttpKernel::SUB_REQUEST); | |
$response->setStatusCode(404, 'Not Found'); | |
} | |
else { | |
diff --git a/core/lib/Drupal/Core/Language/Language.php b/core/lib/Drupal/Core/Language/Language.php | |
index e774fa9..9ace41f 100644 | |
--- a/core/lib/Drupal/Core/Language/Language.php | |
+++ b/core/lib/Drupal/Core/Language/Language.php | |
@@ -44,8 +44,8 @@ class Language { | |
* | |
* @todo Remove this function once $GLOBALS['language'] is gone. | |
*/ | |
- public function extend($obj) { | |
- $vars = get_object_vars($obj); | |
+ public function extend($info) { | |
+ $vars = is_array($info) ? $info : get_object_vars($info); | |
foreach ($vars as $var => $value) { | |
$this->$var = $value; | |
} | |
diff --git a/core/lib/Drupal/Core/Path/PathRegistry.php b/core/lib/Drupal/Core/Path/PathRegistry.php | |
new file mode 100644 | |
index 0000000..c1d9c0d | |
--- /dev/null | |
+++ b/core/lib/Drupal/Core/Path/PathRegistry.php | |
@@ -0,0 +1,40 @@ | |
+<?php | |
+ | |
+/** | |
+ * @file | |
+ * Definition of Drupal\Core\Path\PathRegistry. | |
+ */ | |
+ | |
+namespace Drupal\Core\Path; | |
+ | |
+use Drupal\Core\Path\PathRegistryInterface; | |
+use Drupal\Core\Database\Database; | |
+use Drupal\Core\Database\Connection; | |
+ | |
+class PathRegistry implements PathRegistryInterface { | |
+ | |
+ public function save($source, $alias, $langcode = LANGUAGE_NOT_SPECIFIED, $pid = NULL) { | |
+ return FALSE; | |
+ } | |
+ | |
+ public function load($conditions) { | |
+ return FALSE; | |
+ } | |
+ | |
+ public function delete($conditions) { | |
+ return 0; | |
+ } | |
+ | |
+ public function getSystemPath($path, $path_language = NULL) { | |
+ return $path; | |
+ } | |
+ | |
+ public function getPathAlias($path = NULL, $path_language = NULL) { | |
+ return isset($path) ? $path : NULL; | |
+ } | |
+ | |
+ public function cacheClear($source = NULL) { | |
+ | |
+ } | |
+} | |
+ | |
diff --git a/core/lib/Drupal/Core/Path/PathRegistryInterface.php b/core/lib/Drupal/Core/Path/PathRegistryInterface.php | |
new file mode 100644 | |
index 0000000..251849b | |
--- /dev/null | |
+++ b/core/lib/Drupal/Core/Path/PathRegistryInterface.php | |
@@ -0,0 +1,88 @@ | |
+<?php | |
+ | |
+/** | |
+ * @file | |
+ * Definition of Drupal\Core\Path\PathRegistryInterface. | |
+ */ | |
+ | |
+namespace Drupal\Core\Path; | |
+ | |
+interface PathRegistryInterface { | |
+ /** | |
+ * Save a path alias to the database. | |
+ * | |
+ * @param $source | |
+ * The internal system path. | |
+ * @param $alias | |
+ * The URL alias. | |
+ * @param $langcode | |
+ * The language of the alias. | |
+ * @param $pid | |
+ * Unique path alias identifier. | |
+ */ | |
+ public function save($source, $alias, $langcode = LANGUAGE_NOT_SPECIFIED, $pid = NULL); | |
+ | |
+ /** | |
+ * Fetch a specific URL alias from the database. | |
+ * | |
+ * @param $conditions | |
+ * A string representing the source, a number representing the pid, or an | |
+ * array of query conditions. | |
+ * | |
+ * @return | |
+ * FALSE if no alias was found or an associative array containing the | |
+ * following keys: | |
+ * - source: The internal system path. | |
+ * - alias: The URL alias. | |
+ * - pid: Unique path alias identifier. | |
+ * - language: The language of the alias. | |
+ */ | |
+ public function load($conditions); | |
+ | |
+ /** | |
+ * Delete a URL alias. | |
+ * | |
+ * @param $criteria | |
+ * A number representing the pid or an array of criteria. | |
+ */ | |
+ public function delete($pid); | |
+ | |
+ /** | |
+ * Given a path alias, return the internal path it represents. | |
+ * | |
+ * @param $path | |
+ * A Drupal path alias. | |
+ * @param $path_language | |
+ * An optional language code to look up the path in. | |
+ * | |
+ * @return | |
+ * The internal path represented by the alias, or the original alias if no | |
+ * internal path was found. | |
+ */ | |
+ public function getSystemPath($path, $path_language = NULL); | |
+ | |
+ /** | |
+ * Given an internal Drupal path, return the alias set by the administrator. | |
+ * | |
+ * If no path is provided, the function will return the alias of the current | |
+ * page. | |
+ * | |
+ * @param $path | |
+ * An optional internal Drupal path. | |
+ * @param $path_language | |
+ * An optional language code to look up the path in. | |
+ * | |
+ * @return | |
+ * An aliased path if one was found, or the original path if no alias was | |
+ * found. | |
+ */ | |
+ public function getPathAlias($path = NULL, $path_language = NULL); | |
+ | |
+ /** | |
+ * Clear the path cache. | |
+ * | |
+ * @param $source | |
+ * An optional system path for which an alias is being changed. | |
+ */ | |
+ public function cacheClear($source = NULL); | |
+} | |
diff --git a/core/modules/block/block.module b/core/modules/block/block.module | |
index 50bae76..aab2098 100644 | |
--- a/core/modules/block/block.module | |
+++ b/core/modules/block/block.module | |
@@ -851,7 +851,7 @@ function block_block_list_alter(&$blocks) { | |
if ($block->visibility < BLOCK_VISIBILITY_PHP) { | |
// Compare the lowercase path alias (if any) and internal path. | |
$path = current_path(); | |
- $path_alias = drupal_strtolower(drupal_get_path_alias($path)); | |
+ $path_alias = drupal_strtolower(drupal_container()->get('path_registry')->getPathAlias($path)); | |
$page_match = drupal_match_path($path_alias, $pages) || (($path != $path_alias) && drupal_match_path($path, $pages)); | |
// When $block->visibility has a value of 0 (BLOCK_VISIBILITY_NOTLISTED), | |
// the block is displayed on all pages except those listed in $block->pages. | |
diff --git a/core/modules/locale/lib/Drupal/locale/Tests/LocalePathTest.php b/core/modules/locale/lib/Drupal/locale/Tests/LocalePathTest.php | |
index 5476a7a..9ed5f75 100644 | |
--- a/core/modules/locale/lib/Drupal/locale/Tests/LocalePathTest.php | |
+++ b/core/modules/locale/lib/Drupal/locale/Tests/LocalePathTest.php | |
@@ -96,38 +96,23 @@ class LocalePathTest extends WebTestBase { | |
$custom_path = $this->randomName(8); | |
// Check priority of language for alias by source path. | |
- $edit = array( | |
- 'source' => 'node/' . $node->nid, | |
- 'alias' => $custom_path, | |
- 'langcode' => LANGUAGE_NOT_SPECIFIED, | |
- ); | |
- path_save($edit); | |
- $lookup_path = drupal_lookup_path('alias', 'node/' . $node->nid, 'en'); | |
+ drupal_container()->get('path_registry')->save('node/' . $node->nid, $custom_path, LANGUAGE_NOT_SPECIFIED); | |
+ $lookup_path = drupal_container()->get('path_registry')->getPathAlias('node/' . $node->nid, 'en'); | |
$this->assertEqual($english_path, $lookup_path, t('English language alias has priority.')); | |
// Same check for language 'xx'. | |
- $lookup_path = drupal_lookup_path('alias', 'node/' . $node->nid, $prefix); | |
+ $lookup_path = drupal_container()->get('path_registry')->getPathAlias('node/' . $node->nid, $prefix); | |
$this->assertEqual($custom_language_path, $lookup_path, t('Custom language alias has priority.')); | |
- path_delete($edit); | |
+ drupal_container()->get('path_registry')->delete(array('source' => 'node/' . $node->nid, 'alias' => $custom_path, 'langcode' => LANGUAGE_NOT_SPECIFIED)); | |
// Create language nodes to check priority of aliases. | |
$first_node = $this->drupalCreateNode(array('type' => 'page', 'promote' => 1)); | |
$second_node = $this->drupalCreateNode(array('type' => 'page', 'promote' => 1)); | |
// Assign a custom path alias to the first node with the English language. | |
- $edit = array( | |
- 'source' => 'node/' . $first_node->nid, | |
- 'alias' => $custom_path, | |
- 'langcode' => 'en', | |
- ); | |
- path_save($edit); | |
+ drupal_container()->get('path_registry')->save('node/' . $first_node->nid, $custom_path, 'en'); | |
// Assign a custom path alias to second node with LANGUAGE_NOT_SPECIFIED. | |
- $edit = array( | |
- 'source' => 'node/' . $second_node->nid, | |
- 'alias' => $custom_path, | |
- 'langcode' => LANGUAGE_NOT_SPECIFIED, | |
- ); | |
- path_save($edit); | |
+ drupal_container()->get('path_registry')->save('node/' . $second_node->nid, $custom_path, LANGUAGE_NOT_SPECIFIED); | |
// Test that both node titles link to our path alias. | |
$this->drupalGet('<front>'); | |
diff --git a/core/modules/menu/menu.admin.inc b/core/modules/menu/menu.admin.inc | |
index 496ff88..67213b9 100644 | |
--- a/core/modules/menu/menu.admin.inc | |
+++ b/core/modules/menu/menu.admin.inc | |
@@ -369,7 +369,7 @@ function menu_edit_item($form, &$form_state, $type, $item, $menu) { | |
*/ | |
function menu_edit_item_validate($form, &$form_state) { | |
$item = &$form_state['values']; | |
- $normal_path = drupal_get_normal_path($item['link_path']); | |
+ $normal_path = drupal_container()->get('path_registry')->getSystemPath($item['link_path']); | |
if ($item['link_path'] != $normal_path) { | |
drupal_set_message(t('The menu system stores system paths only, but will use the URL alias for display. %link_path has been stored as %normal_path', array('%link_path' => $item['link_path'], '%normal_path' => $normal_path))); | |
$item['link_path'] = $normal_path; | |
diff --git a/core/modules/path/lib/Drupal/path/PathBundle.php b/core/modules/path/lib/Drupal/path/PathBundle.php | |
new file mode 100644 | |
index 0000000..d450fee | |
--- /dev/null | |
+++ b/core/modules/path/lib/Drupal/path/PathBundle.php | |
@@ -0,0 +1,18 @@ | |
+<?php | |
+ | |
+namespace Drupal\path; | |
+ | |
+use Symfony\Component\DependencyInjection\Definition; | |
+use Symfony\Component\DependencyInjection\ContainerBuilder; | |
+use Symfony\Component\DependencyInjection\Reference; | |
+use Symfony\Component\HttpKernel\Bundle\Bundle; | |
+ | |
+class PathBundle extends Bundle | |
+{ | |
+ public function build(ContainerBuilder $container) | |
+ { | |
+ $container->set('path_registry', NULL); | |
+ $definition = new Definition('Drupal\path\PathRegistry', array(new Reference('database'))); | |
+ $container->setDefinition('path_registry', $definition); | |
+ } | |
+} | |
\ No newline at end of file | |
diff --git a/core/modules/path/lib/Drupal/path/PathRegistry.php b/core/modules/path/lib/Drupal/path/PathRegistry.php | |
new file mode 100644 | |
index 0000000..cceaa7c | |
--- /dev/null | |
+++ b/core/modules/path/lib/Drupal/path/PathRegistry.php | |
@@ -0,0 +1,317 @@ | |
+<?php | |
+ | |
+/** | |
+ * @file | |
+ * Definition of Drupal\path\PathRegistry. | |
+ */ | |
+ | |
+namespace Drupal\path; | |
+ | |
+use Drupal\Core\Path\PathRegistryInterface; | |
+use Drupal\Core\Database\Database; | |
+use Drupal\Core\Database\Connection; | |
+ | |
+class PathRegistry implements PathRegistryInterface { | |
+ | |
+ public function __construct(Connection $connection) { | |
+ $this->connection = $connection; | |
+ } | |
+ | |
+ public function save($source, $alias, $langcode = LANGUAGE_NOT_SPECIFIED, $pid = NULL) { | |
+ | |
+ $fields = array( | |
+ 'source' => $source, | |
+ 'alias' => $alias, | |
+ 'langcode' => $langcode, | |
+ ); | |
+ | |
+ // Insert or update the alias. | |
+ if (empty($pid)) { | |
+ $query = $this->connection->insert('url_alias', array('return' => Database::RETURN_INSERT_ID)) | |
+ ->fields($fields); | |
+ } | |
+ else { | |
+ $fields['pid'] = $pid; | |
+ $query = $this->connection->update('url_alias') | |
+ ->fields($fields) | |
+ ->condition('pid', $pid); | |
+ } | |
+ if ($pid = $query->execute()) { | |
+ $fields['pid'] = $pid; | |
+ $this->cacheClear($source); | |
+ return $fields; | |
+ } | |
+ return FALSE; | |
+ } | |
+ | |
+ public function load($conditions) { | |
+ if (is_numeric($conditions)) { | |
+ $conditions = array('pid' => $conditions); | |
+ } | |
+ elseif (is_string($conditions)) { | |
+ $conditions = array('source' => $conditions); | |
+ } | |
+ elseif (!is_array($conditions)) { | |
+ return FALSE; | |
+ } | |
+ $select = $this->connection->select('url_alias'); | |
+ foreach ($conditions as $field => $value) { | |
+ $select->condition($field, $value); | |
+ } | |
+ return $select | |
+ ->fields('url_alias') | |
+ ->execute() | |
+ ->fetchAssoc(); | |
+ } | |
+ | |
+ public function delete($conditions) { | |
+ if (!is_array($conditions)) { | |
+ $conditions = array('pid' => $conditions); | |
+ } | |
+ $path = $this->load($conditions); | |
+ $query = $this->connection->delete('url_alias'); | |
+ foreach ($conditions as $field => $value) { | |
+ $query->condition($field, $value); | |
+ } | |
+ $deleted = $query->execute(); | |
+ $this->cacheClear($path['source']); | |
+ // TODO: figure out where we can invoke hook_path_delete() | |
+ return $deleted; | |
+ } | |
+ | |
+ public function getSystemPath($path, $path_language = NULL) { | |
+ $original_path = $path; | |
+ | |
+ // Lookup the path alias first. | |
+ if ($source = $this->lookup_path('source', $path, $path_language)) { | |
+ $path = $source; | |
+ } | |
+ | |
+ // Allow other modules to alter the inbound URL. We cannot use drupal_alter() | |
+ // here because we need to run hook_url_inbound_alter() in the reverse order | |
+ // of hook_url_outbound_alter(). | |
+ foreach (array_reverse(module_implements('url_inbound_alter')) as $module) { | |
+ $function = $module . '_url_inbound_alter'; | |
+ $function($path, $original_path, $path_language); | |
+ } | |
+ | |
+ return $path; | |
+ } | |
+ | |
+ public function getPathAlias($path = NULL, $path_language = NULL) { | |
+ // If no path is specified, use the current page's path. | |
+ if ($path === NULL) { | |
+ $path = _current_path(); | |
+ } | |
+ $result = $path; | |
+ if ($alias = $this->lookup_path('alias', $path, $path_language)) { | |
+ $result = $alias; | |
+ } | |
+ return $result; | |
+ } | |
+ | |
+ public function cacheClear($source = NULL) { | |
+ drupal_static_reset('drupal_lookup_path'); | |
+ $this->path_alias_whitelist_rebuild($source); | |
+ } | |
+ | |
+ /** | |
+ * Given an alias, return its Drupal system URL if one exists. Given a Drupal | |
+ * system URL return one of its aliases if such a one exists. Otherwise, | |
+ * return FALSE. | |
+ * | |
+ * @param $action | |
+ * One of the following values: | |
+ * - wipe: delete the alias cache. | |
+ * - alias: return an alias for a given Drupal system path (if one exists). | |
+ * - source: return the Drupal system URL for a path alias (if one exists). | |
+ * @param $path | |
+ * The path to investigate for corresponding aliases or system URLs. | |
+ * @param $langcode | |
+ * Optional language code to search the path with. Defaults to the page language. | |
+ * If there's no path defined for that language it will search paths without | |
+ * language. | |
+ * | |
+ * @return | |
+ * Either a Drupal system path, an aliased path, or FALSE if no path was | |
+ * found. | |
+ */ | |
+ private function lookup_path($action, $path = '', $langcode = NULL) { | |
+ // Use the advanced drupal_static() pattern, since this is called very often. | |
+ static $drupal_static_fast; | |
+ if (!isset($drupal_static_fast)) { | |
+ $drupal_static_fast['cache'] = &drupal_static('drupal_lookup_path'); | |
+ } | |
+ $cache = &$drupal_static_fast['cache']; | |
+ | |
+ if (!isset($cache)) { | |
+ $cache = array( | |
+ 'map' => array(), | |
+ 'no_source' => array(), | |
+ 'whitelist' => NULL, | |
+ 'system_paths' => array(), | |
+ 'no_aliases' => array(), | |
+ 'first_call' => TRUE, | |
+ ); | |
+ } | |
+ | |
+ // Retrieve the path alias whitelist. | |
+ if (!isset($cache['whitelist'])) { | |
+ $cache['whitelist'] = variable_get('path_alias_whitelist', NULL); | |
+ if (!isset($cache['whitelist'])) { | |
+ $cache['whitelist'] = $this->path_alias_whitelist_rebuild(); | |
+ } | |
+ } | |
+ | |
+ // If no language is explicitly specified we default to the current URL | |
+ // language. If we used a language different from the one conveyed by the | |
+ // requested URL, we might end up being unable to check if there is a path | |
+ // alias matching the URL path. | |
+ $langcode = $langcode ? $langcode : drupal_container()->get(LANGUAGE_TYPE_URL)->langcode; | |
+ | |
+ if ($action == 'wipe') { | |
+ $cache = array(); | |
+ $cache['whitelist'] = $this->path_alias_whitelist_rebuild(); | |
+ } | |
+ elseif ($cache['whitelist'] && $path != '') { | |
+ if ($action == 'alias') { | |
+ // During the first call to this function per language, load the expected | |
+ // system paths for the page from cache. | |
+ if (!empty($cache['first_call'])) { | |
+ $cache['first_call'] = FALSE; | |
+ | |
+ $cache['map'][$langcode] = array(); | |
+ // Load system paths from cache. | |
+ $cid = current_path(); | |
+ if ($cached = cache('path')->get($cid)) { | |
+ $cache['system_paths'] = $cached->data; | |
+ // Now fetch the aliases corresponding to these system paths. | |
+ $args = array( | |
+ ':system' => $cache['system_paths'], | |
+ ':langcode' => $langcode, | |
+ ':langcode_undetermined' => LANGUAGE_NOT_SPECIFIED, | |
+ ); | |
+ // Always get the language-specific alias before the language-neutral | |
+ // one. For example 'de' is less than 'und' so the order needs to be | |
+ // ASC, while 'xx-lolspeak' is more than 'und' so the order needs to | |
+ // be DESC. We also order by pid ASC so that fetchAllKeyed() returns | |
+ // the most recently created alias for each source. Subsequent queries | |
+ // using fetchField() must use pid DESC to have the same effect. | |
+ // For performance reasons, the query builder is not used here. | |
+ if ($langcode == LANGUAGE_NOT_SPECIFIED) { | |
+ // Prevent PDO from complaining about a token the query doesn't use. | |
+ unset($args[':langcode']); | |
+ $result = $this->connection->query('SELECT source, alias FROM {url_alias} WHERE source IN (:system) AND langcode = :langcode_undetermined ORDER BY pid ASC', $args); | |
+ } | |
+ elseif ($langcode < LANGUAGE_NOT_SPECIFIED) { | |
+ $result = $this->connection->query('SELECT source, alias FROM {url_alias} WHERE source IN (:system) AND langcode IN (:langcode, :langcode_undetermined) ORDER BY langcode ASC, pid ASC', $args); | |
+ } | |
+ else { | |
+ $result = $this->connection->query('SELECT source, alias FROM {url_alias} WHERE source IN (:system) AND langcode IN (:langcode, :langcode_undetermined) ORDER BY langcode DESC, pid ASC', $args); | |
+ } | |
+ $cache['map'][$langcode] = $result->fetchAllKeyed(); | |
+ // Keep a record of paths with no alias to avoid querying twice. | |
+ $cache['no_aliases'][$langcode] = array_flip(array_diff_key($cache['system_paths'], array_keys($cache['map'][$langcode]))); | |
+ } | |
+ } | |
+ // If the alias has already been loaded, return it. | |
+ if (isset($cache['map'][$langcode][$path])) { | |
+ return $cache['map'][$langcode][$path]; | |
+ } | |
+ // Check the path whitelist, if the top-level part before the first / | |
+ // is not in the list, then there is no need to do anything further, | |
+ // it is not in the database. | |
+ elseif (!isset($cache['whitelist'][strtok($path, '/')])) { | |
+ return FALSE; | |
+ } | |
+ // For system paths which were not cached, query aliases individually. | |
+ elseif (!isset($cache['no_aliases'][$langcode][$path])) { | |
+ $args = array( | |
+ ':source' => $path, | |
+ ':langcode' => $langcode, | |
+ ':langcode_undetermined' => LANGUAGE_NOT_SPECIFIED, | |
+ ); | |
+ // See the queries above. | |
+ if ($langcode == LANGUAGE_NOT_SPECIFIED) { | |
+ unset($args[':langcode']); | |
+ $alias = $this->connection->query("SELECT alias FROM {url_alias} WHERE source = :source AND langcode = :langcode_undetermined ORDER BY pid DESC", $args)->fetchField(); | |
+ } | |
+ elseif ($langcode > LANGUAGE_NOT_SPECIFIED) { | |
+ $alias = $this->connection->query("SELECT alias FROM {url_alias} WHERE source = :source AND langcode IN (:langcode, :langcode_undetermined) ORDER BY langcode DESC, pid DESC", $args)->fetchField(); | |
+ } | |
+ else { | |
+ $alias = $this->connection->query("SELECT alias FROM {url_alias} WHERE source = :source AND langcode IN (:langcode, :langcode_undetermined) ORDER BY langcode ASC, pid DESC", $args)->fetchField(); | |
+ } | |
+ $cache['map'][$langcode][$path] = $alias; | |
+ return $alias; | |
+ } | |
+ } | |
+ // Check $no_source for this $path in case we've already determined that there | |
+ // isn't a path that has this alias | |
+ elseif ($action == 'source' && !isset($cache['no_source'][$langcode][$path])) { | |
+ // Look for the value $path within the cached $map | |
+ $source = FALSE; | |
+ if (!isset($cache['map'][$langcode]) || !($source = array_search($path, $cache['map'][$langcode]))) { | |
+ $args = array( | |
+ ':alias' => $path, | |
+ ':langcode' => $langcode, | |
+ ':langcode_undetermined' => LANGUAGE_NOT_SPECIFIED, | |
+ ); | |
+ // See the queries above. | |
+ if ($langcode == LANGUAGE_NOT_SPECIFIED) { | |
+ unset($args[':langcode']); | |
+ $result = $this->connection->query("SELECT source FROM {url_alias} WHERE alias = :alias AND langcode = :langcode_undetermined ORDER BY pid DESC", $args); | |
+ } | |
+ elseif ($langcode > LANGUAGE_NOT_SPECIFIED) { | |
+ $result = $this->connection->query("SELECT source FROM {url_alias} WHERE alias = :alias AND langcode IN (:langcode, :langcode_undetermined) ORDER BY langcode DESC, pid DESC", $args); | |
+ } | |
+ else { | |
+ $result = $this->connection->query("SELECT source FROM {url_alias} WHERE alias = :alias AND langcode IN (:langcode, :langcode_undetermined) ORDER BY langcode ASC, pid DESC", $args); | |
+ } | |
+ if ($source = $result->fetchField()) { | |
+ $cache['map'][$langcode][$source] = $path; | |
+ } | |
+ else { | |
+ // We can't record anything into $map because we do not have a valid | |
+ // index and there is no need because we have not learned anything | |
+ // about any Drupal path. Thus cache to $no_source. | |
+ $cache['no_source'][$langcode][$path] = TRUE; | |
+ } | |
+ } | |
+ return $source; | |
+ } | |
+ } | |
+ | |
+ return FALSE; | |
+ } | |
+ /** | |
+ * Rebuild the path alias white list. | |
+ * | |
+ * @param $source | |
+ * An optional system path for which an alias is being inserted. | |
+ * | |
+ * @return | |
+ * An array containing a white list of path aliases. | |
+ */ | |
+ private function path_alias_whitelist_rebuild($source = NULL) { | |
+ // When paths are inserted, only rebuild the whitelist if the system path | |
+ // has a top level component which is not already in the whitelist. | |
+ if (!empty($source)) { | |
+ $whitelist = variable_get('path_alias_whitelist', NULL); | |
+ if (isset($whitelist[strtok($source, '/')])) { | |
+ return $whitelist; | |
+ } | |
+ } | |
+ // For each alias in the database, get the top level component of the system | |
+ // path it corresponds to. This is the portion of the path before the first | |
+ // '/', if present, otherwise the whole path itself. | |
+ $whitelist = array(); | |
+ $result = $this->connection->query("SELECT DISTINCT SUBSTRING_INDEX(source, '/', 1) AS path FROM {url_alias}"); | |
+ foreach ($result as $row) { | |
+ $whitelist[$row->path] = TRUE; | |
+ } | |
+ variable_set('path_alias_whitelist', $whitelist); | |
+ return $whitelist; | |
+ } | |
+} | |
+ | |
diff --git a/core/modules/path/lib/Drupal/path/Tests/LookupTest.php b/core/modules/path/lib/Drupal/path/Tests/LookupTest.php | |
new file mode 100644 | |
index 0000000..4620615 | |
--- /dev/null | |
+++ b/core/modules/path/lib/Drupal/path/Tests/LookupTest.php | |
@@ -0,0 +1,82 @@ | |
+<?php | |
+ | |
+/** | |
+ * @file | |
+ * Definition of Drupal\path\Tests\Path\LookupTest. | |
+ */ | |
+ | |
+namespace Drupal\path\Tests\Path; | |
+ | |
+use Drupal\simpletest\WebTestBase; | |
+ | |
+/** | |
+ * Tests for DrupalPathRegistry. | |
+ */ | |
+class LookupTest extends WebTestBase { | |
+ public static function getInfo() { | |
+ return array( | |
+ 'name' => t('Path lookup'), | |
+ 'description' => t('Tests that DrupalPathRegistry returns correct paths.'), | |
+ 'group' => t('Path API'), | |
+ ); | |
+ } | |
+ | |
+ /** | |
+ * Test that DrupalPathRegistry returns the correct path. | |
+ */ | |
+ function testDrupalLookupPath() { | |
+ $account = $this->drupalCreateUser(); | |
+ $uid = $account->uid; | |
+ $name = $account->name; | |
+ | |
+ // Test the situation where the source is the same for multiple aliases. | |
+ // Start with a language-neutral alias, which we will override. | |
+ $path = array( | |
+ 'source' => "user/$uid", | |
+ 'alias' => 'foo', | |
+ ); | |
+ drupal_container()->get('path_registry')->save($path['source'], $path['alias']); | |
+ $this->assertEqual(drupal_container()->get('path_registry')->getPathAlias($path['source']), $path['alias'], t('Basic alias lookup works.')); | |
+ $this->assertEqual(drupal_container()->get('path_registry')->getSystemPath($path['alias']), $path['source'], t('Basic source lookup works.')); | |
+ | |
+ // Create a language specific alias for the default language (English). | |
+ $path = array( | |
+ 'source' => "user/$uid", | |
+ 'alias' => "users/$name", | |
+ 'langcode' => 'en', | |
+ ); | |
+ drupal_container()->get('path_registry')->save($path['source'], $path['alias'], $path['langcode']); | |
+ $this->assertEqual(drupal_container()->get('path_registry')->getPathAlias($path['source']), $path['alias'], t('English alias overrides language-neutral alias.')); | |
+ $this->assertEqual(drupal_container()->get('path_registry')->getSystemPath($path['alias']), $path['source'], t('English source overrides language-neutral source.')); | |
+ | |
+ // Create a language-neutral alias for the same path, again. | |
+ drupal_container()->get('path_registry')->save("user/$uid", 'bar'); | |
+ $this->assertEqual(drupal_container()->get('path_registry')->getPathAlias("user/$uid"), "users/$name", t('English alias still returned after entering a language-neutral alias.')); | |
+ | |
+ // Create a language-specific (xx-lolspeak) alias for the same path. | |
+ drupal_container()->get('path_registry')->save("user/$uid", 'LOL', 'xx-lolspeak'); | |
+ $this->assertEqual(drupal_container()->get('path_registry')->getPathAlias("user/$uid"), "users/$name", t('English alias still returned after entering a LOLspeak alias.')); | |
+ // The LOLspeak alias should be returned if we really want LOLspeak. | |
+ $this->assertEqual(drupal_container()->get('path_registry')->getPathAlias("user/$uid", 'xx-lolspeak'), 'LOL', t('LOLspeak alias returned if we specify xx-lolspeak to DrupalPathRegistry.')); | |
+ | |
+ // Create a new alias for this path in English, which should override the | |
+ // previous alias for "user/$uid". | |
+ drupal_container()->get('path_registry')->save("user/$uid", 'users/my-new-path', 'en'); | |
+ $this->assertEqual(drupal_container()->get('path_registry')->getPathAlias("user/$uid"), 'users/my-new-path', t('Recently created English alias returned.')); | |
+ $this->assertEqual(drupal_container()->get('path_registry')->getSystemPath('users/my-new-path'), "user/$uid", t('Recently created English source returned.')); | |
+ | |
+ // Remove the English aliases, which should cause a fallback to the most | |
+ // recently created language-neutral alias, 'bar'. | |
+ db_delete('url_alias') | |
+ ->condition('langcode', 'en') | |
+ ->execute(); | |
+ drupal_container()->get('path_registry')->cacheClear(); | |
+ $this->assertEqual(drupal_container()->get('path_registry')->getPathAlias($path['source']), 'bar', t('Path lookup falls back to recently created language-neutral alias.')); | |
+ | |
+ // Test the situation where the alias and language are the same, but | |
+ // the source differs. The newer alias record should be returned. | |
+ $account2 = $this->drupalCreateUser(); | |
+ drupal_container()->get('path_registry')->save('user/' . $account2->uid, 'bar'); | |
+ $this->assertEqual(drupal_container()->get('path_registry')->getPathAlias('source', 'bar'), 'user/' . $account2->uid, t('Newer alias record is returned when comparing two LANGUAGE_NOT_SPECIFIED paths with the same alias.')); | |
+ } | |
+} | |
diff --git a/core/modules/path/lib/Drupal/path/Tests/PathAliasTest.php b/core/modules/path/lib/Drupal/path/Tests/PathAliasTest.php | |
index af8b0c7..457230b 100644 | |
--- a/core/modules/path/lib/Drupal/path/Tests/PathAliasTest.php | |
+++ b/core/modules/path/lib/Drupal/path/Tests/PathAliasTest.php | |
@@ -84,7 +84,7 @@ class PathAliasTest extends PathTestBase { | |
$this->assertText($node1->title, 'Changed alias works.'); | |
$this->assertResponse(200); | |
- drupal_static_reset('drupal_lookup_path'); | |
+ drupal_container()->get('path_registry')->cacheClear(); | |
// Confirm that previous alias no longer works. | |
$this->drupalGet($previous); | |
$this->assertNoText($node1->title, 'Previous alias no longer works.'); | |
diff --git a/core/modules/path/lib/Drupal/path/Tests/PathLanguageTest.php b/core/modules/path/lib/Drupal/path/Tests/PathLanguageTest.php | |
index b3dba0e..a297168 100644 | |
--- a/core/modules/path/lib/Drupal/path/Tests/PathLanguageTest.php | |
+++ b/core/modules/path/lib/Drupal/path/Tests/PathLanguageTest.php | |
@@ -70,7 +70,7 @@ class PathLanguageTest extends PathTestBase { | |
$this->drupalPost(NULL, $edit, t('Save')); | |
// Clear the path lookup cache. | |
- drupal_lookup_path('wipe'); | |
+ drupal_container()->get('path_registry')->cacheClear(); | |
// Ensure the node was created. | |
$french_node = $this->drupalGetNodeByTitle($edit["title"]); | |
@@ -109,7 +109,7 @@ class PathLanguageTest extends PathTestBase { | |
// We need to ensure that the user language preference is not taken into | |
// account while determining the path alias language, because if this | |
// happens we have no way to check that the path alias is valid: there is no | |
- // path alias for French matching the english alias. So drupal_lookup_path() | |
+ // path alias for French matching the english alias. So DrupalPathRegistry | |
// needs to use the URL language to check whether the alias is valid. | |
$this->drupalGet($english_alias); | |
$this->assertText($english_node->title, 'Alias for English translation works.'); | |
@@ -133,20 +133,20 @@ class PathLanguageTest extends PathTestBase { | |
$this->drupalGet($french_alias); | |
$this->assertResponse(404, t('Alias for French translation is unavailable when URL language negotiation is disabled.')); | |
- // drupal_lookup_path() has an internal static cache. Check to see that | |
+ // DrupalPathRegistry has an internal static cache. Check to see that | |
// it has the appropriate contents at this point. | |
- drupal_lookup_path('wipe'); | |
- $french_node_path = drupal_lookup_path('source', $french_alias, $french_node->langcode); | |
+ drupal_container()->get('path_registry')->cacheClear(); | |
+ $french_node_path = drupal_container()->get('path_registry')->getSystemPath($french_alias, $french_node->langcode); | |
$this->assertEqual($french_node_path, 'node/' . $french_node->nid, t('Normal path works.')); | |
// Second call should return the same path. | |
- $french_node_path = drupal_lookup_path('source', $french_alias, $french_node->langcode); | |
+ $french_node_path = drupal_container()->get('path_registry')->getSystemPath($french_alias, $french_node->langcode); | |
$this->assertEqual($french_node_path, 'node/' . $french_node->nid, t('Normal path is the same.')); | |
// Confirm that the alias works. | |
- $french_node_alias = drupal_lookup_path('alias', 'node/' . $french_node->nid, $french_node->langcode); | |
+ $french_node_alias = drupal_container()->get('path_registry')->getPathAlias('node/' . $french_node->nid, $french_node->langcode); | |
$this->assertEqual($french_node_alias, $french_alias, t('Alias works.')); | |
// Second call should return the same alias. | |
- $french_node_alias = drupal_lookup_path('alias', 'node/' . $french_node->nid, $french_node->langcode); | |
+ $french_node_alias = drupal_container()->get('path_registry')->getPathAlias('node/' . $french_node->nid, $french_node->langcode); | |
$this->assertEqual($french_node_alias, $french_alias, t('Alias is the same.')); | |
} | |
} | |
diff --git a/core/modules/path/path.admin.inc b/core/modules/path/path.admin.inc | |
index 4188eff..b32542e 100644 | |
--- a/core/modules/path/path.admin.inc | |
+++ b/core/modules/path/path.admin.inc | |
@@ -76,7 +76,7 @@ function path_admin_overview($keys = NULL) { | |
// If the system path maps to a different URL alias, highlight this table | |
// row to let the user know of old aliases. | |
- if ($data->alias != drupal_get_path_alias($data->source, $data->langcode)) { | |
+ if ($data->alias != drupal_container()->get('path_registry')->getPathAlias($data->source, $data->langcode)) { | |
$row['class'] = array('warning'); | |
} | |
@@ -218,7 +218,7 @@ function path_admin_form_delete_submit($form, &$form_state) { | |
*/ | |
function path_admin_form_validate($form, &$form_state) { | |
$source = &$form_state['values']['source']; | |
- $source = drupal_get_normal_path($source); | |
+ $source = drupal_container()->get('path_registry')->getSystemPath($source); | |
$alias = $form_state['values']['alias']; | |
$pid = isset($form_state['values']['pid']) ? $form_state['values']['pid'] : 0; | |
// Language is only set if language.module is enabled, otherwise save for all | |
@@ -250,7 +250,18 @@ function path_admin_form_submit($form, &$form_state) { | |
// Remove unnecessary values. | |
form_state_values_clean($form_state); | |
- path_save($form_state['values']); | |
+ $pid = isset($form_state['values']['pid']) ? $form_state['values']['pid'] : 0; | |
+ $source = &$form_state['values']['source']; | |
+ $source = drupal_container()->get('path_registry')->getSystemPath($source); | |
+ $alias = $form_state['values']['alias']; | |
+ // Language is only set if language.module is enabled, otherwise save for all | |
+ // languages. | |
+ $langcode = isset($form_state['values']['langcode']) ? $form_state['values']['langcode'] : LANGUAGE_NOT_SPECIFIED; | |
+ | |
+ $op = $pid ? 'update' : 'insert'; | |
+ if ($path = drupal_container()->get('path_registry')->save($source, $alias, $langcode, $pid)) { | |
+ module_invoke_all('path_' . $op, $path); | |
+ } | |
drupal_set_message(t('The alias has been saved.')); | |
$form_state['redirect'] = 'admin/config/search/path'; | |
@@ -282,7 +293,7 @@ function path_admin_delete_confirm($form, &$form_state, $path) { | |
*/ | |
function path_admin_delete_confirm_submit($form, &$form_state) { | |
if ($form_state['values']['confirm']) { | |
- path_delete($form_state['path']['pid']); | |
+ drupal_container()->get('path_registry')->delete($form_state['path']['pid']); | |
$form_state['redirect'] = 'admin/config/search/path'; | |
} | |
} | |
diff --git a/core/modules/path/path.api.php b/core/modules/path/path.api.php | |
index f2c5ece..09901aa 100644 | |
--- a/core/modules/path/path.api.php | |
+++ b/core/modules/path/path.api.php | |
@@ -20,7 +20,7 @@ | |
* - pid: Unique path alias identifier. | |
* - langcode: The language code of the alias. | |
* | |
- * @see path_save() | |
+ * @see DrupalPathRegistry::save() | |
*/ | |
function hook_path_insert($path) { | |
db_insert('mytable') | |
@@ -41,7 +41,7 @@ function hook_path_insert($path) { | |
* - pid: Unique path alias identifier. | |
* - langcode: The language code of the alias. | |
* | |
- * @see path_save() | |
+ * @see DrupalPathRegistry::save() | |
*/ | |
function hook_path_update($path) { | |
db_update('mytable') | |
@@ -60,7 +60,7 @@ function hook_path_update($path) { | |
* - pid: Unique path alias identifier. | |
* - langcode: The language code of the alias. | |
* | |
- * @see path_delete() | |
+ * @see DrupalPathRegistry::delete() | |
*/ | |
function hook_path_delete($path) { | |
db_delete('mytable') | |
diff --git a/core/modules/path/path.module b/core/modules/path/path.module | |
index d01c623..cc1e906 100644 | |
--- a/core/modules/path/path.module | |
+++ b/core/modules/path/path.module | |
@@ -105,7 +105,7 @@ function path_form_node_form_alter(&$form, $form_state) { | |
if ($form['#node']->langcode != LANGUAGE_NOT_SPECIFIED) { | |
$conditions['langcode'] = $form['#node']->langcode; | |
} | |
- $path = path_load($conditions); | |
+ $path = drupal_container()->get('path_registry')->load($conditions); | |
if ($path === FALSE) { | |
$path = array(); | |
} | |
@@ -190,14 +190,15 @@ function path_form_element_validate($element, &$form_state, $complete_form) { | |
*/ | |
function path_node_insert(Node $node) { | |
if (isset($node->path)) { | |
- $path = $node->path; | |
- $path['alias'] = trim($path['alias']); | |
+ $alias = trim($node->path['alias']); | |
// Only save a non-empty alias. | |
- if (!empty($path['alias'])) { | |
+ if (!empty($alias)) { | |
// Ensure fields for programmatic executions. | |
- $path['source'] = 'node/' . $node->nid; | |
- $path['langcode'] = isset($node->langcode) ? $node->langcode : LANGUAGE_NOT_SPECIFIED; | |
- path_save($path); | |
+ $source = 'node/' . $node->nid; | |
+ $langcode = isset($node->langcode) ? $node->langcode : LANGUAGE_NOT_SPECIFIED; | |
+ if ($path = drupal_container()->get('path_registry')->save($source, $alias, $langcode)) { | |
+ module_invoke_all('path_insert', $path); | |
+ } | |
} | |
} | |
} | |
@@ -208,17 +209,19 @@ function path_node_insert(Node $node) { | |
function path_node_update(Node $node) { | |
if (isset($node->path)) { | |
$path = $node->path; | |
- $path['alias'] = trim($path['alias']); | |
+ $alias = trim($path['alias']); | |
// Delete old alias if user erased it. | |
if (!empty($path['pid']) && empty($path['alias'])) { | |
- path_delete($path['pid']); | |
+ drupal_container()->get('path_registry')->delete($path['pid']); | |
} | |
// Only save a non-empty alias. | |
if (!empty($path['alias'])) { | |
// Ensure fields for programmatic executions. | |
- $path['source'] = 'node/' . $node->nid; | |
- $path['langcode'] = isset($node->langcode) ? $node->langcode : LANGUAGE_NOT_SPECIFIED; | |
- path_save($path); | |
+ $source = 'node/' . $node->nid; | |
+ $langcode = isset($node->langcode) ? $node->langcode : LANGUAGE_NOT_SPECIFIED; | |
+ if ($path = drupal_container()->get('path_registry')->save($source, $alias, $langcode, $path['pid'])) { | |
+ module_invoke_all('path_update', $path); | |
+ } | |
} | |
} | |
} | |
@@ -228,7 +231,7 @@ function path_node_update(Node $node) { | |
*/ | |
function path_node_predelete(Node $node) { | |
// Delete all aliases associated with this node. | |
- path_delete(array('source' => 'node/' . $node->nid)); | |
+ drupal_container()->get('path_registry')->delete(array('source' => 'node/' . $node->nid)); | |
} | |
/** | |
@@ -237,7 +240,7 @@ function path_node_predelete(Node $node) { | |
function path_form_taxonomy_form_term_alter(&$form, $form_state) { | |
// Make sure this does not show up on the delete confirmation form. | |
if (empty($form_state['confirm_delete'])) { | |
- $path = (isset($form['#term']['tid']) ? path_load('taxonomy/term/' . $form['#term']['tid']) : array()); | |
+ $path = (isset($form['#term']['tid']) ? drupal_container()->get('path_registry')->load('taxonomy/term/' . $form['#term']['tid']) : array()); | |
if ($path === FALSE) { | |
$path = array(); | |
} | |
@@ -278,7 +281,7 @@ function path_taxonomy_term_insert(Term $term) { | |
// Ensure fields for programmatic executions. | |
$path['source'] = 'taxonomy/term/' . $term->tid; | |
$path['langcode'] = LANGUAGE_NOT_SPECIFIED; | |
- path_save($path); | |
+ drupal_container()->get('path_registry')->save($path); | |
} | |
} | |
} | |
@@ -292,14 +295,14 @@ function path_taxonomy_term_update(Term $term) { | |
$path['alias'] = trim($path['alias']); | |
// Delete old alias if user erased it. | |
if (!empty($path['pid']) && empty($path['alias'])) { | |
- path_delete($path['pid']); | |
+ drupal_container()->get('path_registry')->delete($path['pid']); | |
} | |
// Only save a non-empty alias. | |
if (!empty($path['alias'])) { | |
// Ensure fields for programmatic executions. | |
$path['source'] = 'taxonomy/term/' . $term->tid; | |
$path['langcode'] = LANGUAGE_NOT_SPECIFIED; | |
- path_save($path); | |
+ drupal_container()->get('path_registry')->save($path); | |
} | |
} | |
} | |
@@ -309,5 +312,5 @@ function path_taxonomy_term_update(Term $term) { | |
*/ | |
function path_taxonomy_term_delete(Term $term) { | |
// Delete all aliases associated with this term. | |
- path_delete(array('source' => 'taxonomy/term/' . $term->tid)); | |
+ drupal_container()->get('path_registry')->delete(array('source' => 'taxonomy/term/' . $term->tid)); | |
} | |
diff --git a/core/modules/search/search.module b/core/modules/search/search.module | |
index f567dae..f903daa 100644 | |
--- a/core/modules/search/search.module | |
+++ b/core/modules/search/search.module | |
@@ -640,7 +640,7 @@ function search_index($sid, $module, $text) { | |
if ($tagname == 'a') { | |
// Check if link points to a node on this site | |
if (preg_match($node_regexp, $value, $match)) { | |
- $path = drupal_get_normal_path($match[1]); | |
+ $path = drupal_container()->get('path_registry')->getSystemPath($match[1]); | |
if (preg_match('!(?:node|book)/(?:view/)?([0-9]+)!i', $path, $match)) { | |
$linknid = $match[1]; | |
if ($linknid > 0) { | |
diff --git a/core/modules/shortcut/lib/Drupal/shortcut/Tests/ShortcutLinksTest.php b/core/modules/shortcut/lib/Drupal/shortcut/Tests/ShortcutLinksTest.php | |
index 278b1e0..e1c1959 100644 | |
--- a/core/modules/shortcut/lib/Drupal/shortcut/Tests/ShortcutLinksTest.php | |
+++ b/core/modules/shortcut/lib/Drupal/shortcut/Tests/ShortcutLinksTest.php | |
@@ -27,18 +27,15 @@ class ShortcutLinksTest extends ShortcutTestBase { | |
$set = $this->set; | |
// Create an alias for the node so we can test aliases. | |
- $path = array( | |
- 'source' => 'node/' . $this->node->nid, | |
- 'alias' => $this->randomName(8), | |
- ); | |
- path_save($path); | |
+ $alias = $this->randomName(8); | |
+ drupal_container()->get('path_registry')->save('node/' . $this->node->nid, $alias); | |
// Create some paths to test. | |
$test_cases = array( | |
array('path' => 'admin'), | |
array('path' => 'admin/config/system/site-information'), | |
array('path' => "node/{$this->node->nid}/edit"), | |
- array('path' => $path['alias']), | |
+ array('path' => $alias), | |
); | |
// Check that each new shortcut links where it should. | |
@@ -52,7 +49,7 @@ class ShortcutLinksTest extends ShortcutTestBase { | |
$this->assertResponse(200); | |
$saved_set = shortcut_set_load($set->set_name); | |
$paths = $this->getShortcutInformation($saved_set, 'link_path'); | |
- $this->assertTrue(in_array(drupal_get_normal_path($test['path']), $paths), 'Shortcut created: '. $test['path']); | |
+ $this->assertTrue(in_array(drupal_container()->get('path_registry')->getSystemPath($test['path']), $paths), 'Shortcut created: '. $test['path']); | |
$this->assertLink($title, 0, 'Shortcut link found on the page.'); | |
} | |
} | |
diff --git a/core/modules/shortcut/shortcut.admin.inc b/core/modules/shortcut/shortcut.admin.inc | |
index 9f1888a..2d43aea 100644 | |
--- a/core/modules/shortcut/shortcut.admin.inc | |
+++ b/core/modules/shortcut/shortcut.admin.inc | |
@@ -473,7 +473,7 @@ function _shortcut_link_form_elements($shortcut_link = NULL) { | |
); | |
} | |
else { | |
- $shortcut_link['link_path'] = drupal_get_path_alias($shortcut_link['link_path']); | |
+ $shortcut_link['link_path'] = drupal_container()->get('path_registry')->getPathAlias($shortcut_link['link_path']); | |
} | |
$form['shortcut_link']['#tree'] = TRUE; | |
@@ -520,7 +520,7 @@ function shortcut_link_edit_validate($form, &$form_state) { | |
*/ | |
function shortcut_link_edit_submit($form, &$form_state) { | |
// Normalize the path in case it is an alias. | |
- $form_state['values']['shortcut_link']['link_path'] = drupal_get_normal_path($form_state['values']['shortcut_link']['link_path']); | |
+ $form_state['values']['shortcut_link']['link_path'] = drupal_container()->get('path_registry')->getSystemPath($form_state['values']['shortcut_link']['link_path']); | |
$shortcut_link = array_merge($form_state['values']['original_shortcut_link'], $form_state['values']['shortcut_link']); | |
@@ -576,7 +576,7 @@ function shortcut_admin_add_link($shortcut_link, &$shortcut_set, $limit = NULL) | |
} | |
// Normalize the path in case it is an alias. | |
- $shortcut_link['link_path'] = drupal_get_normal_path($shortcut_link['link_path']); | |
+ $shortcut_link['link_path'] = drupal_container()->get('path_registry')->getSystemPath($shortcut_link['link_path']); | |
// Add the link to the end of the list. | |
$shortcut_set->links[] = $shortcut_link; | |
diff --git a/core/modules/shortcut/shortcut.module b/core/modules/shortcut/shortcut.module | |
index be29dce..83c37e9 100644 | |
--- a/core/modules/shortcut/shortcut.module | |
+++ b/core/modules/shortcut/shortcut.module | |
@@ -613,7 +613,7 @@ function shortcut_set_title_exists($title) { | |
*/ | |
function shortcut_valid_link($path) { | |
// Do not use URL aliases. | |
- $normal_path = drupal_get_normal_path($path); | |
+ $normal_path = drupal_container()->get('path_registry')->getSystemPath($path); | |
if ($path != $normal_path) { | |
$path = $normal_path; | |
} | |
diff --git a/core/modules/statistics/statistics.module b/core/modules/statistics/statistics.module | |
index ef1bceb..25bb4eb 100644 | |
--- a/core/modules/statistics/statistics.module | |
+++ b/core/modules/statistics/statistics.module | |
@@ -386,7 +386,7 @@ function statistics_block_view($delta = '') { | |
* A string as a link, truncated to the width, linked to the given $path. | |
*/ | |
function _statistics_link($path, $width = 35) { | |
- $title = drupal_get_path_alias($path); | |
+ $title = drupal_container()->get('path_registry')->getPathAlias($path); | |
$title = truncate_utf8($title, $width, FALSE, TRUE); | |
return l($title, $path); | |
} | |
diff --git a/core/modules/system/lib/Drupal/system/Tests/Path/LookupTest.php b/core/modules/system/lib/Drupal/system/Tests/Path/LookupTest.php | |
deleted file mode 100644 | |
index a90b5f4..0000000 | |
--- a/core/modules/system/lib/Drupal/system/Tests/Path/LookupTest.php | |
+++ /dev/null | |
@@ -1,100 +0,0 @@ | |
-<?php | |
- | |
-/** | |
- * @file | |
- * Definition of Drupal\system\Tests\Path\LookupTest. | |
- */ | |
- | |
-namespace Drupal\system\Tests\Path; | |
- | |
-use Drupal\simpletest\WebTestBase; | |
- | |
-/** | |
- * Unit test for drupal_lookup_path(). | |
- */ | |
-class LookupTest extends WebTestBase { | |
- public static function getInfo() { | |
- return array( | |
- 'name' => t('Path lookup'), | |
- 'description' => t('Tests that drupal_lookup_path() returns correct paths.'), | |
- 'group' => t('Path API'), | |
- ); | |
- } | |
- | |
- /** | |
- * Test that drupal_lookup_path() returns the correct path. | |
- */ | |
- function testDrupalLookupPath() { | |
- $account = $this->drupalCreateUser(); | |
- $uid = $account->uid; | |
- $name = $account->name; | |
- | |
- // Test the situation where the source is the same for multiple aliases. | |
- // Start with a language-neutral alias, which we will override. | |
- $path = array( | |
- 'source' => "user/$uid", | |
- 'alias' => 'foo', | |
- ); | |
- path_save($path); | |
- $this->assertEqual(drupal_lookup_path('alias', $path['source']), $path['alias'], t('Basic alias lookup works.')); | |
- $this->assertEqual(drupal_lookup_path('source', $path['alias']), $path['source'], t('Basic source lookup works.')); | |
- | |
- // Create a language specific alias for the default language (English). | |
- $path = array( | |
- 'source' => "user/$uid", | |
- 'alias' => "users/$name", | |
- 'langcode' => 'en', | |
- ); | |
- path_save($path); | |
- $this->assertEqual(drupal_lookup_path('alias', $path['source']), $path['alias'], t('English alias overrides language-neutral alias.')); | |
- $this->assertEqual(drupal_lookup_path('source', $path['alias']), $path['source'], t('English source overrides language-neutral source.')); | |
- | |
- // Create a language-neutral alias for the same path, again. | |
- $path = array( | |
- 'source' => "user/$uid", | |
- 'alias' => 'bar', | |
- ); | |
- path_save($path); | |
- $this->assertEqual(drupal_lookup_path('alias', $path['source']), "users/$name", t('English alias still returned after entering a language-neutral alias.')); | |
- | |
- // Create a language-specific (xx-lolspeak) alias for the same path. | |
- $path = array( | |
- 'source' => "user/$uid", | |
- 'alias' => 'LOL', | |
- 'langcode' => 'xx-lolspeak', | |
- ); | |
- path_save($path); | |
- $this->assertEqual(drupal_lookup_path('alias', $path['source']), "users/$name", t('English alias still returned after entering a LOLspeak alias.')); | |
- // The LOLspeak alias should be returned if we really want LOLspeak. | |
- $this->assertEqual(drupal_lookup_path('alias', $path['source'], 'xx-lolspeak'), 'LOL', t('LOLspeak alias returned if we specify xx-lolspeak to drupal_lookup_path().')); | |
- | |
- // Create a new alias for this path in English, which should override the | |
- // previous alias for "user/$uid". | |
- $path = array( | |
- 'source' => "user/$uid", | |
- 'alias' => 'users/my-new-path', | |
- 'langcode' => 'en', | |
- ); | |
- path_save($path); | |
- $this->assertEqual(drupal_lookup_path('alias', $path['source']), $path['alias'], t('Recently created English alias returned.')); | |
- $this->assertEqual(drupal_lookup_path('source', $path['alias']), $path['source'], t('Recently created English source returned.')); | |
- | |
- // Remove the English aliases, which should cause a fallback to the most | |
- // recently created language-neutral alias, 'bar'. | |
- db_delete('url_alias') | |
- ->condition('langcode', 'en') | |
- ->execute(); | |
- drupal_clear_path_cache(); | |
- $this->assertEqual(drupal_lookup_path('alias', $path['source']), 'bar', t('Path lookup falls back to recently created language-neutral alias.')); | |
- | |
- // Test the situation where the alias and language are the same, but | |
- // the source differs. The newer alias record should be returned. | |
- $account2 = $this->drupalCreateUser(); | |
- $path = array( | |
- 'source' => 'user/' . $account2->uid, | |
- 'alias' => 'bar', | |
- ); | |
- path_save($path); | |
- $this->assertEqual(drupal_lookup_path('source', $path['alias']), $path['source'], t('Newer alias record is returned when comparing two LANGUAGE_NOT_SPECIFIED paths with the same alias.')); | |
- } | |
-} | |
diff --git a/core/modules/system/lib/Drupal/system/Tests/Path/SaveTest.php b/core/modules/system/lib/Drupal/system/Tests/Path/SaveTest.php | |
index a34b384..9654d8d 100644 | |
--- a/core/modules/system/lib/Drupal/system/Tests/Path/SaveTest.php | |
+++ b/core/modules/system/lib/Drupal/system/Tests/Path/SaveTest.php | |
@@ -10,13 +10,13 @@ namespace Drupal\system\Tests\Path; | |
use Drupal\simpletest\WebTestBase; | |
/** | |
- * Tests the path_save() function. | |
+ * Tests the drupal_container()->get('path_registry')->save() function. | |
*/ | |
class SaveTest extends WebTestBase { | |
public static function getInfo() { | |
return array( | |
'name' => t('Path save'), | |
- 'description' => t('Tests that path_save() exposes the previous alias value.'), | |
+ 'description' => t('Tests that the save() method of PathRegistry exposes the previous alias value.'), | |
'group' => t('Path API'), | |
); | |
} | |
@@ -28,7 +28,7 @@ class SaveTest extends WebTestBase { | |
} | |
/** | |
- * Tests that path_save() makes the original path available to modules. | |
+ * Tests that drupal_container()->get('path_registry')->save() makes the original path available to modules. | |
*/ | |
function testDrupalSaveOriginalPath() { | |
$account = $this->drupalCreateUser(); | |
@@ -41,11 +41,11 @@ class SaveTest extends WebTestBase { | |
'alias' => 'foo', | |
); | |
$path_original = $path; | |
- path_save($path); | |
+ drupal_container()->get('path_registry')->save($path['source'], $path['alias']); | |
// Alter the path. | |
$path['alias'] = 'bar'; | |
- path_save($path); | |
+ drupal_container()->get('path_registry')->save($path['source'], $path['alias']); | |
// Test to see if the original alias is available to modules during | |
// hook_path_update(). | |
diff --git a/core/modules/system/lib/Drupal/system/Tests/Path/UrlAlterFunctionalTest.php b/core/modules/system/lib/Drupal/system/Tests/Path/UrlAlterFunctionalTest.php | |
index 9188b02..c83d643 100644 | |
--- a/core/modules/system/lib/Drupal/system/Tests/Path/UrlAlterFunctionalTest.php | |
+++ b/core/modules/system/lib/Drupal/system/Tests/Path/UrlAlterFunctionalTest.php | |
@@ -40,8 +40,7 @@ class UrlAlterFunctionalTest extends WebTestBase { | |
$this->assertUrlOutboundAlter("user/$uid", "user/$name"); | |
// Test that a path always uses its alias. | |
- $path = array('source' => "user/$uid/test1", 'alias' => 'alias/test1'); | |
- path_save($path); | |
+ drupal_container()->get('path_registry')->save("user/$uid/test1", 'alias/test1'); | |
$this->assertUrlInboundAlter('alias/test1', "user/$uid/test1"); | |
$this->assertUrlOutboundAlter("user/$uid/test1", 'alias/test1'); | |
@@ -114,7 +113,7 @@ class UrlAlterFunctionalTest extends WebTestBase { | |
* | |
* @param $original | |
* A string with the aliased or un-normal path that is run through | |
- * drupal_get_normal_path(). | |
+ * drupal_container()->get('path_registry')->getSystemPath(). | |
* @param $final | |
* A string with the expected result after url(). | |
* @return | |
@@ -122,7 +121,7 @@ class UrlAlterFunctionalTest extends WebTestBase { | |
*/ | |
protected function assertUrlInboundAlter($original, $final) { | |
// Test inbound altering. | |
- $result = drupal_get_normal_path($original); | |
+ $result = drupal_container()->get('path_registry')->getSystemPath($original); | |
$this->assertIdentical($result, $final, t('Altered inbound URL %original, expected %final, and got %result.', array('%original' => $original, '%final' => $final, '%result' => $result))); | |
} | |
} | |
diff --git a/core/modules/system/system.admin.inc b/core/modules/system/system.admin.inc | |
index a60c3fb..6978549 100644 | |
--- a/core/modules/system/system.admin.inc | |
+++ b/core/modules/system/system.admin.inc | |
@@ -1499,10 +1499,11 @@ function system_site_information_settings($form, &$form_state) { | |
'#type' => 'fieldset', | |
'#title' => t('Front page'), | |
); | |
+ $front_page = $site_config->get('page.front') != 'user' ? drupal_container()->get('path_registry')->getPathAlias($site_config->get('page.front')) : ''; | |
$form['front_page']['site_frontpage'] = array( | |
'#type' => 'textfield', | |
'#title' => t('Default front page'), | |
- '#default_value' => ($site_config->get('page.front') != 'user' ? drupal_get_path_alias($site_config->get('page.front')) : ''), | |
+ '#default_value' => $front_page, | |
'#size' => 40, | |
'#description' => t('Optionally, specify a relative URL to display as the front page. Leave blank to display the default content feed.'), | |
'#field_prefix' => url(NULL, array('absolute' => TRUE)), | |
@@ -1544,7 +1545,7 @@ function system_site_information_settings_validate($form, &$form_state) { | |
} | |
else { | |
// Get the normal path of the front page. | |
- form_set_value($form['front_page']['site_frontpage'], drupal_get_normal_path($form_state['values']['site_frontpage']), $form_state); | |
+ form_set_value($form['front_page']['site_frontpage'], drupal_container()->get('path_registry')->getSystemPath($form_state['values']['site_frontpage']), $form_state); | |
} | |
// Validate front page path. | |
if (!drupal_valid_path($form_state['values']['site_frontpage'])) { | |
@@ -1552,10 +1553,10 @@ function system_site_information_settings_validate($form, &$form_state) { | |
} | |
// Get the normal paths of both error pages. | |
if (!empty($form_state['values']['site_403'])) { | |
- form_set_value($form['error_page']['site_403'], drupal_get_normal_path($form_state['values']['site_403']), $form_state); | |
+ form_set_value($form['error_page']['site_403'], drupal_container()->get('path_registry')->getSystemPath($form_state['values']['site_403']), $form_state); | |
} | |
if (!empty($form_state['values']['site_404'])) { | |
- form_set_value($form['error_page']['site_404'], drupal_get_normal_path($form_state['values']['site_404']), $form_state); | |
+ form_set_value($form['error_page']['site_404'], drupal_container()->get('path_registry')->getSystemPath($form_state['values']['site_404']), $form_state); | |
} | |
// Validate 403 error path. | |
if (!empty($form_state['values']['site_403']) && !drupal_valid_path($form_state['values']['site_403'])) { | |
diff --git a/core/modules/system/system.api.php b/core/modules/system/system.api.php | |
index 12428fe..78aba1f 100644 | |
--- a/core/modules/system/system.api.php | |
+++ b/core/modules/system/system.api.php | |
@@ -3718,7 +3718,7 @@ function hook_system_themes_page_alter(&$theme_groups) { | |
* @param $path_language | |
* The language of the path. | |
* | |
- * @see drupal_get_normal_path() | |
+ * @see DrupalPathRegistry::getSystemPath() | |
*/ | |
function hook_url_inbound_alter(&$path, $original_path, $path_language) { | |
// Create the path user/me/edit, which allows a user to edit their account. | |
diff --git a/core/scripts/generate-d7-content.sh b/core/scripts/generate-d7-content.sh | |
index 7f03846..c769323 100644 | |
--- a/core/scripts/generate-d7-content.sh | |
+++ b/core/scripts/generate-d7-content.sh | |
@@ -253,7 +253,7 @@ for ($i = 0; $i < 12; $i++) { | |
'alias' => "content/poll/$i/results", | |
'source' => "node/$node->nid/results", | |
); | |
- path_save($path); | |
+ drupal_container()->get('path_registry')->save($path); | |
// Add some votes | |
$node = node_load($node->nid); | |
diff --git a/index.php b/index.php | |
index 7b99d10..df4b2b6 100644 | |
--- a/index.php | |
+++ b/index.php | |
@@ -11,6 +11,7 @@ | |
* See COPYRIGHT.txt and LICENSE.txt files in the "core" directory. | |
*/ | |
+use Drupal\Core\DrupalKernel; | |
use Symfony\Component\HttpFoundation\Request; | |
/** | |
@@ -29,6 +30,9 @@ $request = Request::createFromGlobals(); | |
// container at some point. | |
request($request); | |
+$kernel = new DrupalKernel('prod', FALSE); | |
+$kernel->boot(); | |
+ | |
// Bootstrap all of Drupal's subsystems, but do not initialize anything that | |
// depends on the fully resolved Drupal path, because path resolution happens | |
// during the REQUEST event of the kernel. | |
@@ -36,6 +40,6 @@ request($request); | |
// @see Drupal\Core\EventSubscriber\LegacyRequestSubscriber; | |
drupal_bootstrap(DRUPAL_BOOTSTRAP_CODE); | |
-$kernel = drupal_container()->get('httpkernel'); | |
$response = $kernel->handle($request)->prepare($request)->send(); | |
+ | |
$kernel->terminate($request, $response); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment