simplemenu.module 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. <?php
  2. // $Id$
  3. /**
  4. * @file
  5. * Creates a simplemenu.
  6. */
  7. /**
  8. * Implementation of hook_menu().
  9. */
  10. function simplemenu_menu() {
  11. $items = array();
  12. $items['admin/settings/simplemenu'] = array(
  13. 'title' => 'SimpleMenu',
  14. 'description' => 'Select the menu to display.',
  15. 'page callback' => 'drupal_get_form',
  16. 'page arguments' => array('simplemenu_admin_settings'),
  17. 'access arguments' => array('administer simplemenu'),
  18. 'file' => 'simplemenu.admin.inc',
  19. );
  20. return $items;
  21. }
  22. /**
  23. * Is simplemenu enabled for this page request?
  24. */
  25. function simplemenu_enabled() {
  26. static $enabled;
  27. if (!isset($enabled)) {
  28. global $theme;
  29. $exclusions = variable_get('simplemenu_exclusions', array());
  30. $enabled = (user_access('view simplemenu')
  31. && (!isset($exclusions[$theme]) || !$exclusions[$theme])
  32. && _simplemenu_page_visibility()
  33. && _simplemenu_superuser_active());
  34. }
  35. return $enabled;
  36. }
  37. /**
  38. * Implementation of hook_init().
  39. */
  40. function simplemenu_init() {
  41. // do a simple access check here, since theme isn't available to check yet
  42. if (user_access('view simplemenu') && simplemenu_enabled()) {
  43. $path = drupal_get_path('module', 'simplemenu');
  44. drupal_add_css($path .'/simplemenu.css');
  45. $simplemenu_theme = variable_get('simplemenu_theme', 'original');
  46. if ($simplemenu_theme != 'custom') {
  47. drupal_add_css($path .'/themes/'. $simplemenu_theme .'/'. $simplemenu_theme .'.css');
  48. }
  49. $settings = array(
  50. 'effect' => variable_get('simplemenu_effect', 'opacity'),
  51. 'effectSpeed' => variable_get('simplemenu_effect_speed', 'fast'),
  52. 'element' => variable_get('simplemenu_element', 'body'),
  53. 'hideDelay' => variable_get('simplemenu_hide_delay', 800),
  54. 'placement' => variable_get('simplemenu_element_method', 'prepend'),
  55. 'detectPopup' => variable_get('simplemenu_detect_popop', 1),
  56. );
  57. drupal_add_js(array('simplemenu' => $settings), 'setting');
  58. drupal_add_js($path .'/simplemenu.js');
  59. drupal_add_js($path .'/superfish.js');
  60. }
  61. }
  62. /**
  63. * Implementation of hook_footer().
  64. *
  65. * This has been broken off of simplemenu_init() because simplemenu_get_menu()
  66. * calls simplemenu_menu_tree() which calls menu_tree_output() which has several
  67. * calls to theme(). This initializes the theme system too early causing hard
  68. * to track bugs.
  69. *
  70. * @see http://drupal.org/node/219910
  71. */
  72. function simplemenu_footer() {
  73. if (simplemenu_enabled()) {
  74. $simplemenu = drupal_to_js(simplemenu_get_menu());
  75. $path = base_path() . drupal_get_path('module', 'simplemenu');
  76. $output = "<script type=\"text/javascript\">var simplemenu = $simplemenu;</script>\n";
  77. return $output;
  78. }
  79. }
  80. /**
  81. * Implementation of hook_perm().
  82. */
  83. function simplemenu_perm() {
  84. return array('view simplemenu', 'administer simplemenu');
  85. }
  86. /**
  87. * Render an HTML list of links for a given menu.
  88. */
  89. function simplemenu_get_menu() {
  90. $output = '';
  91. // if a user turned off menu module but SimpleMenu was previously set
  92. // reset variable so a menu appears
  93. $menu_name = module_exists('menu') ? variable_get('simplemenu_menu', 'navigation:0') : 'navigation:0';
  94. $menu = simplemenu_menu_tree($menu_name);
  95. if (!$menu) {
  96. $menu = '<li><a href="'. url('admin/settings/simplemenu') .'">'. t('No menu items found. Try a different menu as the default.') .'</a></li>';
  97. }
  98. // This is ugly, I know, but it is the only way I can see to get the additional
  99. // links inside the <ul> tags
  100. if ($devel = simplemenu_get_devel()) {
  101. $pos = strpos($menu, '>') + 1;
  102. $menu = substr($menu, 0, $pos) . $devel . substr($menu, $pos);
  103. }
  104. $output .= $menu;
  105. return $output;
  106. }
  107. /**
  108. * Custom implementation of menu_tree().
  109. * We want to retrieve the entire menu structure for a given menu,
  110. * regardless of whether or not the menu item is expanded or not.
  111. */
  112. function simplemenu_menu_tree($menu_name = 'navigation:0') {
  113. static $menu_output = array();
  114. if (!isset($menu_output[$menu_name])) {
  115. $tree = simplemenu_tree_all_data($menu_name);
  116. $menu_output[$menu_name] = menu_tree_output($tree);
  117. }
  118. return $menu_output[$menu_name];
  119. }
  120. /**
  121. * Modified menu_tree_all_data(), providing the complete menu tree below $root_menu
  122. * (which can be *any* menu item, not just the root of a custom menu).
  123. *
  124. * @param $root_menu
  125. * root menu item of the tree to return as "menu_name:mlid" (mlid = menu link id)
  126. *
  127. * @todo we don't actually need $menu_name, $mlid would be sufficient
  128. */
  129. function simplemenu_tree_all_data($root_menu = 'navigation:0') {
  130. static $tree = array();
  131. list($menu_name, $mlid) = explode(':', $root_menu);
  132. // Generate the cache ID.
  133. // "links:navigation:all:2" means "all from root to 2" (what the ...), so for "all from 2 down" we do "links:navigation:all:2:all"
  134. $cid = "links:$menu_name:all:$mlid". ($mlid ? ':all' : '');
  135. if (!isset($tree[$cid])) {
  136. // If the static variable doesn't have the data, check {cache_menu}.
  137. $cache = cache_get($cid, 'cache_menu');
  138. if ($cache && isset($cache->data)) {
  139. $data = $cache->data;
  140. }
  141. else {
  142. // Build and run the query, and build the tree.
  143. if ($mlid > 0) {
  144. $item = menu_link_load($mlid);
  145. // The tree is a subtree of $menu_name, so we need to restrict the query to
  146. // this subtree.
  147. $px = "p$item[depth]";
  148. $where = " AND ml.$px = %d AND ml.mlid != %d";
  149. $args = array($item[$px], $mlid);
  150. }
  151. else {
  152. // Get all links in this menu.
  153. $where = '';
  154. $args = array();
  155. }
  156. array_unshift($args, $menu_name);
  157. // Select the links from the table, and recursively build the tree. We
  158. // LEFT JOIN since there is no match in {menu_router} for an external
  159. // link.
  160. $data['tree'] = menu_tree_data(db_query("
  161. SELECT m.load_functions, m.to_arg_functions, m.access_callback, m.access_arguments, m.page_callback, m.page_arguments, m.title, m.title_callback, m.title_arguments, m.type, m.description, ml.*
  162. FROM {menu_links} ml LEFT JOIN {menu_router} m ON m.path = ml.router_path
  163. WHERE ml.menu_name = '%s'". $where ."
  164. ORDER BY p1 ASC, p2 ASC, p3 ASC, p4 ASC, p5 ASC, p6 ASC, p7 ASC, p8 ASC, p9 ASC", $args));
  165. $data['node_links'] = array();
  166. menu_tree_collect_node_links($data['tree'], $data['node_links']);
  167. // Cache the data.
  168. cache_set($cid, $data, 'cache_menu');
  169. }
  170. // Check access for the current user to each item in the tree.
  171. menu_tree_check_access($data['tree'], $data['node_links']);
  172. $tree[$cid] = $data['tree'];
  173. }
  174. return $tree[$cid];
  175. }
  176. /**
  177. * Return a list of devel module links if the module is enabled
  178. * and the user has access to this module.
  179. */
  180. function simplemenu_get_devel() {
  181. $output = '';
  182. if (variable_get('simplemenu_devel', 0) && module_exists('devel')) {
  183. if (user_access('access devel information')) {
  184. $output = '<li class="expanded"><a href="'. url('admin/settings/devel') .'">'. t('Devel module') .'</a>';
  185. $output .= simplemenu_menu_tree('devel');
  186. $output .= '</li>';
  187. }
  188. }
  189. return $output;
  190. }
  191. /**
  192. * Determine if simplemenu should be displayed based on visibility settings.
  193. *
  194. * @return boolean
  195. */
  196. function _simplemenu_page_visibility() {
  197. $operator = variable_get('simplemenu_visibility_operator', 0);
  198. $pages = variable_get('simplemenu_visibility_pages', '');
  199. if ($pages) {
  200. $path = drupal_get_path_alias($_GET['q']);
  201. // Compare with the internal and path alias (if any).
  202. $page_match = drupal_match_path($path, $pages);
  203. if ($path != $_GET['q']) {
  204. $page_match = $page_match || drupal_match_path($_GET['q'], $pages);
  205. }
  206. // When $operator has a value of 0, the menu is displayed on
  207. // all pages except those listed in $pages. When set to 1, it
  208. // is displayed only on those pages listed in $pages.
  209. $page_match = !($operator ^ $page_match);
  210. }
  211. else {
  212. $page_match = TRUE;
  213. }
  214. return $page_match;
  215. }
  216. /**
  217. * Check whether the superuser/admin should be shown simplemenu.
  218. */
  219. function _simplemenu_superuser_active() {
  220. global $user;
  221. return $user->uid != 1 || variable_get('simplemenu_uid1', 1) == 1;
  222. }
  223. // vim: ts=2 sw=2 et syntax=php