includes.path.inc

  1. <?php
  2. // $Id: path.inc,v 1.19 2007/11/04 16:42:45 goba Exp $
  3. /**
  4.  * @file
  5.  * Functions to handle paths in Drupal, including path aliasing.
  6.  *
  7.  * These functions are not loaded for cached pages, but modules that need
  8.  * to use them in hook_init() or hook exit() can make them available, by
  9.  * executing "drupal_bootstrap(DRUPAL_BOOTSTRAP_PATH);".
  10.  */
  11. /**
  12.  * Initialize the $_GET['q'] variable to the proper normal path.
  13.  */
  14. function drupal_init_path() {
  15.   if (!empty($_GET['q'])) {
  16.     $_GET['q'] = drupal_get_normal_path(trim($_GET['q'], '/'));
  17.   }
  18.   else {
  19.     $_GET['q'] = drupal_get_normal_path(variable_get('site_frontpage''node'));
  20.   }
  21. }
  22. /**
  23.  * Given an alias, return its Drupal system URL if one exists. Given a Drupal
  24.  * system URL return one of its aliases if such a one exists. Otherwise,
  25.  * return FALSE.
  26.  *
  27.  * @param $action
  28.  *   One of the following values:
  29.  *   - wipe: delete the alias cache.
  30.  *   - alias: return an alias for a given Drupal system path (if one exists).
  31.  *   - source: return the Drupal system URL for a path alias (if one exists).
  32.  * @param $path
  33.  *   The path to investigate for corresponding aliases or system URLs.
  34.  * @param $path_language
  35.  *   Optional language code to search the path with. Defaults to the page language.
  36.  *   If there's no path defined for that language it will search paths without
  37.  *   language.
  38.  *
  39.  * @return
  40.  *   Either a Drupal system path, an aliased path, or FALSE if no path was
  41.  *   found.
  42.  */
  43. function drupal_lookup_path($action$path ''$path_language '') {
  44.   global $language;
  45.   // $map is an array with language keys, holding arrays of Drupal paths to alias relations
  46.   static $map = array(), $no_src = array(), $count;
  47.   $path_language $path_language $path_language $language->language;
  48.   // Use $count to avoid looking up paths in subsequent calls if there simply are no aliases
  49.   if (!isset($count)) {
  50.     $count db_result(db_query('SELECT COUNT(pid) FROM {url_alias}'));
  51.   }
  52.   if ($action == 'wipe') {
  53.     $map = array();
  54.     $no_src = array();
  55.   }
  56.   elseif ($count && $path != '') {
  57.     if ($action == 'alias') {
  58.       if (isset($map[$path_language][$path])) {
  59.         return $map[$path_language][$path];
  60.       }
  61.       // Get the most fitting result falling back with alias without language
  62.       $alias db_result(db_query("SELECT dst FROM {url_alias} WHERE src = '%s' AND language IN('%s', '') ORDER BY language DESC"$path$path_language));
  63.       $map[$path_language][$path] = $alias;
  64.       return $alias;
  65.     }
  66.     // Check $no_src for this $path in case we've already determined that there
  67.     // isn't a path that has this alias
  68.     elseif ($action == 'source' && !isset($no_src[$path_language][$path])) {
  69.       // Look for the value $path within the cached $map
  70.       $src '';
  71.       if (!isset($map[$path_language]) || !($src array_search($path$map[$path_language]))) {
  72.         // Get the most fitting result falling back with alias without language
  73.         if ($src db_result(db_query("SELECT src FROM {url_alias} WHERE dst = '%s' AND language IN('%s', '') ORDER BY language DESC"$path$path_language))) {
  74.           $map[$path_language][$src] = $path;
  75.         }
  76.         else {
  77.           // We can't record anything into $map because we do not have a valid
  78.           // index and there is no need because we have not learned anything
  79.           // about any Drupal path. Thus cache to $no_src.
  80.           $no_src[$path_language][$path] = TRUE;
  81.         }
  82.       }
  83.       return $src;
  84.     }
  85.   }
  86.   return FALSE;
  87. }
  88. /**
  89.  * Given an internal Drupal path, return the alias set by the administrator.
  90.  *
  91.  * @param $path
  92.  *   An internal Drupal path.
  93.  * @param $path_language
  94.  *   An optional language code to look up the path in.
  95.  *
  96.  * @return
  97.  *   An aliased path if one was found, or the original path if no alias was
  98.  *   found.
  99.  */
  100. function drupal_get_path_alias($path$path_language '') {
  101.   $result $path;
  102.   if ($alias drupal_lookup_path('alias'$path$path_language)) {
  103.     $result $alias;
  104.   }
  105.   return $result;
  106. }
  107. /**
  108.  * Given a path alias, return the internal path it represents.
  109.  *
  110.  * @param $path
  111.  *   A Drupal path alias.
  112.  * @param $path_language
  113.  *   An optional language code to look up the path in.
  114.  *
  115.  * @return
  116.  *   The internal path represented by the alias, or the original alias if no
  117.  *   internal path was found.
  118.  */
  119. function drupal_get_normal_path($path$path_language '') {
  120.   $result $path;
  121.   if ($src drupal_lookup_path('source'$path$path_language)) {
  122.     $result $src;
  123.   }
  124.   if (function_exists('custom_url_rewrite_inbound')) {
  125.     // Modules may alter the inbound request path by reference.
  126.     custom_url_rewrite_inbound($result$path$path_language);
  127.   }
  128.   return $result;
  129. }
  130. /**
  131.  * Return a component of the current Drupal path.
  132.  *
  133.  * When viewing a page at the path "admin/content/types", for example, arg(0)
  134.  * would return "admin", arg(1) would return "content", and arg(2) would return
  135.  * "types".
  136.  *
  137.  * Avoid use of this function where possible, as resulting code is hard to read.
  138.  * Instead, attempt to use named arguments in menu callback functions. See the
  139.  * explanation in menu.inc for how to construct callbacks that take arguments.
  140.  *
  141.  * @param $index
  142.  *   The index of the component, where each component is separated by a '/'
  143.  *   (forward-slash), and where the first component has an index of 0 (zero).
  144.  *
  145.  * @return
  146.  *   The component specified by $index, or NULL if the specified component was
  147.  *   not found.
  148.  */
  149. function arg($index NULL$path NULL) {
  150.   static $arguments;
  151.   if (!isset($path)) {
  152.     $path $_GET['q'];
  153.   }
  154.   if (!isset($arguments[$path])) {
  155.     $arguments[$path] = explode('/'$path);
  156.   }
  157.   if (!isset($index)) {
  158.     return $arguments[$path];
  159.   }
  160.   if (isset($arguments[$path][$index])) {
  161.     return $arguments[$path][$index];
  162.   }
  163. }
  164. /**
  165.  * Get the title of the current page, for display on the page and in the title bar.
  166.  *
  167.  * @return
  168.  *   The current page's title.
  169.  */
  170. function drupal_get_title() {
  171.   $title drupal_set_title();
  172.   // during a bootstrap, menu.inc is not included and thus we cannot provide a title
  173.   if (!isset($title) && function_exists('menu_get_active_title')) {
  174.     $title check_plain(menu_get_active_title());
  175.   }
  176.   return $title;
  177. }
  178. /**
  179.  * Set the title of the current page, for display on the page and in the title bar.
  180.  *
  181.  * @param $title
  182.  *   Optional string value to assign to the page title; or if set to NULL
  183.  *   (default), leaves the current title unchanged.
  184.  *
  185.  * @return
  186.  *   The updated title of the current page.
  187.  */
  188. function drupal_set_title($title NULL) {
  189.   static $stored_title;
  190.   if (isset($title)) {
  191.     $stored_title $title;
  192.   }
  193.   return $stored_title;
  194. }
  195. /**
  196.  * Check if the current page is the front page.
  197.  *
  198.  * @return
  199.  *   Boolean value: TRUE if the current page is the front page; FALSE if otherwise.
  200.  */
  201. function drupal_is_front_page() {
  202.   // As drupal_init_path updates $_GET['q'] with the 'site_frontpage' path,
  203.   // we can check it against the 'site_frontpage' variable.
  204.   return $_GET['q'] == drupal_get_normal_path(variable_get('site_frontpage''node'));
  205. }
  206. /**
  207.  * Check if a path matches any pattern in a set of patterns.
  208.  *
  209.  * @param $path
  210.  *   The path to match.
  211.  * @param $patterns
  212.  *   String containing a set of patterns separated by \n, \r or \r\n.
  213.  *
  214.  * @return
  215.  *   Boolean value: TRUE if the path matches a pattern, FALSE otherwise.
  216.  */
  217. function drupal_match_path($path$patterns) {
  218.   static $regexps;
  219.   if (!isset($regexps[$patterns])) {
  220.     $regexps[$patterns] = '/^('preg_replace(array('/(\r\n?|\n)/''/\\\\\*/''/(^|\|)\\\\<front\\\\>($|\|)/'), array('|''.*''\1'preg_quote(variable_get('site_frontpage''node'), '/') .'\2'), preg_quote($patterns'/')) .')$/';
  221.   }
  222.   return preg_match($regexps[$patterns], $path);
  223. }