Created
July 22, 2018 11:13
-
-
Save amcgowanca/fc5dca57785d9094aab99af2d5631959 to your computer and use it in GitHub Desktop.
Drupal 7.59 reroll of Path Cache modifications
This file contains hidden or 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/includes/path.inc b/includes/path.inc | |
index 6bd48d3..d3b8d9f 100644 | |
--- a/includes/path.inc | |
+++ b/includes/path.inc | |
@@ -77,8 +77,7 @@ function drupal_lookup_path($action, $path = '', $path_language = NULL) { | |
$path_language = $path_language ? $path_language : $language_url->language; | |
if ($action == 'wipe') { | |
- $cache = array(); | |
- $cache['whitelist'] = drupal_path_alias_whitelist_rebuild(); | |
+ $cache = NULL; | |
} | |
elseif ($cache['whitelist'] && $path != '') { | |
if ($action == 'alias') { | |
@@ -90,8 +89,47 @@ function drupal_lookup_path($action, $path = '', $path_language = NULL) { | |
$cache['map'][$path_language] = array(); | |
// Load system paths from cache. | |
$cid = current_path(); | |
- if ($cached = cache_get($cid, 'cache_path')) { | |
- $cache['system_paths'] = $cached->data; | |
+ | |
+ // Small hack to allow pre-filling of system paths cache via | |
+ // drupal_static(), you can set $cache['system_paths'] and | |
+ // $cache['first_call'] then get multiple lookups for any | |
+ // arbitrary set of system paths.. | |
+ $cached = FALSE; | |
+ if (!empty($cache['system_paths']) || ($cached = cache_get($cid, 'cache_path'))) { | |
+ if ($cached) { | |
+ $cache['system_paths'] = $cached->data; | |
+ } | |
+ // End hack. | |
+ | |
+ // Now fetch the aliases corresponding to these system paths. | |
+ // We order by ASC and overwrite array keys to ensure the correct | |
+ // alias is used when there are multiple aliases per path. | |
+ | |
+ // First try to fetch the path aliaes from cache. By using | |
+ // cache_get_multiple() we allow caching backends which support it to | |
+ // fetch all cached paths in a single request. $cid needs to be built | |
+ // from both path language and path. | |
+ foreach ($cache['system_paths'] as $system_path) { | |
+ $system_cids[] = $path_language . ':' . $system_path; | |
+ $system_paths[$system_path] = $system_path; | |
+ } | |
+ if ($cached_paths = cache_get_multiple($system_cids, 'cache_path_alias')) { | |
+ foreach ($cached_paths as $cached) { | |
+ $system_path = str_replace($path_language . ':', '', $cached->cid); | |
+ // Remove this path from the aliases to query against the | |
+ // database. | |
+ unset($system_paths[$system_path]); | |
+ if ($cached->data) { | |
+ $cache['map'][$path_language][$system_path] = $cached->data; | |
+ } | |
+ else { | |
+ $cache['no_aliases'][$path_language][$system_path] = $system_path; | |
+ } | |
+ } | |
+ } | |
+ } | |
+ // Fetch remaining paths from the database. | |
+ if (!empty($system_paths)) { | |
// Now fetch the aliases corresponding to these system paths. | |
$args = array( | |
':system' => $cache['system_paths'], | |
@@ -116,9 +154,20 @@ function drupal_lookup_path($action, $path = '', $path_language = NULL) { | |
else { | |
$result = db_query('SELECT source, alias FROM {url_alias} WHERE source IN (:system) AND language IN (:language, :language_none) ORDER BY language DESC, pid ASC', $args); | |
} | |
- $cache['map'][$path_language] = $result->fetchAllKeyed(); | |
+ $new_paths = $result->fetchAllKeyed(); | |
+ $cache['map'][$path_language] += $new_paths; | |
// Keep a record of paths with no alias to avoid querying twice. | |
- $cache['no_aliases'][$path_language] = array_flip(array_diff_key($cache['system_paths'], array_keys($cache['map'][$path_language]))); | |
+ $new_misses = array_diff_key($cache['system_paths'], array_keys($cache['map'][$path_language])); | |
+ foreach ($new_misses as $new_miss) { | |
+ $path_cid = $path_language . ':' . $new_miss; | |
+ cache_set($path_cid, '', 'cache_path_alias'); | |
+ $cache['no_aliases'][$path_language][$new_miss] = $new_miss; | |
+ } | |
+ // Cache the individual paths. | |
+ foreach ($new_paths as $new_path => $new_alias) { | |
+ $path_cid = $path_language . ':' . $new_path; | |
+ cache_set($path_cid, $new_alias, 'cache_path_alias'); | |
+ } | |
} | |
} | |
// If the alias has already been loaded, return it. | |
@@ -133,6 +182,12 @@ function drupal_lookup_path($action, $path = '', $path_language = NULL) { | |
} | |
// For system paths which were not cached, query aliases individually. | |
elseif (!isset($cache['no_aliases'][$path_language][$path])) { | |
+ $path_cid = $path_language . ':' . $path; | |
+ $cached = cache_get($path_cid, 'cache_path_alias'); | |
+ if ($cached) { | |
+ $cache['map'][$path_language][$path] = $alias = $cached->data; | |
+ return $alias; | |
+ } | |
$args = array( | |
':source' => $path, | |
':language' => $path_language, | |
@@ -150,6 +205,15 @@ function drupal_lookup_path($action, $path = '', $path_language = NULL) { | |
$alias = db_query("SELECT alias FROM {url_alias} WHERE source = :source AND language IN (:language, :language_none) ORDER BY language ASC, pid DESC", $args)->fetchField(); | |
} | |
$cache['map'][$path_language][$path] = $alias; | |
+ if ($alias) { | |
+ cache_set($path_cid, $alias, 'cache_path_alias'); | |
+ } | |
+ else { | |
+ // When there is no alias, cache this fact as well, but only when | |
+ // the user is anonymous to avoid bloating the cache with paths | |
+ // like node/n/edit. | |
+ cache_set($path_cid, '', 'cache_path_alias'); | |
+ } | |
return $alias; | |
} | |
} | |
@@ -159,6 +223,17 @@ function drupal_lookup_path($action, $path = '', $path_language = NULL) { | |
// Look for the value $path within the cached $map | |
$source = FALSE; | |
if (!isset($cache['map'][$path_language]) || !($source = array_search($path, $cache['map'][$path_language]))) { | |
+ $path_cid = $path_language . ':' . $path; | |
+ | |
+ if ($cached = cache_get($path_cid, 'cache_path_source')) { | |
+ if (!empty($cached->data)) { | |
+ $cache['map'][$path_language][$source] = $source = $cached->data; | |
+ } | |
+ else { | |
+ $cache['no_source'][$path_language][$path] = TRUE; | |
+ } | |
+ return $source; | |
+ } | |
$args = array( | |
':alias' => $path, | |
':language' => $path_language, | |
@@ -177,12 +252,22 @@ function drupal_lookup_path($action, $path = '', $path_language = NULL) { | |
} | |
if ($source = $result->fetchField()) { | |
$cache['map'][$path_language][$source] = $path; | |
+ cache_set($path_cid, $source, 'cache_path_source'); | |
} | |
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'][$path_language][$path] = TRUE; | |
+ // Add a cache entry with an empty string - this saves hitting the | |
+ // db for zero results. We can afford to do this because the | |
+ // whitelist will prevent attempts to cache paths like comment/$cid. | |
+ // And because memcache operates an LRU cache. However, only do this | |
+ // for anonymous users to avoid bloating the cache with paths like | |
+ // node/n/edit. | |
+ if (empty($GLOBALS['user']->uid)) { | |
+ cache_set($path_cid, '', 'cache_path_source'); | |
+ } | |
} | |
} | |
return $source; | |
@@ -432,27 +517,21 @@ function path_load($conditions) { | |
* - language: (optional) The language of the alias. | |
*/ | |
function path_save(&$path) { | |
- $path += array('language' => LANGUAGE_NONE); | |
+ $path += array('pid' => NULL, 'language' => LANGUAGE_NONE); | |
- // Load the stored alias, if any. | |
- if (!empty($path['pid']) && !isset($path['original'])) { | |
- $path['original'] = path_load($path['pid']); | |
- } | |
+ // Insert or update the alias. | |
+ $status = drupal_write_record('url_alias', $path, (!empty($path['pid']) ? 'pid' : array())); | |
- 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); | |
+ // Verify that a record was written. | |
+ if ($status) { | |
+ if ($status === SAVED_NEW) { | |
+ module_invoke_all('path_insert', $path); | |
+ } | |
+ else { | |
+ module_invoke_all('path_update', $path); | |
+ } | |
+ drupal_clear_path_cache($path['source']); | |
} | |
- | |
- // Clear internal properties. | |
- unset($path['original']); | |
- | |
- // Clear the static alias cache. | |
- drupal_clear_path_cache($path['source']); | |
} | |
/** |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment