menu.inc

  1. 7.x includes/menu.inc
  2. 6.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. if (!$router_item || $router_item == NULL || $router_item == FALSE || $router_item == '') {
  68. return FALSE; // No router item given, so return FALSE.
  69. }
  70. $access = FALSE;
  71. if ($router_item['access_callback'] === '1' || $router_item["access_callback"] === 1 || $router_item["access_callback"] === TRUE) {
  72. $access = TRUE;
  73. }
  74. if (isset($router_item["access_arguments"]) && is_array($router_item["access_arguments"])) {
  75. if (!isset($router_item['access_callback']) || $router_item["access_callback"] == "") {
  76. // If we specified access arguments, but not a callback, assume it
  77. // is the function user_has_permission().
  78. $router_item["access_callback"] = "user_has_permission";
  79. }
  80. }
  81. // Does the access_arguments have any wildcards?
  82. if (isset($router_item['access_arguments']) && is_array($router_item['access_arguments'])) {
  83. if (count($router_item['access_arguments']) == 1 && !$router_item['access_arguments'][0]) {
  84. // Meanng, access arguments has been created, but nothing there. We likely need to populate it if there are wildcards in this item.
  85. $router_item = menu_get_item($router_item['path']);
  86. }
  87. }
  88. if (!$access && $router_item["access_callback"] != "") {
  89. // We need to see if the user has the right permissions to use this item. We will do this
  90. // by calling the access_callback, passing it the access_arguments
  91. $access = call_user_func_array($router_item["access_callback"], $router_item["access_arguments"]);
  92. }
  93. return $access;
  94. }
  95. function menu_execute_page_request($path = "") {
  96. if ($path == "") {
  97. $path = @$_GET["q"];
  98. }
  99. //If the path is blank, figure out what the "font page" is, and use that path.
  100. if ($path == "") {
  101. $path = variable_get("front_page", "main");
  102. }
  103. if ($router_item = menu_get_item($path)) {
  104. // Let's save the router item in the GLOBALS array, so we can use information from it
  105. // throughout FlightPath, if we need to.
  106. $GLOBALS["fp_current_menu_router_item"] = $router_item;
  107. // If the menu item contains a "redirect", then we should perform
  108. // an fp_goto to that immediately.
  109. if (isset($router_item["page_settings"]["redirect"])) {
  110. $p = $router_item["page_settings"]["redirect"]["path"];
  111. $q = $router_item["page_settings"]["redirect"]["query"];
  112. fp_goto($p, $q);
  113. return;
  114. }
  115. // Let's figure out if the user has access to this menu item or not.
  116. if (menu_check_user_access($router_item)) {
  117. if ($router_item['file'] != "") {
  118. require_once($router_item['file']);
  119. }
  120. $page = array();
  121. $page["content"] = call_user_func_array($router_item['page_callback'], $router_item['page_arguments']);
  122. $page["path"] = $path;
  123. $page["title"] = $router_item["title"];
  124. $page["router_item"] = $router_item;
  125. return $page;
  126. }
  127. else {
  128. return MENU_ACCESS_DENIED;
  129. }
  130. }
  131. return MENU_NOT_FOUND;
  132. }
  133. /**
  134. * Return menu_items whose path begins with the menu_root.
  135. * Ex: "tools" would return tools/fun and tools/here/there
  136. */
  137. function menu_get_items_beginning_with($menu_root) {
  138. $rtn = array();
  139. $res = db_query("SELECT path FROM menu_router WHERE path LIKE ?
  140. ORDER BY weight, title", $menu_root . "%");
  141. while ($cur = db_fetch_array($res)) {
  142. $path = $cur["path"];
  143. $item = menu_get_item($path);
  144. if ($item) {
  145. $rtn[] = $item;
  146. }
  147. }
  148. return $rtn;
  149. }
  150. function menu_get_items_in_tab_family($tab_family) {
  151. $rtn = array();
  152. $res = db_query("SELECT path FROM menu_router WHERE tab_family = ?
  153. ORDER BY weight, title", $tab_family);
  154. while ($cur = db_fetch_array($res)) {
  155. $path = $cur["path"];
  156. $item = menu_get_item($path);
  157. if ($item) {
  158. $rtn[] = $item;
  159. }
  160. }
  161. return $rtn;
  162. }
  163. /**
  164. * Figure out which menu_router path matches the supplied path and return it.
  165. *
  166. */
  167. function menu_get_item($path) {
  168. // Since the menu item may be using wildcards, we must
  169. // try to figure out exactly which defined path is the best one
  170. // to take.
  171. $menu_items = array();
  172. /*
  173. if ($bool_reset) {
  174. unset($GLOBALS["fp_menu_items"]);
  175. }
  176. */
  177. // To cut down on the amount we need to query, we will use a global variable.
  178. if (!isset($GLOBALS["fp_menu_items"]) || !is_array($GLOBALS["fp_menu_items"]) || count($GLOBALS["fp_menu_items"]) == 0) {
  179. // The global array is not set. Let's populate it from the database.
  180. $res = db_query("SELECT path FROM menu_router");
  181. while ($cur = db_fetch_array($res)) {
  182. $GLOBALS["fp_menu_items"][] = $cur["path"];
  183. }
  184. }
  185. $menu_items = $GLOBALS["fp_menu_items"] ?? NULL;
  186. // Okay, first things first, does the path *exactly* match anything in our GLOBALS array?
  187. if (is_array($menu_items) && in_array($path, $menu_items)) {
  188. return menu_get_menu_router_item_from_db($path);
  189. }
  190. // If we are here, we didn't see an exact match. That may mean we are using wildcards,
  191. // and therefore we should pick only the best match.
  192. // For example, if the path is "node/5/edit", we should return the
  193. // menu_router item "node/%/edit", but not "node/%/%". We will figure this out
  194. // by breaking up our paths into pieces, and then comparing each piece, and scoring URLs
  195. // as we do on how many levels they match on. The URL with the higest match wins.
  196. $defined_score = array();
  197. // Now, go through and find the best URL definition that matches the given URL.
  198. $given_pieces = explode("/", $path);
  199. foreach ($menu_items as $defined_url) {
  200. $defined_pieces = explode("/", $defined_url);
  201. // First, make only look for the ones with the exact same count as us...
  202. if (count($defined_pieces) != count($given_pieces)) continue;
  203. if (!isset($defined_score[$defined_url])) $defined_score[$defined_url] = 0;
  204. $defined_score[$defined_url]++;
  205. // Okay, now go through the pieces and compare.
  206. foreach ($defined_pieces as $c => $defined_piece) {
  207. // If it's exactly a match, then inc its score.
  208. if ($defined_piece == $given_pieces[$c]) {
  209. $defined_score[$defined_url]++;
  210. }
  211. // If it's totally off, then kick it out!
  212. if ($defined_piece != "%" && $defined_piece != $given_pieces[$c]) {
  213. unset($defined_score[$defined_url]);
  214. break;
  215. }
  216. }
  217. }
  218. arsort($defined_score);
  219. $best_match_path = "";
  220. if (count($defined_score) > 0) {
  221. $best_match_path = key($defined_score);
  222. }
  223. // Okay, the best_match_path is the one that best fits our path. Let's return the details
  224. // for it from menu_router.
  225. if ($best_match_path) {
  226. return menu_get_menu_router_item_from_db($best_match_path);
  227. }
  228. // Else, nothing was found!
  229. return NULL;
  230. }
  231. /**
  232. * Return array from menu_router for this item. *
  233. */
  234. function menu_get_menu_router_item_from_db($path) {
  235. $res = db_query("SELECT * FROM menu_router WHERE path = ?", array($path));
  236. $cur = db_fetch_array($res);
  237. if (!$cur || (($cur["path"] ?? '') != $path)) {
  238. // It was not found!
  239. return NULL;
  240. }
  241. // Unserialize the things which are supposed to be unserialized.
  242. $cur["page_arguments"] = unserialize($cur["page_arguments"]);
  243. if (!is_array($cur["page_arguments"])) {
  244. $cur["page_arguments"] = array();
  245. }
  246. // If any of the page_arguments is a number by itself, we will instead
  247. // use the number of the URL args.
  248. // For example, if the URL path is "node/edit/apple"
  249. // and there is a page_argument for the number 2, we will replace
  250. // it with "apple". This is how the menu system can use wildcards from the url
  251. // for the page arguments.
  252. foreach ($cur["page_arguments"] as $c => $arg) {
  253. if (is_numeric($arg)) {
  254. $temp = explode("/", $_REQUEST["q"]);
  255. $cur["page_arguments"][$c] = @$temp[$arg];
  256. }
  257. }
  258. $cur["access_arguments"] = unserialize($cur["access_arguments"]);
  259. if (!is_array($cur["access_arguments"])) {
  260. $cur["access_arguments"] = array();
  261. }
  262. // Same situation for access_arguments as the page_arguments above.
  263. foreach ($cur["access_arguments"] as $c => $arg) {
  264. if (is_numeric($arg)) {
  265. $temp = explode("/", $_REQUEST["q"]);
  266. $cur["access_arguments"][$c] = @$temp[$arg];
  267. }
  268. }
  269. //fpm($_REQUEST);
  270. //fpm($cur);
  271. $cur["page_settings"] = unserialize($cur["page_settings"]);
  272. if (!is_array($cur["page_settings"])) {
  273. $cur["page_settings"] = array();
  274. }
  275. // If there is a title property, run it through t()
  276. if ($cur["title"] != "") {
  277. $cur["title"] = t($cur["title"]);
  278. }
  279. // If there is a description, run through t()
  280. if ($cur["description"] != "") {
  281. $cur["description"] = t($cur["description"]);
  282. }
  283. // If the page_settings has menu links, run their texts through t().
  284. foreach ($cur["page_settings"] as $key => $val) {
  285. if ($key == "menu_links" && is_array($val)) {
  286. foreach ($val as $c => $mitems) {
  287. if ($mitems["text"] != "") {
  288. $cur["page_settings"]["menu_links"][$c]["text"] = t($mitems["text"]);
  289. }
  290. }
  291. }
  292. }
  293. return $cur;
  294. }

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.