Skip to content

Instantly share code, notes, and snippets.

@makara
Created August 29, 2011 08:43
Show Gist options
  • Save makara/1178021 to your computer and use it in GitHub Desktop.
Save makara/1178021 to your computer and use it in GitHub Desktop.
Drupal 7 Modules
diff --git includes/features.user.inc includes/features.user.inc
index c76455d..a11e078 100644
--- includes/features.user.inc
+++ includes/features.user.inc
@@ -26,12 +26,10 @@ function user_features_api() {
function user_permission_features_export($data, &$export, $module_name = '') {
$export['dependencies']['features'] = 'features';
- // Ensure the modules that provide the given permissions are included as dependencies.
+ // Ensure the given permissions exist.
$map = user_permission_get_modules();
foreach ($data as $perm) {
if (isset($map[$perm])) {
- $perm_module = $map[$perm];
- $export['dependencies'][$perm_module] = $perm_module;
$export['features']['user_permission'][$perm] = $perm;
}
}
@@ -64,12 +62,12 @@ function user_permission_features_export_options() {
/**
* Implements hook_features_export_render().
*/
-function user_permission_features_export_render($module, $data) {
+function user_permission_features_export_render($module, $data) {
$perm_modules = &drupal_static(__FUNCTION__ . '_perm_modules');
if (!isset($perm_modules)) {
$perm_modules = user_permission_get_modules();
}
-
+
$code = array();
$code[] = ' $permissions = array();';
$code[] = '';
diff --git a/geofield.make b/geofield.make
deleted file mode 100644
index 6adff6d..0000000
--- a/geofield.make
+++ /dev/null
@@ -1,11 +0,0 @@
-; $Id$
-
-api = 2
-
-core = 7.x
-
-projects[] = libraries
-libraries[geophp][download][type] = "get"
-libraries[geophp][download][url] = "https://github.com/downloads/phayes/geoPHP/geophp.tar.gz"
-libraries[geophp][directory_name] = "geoPHP"
-libraries[geophp][destination] = "libraries"
diff --git README.txt README.txt
index a74684a..fb9b1e1 100644
--- README.txt
+++ README.txt
@@ -1,4 +1,3 @@
-// $Id$
The Path Cache module stores paths in a cache so that Drupal does not have
to look them up from the database.
diff --git path.inc path.inc
new file mode 100644
index 0000000..f3920e8
--- /dev/null
+++ path.inc
@@ -0,0 +1,667 @@
+<?php
+
+/**
+ * @file
+ * Functions to handle paths in Drupal, including path aliasing.
+ *
+ * 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
+ * executing "drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);".
+ */
+
+/**
+ * Initialize the $_GET['q'] variable to the proper normal path.
+ */
+function drupal_path_initialize() {
+ // Ensure $_GET['q'] is set before calling drupal_normal_path(), to support
+ // path caching with hook_url_inbound_alter().
+ if (empty($_GET['q'])) {
+ $_GET['q'] = variable_get('site_frontpage', 'node');
+ }
+ $_GET['q'] = drupal_get_normal_path($_GET['q']);
+}
+
+/**
+ * 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 $path_language
+ * 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 = '', $path_language = NULL) {
+ global $language_url;
+ // 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.
+ $path_language = $path_language ? $path_language : $language_url->language;
+
+ 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'][$path_language] = array();
+ // Load system paths from cache.
+ $cid = current_path();
+
+ // 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'],
+ ':language' => $path_language,
+ ':language_none' => LANGUAGE_NONE,
+ );
+ // 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 ($path_language == LANGUAGE_NONE) {
+ // Prevent PDO from complaining about a token the query doesn't use.
+ unset($args[':language']);
+ $result = db_query('SELECT source, alias FROM {url_alias} WHERE source IN (:system) AND language = :language_none ORDER BY pid ASC', $args);
+ }
+ elseif ($path_language < LANGUAGE_NONE) {
+ $result = db_query('SELECT source, alias FROM {url_alias} WHERE source IN (:system) AND language IN (:language, :language_none) ORDER BY language ASC, pid ASC', $args);
+ }
+ 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);
+ }
+ $new_paths = $result->fetchAllKeyed();
+ $cache['map'][$path_language] += $new_paths;
+ // Keep a record of paths with no alias to avoid querying twice.
+ $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.
+ if (isset($cache['map'][$path_language][$path])) {
+ return $cache['map'][$path_language][$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'][$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,
+ ':language_none' => LANGUAGE_NONE,
+ );
+ // See the queries above.
+ if ($path_language == LANGUAGE_NONE) {
+ unset($args[':language']);
+ $alias = db_query("SELECT alias FROM {url_alias} WHERE source = :source AND language = :language_none ORDER BY pid DESC", $args)->fetchField();
+ }
+ elseif ($path_language > LANGUAGE_NONE) {
+ $alias = db_query("SELECT alias FROM {url_alias} WHERE source = :source AND language IN (:language, :language_none) ORDER BY language DESC, pid DESC", $args)->fetchField();
+ }
+ else {
+ $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;
+ }
+ }
+ // 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'][$path_language][$path])) {
+ // 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,
+ ':language_none' => LANGUAGE_NONE,
+ );
+ // See the queries above.
+ if ($path_language == LANGUAGE_NONE) {
+ unset($args[':language']);
+ $result = db_query("SELECT source FROM {url_alias} WHERE alias = :alias AND language = :language_none ORDER BY pid DESC", $args);
+ }
+ elseif ($path_language > LANGUAGE_NONE) {
+ $result = db_query("SELECT source FROM {url_alias} WHERE alias = :alias AND language IN (:language, :language_none) ORDER BY language DESC, pid DESC", $args);
+ }
+ else {
+ $result = db_query("SELECT source FROM {url_alias} WHERE alias = :alias AND language IN (:language, :language_none) ORDER BY language ASC, pid DESC", $args);
+ }
+ 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;
+ }
+ }
+
+ 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().
+ */
+function drupal_cache_system_paths() {
+ // Check if the system paths for this page were loaded from cache in this
+ // request to avoid writing to cache on every request.
+ $cache = &drupal_static('drupal_lookup_path', array());
+ 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.
+ if ($paths = current($cache['map'])) {
+ $data = array_keys($paths);
+ $expire = REQUEST_TIME + (60 * 60 * 24);
+ cache_set($cid, $data, 'cache_path', $expire);
+ }
+ }
+}
+
+/**
+ * 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 $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.
+ */
+function drupal_get_path_alias($path = NULL, $path_language = NULL) {
+ // If no path is specified, use the current page's path.
+ if ($path == NULL) {
+ $path = $_GET['q'];
+ }
+ $result = $path;
+ if ($alias = drupal_lookup_path('alias', $path, $path_language)) {
+ $result = $alias;
+ }
+ return $result;
+}
+
+/**
+ * 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.
+ */
+function drupal_get_normal_path($path, $path_language = NULL) {
+ $original_path = $path;
+
+ // Lookup the path alias first.
+ if ($source = drupal_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;
+}
+
+/**
+ * Check if the current page is the front page.
+ *
+ * @return
+ * Boolean value: TRUE if the current page is the front page; FALSE if otherwise.
+ */
+function drupal_is_front_page() {
+ // Use the advanced drupal_static() pattern, since this is called very often.
+ static $drupal_static_fast;
+ if (!isset($drupal_static_fast)) {
+ $drupal_static_fast['is_front_page'] = &drupal_static(__FUNCTION__);
+ }
+ $is_front_page = &$drupal_static_fast['is_front_page'];
+
+ if (!isset($is_front_page)) {
+ // As drupal_path_initialize updates $_GET['q'] with the 'site_frontpage' path,
+ // we can check it against the 'site_frontpage' variable.
+ $is_front_page = ($_GET['q'] == variable_get('site_frontpage', 'node'));
+ }
+
+ return $is_front_page;
+}
+
+/**
+ * Check if a path matches any pattern in a set of patterns.
+ *
+ * @param $path
+ * The path to match.
+ * @param $patterns
+ * String containing a set of patterns separated by \n, \r or \r\n.
+ *
+ * @return
+ * Boolean value: TRUE if the path matches a pattern, FALSE otherwise.
+ */
+function drupal_match_path($path, $patterns) {
+ $regexps = &drupal_static(__FUNCTION__);
+
+ if (!isset($regexps[$patterns])) {
+ // Convert path settings to a regular expression.
+ // Therefore replace newlines with a logical or, /* with asterisks and the <front> with the frontpage.
+ $to_replace = array(
+ '/(\r\n?|\n)/', // newlines
+ '/\\\\\*/', // asterisks
+ '/(^|\|)\\\\<front\\\\>($|\|)/' // <front>
+ );
+ $replacements = array(
+ '|',
+ '.*',
+ '\1' . preg_quote(variable_get('site_frontpage', 'node'), '/') . '\2'
+ );
+ $patterns_quoted = preg_quote($patterns, '/');
+ $regexps[$patterns] = '/^(' . preg_replace($to_replace, $replacements, $patterns_quoted) . ')$/';
+ }
+ return (bool)preg_match($regexps[$patterns], $path);
+}
+
+/**
+ * Return the current URL path of the page being viewed.
+ *
+ * Examples:
+ * - http://example.com/node/306 returns "node/306".
+ * - http://example.com/drupalfolder/node/306 returns "node/306" while
+ * base_path() returns "/drupalfolder/".
+ * - http://example.com/path/alias (which is a path alias for node/306) returns
+ * "node/306" as opposed to the path alias.
+ *
+ * This function is not available in hook_boot() so use $_GET['q'] instead.
+ * However, be careful when doing that because in the case of Example #3
+ * $_GET['q'] will contain "path/alias". If "node/306" is needed, calling
+ * drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL) makes this function available.
+ *
+ * @return
+ * The current Drupal URL path.
+ *
+ * @see request_path()
+ */
+function current_path() {
+ return $_GET['q'];
+}
+
+/**
+ * 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.
+ * - language: The language 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.
+ * - language: (optional) The language of the alias.
+ */
+function path_save(&$path) {
+ $path += array('pid' => NULL, 'language' => LANGUAGE_NONE);
+
+ // Insert or update the alias.
+ $status = drupal_write_record('url_alias', $path, (!empty($path['pid']) ? 'pid' : array()));
+
+ // 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']);
+ }
+}
+
+/**
+ * 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
+ * match any of the patterns in path_get_admin_paths(), or if it matches both
+ * administrative and non-administrative patterns, it is considered
+ * non-administrative.
+ *
+ * @param $path
+ * A Drupal path.
+ *
+ * @return
+ * TRUE if the path is administrative, FALSE otherwise.
+ *
+ * @see path_get_admin_paths()
+ * @see hook_admin_paths()
+ * @see hook_admin_paths_alter()
+ */
+function path_is_admin($path) {
+ $path_map = &drupal_static(__FUNCTION__);
+ if (!isset($path_map['admin'][$path])) {
+ $patterns = path_get_admin_paths();
+ $path_map['admin'][$path] = drupal_match_path($path, $patterns['admin']);
+ $path_map['non_admin'][$path] = drupal_match_path($path, $patterns['non_admin']);
+ }
+ return $path_map['admin'][$path] && !$path_map['non_admin'][$path];
+}
+
+/**
+ * Get a list of administrative and non-administrative paths.
+ *
+ * @return array
+ * An associative array containing the following keys:
+ * 'admin': An array of administrative paths and regular expressions
+ * in a format suitable for drupal_match_path().
+ * 'non_admin': An array of non-administrative paths and regular expressions.
+ *
+ * @see hook_admin_paths()
+ * @see hook_admin_paths_alter()
+ */
+function path_get_admin_paths() {
+ $patterns = &drupal_static(__FUNCTION__);
+ if (!isset($patterns)) {
+ $paths = module_invoke_all('admin_paths');
+ drupal_alter('admin_paths', $paths);
+ // Combine all admin paths into one array, and likewise for non-admin paths,
+ // for easier handling.
+ $patterns = array();
+ $patterns['admin'] = array();
+ $patterns['non_admin'] = array();
+ foreach ($paths as $path => $enabled) {
+ if ($enabled) {
+ $patterns['admin'][] = $path;
+ }
+ else {
+ $patterns['non_admin'][] = $path;
+ }
+ }
+ $patterns['admin'] = implode("\n", $patterns['admin']);
+ $patterns['non_admin'] = implode("\n", $patterns['non_admin']);
+ }
+ return $patterns;
+}
+
+/**
+ * Checks a path exists and the current user has access to it.
+ *
+ * @param $path
+ * The path to check.
+ * @param $dynamic_allowed
+ * Whether paths with menu wildcards (like user/%) should be allowed.
+ *
+ * @return
+ * TRUE if it is a valid path AND the current user has access permission,
+ * FALSE otherwise.
+ */
+function drupal_valid_path($path, $dynamic_allowed = FALSE) {
+ global $menu_admin;
+ // We indicate that a menu administrator is running the menu access check.
+ $menu_admin = TRUE;
+ if ($path == '<front>' || url_is_external($path)) {
+ $item = array('access' => TRUE);
+ }
+ elseif ($dynamic_allowed && preg_match('/\/\%/', $path)) {
+ // Path is dynamic (ie 'user/%'), so check directly against menu_router table.
+ if ($item = db_query("SELECT * FROM {menu_router} where path = :path", array(':path' => $path))->fetchAssoc()) {
+ $item['link_path'] = $form_item['link_path'];
+ $item['link_title'] = $form_item['link_title'];
+ $item['external'] = FALSE;
+ $item['options'] = '';
+ _menu_link_translate($item);
+ }
+ }
+ else {
+ $item = menu_get_item($path);
+ }
+ $menu_admin = 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 pathcache.info pathcache.info
index adde30a..6118cbb 100644
--- pathcache.info
+++ pathcache.info
@@ -1,6 +1,5 @@
-; $Id$
name = Path Cache
description = Perform path caching for better URL alias performance.
dependencies[] = path
package = Caching
-core = 6.x
\ No newline at end of file
+core = 7.x
\ No newline at end of file
diff --git pathcache.install pathcache.install
index 87e746f..e06a13d 100644
--- pathcache.install
+++ pathcache.install
@@ -1,87 +1,37 @@
<?php
-// $Id$
/**
* @file
- * .install file for pathcache module.
+ * Install, update and uninstall functions for the pathcache module.
*/
/**
- * Implementation of hook_requirements().
- */
-function pathcache_requirements($phase) {
- // Ensure translations don't break at install time.
- $t = get_t();
- $requirements = array();
- if ($phase == 'runtime') {
- $aliases_exist = (int)db_result(db_query('SELECT pid FROM {url_alias} LIMIT 1'));
- $requirements['pathcache'] = array(
- 'title' => $t('Path Cache'),
- 'value' => $aliases_exist ? t('URL aliases present') : t('No URL aliases exist'),
- 'severity' => $aliases_exist ? REQUIREMENT_OK : REQUIREMENT_WARNING,
- 'description' => $aliases_exist ? '' : $t('The path cache module expects to have URL aliases in your url_aliases database table. Currently that table is empty. If you are not using path aliases (by using the Path module, for example) the Path Cache module will actually slow down your site instead of speeding it up.'),
- );
- }
- return $requirements;
+ * Implements hook_schema().
+*/
+function pathcache_schema() {
+ $schema = array();
+ $cache_schema = drupal_get_schema_unprocessed('system', 'cache');
+ $description = 'Cache table for URL aliases';
+ $schema['cache_path_source'] = $cache_schema;
+ $schema['cache_path_source']['description'] = $description;
+ $schema['cache_path_alias'] = $cache_schema;
+ $schema['cache_path_alias']['description'] = $description;
+ return $schema;
}
/**
- * Implementation of hook_install().
+ * Implements hook_install().
*/
function pathcache_install() {
- drupal_install_schema('pathcache');
+ variable_set('path_inc', drupal_get_path('module', 'pathcache') . '/path.inc');
}
/**
- * Implementation of hook_uninstall().
+ * Implements hook_uninstall().
*/
function pathcache_uninstall() {
- // Remove tables.
- drupal_uninstall_schema('pathcache');
+ // Only reset the path_inc variable if it currently points to pathcache.
+ if (variable_get('path_inc') == drupal_get_path('module', 'pathcache') . '/path.inc') {
+ variable_del('path_inc');
+ }
}
-
-/**
- * Implementation of hook_schema().
- */
-function pathcache_schema() {
- $schema['cache_pathsrc'] = array(
- 'description' => t('Cache table for URL aliases.'),
- 'fields' => array(
- 'cid' => array(
- 'description' => t('Primary Key: Unique cache ID.'),
- 'type' => 'varchar',
- 'length' => 255,
- 'not null' => TRUE,
- 'default' => ''),
- 'data' => array(
- 'description' => t('A collection of data to cache.'),
- 'type' => 'blob',
- 'not null' => FALSE,
- 'size' => 'big'),
- 'expire' => array(
- 'description' => t('A Unix timestamp indicating when the cache entry should expire, or 0 for never.'),
- 'type' => 'int',
- 'not null' => TRUE,
- 'default' => 0),
- 'created' => array(
- 'description' => t('A Unix timestamp indicating when the cache entry was created.'),
- 'type' => 'int',
- 'not null' => TRUE,
- 'default' => 0),
- 'headers' => array(
- 'description' => t('Any custom HTTP headers to be added to cached data.'),
- 'type' => 'text',
- 'not null' => FALSE),
- 'serialized' => array(
- 'description' => t('A flag to indicate whether content is serialized (1) or not (0).'),
- 'type' => 'int',
- 'size' => 'small',
- 'not null' => TRUE,
- 'default' => 0)
- ),
- 'indexes' => array('expire' => array('expire')),
- 'primary key' => array('cid'),
- );
- $schema['cache_pathdst'] = $schema['cache_pathsrc'];
- return $schema;
-}
\ No newline at end of file
diff --git pathcache.module pathcache.module
index 27ae578..169bc6f 100644
--- pathcache.module
+++ pathcache.module
@@ -1,5 +1,4 @@
<?php
-// $Id$
/**
* @file
@@ -7,11 +6,43 @@
*/
/**
- * Implementation of hook_flush_caches().
+ * Implements hook_flush_caches().
*/
function pathcache_flush_caches() {
- return array(
- 'cache_pathsrc',
- 'cache_pathdst',
- );
-}
\ No newline at end of file
+ return array('cache_path_source', 'cache_path_alias');
+}
+
+/**
+ * Helper function to clear the alias and source caches for a path.
+ */
+function pathcache_clear_cache($path) {
+ // Since adding a path in any language could affect results for both
+ // that language and the default language, clear all possible
+ // combinations here.
+ $languages = language_list();
+ foreach ($languages as $language => $data) {
+ cache_clear_all($language . ':' . $path['source'], 'cache_path_alias');
+ cache_clear_all($language . ':' . $path['alias'], 'cache_path_source');
+ }
+}
+
+/**
+ * Implements hook_path_insert().
+ */
+function pathcache_path_insert($path) {
+ pathcache_clear_cache($path);
+}
+
+/**
+ * Implements hook_path_update().
+ */
+function pathcache_path_update($path) {
+ pathcache_clear_cache($path);
+}
+
+/**
+ * Implements hook_path_delete().
+ */
+function pathcache_path_delete($path) {
+ pathcache_clear_cache($path);
+}
diff --git a/http/apache/apache_service.inc b/http/apache/apache_service.inc
index bf5dc21..1405470 100644
--- a/http/apache/apache_service.inc
+++ b/http/apache/apache_service.inc
@@ -49,7 +49,7 @@ class provisionService_http_apache extends provisionService_http_public {
/**
* Restart apache to pick up the new config files.
- */
+ */
function parse_configs() {
return $this->restart();
}
@@ -63,6 +63,8 @@ class provisionConfig_apache_server extends provisionConfig_http_server {
parent::process();
$this->data['extra_config'] = "# Extra configuration from modules:\n";
$this->data['extra_config'] .= join("\n", drush_command_invoke_all('provision_apache_server_config', $this->data));
+ // #1087648 - only use ip-based virtual hosting when it's forced.
+ $this->data['force_ip'] = drush_get_option('aegir_apache_server_force_ip', FALSE);
}
}
@@ -77,7 +79,7 @@ class provisionConfig_apache_platform extends provisionConfig_http_platform {
}
}
-/**
+/**
* Apache site level config class. Virtual host.
*/
class provisionConfig_apache_site extends provisionConfig_http_site {
@@ -85,6 +87,8 @@ class provisionConfig_apache_site extends provisionConfig_http_site {
parent::process();
$this->data['extra_config'] = "# Extra configuration from modules:\n";
$this->data['extra_config'] .= join("\n", drush_command_invoke_all('provision_apache_vhost_config', $this->uri, $this->data));
+ // #1087648 - only use ip-based virtual hosting when it's forced.
+ $this->data['force_ip'] = drush_get_option('aegir_apache_site_force_ip', FALSE);
}
}
diff --git a/http/apache/vhost.tpl.php b/http/apache/vhost.tpl.php
index be7ae0c..ac17b74 100644
--- a/http/apache/vhost.tpl.php
+++ b/http/apache/vhost.tpl.php
@@ -1,10 +1,10 @@
-<VirtualHost *:<?php print $http_port; ?>>
+<VirtualHost <?php print !empty($force_ip) ? $ip_address : '*' ?>:<?php print $http_port; ?>>
<?php if ($this->site_mail) : ?>
- ServerAdmin <?php print $this->site_mail; ?>
+ ServerAdmin <?php print $this->site_mail; ?>
<?php endif;?>
- DocumentRoot <?php print $this->root; ?>
-
+ DocumentRoot <?php print $this->root; ?>
+
ServerName <?php print $this->uri; ?>
SetEnv db_type <?php print urlencode($db_type); ?>
@@ -20,11 +20,11 @@
SetEnv db_port <?php print urlencode($db_port); ?>
-<?php
+<?php
if (sizeof($this->aliases)) {
print "\n ServerAlias " . implode("\n ServerAlias ", $this->aliases) . "\n";
}
-
+
if ($this->redirection || $ssl_redirection) {
print " RewriteEngine on\n";
@@ -61,7 +61,7 @@ if ($this->redirection || $ssl_redirection) {
Options None
Options +FollowSymLinks
</DirectoryMatch>
-
+
</VirtualHost>
diff --git a/subpathauto.module b/subpathauto.module
index 2175e90..857692b 100644
--- a/subpathauto.module
+++ b/subpathauto.module
@@ -63,12 +63,14 @@ function subpathauto_url_outbound_alter(&$path, &$options, $original_path) {
function subpathauto_lookup_subpath($action, $path = '', $original_path, $path_language = NULL) {
global $language_url;
- // Use the advanced drupal_static() pattern, since this is called very often.
- static $drupal_static_fast;
- if (!isset($drupal_static_fast)) {
- $drupal_static_fast = &drupal_static(__FUNCTION__, array(
- 'max_depth' => NULL,
- ));
+ $max_depth = variable_get('subpathauto_depth', 1);
+ if (empty($max_depth)) {
+ return FALSE;
+ }
+
+ // .
+ if (!isset($original_path) || drupal_lookup_path($action, $original_path, $path_language)) {
+ return FALSE;
}
if ($path == '' || strpos($path, '/') === FALSE) {
@@ -90,14 +92,6 @@ function subpathauto_lookup_subpath($action, $path = '', $original_path, $path_l
return FALSE;
}
- $max_depth = &$drupal_static_fast['max_depth'];
- if (!isset($max_depth)) {
- $max_depth = variable_get('subpathauto_depth', 1);
- }
- if (!$max_depth) {
- return FALSE;
- }
-
// 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
@@ -116,6 +110,9 @@ function subpathauto_lookup_subpath($action, $path = '', $original_path, $path_l
if ($action == 'alias' && $aliased_base_path = drupal_lookup_path('alias', $base_path, $path_language)) {
if ($aliased_base_path != $base_path) {
$alias = $aliased_base_path . '/' . implode('/', $path_suffix);
+ if (module_exists('pathcache')) {
+ cache_set($path_language . ':' . $original_path, $alias, 'cache_path_alias');
+ }
//subpathauto_cache_subpath_alias($path, $alias, $path_language);
return $alias;
}
@@ -123,6 +120,9 @@ function subpathauto_lookup_subpath($action, $path = '', $original_path, $path_l
elseif ($action == 'source' && $sourced_base_path = drupal_lookup_path('source', $base_path, $path_language)) {
if ($sourced_base_path != $base_path) {
$source = $sourced_base_path . '/' . implode('/', $path_suffix);
+ if (module_exists('pathcache')) {
+ cache_set($path_language . ':' . $original_path, $source, 'cache_path_source');
+ }
//subpathauto_cache_subpath_alias($source, $path, $path_language);
return $source;
}
diff --git varnish.cache.inc varnish.cache.inc
index 5d34cb2..9313f7d 100644
--- varnish.cache.inc
+++ varnish.cache.inc
@@ -35,7 +35,7 @@ class VarnishCache implements DrupalCacheInterface {
function clear($cid = NULL, $wildcard = FALSE) {
global $user;
// Check that we really want to do a cache flush.
- if (!module_exists('varnish') ||
+ if (!module_exists('varnish') || !variable_get('varnish_cache_clear', 1) ||
(variable_get('varnish_flush_cron', 0) && lock_may_be_available('cron'))) {
return;
}
@@ -73,7 +73,7 @@ class VarnishCache implements DrupalCacheInterface {
$host = _varnish_get_host();
$base = base_path();
$purge = $cid . '(.*)';
- _varnish_terminal_run(array('purge req.http.host ~ ' . $host . ' && req.url ~ "^' . $base . $purge . '$"'));
+ varnish_purge($host, '^' . $base . $purge . '$');
}
}
elseif (is_array($cid)) {
diff --git modules/taxonomy/views_handler_relationship_node_term_data.inc modules/taxonomy/views_handler_relationship_node_term_data.inc
index 2f013da..1a66e81 100644
--- modules/taxonomy/views_handler_relationship_node_term_data.inc
+++ modules/taxonomy/views_handler_relationship_node_term_data.inc
@@ -48,27 +48,29 @@ class views_handler_relationship_node_term_data extends views_handler_relationsh
function query() {
$this->ensure_my_table();
- $def = $this->definition;
+ $vocabularies = array_filter($this->options['vocabularies']);
+
+ $def = array();
$def['table'] = 'taxonomy_term_data';
- if (!array_filter($this->options['vocabularies'])) {
+ if (empty($vocabularies) || !empty($this->options['required'])) {
$term_node = $this->query->add_table('taxonomy_index', $this->relationship);
- $def['left_table'] = 'taxonomy_index';
+ $def['left_table'] = $term_node;
$def['left_field'] = 'tid';
$def['field'] = 'tid';
$def['type'] = empty($this->options['required']) ? 'LEFT' : 'INNER';
}
else {
- // If vocabularies are supplied join a subselect instead
+ // If vocabularies are supplied and the relationship is not required, join a subselect.
$def['left_table'] = $this->table_alias;
$def['left_field'] = 'nid';
$def['field'] = 'nid';
- $def['type'] = empty($this->options['required']) ? 'LEFT' : 'INNER';
+ $def['type'] = 'LEFT';
$query = db_select('taxonomy_term_data', 'td');
- $query->addJoin($def['type'], 'taxonomy_vocabulary', 'tv', 'td.vid = tv.vid');
- $query->addJoin($def['type'], 'taxonomy_index', 'tn', 'tn.tid = td.tid');
- $query->condition('tv.machine_name', array_filter($this->options['vocabularies']));
+ $query->addJoin('INNER', 'taxonomy_vocabulary', 'tv', 'td.vid = tv.vid');
+ $query->addJoin('INNER', 'taxonomy_index', 'tn', 'tn.tid = td.tid');
+ $query->condition('tv.machine_name', $vocabularies);
$query->addTag('term_access');
$query->fields('td');
$query->fields('tn', array('nid'));
@@ -76,14 +78,17 @@ class views_handler_relationship_node_term_data extends views_handler_relationsh
}
$join = new views_join();
-
$join->definition = $def;
$join->construct();
$join->adjusted = TRUE;
- // use a short alias for this:
$alias = $def['table'] . '_' . $this->table;
-
$this->alias = $this->query->add_relationship($alias, $join, 'taxonomy_term_data', $this->relationship);
+
+ if (!empty($vocabularies) && !empty($this->options['required'])) {
+ // If vocabularies are supplied and the relationship is required, filter by the vocabularies.
+ $vocabulary = $this->query->ensure_table('taxonomy_vocabulary', $this->alias);
+ $this->query->add_where(0, "$vocabulary.machine_name", $vocabularies);
+ }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment