menu.inc

  1. 6.x includes/menu.inc
  2. 4.x includes/menu.inc
  3. 5.x includes/menu.inc

File

includes/menu.inc
View source
  1. <?php
  2. /**
  3. * This file contains mostly menu-related all-purpose functions
  4. * for FlightPath
  5. */
  6. /**
  7. * Look for modules implementing hook_menu_handle_replacement_pattern, and apply to str.
  8. *
  9. * @param unknown_type $str
  10. */
  11. function menu_convert_replacement_pattern($str) {
  12. // Find modules which implement the hook_menu_handle_replacement_pattern function.
  13. $modules = modules_implement_hook("menu_handle_replacement_pattern");
  14. foreach($modules as $module) {
  15. $str = call_user_func($module . '_menu_handle_replacement_pattern', $str);
  16. }
  17. return $str;
  18. }
  19. /**
  20. * Go through all installed modules and rebuild the menu_router table,
  21. * based on each module's hook_menu function.
  22. */
  23. function menu_rebuild_cache($bool_display_message = TRUE) {
  24. // Begin by wiping out the menu_router table
  25. db_query("TRUNCATE TABLE menu_router ");
  26. $modules = modules_implement_hook("menu");
  27. foreach ($modules as $module) {
  28. $items = call_user_func($module . "_menu");
  29. // Invoke hook_menu_alter() to see if we need to alter these items or not.
  30. invoke_hook('menu_alter', array(&$items));
  31. // Okay, now go through the $items array, and write the needed information
  32. // to the menu_router array.
  33. foreach ($items as $path => $item) {
  34. if (is_numeric($path)) continue; // problem, so skip.
  35. // Update our menu_router table.
  36. // Now, insert the new one.
  37. db_query("INSERT INTO menu_router
  38. (path, access_callback, access_arguments, page_callback, page_arguments, title, description, type, weight, icon, page_settings, tab_family, tab_parent, file)
  39. VALUES
  40. (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
  41. ", $path, @$item["access_callback"], @serialize($item["access_arguments"]), @$item["page_callback"],
  42. @serialize($item['page_arguments']), @$item['title'], @$item['description'], @$item['type'], @$item['weight'], @$item['icon'],
  43. @serialize($item['page_settings']), @$item['tab_family'], @$item['tab_parent'], @$item['file']);
  44. }
  45. }
  46. if ($bool_display_message) {
  47. fp_add_message(t("The menu router has been rebuilt"));
  48. }
  49. }
  50. function menu_get_module_path($module, $bool_include_file_system_path = FALSE) {
  51. $system_path = "";
  52. if ($bool_include_file_system_path) {
  53. $system_path = $GLOBALS["fp_system_settings"]["file_system_path"] . "/";
  54. }
  55. if (isset($GLOBALS["fp_system_settings"]["modules"][$module]["path"])) {
  56. return $system_path . $GLOBALS["fp_system_settings"]["modules"][$module]["path"];
  57. }
  58. else {
  59. return FALSE;
  60. }
  61. }
  62. /**
  63. * Looks at the router item's details (from menu_get_item)
  64. * and returns TRUE or FALSE if the user can access this item.
  65. */
  66. function menu_check_user_access($router_item) {
  67. $access = FALSE;
  68. if ($router_item["access_callback"] == 1) {
  69. $access = TRUE;
  70. }
  71. if (is_array($router_item["access_arguments"])) {
  72. if ($router_item["access_callback"] == "") {
  73. // If we specified access arguments, but not a callback, assume it
  74. // is the function user_has_permission().
  75. $router_item["access_callback"] = "user_has_permission";
  76. }
  77. }
  78. // Does the access_arguments have any wildcards?
  79. if (isset($router_item['access_arguments']) && is_array($router_item['access_arguments'])) {
  80. if (count($router_item['access_arguments']) == 1 && !$router_item['access_arguments'][0]) {
  81. // Meanng, access arguments has been created, but nothing there. We likely need to populate it if there are wildcards in this item.
  82. $router_item = menu_get_item($router_item['path']);
  83. }
  84. }
  85. if (!$access && $router_item["access_callback"] != "") {
  86. // We need to see if the user has the right permissions to use this item. We will do this
  87. // by calling the access_callback, passing it the access_arguments
  88. $access = call_user_func_array($router_item["access_callback"], $router_item["access_arguments"]);
  89. }
  90. return $access;
  91. }
  92. function menu_execute_page_request($path = "") {
  93. if ($path == "") {
  94. $path = @$_GET["q"];
  95. }
  96. //If the path is blank, figure out what the "font page" is, and use that path.
  97. if ($path == "") {
  98. $path = variable_get("front_page", "main");
  99. }
  100. if ($router_item = menu_get_item($path)) {
  101. // Let's save the router item in the GLOBALS array, so we can use information from it
  102. // throughout FlightPath, if we need to.
  103. $GLOBALS["fp_current_menu_router_item"] = $router_item;
  104. // If the menu item contains a "redirect", then we should perform
  105. // an fp_goto to that immediately.
  106. if (isset($router_item["page_settings"]["redirect"])) {
  107. $p = $router_item["page_settings"]["redirect"]["path"];
  108. $q = $router_item["page_settings"]["redirect"]["query"];
  109. fp_goto($p, $q);
  110. return;
  111. }
  112. // Let's figure out if the user has access to this menu item or not.
  113. if (menu_check_user_access($router_item)) {
  114. if ($router_item['file'] != "") {
  115. require_once($router_item['file']);
  116. }
  117. $page = array();
  118. $page["content"] = call_user_func_array($router_item['page_callback'], $router_item['page_arguments']);
  119. $page["path"] = $path;
  120. $page["title"] = $router_item["title"];
  121. $page["router_item"] = $router_item;
  122. return $page;
  123. }
  124. else {
  125. return MENU_ACCESS_DENIED;
  126. }
  127. }
  128. return MENU_NOT_FOUND;
  129. }
  130. /**
  131. * Return menu_items whose path begins with the menu_root.
  132. * Ex: "tools" would return tools/fun and tools/here/there
  133. */
  134. function menu_get_items_beginning_with($menu_root) {
  135. $rtn = array();
  136. $res = db_query("SELECT path FROM menu_router WHERE path LIKE ?
  137. ORDER BY weight, title", $menu_root . "%");
  138. while ($cur = db_fetch_array($res)) {
  139. $path = $cur["path"];
  140. $item = menu_get_item($path);
  141. if ($item) {
  142. $rtn[] = $item;
  143. }
  144. }
  145. return $rtn;
  146. }
  147. function menu_get_items_in_tab_family($tab_family) {
  148. $rtn = array();
  149. $res = db_query("SELECT path FROM menu_router WHERE tab_family = ?
  150. ORDER BY weight, title", $tab_family);
  151. while ($cur = db_fetch_array($res)) {
  152. $path = $cur["path"];
  153. $item = menu_get_item($path);
  154. if ($item) {
  155. $rtn[] = $item;
  156. }
  157. }
  158. return $rtn;
  159. }
  160. /**
  161. * Figure out which menu_router path matches the supplied path and return it.
  162. *
  163. */
  164. function menu_get_item($path) {
  165. // Since the menu item may be using wildcards, we must
  166. // try to figure out exactly which defined path is the best one
  167. // to take.
  168. $menu_items = array();
  169. /*
  170. if ($bool_reset) {
  171. unset($GLOBALS["fp_menu_items"]);
  172. }
  173. */
  174. // To cut down on the amount we need to query, we will use a global variable.
  175. if (!isset($GLOBALS["fp_menu_items"]) || !is_array($GLOBALS["fp_menu_items"]) || count($GLOBALS["fp_menu_items"]) == 0) {
  176. // The global array is not set. Let's populate it from the database.
  177. $res = db_query("SELECT path FROM menu_router");
  178. while ($cur = db_fetch_array($res)) {
  179. $GLOBALS["fp_menu_items"][] = $cur["path"];
  180. }
  181. }
  182. $menu_items = $GLOBALS["fp_menu_items"];
  183. // Okay, first things first, does the path *exactly* match anything in our GLOBALS array?
  184. if (in_array($path, $menu_items)) {
  185. return menu_get_menu_router_item_from_db($path);
  186. }
  187. // If we are here, we didn't see an exact match. That may mean we are using wildcards,
  188. // and therefore we should pick only the best match.
  189. // For example, if the path is "node/5/edit", we should return the
  190. // menu_router item "node/%/edit", but not "node/%/%". We will figure this out
  191. // by breaking up our paths into pieces, and then comparing each piece, and scoring URLs
  192. // as we do on how many levels they match on. The URL with the higest match wins.
  193. $defined_score = array();
  194. // Now, go through and find the best URL definition that matches the given URL.
  195. $given_pieces = explode("/", $path);
  196. foreach ($menu_items as $defined_url) {
  197. $defined_pieces = explode("/", $defined_url);
  198. // First, make only look for the ones with the exact same count as us...
  199. if (count($defined_pieces) != count($given_pieces)) continue;
  200. if (!isset($defined_score[$defined_url])) $defined_score[$defined_url] = 0;
  201. $defined_score[$defined_url]++;
  202. // Okay, now go through the pieces and compare.
  203. foreach ($defined_pieces as $c => $defined_piece) {
  204. // If it's exactly a match, then inc its score.
  205. if ($defined_piece == $given_pieces[$c]) {
  206. $defined_score[$defined_url]++;
  207. }
  208. // If it's totally off, then kick it out!
  209. if ($defined_piece != "%" && $defined_piece != $given_pieces[$c]) {
  210. unset($defined_score[$defined_url]);
  211. break;
  212. }
  213. }
  214. }
  215. arsort($defined_score);
  216. $best_match_path = "";
  217. if (count($defined_score) > 0) {
  218. $best_match_path = key($defined_score);
  219. }
  220. // Okay, the best_match_path is the one that best fits our path. Let's return the details
  221. // for it from menu_router.
  222. if ($best_match_path) {
  223. return menu_get_menu_router_item_from_db($best_match_path);
  224. }
  225. // Else, nothing was found!
  226. return NULL;
  227. }
  228. /**
  229. * Return array from menu_router for this item. *
  230. */
  231. function menu_get_menu_router_item_from_db($path) {
  232. $res = db_query("SELECT * FROM menu_router WHERE path = ?", array($path));
  233. $cur = db_fetch_array($res);
  234. if ($cur["path"] != $path) {
  235. // It was not found!
  236. return NULL;
  237. }
  238. // Unserialize the things which are supposed to be unserialized.
  239. $cur["page_arguments"] = unserialize($cur["page_arguments"]);
  240. if (!is_array($cur["page_arguments"])) {
  241. $cur["page_arguments"] = array();
  242. }
  243. // If any of the page_arguments is a number by itself, we will instead
  244. // use the number of the URL args.
  245. // For example, if the URL path is "node/edit/apple"
  246. // and there is a page_argument for the number 2, we will replace
  247. // it with "apple". This is how the menu system can use wildcards from the url
  248. // for the page arguments.
  249. foreach ($cur["page_arguments"] as $c => $arg) {
  250. if (is_numeric($arg)) {
  251. $temp = explode("/", $_REQUEST["q"]);
  252. $cur["page_arguments"][$c] = @$temp[$arg];
  253. }
  254. }
  255. $cur["access_arguments"] = unserialize($cur["access_arguments"]);
  256. if (!is_array($cur["access_arguments"])) {
  257. $cur["access_arguments"] = array();
  258. }
  259. // Same situation for access_arguments as the page_arguments above.
  260. foreach ($cur["access_arguments"] as $c => $arg) {
  261. if (is_numeric($arg)) {
  262. $temp = explode("/", $_REQUEST["q"]);
  263. $cur["access_arguments"][$c] = @$temp[$arg];
  264. }
  265. }
  266. //fpm($_REQUEST);
  267. //fpm($cur);
  268. $cur["page_settings"] = unserialize($cur["page_settings"]);
  269. if (!is_array($cur["page_settings"])) {
  270. $cur["page_settings"] = array();
  271. }
  272. // If there is a title property, run it through t()
  273. if ($cur["title"] != "") {
  274. $cur["title"] = t($cur["title"]);
  275. }
  276. // If there is a description, run through t()
  277. if ($cur["description"] != "") {
  278. $cur["description"] = t($cur["description"]);
  279. }
  280. // If the page_settings has menu links, run their texts through t().
  281. foreach ($cur["page_settings"] as $key => $val) {
  282. if ($key == "menu_links" && is_array($val)) {
  283. foreach ($val as $c => $mitems) {
  284. if ($mitems["text"] != "") {
  285. $cur["page_settings"]["menu_links"][$c]["text"] = t($mitems["text"]);
  286. }
  287. }
  288. }
  289. }
  290. return $cur;
  291. }

Functions

Namesort descending Description
menu_check_user_access Looks at the router item's details (from menu_get_item) and returns TRUE or FALSE if the user can access this item.
menu_convert_replacement_pattern Look for modules implementing hook_menu_handle_replacement_pattern, and apply to str.
menu_execute_page_request
menu_get_item Figure out which menu_router path matches the supplied path and return it.
menu_get_items_beginning_with Return menu_items whose path begins with the menu_root. Ex: "tools" would return tools/fun and tools/here/there
menu_get_items_in_tab_family
menu_get_menu_router_item_from_db Return array from menu_router for this item. *
menu_get_module_path
menu_rebuild_cache Go through all installed modules and rebuild the menu_router table, based on each module's hook_menu function.