annotate includes/path.inc @ 13:134d4b2e75f6

updated quicktabs and google analytics modules
author danieleb <danielebarchiesi@me.com>
date Tue, 29 Oct 2013 13:48:59 +0000
parents ff03f76ab3fe
children
rev   line source
danielebarchiesi@0 1 <?php
danielebarchiesi@0 2
danielebarchiesi@0 3 /**
danielebarchiesi@0 4 * @file
danielebarchiesi@0 5 * Functions to handle paths in Drupal, including path aliasing.
danielebarchiesi@0 6 *
danielebarchiesi@0 7 * These functions are not loaded for cached pages, but modules that need
danielebarchiesi@0 8 * to use them in hook_boot() or hook exit() can make them available, by
danielebarchiesi@0 9 * executing "drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);".
danielebarchiesi@0 10 */
danielebarchiesi@0 11
danielebarchiesi@0 12 /**
danielebarchiesi@0 13 * Initialize the $_GET['q'] variable to the proper normal path.
danielebarchiesi@0 14 */
danielebarchiesi@0 15 function drupal_path_initialize() {
danielebarchiesi@0 16 // Ensure $_GET['q'] is set before calling drupal_normal_path(), to support
danielebarchiesi@0 17 // path caching with hook_url_inbound_alter().
danielebarchiesi@0 18 if (empty($_GET['q'])) {
danielebarchiesi@0 19 $_GET['q'] = variable_get('site_frontpage', 'node');
danielebarchiesi@0 20 }
danielebarchiesi@0 21 $_GET['q'] = drupal_get_normal_path($_GET['q']);
danielebarchiesi@0 22 }
danielebarchiesi@0 23
danielebarchiesi@0 24 /**
danielebarchiesi@0 25 * Given an alias, return its Drupal system URL if one exists. Given a Drupal
danielebarchiesi@0 26 * system URL return one of its aliases if such a one exists. Otherwise,
danielebarchiesi@0 27 * return FALSE.
danielebarchiesi@0 28 *
danielebarchiesi@0 29 * @param $action
danielebarchiesi@0 30 * One of the following values:
danielebarchiesi@0 31 * - wipe: delete the alias cache.
danielebarchiesi@0 32 * - alias: return an alias for a given Drupal system path (if one exists).
danielebarchiesi@0 33 * - source: return the Drupal system URL for a path alias (if one exists).
danielebarchiesi@0 34 * @param $path
danielebarchiesi@0 35 * The path to investigate for corresponding aliases or system URLs.
danielebarchiesi@0 36 * @param $path_language
danielebarchiesi@0 37 * Optional language code to search the path with. Defaults to the page language.
danielebarchiesi@0 38 * If there's no path defined for that language it will search paths without
danielebarchiesi@0 39 * language.
danielebarchiesi@0 40 *
danielebarchiesi@0 41 * @return
danielebarchiesi@0 42 * Either a Drupal system path, an aliased path, or FALSE if no path was
danielebarchiesi@0 43 * found.
danielebarchiesi@0 44 */
danielebarchiesi@0 45 function drupal_lookup_path($action, $path = '', $path_language = NULL) {
danielebarchiesi@0 46 global $language_url;
danielebarchiesi@0 47 // Use the advanced drupal_static() pattern, since this is called very often.
danielebarchiesi@0 48 static $drupal_static_fast;
danielebarchiesi@0 49 if (!isset($drupal_static_fast)) {
danielebarchiesi@0 50 $drupal_static_fast['cache'] = &drupal_static(__FUNCTION__);
danielebarchiesi@0 51 }
danielebarchiesi@0 52 $cache = &$drupal_static_fast['cache'];
danielebarchiesi@0 53
danielebarchiesi@0 54 if (!isset($cache)) {
danielebarchiesi@0 55 $cache = array(
danielebarchiesi@0 56 'map' => array(),
danielebarchiesi@0 57 'no_source' => array(),
danielebarchiesi@0 58 'whitelist' => NULL,
danielebarchiesi@0 59 'system_paths' => array(),
danielebarchiesi@0 60 'no_aliases' => array(),
danielebarchiesi@0 61 'first_call' => TRUE,
danielebarchiesi@0 62 );
danielebarchiesi@0 63 }
danielebarchiesi@0 64
danielebarchiesi@0 65 // Retrieve the path alias whitelist.
danielebarchiesi@0 66 if (!isset($cache['whitelist'])) {
danielebarchiesi@0 67 $cache['whitelist'] = variable_get('path_alias_whitelist', NULL);
danielebarchiesi@0 68 if (!isset($cache['whitelist'])) {
danielebarchiesi@0 69 $cache['whitelist'] = drupal_path_alias_whitelist_rebuild();
danielebarchiesi@0 70 }
danielebarchiesi@0 71 }
danielebarchiesi@0 72
danielebarchiesi@0 73 // If no language is explicitly specified we default to the current URL
danielebarchiesi@0 74 // language. If we used a language different from the one conveyed by the
danielebarchiesi@0 75 // requested URL, we might end up being unable to check if there is a path
danielebarchiesi@0 76 // alias matching the URL path.
danielebarchiesi@0 77 $path_language = $path_language ? $path_language : $language_url->language;
danielebarchiesi@0 78
danielebarchiesi@0 79 if ($action == 'wipe') {
danielebarchiesi@0 80 $cache = array();
danielebarchiesi@0 81 $cache['whitelist'] = drupal_path_alias_whitelist_rebuild();
danielebarchiesi@0 82 }
danielebarchiesi@0 83 elseif ($cache['whitelist'] && $path != '') {
danielebarchiesi@0 84 if ($action == 'alias') {
danielebarchiesi@0 85 // During the first call to drupal_lookup_path() per language, load the
danielebarchiesi@0 86 // expected system paths for the page from cache.
danielebarchiesi@0 87 if (!empty($cache['first_call'])) {
danielebarchiesi@0 88 $cache['first_call'] = FALSE;
danielebarchiesi@0 89
danielebarchiesi@0 90 $cache['map'][$path_language] = array();
danielebarchiesi@0 91 // Load system paths from cache.
danielebarchiesi@0 92 $cid = current_path();
danielebarchiesi@0 93 if ($cached = cache_get($cid, 'cache_path')) {
danielebarchiesi@0 94 $cache['system_paths'] = $cached->data;
danielebarchiesi@0 95 // Now fetch the aliases corresponding to these system paths.
danielebarchiesi@0 96 $args = array(
danielebarchiesi@0 97 ':system' => $cache['system_paths'],
danielebarchiesi@0 98 ':language' => $path_language,
danielebarchiesi@0 99 ':language_none' => LANGUAGE_NONE,
danielebarchiesi@0 100 );
danielebarchiesi@0 101 // Always get the language-specific alias before the language-neutral
danielebarchiesi@0 102 // one. For example 'de' is less than 'und' so the order needs to be
danielebarchiesi@0 103 // ASC, while 'xx-lolspeak' is more than 'und' so the order needs to
danielebarchiesi@0 104 // be DESC. We also order by pid ASC so that fetchAllKeyed() returns
danielebarchiesi@0 105 // the most recently created alias for each source. Subsequent queries
danielebarchiesi@0 106 // using fetchField() must use pid DESC to have the same effect.
danielebarchiesi@0 107 // For performance reasons, the query builder is not used here.
danielebarchiesi@0 108 if ($path_language == LANGUAGE_NONE) {
danielebarchiesi@0 109 // Prevent PDO from complaining about a token the query doesn't use.
danielebarchiesi@0 110 unset($args[':language']);
danielebarchiesi@0 111 $result = db_query('SELECT source, alias FROM {url_alias} WHERE source IN (:system) AND language = :language_none ORDER BY pid ASC', $args);
danielebarchiesi@0 112 }
danielebarchiesi@0 113 elseif ($path_language < LANGUAGE_NONE) {
danielebarchiesi@0 114 $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);
danielebarchiesi@0 115 }
danielebarchiesi@0 116 else {
danielebarchiesi@0 117 $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);
danielebarchiesi@0 118 }
danielebarchiesi@0 119 $cache['map'][$path_language] = $result->fetchAllKeyed();
danielebarchiesi@0 120 // Keep a record of paths with no alias to avoid querying twice.
danielebarchiesi@0 121 $cache['no_aliases'][$path_language] = array_flip(array_diff_key($cache['system_paths'], array_keys($cache['map'][$path_language])));
danielebarchiesi@0 122 }
danielebarchiesi@0 123 }
danielebarchiesi@0 124 // If the alias has already been loaded, return it.
danielebarchiesi@0 125 if (isset($cache['map'][$path_language][$path])) {
danielebarchiesi@0 126 return $cache['map'][$path_language][$path];
danielebarchiesi@0 127 }
danielebarchiesi@0 128 // Check the path whitelist, if the top_level part before the first /
danielebarchiesi@0 129 // is not in the list, then there is no need to do anything further,
danielebarchiesi@0 130 // it is not in the database.
danielebarchiesi@0 131 elseif (!isset($cache['whitelist'][strtok($path, '/')])) {
danielebarchiesi@0 132 return FALSE;
danielebarchiesi@0 133 }
danielebarchiesi@0 134 // For system paths which were not cached, query aliases individually.
danielebarchiesi@0 135 elseif (!isset($cache['no_aliases'][$path_language][$path])) {
danielebarchiesi@0 136 $args = array(
danielebarchiesi@0 137 ':source' => $path,
danielebarchiesi@0 138 ':language' => $path_language,
danielebarchiesi@0 139 ':language_none' => LANGUAGE_NONE,
danielebarchiesi@0 140 );
danielebarchiesi@0 141 // See the queries above.
danielebarchiesi@0 142 if ($path_language == LANGUAGE_NONE) {
danielebarchiesi@0 143 unset($args[':language']);
danielebarchiesi@0 144 $alias = db_query("SELECT alias FROM {url_alias} WHERE source = :source AND language = :language_none ORDER BY pid DESC", $args)->fetchField();
danielebarchiesi@0 145 }
danielebarchiesi@0 146 elseif ($path_language > LANGUAGE_NONE) {
danielebarchiesi@0 147 $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();
danielebarchiesi@0 148 }
danielebarchiesi@0 149 else {
danielebarchiesi@0 150 $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();
danielebarchiesi@0 151 }
danielebarchiesi@0 152 $cache['map'][$path_language][$path] = $alias;
danielebarchiesi@0 153 return $alias;
danielebarchiesi@0 154 }
danielebarchiesi@0 155 }
danielebarchiesi@0 156 // Check $no_source for this $path in case we've already determined that there
danielebarchiesi@0 157 // isn't a path that has this alias
danielebarchiesi@0 158 elseif ($action == 'source' && !isset($cache['no_source'][$path_language][$path])) {
danielebarchiesi@0 159 // Look for the value $path within the cached $map
danielebarchiesi@0 160 $source = FALSE;
danielebarchiesi@0 161 if (!isset($cache['map'][$path_language]) || !($source = array_search($path, $cache['map'][$path_language]))) {
danielebarchiesi@0 162 $args = array(
danielebarchiesi@0 163 ':alias' => $path,
danielebarchiesi@0 164 ':language' => $path_language,
danielebarchiesi@0 165 ':language_none' => LANGUAGE_NONE,
danielebarchiesi@0 166 );
danielebarchiesi@0 167 // See the queries above.
danielebarchiesi@0 168 if ($path_language == LANGUAGE_NONE) {
danielebarchiesi@0 169 unset($args[':language']);
danielebarchiesi@0 170 $result = db_query("SELECT source FROM {url_alias} WHERE alias = :alias AND language = :language_none ORDER BY pid DESC", $args);
danielebarchiesi@0 171 }
danielebarchiesi@0 172 elseif ($path_language > LANGUAGE_NONE) {
danielebarchiesi@0 173 $result = db_query("SELECT source FROM {url_alias} WHERE alias = :alias AND language IN (:language, :language_none) ORDER BY language DESC, pid DESC", $args);
danielebarchiesi@0 174 }
danielebarchiesi@0 175 else {
danielebarchiesi@0 176 $result = db_query("SELECT source FROM {url_alias} WHERE alias = :alias AND language IN (:language, :language_none) ORDER BY language ASC, pid DESC", $args);
danielebarchiesi@0 177 }
danielebarchiesi@0 178 if ($source = $result->fetchField()) {
danielebarchiesi@0 179 $cache['map'][$path_language][$source] = $path;
danielebarchiesi@0 180 }
danielebarchiesi@0 181 else {
danielebarchiesi@0 182 // We can't record anything into $map because we do not have a valid
danielebarchiesi@0 183 // index and there is no need because we have not learned anything
danielebarchiesi@0 184 // about any Drupal path. Thus cache to $no_source.
danielebarchiesi@0 185 $cache['no_source'][$path_language][$path] = TRUE;
danielebarchiesi@0 186 }
danielebarchiesi@0 187 }
danielebarchiesi@0 188 return $source;
danielebarchiesi@0 189 }
danielebarchiesi@0 190 }
danielebarchiesi@0 191
danielebarchiesi@0 192 return FALSE;
danielebarchiesi@0 193 }
danielebarchiesi@0 194
danielebarchiesi@0 195 /**
danielebarchiesi@0 196 * Cache system paths for a page.
danielebarchiesi@0 197 *
danielebarchiesi@0 198 * Cache an array of the system paths available on each page. We assume
danielebarchiesi@0 199 * that aliases will be needed for the majority of these paths during
danielebarchiesi@0 200 * subsequent requests, and load them in a single query during
danielebarchiesi@0 201 * drupal_lookup_path().
danielebarchiesi@0 202 */
danielebarchiesi@0 203 function drupal_cache_system_paths() {
danielebarchiesi@0 204 // Check if the system paths for this page were loaded from cache in this
danielebarchiesi@0 205 // request to avoid writing to cache on every request.
danielebarchiesi@0 206 $cache = &drupal_static('drupal_lookup_path', array());
danielebarchiesi@0 207 if (empty($cache['system_paths']) && !empty($cache['map'])) {
danielebarchiesi@0 208 // Generate a cache ID (cid) specifically for this page.
danielebarchiesi@0 209 $cid = current_path();
danielebarchiesi@0 210 // The static $map array used by drupal_lookup_path() includes all
danielebarchiesi@0 211 // system paths for the page request.
danielebarchiesi@0 212 if ($paths = current($cache['map'])) {
danielebarchiesi@0 213 $data = array_keys($paths);
danielebarchiesi@0 214 $expire = REQUEST_TIME + (60 * 60 * 24);
danielebarchiesi@0 215 cache_set($cid, $data, 'cache_path', $expire);
danielebarchiesi@0 216 }
danielebarchiesi@0 217 }
danielebarchiesi@0 218 }
danielebarchiesi@0 219
danielebarchiesi@0 220 /**
danielebarchiesi@0 221 * Given an internal Drupal path, return the alias set by the administrator.
danielebarchiesi@0 222 *
danielebarchiesi@0 223 * If no path is provided, the function will return the alias of the current
danielebarchiesi@0 224 * page.
danielebarchiesi@0 225 *
danielebarchiesi@0 226 * @param $path
danielebarchiesi@0 227 * An internal Drupal path.
danielebarchiesi@0 228 * @param $path_language
danielebarchiesi@0 229 * An optional language code to look up the path in.
danielebarchiesi@0 230 *
danielebarchiesi@0 231 * @return
danielebarchiesi@0 232 * An aliased path if one was found, or the original path if no alias was
danielebarchiesi@0 233 * found.
danielebarchiesi@0 234 */
danielebarchiesi@0 235 function drupal_get_path_alias($path = NULL, $path_language = NULL) {
danielebarchiesi@0 236 // If no path is specified, use the current page's path.
danielebarchiesi@0 237 if ($path == NULL) {
danielebarchiesi@0 238 $path = $_GET['q'];
danielebarchiesi@0 239 }
danielebarchiesi@0 240 $result = $path;
danielebarchiesi@0 241 if ($alias = drupal_lookup_path('alias', $path, $path_language)) {
danielebarchiesi@0 242 $result = $alias;
danielebarchiesi@0 243 }
danielebarchiesi@0 244 return $result;
danielebarchiesi@0 245 }
danielebarchiesi@0 246
danielebarchiesi@0 247 /**
danielebarchiesi@0 248 * Given a path alias, return the internal path it represents.
danielebarchiesi@0 249 *
danielebarchiesi@0 250 * @param $path
danielebarchiesi@0 251 * A Drupal path alias.
danielebarchiesi@0 252 * @param $path_language
danielebarchiesi@0 253 * An optional language code to look up the path in.
danielebarchiesi@0 254 *
danielebarchiesi@0 255 * @return
danielebarchiesi@0 256 * The internal path represented by the alias, or the original alias if no
danielebarchiesi@0 257 * internal path was found.
danielebarchiesi@0 258 */
danielebarchiesi@0 259 function drupal_get_normal_path($path, $path_language = NULL) {
danielebarchiesi@0 260 $original_path = $path;
danielebarchiesi@0 261
danielebarchiesi@0 262 // Lookup the path alias first.
danielebarchiesi@0 263 if ($source = drupal_lookup_path('source', $path, $path_language)) {
danielebarchiesi@0 264 $path = $source;
danielebarchiesi@0 265 }
danielebarchiesi@0 266
danielebarchiesi@0 267 // Allow other modules to alter the inbound URL. We cannot use drupal_alter()
danielebarchiesi@0 268 // here because we need to run hook_url_inbound_alter() in the reverse order
danielebarchiesi@0 269 // of hook_url_outbound_alter().
danielebarchiesi@0 270 foreach (array_reverse(module_implements('url_inbound_alter')) as $module) {
danielebarchiesi@0 271 $function = $module . '_url_inbound_alter';
danielebarchiesi@0 272 $function($path, $original_path, $path_language);
danielebarchiesi@0 273 }
danielebarchiesi@0 274
danielebarchiesi@0 275 return $path;
danielebarchiesi@0 276 }
danielebarchiesi@0 277
danielebarchiesi@0 278 /**
danielebarchiesi@0 279 * Check if the current page is the front page.
danielebarchiesi@0 280 *
danielebarchiesi@0 281 * @return
danielebarchiesi@0 282 * Boolean value: TRUE if the current page is the front page; FALSE if otherwise.
danielebarchiesi@0 283 */
danielebarchiesi@0 284 function drupal_is_front_page() {
danielebarchiesi@0 285 // Use the advanced drupal_static() pattern, since this is called very often.
danielebarchiesi@0 286 static $drupal_static_fast;
danielebarchiesi@0 287 if (!isset($drupal_static_fast)) {
danielebarchiesi@0 288 $drupal_static_fast['is_front_page'] = &drupal_static(__FUNCTION__);
danielebarchiesi@0 289 }
danielebarchiesi@0 290 $is_front_page = &$drupal_static_fast['is_front_page'];
danielebarchiesi@0 291
danielebarchiesi@0 292 if (!isset($is_front_page)) {
danielebarchiesi@0 293 // As drupal_path_initialize updates $_GET['q'] with the 'site_frontpage' path,
danielebarchiesi@0 294 // we can check it against the 'site_frontpage' variable.
danielebarchiesi@0 295 $is_front_page = ($_GET['q'] == variable_get('site_frontpage', 'node'));
danielebarchiesi@0 296 }
danielebarchiesi@0 297
danielebarchiesi@0 298 return $is_front_page;
danielebarchiesi@0 299 }
danielebarchiesi@0 300
danielebarchiesi@0 301 /**
danielebarchiesi@0 302 * Check if a path matches any pattern in a set of patterns.
danielebarchiesi@0 303 *
danielebarchiesi@0 304 * @param $path
danielebarchiesi@0 305 * The path to match.
danielebarchiesi@0 306 * @param $patterns
danielebarchiesi@0 307 * String containing a set of patterns separated by \n, \r or \r\n.
danielebarchiesi@0 308 *
danielebarchiesi@0 309 * @return
danielebarchiesi@0 310 * Boolean value: TRUE if the path matches a pattern, FALSE otherwise.
danielebarchiesi@0 311 */
danielebarchiesi@0 312 function drupal_match_path($path, $patterns) {
danielebarchiesi@0 313 $regexps = &drupal_static(__FUNCTION__);
danielebarchiesi@0 314
danielebarchiesi@0 315 if (!isset($regexps[$patterns])) {
danielebarchiesi@0 316 // Convert path settings to a regular expression.
danielebarchiesi@0 317 // Therefore replace newlines with a logical or, /* with asterisks and the <front> with the frontpage.
danielebarchiesi@0 318 $to_replace = array(
danielebarchiesi@0 319 '/(\r\n?|\n)/', // newlines
danielebarchiesi@0 320 '/\\\\\*/', // asterisks
danielebarchiesi@0 321 '/(^|\|)\\\\<front\\\\>($|\|)/' // <front>
danielebarchiesi@0 322 );
danielebarchiesi@0 323 $replacements = array(
danielebarchiesi@0 324 '|',
danielebarchiesi@0 325 '.*',
danielebarchiesi@0 326 '\1' . preg_quote(variable_get('site_frontpage', 'node'), '/') . '\2'
danielebarchiesi@0 327 );
danielebarchiesi@0 328 $patterns_quoted = preg_quote($patterns, '/');
danielebarchiesi@0 329 $regexps[$patterns] = '/^(' . preg_replace($to_replace, $replacements, $patterns_quoted) . ')$/';
danielebarchiesi@0 330 }
danielebarchiesi@0 331 return (bool)preg_match($regexps[$patterns], $path);
danielebarchiesi@0 332 }
danielebarchiesi@0 333
danielebarchiesi@0 334 /**
danielebarchiesi@0 335 * Return the current URL path of the page being viewed.
danielebarchiesi@0 336 *
danielebarchiesi@0 337 * Examples:
danielebarchiesi@0 338 * - http://example.com/node/306 returns "node/306".
danielebarchiesi@0 339 * - http://example.com/drupalfolder/node/306 returns "node/306" while
danielebarchiesi@0 340 * base_path() returns "/drupalfolder/".
danielebarchiesi@0 341 * - http://example.com/path/alias (which is a path alias for node/306) returns
danielebarchiesi@0 342 * "node/306" as opposed to the path alias.
danielebarchiesi@0 343 *
danielebarchiesi@0 344 * This function is not available in hook_boot() so use $_GET['q'] instead.
danielebarchiesi@0 345 * However, be careful when doing that because in the case of Example #3
danielebarchiesi@0 346 * $_GET['q'] will contain "path/alias". If "node/306" is needed, calling
danielebarchiesi@0 347 * drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL) makes this function available.
danielebarchiesi@0 348 *
danielebarchiesi@0 349 * @return
danielebarchiesi@0 350 * The current Drupal URL path.
danielebarchiesi@0 351 *
danielebarchiesi@0 352 * @see request_path()
danielebarchiesi@0 353 */
danielebarchiesi@0 354 function current_path() {
danielebarchiesi@0 355 return $_GET['q'];
danielebarchiesi@0 356 }
danielebarchiesi@0 357
danielebarchiesi@0 358 /**
danielebarchiesi@0 359 * Rebuild the path alias white list.
danielebarchiesi@0 360 *
danielebarchiesi@0 361 * @param $source
danielebarchiesi@0 362 * An optional system path for which an alias is being inserted.
danielebarchiesi@0 363 *
danielebarchiesi@0 364 * @return
danielebarchiesi@0 365 * An array containing a white list of path aliases.
danielebarchiesi@0 366 */
danielebarchiesi@0 367 function drupal_path_alias_whitelist_rebuild($source = NULL) {
danielebarchiesi@0 368 // When paths are inserted, only rebuild the whitelist if the system path
danielebarchiesi@0 369 // has a top level component which is not already in the whitelist.
danielebarchiesi@0 370 if (!empty($source)) {
danielebarchiesi@0 371 $whitelist = variable_get('path_alias_whitelist', NULL);
danielebarchiesi@0 372 if (isset($whitelist[strtok($source, '/')])) {
danielebarchiesi@0 373 return $whitelist;
danielebarchiesi@0 374 }
danielebarchiesi@0 375 }
danielebarchiesi@0 376 // For each alias in the database, get the top level component of the system
danielebarchiesi@0 377 // path it corresponds to. This is the portion of the path before the first
danielebarchiesi@0 378 // '/', if present, otherwise the whole path itself.
danielebarchiesi@0 379 $whitelist = array();
danielebarchiesi@0 380 $result = db_query("SELECT DISTINCT SUBSTRING_INDEX(source, '/', 1) AS path FROM {url_alias}");
danielebarchiesi@0 381 foreach ($result as $row) {
danielebarchiesi@0 382 $whitelist[$row->path] = TRUE;
danielebarchiesi@0 383 }
danielebarchiesi@0 384 variable_set('path_alias_whitelist', $whitelist);
danielebarchiesi@0 385 return $whitelist;
danielebarchiesi@0 386 }
danielebarchiesi@0 387
danielebarchiesi@0 388 /**
danielebarchiesi@0 389 * Fetches a specific URL alias from the database.
danielebarchiesi@0 390 *
danielebarchiesi@0 391 * @param $conditions
danielebarchiesi@0 392 * A string representing the source, a number representing the pid, or an
danielebarchiesi@0 393 * array of query conditions.
danielebarchiesi@0 394 *
danielebarchiesi@0 395 * @return
danielebarchiesi@0 396 * FALSE if no alias was found or an associative array containing the
danielebarchiesi@0 397 * following keys:
danielebarchiesi@0 398 * - source: The internal system path.
danielebarchiesi@0 399 * - alias: The URL alias.
danielebarchiesi@0 400 * - pid: Unique path alias identifier.
danielebarchiesi@0 401 * - language: The language of the alias.
danielebarchiesi@0 402 */
danielebarchiesi@0 403 function path_load($conditions) {
danielebarchiesi@0 404 if (is_numeric($conditions)) {
danielebarchiesi@0 405 $conditions = array('pid' => $conditions);
danielebarchiesi@0 406 }
danielebarchiesi@0 407 elseif (is_string($conditions)) {
danielebarchiesi@0 408 $conditions = array('source' => $conditions);
danielebarchiesi@0 409 }
danielebarchiesi@0 410 elseif (!is_array($conditions)) {
danielebarchiesi@0 411 return FALSE;
danielebarchiesi@0 412 }
danielebarchiesi@0 413 $select = db_select('url_alias');
danielebarchiesi@0 414 foreach ($conditions as $field => $value) {
danielebarchiesi@0 415 $select->condition($field, $value);
danielebarchiesi@0 416 }
danielebarchiesi@0 417 return $select
danielebarchiesi@0 418 ->fields('url_alias')
danielebarchiesi@0 419 ->execute()
danielebarchiesi@0 420 ->fetchAssoc();
danielebarchiesi@0 421 }
danielebarchiesi@0 422
danielebarchiesi@0 423 /**
danielebarchiesi@0 424 * Save a path alias to the database.
danielebarchiesi@0 425 *
danielebarchiesi@0 426 * @param $path
danielebarchiesi@0 427 * An associative array containing the following keys:
danielebarchiesi@0 428 * - source: The internal system path.
danielebarchiesi@0 429 * - alias: The URL alias.
danielebarchiesi@0 430 * - pid: (optional) Unique path alias identifier.
danielebarchiesi@0 431 * - language: (optional) The language of the alias.
danielebarchiesi@0 432 */
danielebarchiesi@0 433 function path_save(&$path) {
danielebarchiesi@0 434 $path += array('language' => LANGUAGE_NONE);
danielebarchiesi@0 435
danielebarchiesi@0 436 // Load the stored alias, if any.
danielebarchiesi@0 437 if (!empty($path['pid']) && !isset($path['original'])) {
danielebarchiesi@0 438 $path['original'] = path_load($path['pid']);
danielebarchiesi@0 439 }
danielebarchiesi@0 440
danielebarchiesi@0 441 if (empty($path['pid'])) {
danielebarchiesi@0 442 drupal_write_record('url_alias', $path);
danielebarchiesi@0 443 module_invoke_all('path_insert', $path);
danielebarchiesi@0 444 }
danielebarchiesi@0 445 else {
danielebarchiesi@0 446 drupal_write_record('url_alias', $path, array('pid'));
danielebarchiesi@0 447 module_invoke_all('path_update', $path);
danielebarchiesi@0 448 }
danielebarchiesi@0 449
danielebarchiesi@0 450 // Clear internal properties.
danielebarchiesi@0 451 unset($path['original']);
danielebarchiesi@0 452
danielebarchiesi@0 453 // Clear the static alias cache.
danielebarchiesi@0 454 drupal_clear_path_cache($path['source']);
danielebarchiesi@0 455 }
danielebarchiesi@0 456
danielebarchiesi@0 457 /**
danielebarchiesi@0 458 * Delete a URL alias.
danielebarchiesi@0 459 *
danielebarchiesi@0 460 * @param $criteria
danielebarchiesi@0 461 * A number representing the pid or an array of criteria.
danielebarchiesi@0 462 */
danielebarchiesi@0 463 function path_delete($criteria) {
danielebarchiesi@0 464 if (!is_array($criteria)) {
danielebarchiesi@0 465 $criteria = array('pid' => $criteria);
danielebarchiesi@0 466 }
danielebarchiesi@0 467 $path = path_load($criteria);
danielebarchiesi@0 468 $query = db_delete('url_alias');
danielebarchiesi@0 469 foreach ($criteria as $field => $value) {
danielebarchiesi@0 470 $query->condition($field, $value);
danielebarchiesi@0 471 }
danielebarchiesi@0 472 $query->execute();
danielebarchiesi@0 473 module_invoke_all('path_delete', $path);
danielebarchiesi@0 474 drupal_clear_path_cache($path['source']);
danielebarchiesi@0 475 }
danielebarchiesi@0 476
danielebarchiesi@0 477 /**
danielebarchiesi@0 478 * Determines whether a path is in the administrative section of the site.
danielebarchiesi@0 479 *
danielebarchiesi@0 480 * By default, paths are considered to be non-administrative. If a path does
danielebarchiesi@0 481 * not match any of the patterns in path_get_admin_paths(), or if it matches
danielebarchiesi@0 482 * both administrative and non-administrative patterns, it is considered
danielebarchiesi@0 483 * non-administrative.
danielebarchiesi@0 484 *
danielebarchiesi@0 485 * @param $path
danielebarchiesi@0 486 * A Drupal path.
danielebarchiesi@0 487 *
danielebarchiesi@0 488 * @return
danielebarchiesi@0 489 * TRUE if the path is administrative, FALSE otherwise.
danielebarchiesi@0 490 *
danielebarchiesi@0 491 * @see path_get_admin_paths()
danielebarchiesi@0 492 * @see hook_admin_paths()
danielebarchiesi@0 493 * @see hook_admin_paths_alter()
danielebarchiesi@0 494 */
danielebarchiesi@0 495 function path_is_admin($path) {
danielebarchiesi@0 496 $path_map = &drupal_static(__FUNCTION__);
danielebarchiesi@0 497 if (!isset($path_map['admin'][$path])) {
danielebarchiesi@0 498 $patterns = path_get_admin_paths();
danielebarchiesi@0 499 $path_map['admin'][$path] = drupal_match_path($path, $patterns['admin']);
danielebarchiesi@0 500 $path_map['non_admin'][$path] = drupal_match_path($path, $patterns['non_admin']);
danielebarchiesi@0 501 }
danielebarchiesi@0 502 return $path_map['admin'][$path] && !$path_map['non_admin'][$path];
danielebarchiesi@0 503 }
danielebarchiesi@0 504
danielebarchiesi@0 505 /**
danielebarchiesi@0 506 * Gets a list of administrative and non-administrative paths.
danielebarchiesi@0 507 *
danielebarchiesi@0 508 * @return array
danielebarchiesi@0 509 * An associative array containing the following keys:
danielebarchiesi@0 510 * 'admin': An array of administrative paths and regular expressions
danielebarchiesi@0 511 * in a format suitable for drupal_match_path().
danielebarchiesi@0 512 * 'non_admin': An array of non-administrative paths and regular expressions.
danielebarchiesi@0 513 *
danielebarchiesi@0 514 * @see hook_admin_paths()
danielebarchiesi@0 515 * @see hook_admin_paths_alter()
danielebarchiesi@0 516 */
danielebarchiesi@0 517 function path_get_admin_paths() {
danielebarchiesi@0 518 $patterns = &drupal_static(__FUNCTION__);
danielebarchiesi@0 519 if (!isset($patterns)) {
danielebarchiesi@0 520 $paths = module_invoke_all('admin_paths');
danielebarchiesi@0 521 drupal_alter('admin_paths', $paths);
danielebarchiesi@0 522 // Combine all admin paths into one array, and likewise for non-admin paths,
danielebarchiesi@0 523 // for easier handling.
danielebarchiesi@0 524 $patterns = array();
danielebarchiesi@0 525 $patterns['admin'] = array();
danielebarchiesi@0 526 $patterns['non_admin'] = array();
danielebarchiesi@0 527 foreach ($paths as $path => $enabled) {
danielebarchiesi@0 528 if ($enabled) {
danielebarchiesi@0 529 $patterns['admin'][] = $path;
danielebarchiesi@0 530 }
danielebarchiesi@0 531 else {
danielebarchiesi@0 532 $patterns['non_admin'][] = $path;
danielebarchiesi@0 533 }
danielebarchiesi@0 534 }
danielebarchiesi@0 535 $patterns['admin'] = implode("\n", $patterns['admin']);
danielebarchiesi@0 536 $patterns['non_admin'] = implode("\n", $patterns['non_admin']);
danielebarchiesi@0 537 }
danielebarchiesi@0 538 return $patterns;
danielebarchiesi@0 539 }
danielebarchiesi@0 540
danielebarchiesi@0 541 /**
danielebarchiesi@0 542 * Checks a path exists and the current user has access to it.
danielebarchiesi@0 543 *
danielebarchiesi@0 544 * @param $path
danielebarchiesi@0 545 * The path to check.
danielebarchiesi@0 546 * @param $dynamic_allowed
danielebarchiesi@0 547 * Whether paths with menu wildcards (like user/%) should be allowed.
danielebarchiesi@0 548 *
danielebarchiesi@0 549 * @return
danielebarchiesi@0 550 * TRUE if it is a valid path AND the current user has access permission,
danielebarchiesi@0 551 * FALSE otherwise.
danielebarchiesi@0 552 */
danielebarchiesi@0 553 function drupal_valid_path($path, $dynamic_allowed = FALSE) {
danielebarchiesi@0 554 global $menu_admin;
danielebarchiesi@0 555 // We indicate that a menu administrator is running the menu access check.
danielebarchiesi@0 556 $menu_admin = TRUE;
danielebarchiesi@0 557 if ($path == '<front>' || url_is_external($path)) {
danielebarchiesi@0 558 $item = array('access' => TRUE);
danielebarchiesi@0 559 }
danielebarchiesi@0 560 elseif ($dynamic_allowed && preg_match('/\/\%/', $path)) {
danielebarchiesi@0 561 // Path is dynamic (ie 'user/%'), so check directly against menu_router table.
danielebarchiesi@0 562 if ($item = db_query("SELECT * FROM {menu_router} where path = :path", array(':path' => $path))->fetchAssoc()) {
danielebarchiesi@0 563 $item['link_path'] = $form_item['link_path'];
danielebarchiesi@0 564 $item['link_title'] = $form_item['link_title'];
danielebarchiesi@0 565 $item['external'] = FALSE;
danielebarchiesi@0 566 $item['options'] = '';
danielebarchiesi@0 567 _menu_link_translate($item);
danielebarchiesi@0 568 }
danielebarchiesi@0 569 }
danielebarchiesi@0 570 else {
danielebarchiesi@0 571 $item = menu_get_item($path);
danielebarchiesi@0 572 }
danielebarchiesi@0 573 $menu_admin = FALSE;
danielebarchiesi@0 574 return $item && $item['access'];
danielebarchiesi@0 575 }
danielebarchiesi@0 576
danielebarchiesi@0 577 /**
danielebarchiesi@0 578 * Clear the path cache.
danielebarchiesi@0 579 *
danielebarchiesi@0 580 * @param $source
danielebarchiesi@0 581 * An optional system path for which an alias is being changed.
danielebarchiesi@0 582 */
danielebarchiesi@0 583 function drupal_clear_path_cache($source = NULL) {
danielebarchiesi@0 584 // Clear the drupal_lookup_path() static cache.
danielebarchiesi@0 585 drupal_static_reset('drupal_lookup_path');
danielebarchiesi@0 586 drupal_path_alias_whitelist_rebuild($source);
danielebarchiesi@0 587 }