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