? menutrails.install Index: menutrails.module =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/menutrails/menutrails.module,v retrieving revision 1.4.2.11 diff -u -p -r1.4.2.11 menutrails.module --- menutrails.module 2 Feb 2009 15:50:15 -0000 1.4.2.11 +++ menutrails.module 3 Feb 2009 16:22:13 -0000 @@ -24,156 +24,109 @@ function menutrails_menu() { return $items; } + /** - * Implementation of hook_init(). - * - * Detect menutrails for non-node-view pages. - * Currently supports og sub-pages only. + * Save a menu link item for the node using the giving mapping to conver the + * node type to a parent menu link id. * - * @todo Replace TRUE with settings check. - */ -function menutrails_init() { - if (module_exists('og') && variable_get('menutrails_og_sub_pages', TRUE)) { - if ($group = og_get_group_context()) { - $item = menu_get_item(); - if ($item['page_callback'] != 'node_page_view') { - $item = menutrails_node_location($group); - if ($item) { - menu_set_item(NULL, $item); - if (variable_get('menutrails_breadcrumbs', 1)) { - $crumbs = menutrails_get_breadcrumbs(); - $crumbs[] = l($group->title, 'node/'. $group->nid); - drupal_set_breadcrumb($crumbs); - } - } - } - } + * @param $node + * @param $mapping array with node type's as keys and menu link ids as values. + * @return integer menu link id or NULL on error. + */ +function menutrails_save_node_link($node, $mapping) { + if (isset($mapping['nodes'][$node->type])) { + // Save menu links with link_path, link_title, module, hidden = -1, and + // plid which is mlid of parent. + $link = array( + 'link_path' => 'node/'. $node->nid, + 'link_title' => $node->title, + 'menu_name' => variable_get('menutrails_menu_name', 'primary-links'), + 'module' => 'menutrails', + 'hidden' => -1, // Supersecret value from menu.inc that keeps items from appearing in the menus. + 'plid' => $mapping['nodes'][$node->type], + ); + return menu_link_save($link); } + return NULL; } -/** - * Implementation of hook_enable(). - * - * Default menutrails to run after core/og modules for fuller control. - */ -function menutrails_enable() { - db_query("UPDATE {system} SET weight = 1 WHERE name = 'menutrails' AND type = 'module'"); -} +function menutrails_rebuild_menu_links() { + // Map node type to path. + $node_paths = variable_get('menutrails_node_types', array()); -/** - * Implementation of hook_nodeapi(). - * - * This will evaluate individual nodes when being viewed and take the necessary - * steps to set the active_trail for menus. - * - * This will retain menu state at the node/view level. For instance, forum nodes - * would maintain an active trail to the forum menu item. - */ -function menutrails_nodeapi(&$node, $op, $a3 = NULL, $page = FALSE) { - if ($op == 'view' && $page == TRUE) { - $item = menutrails_node_location($node); - if ($item) { - menu_set_item(NULL, $item); - if (variable_get('menutrails_breadcrumbs', 1)) { - drupal_set_breadcrumb(menutrails_get_breadcrumbs()); - } + // Translate those paths into menu link ids. + $mapping = array(); + foreach ($node_paths as $type => $link_path) { + if ($mlid = db_result(db_query("SELECT mlid FROM {menu_links} WHERE link_path = '%s' AND menu_name = '%s'", array($link_path, variable_get('menutrails_menu', 'primary-links'))))) { + $mapping['nodes'][$type] = $mlid; } } + // Store this into an array for easy reference. + variable_set('menutrails_mapping', $mapping); + + // Build a batch to create the menu items. + $batch = array( + 'title' => t('Creating menu items'), + 'operations' => array(array('_menutrails_batch_node_operation', array($mapping))), + 'finished' => '_menutrails_batch_finished', + ); + batch_set($batch); } -/** - * Set Breadcrumbs based on active menu trail. - */ -function menutrails_get_breadcrumbs() { - $item = menu_get_item(); - // Give first priority to the selected menu. - $menu = variable_get('menutrails_menu', FALSE); - if (!$menu) { - $menu = db_result(db_query("SELECT menu_name FROM {menu_links} WHERE link_path = '%s' AND module = 'menu'", $item['href'])); - } - $tree = menu_tree_page_data($menu); - $crumbs = array(l(t('Home'), '')); - _menutrails_recurse_crumbs($tree, $item, $crumbs); - return $crumbs; -} +function _menutrails_batch_node_operation($mapping, &$context) { + $types = array_keys($mapping['nodes']); -function _menutrails_recurse_crumbs($tree, $item, &$crumbs, $above = array()) { - foreach ($tree as $menu_item) { - if ($menu_item['link']['link_path'] == $item['href']) { - foreach ($above as $trail_item) { - $crumbs[] = l($trail_item['link']['link_title'], $trail_item['link']['link_path']); - } - $crumbs[] = l($menu_item['link']['link_title'], $menu_item['link']['link_path']); - break; - } - if (is_array($menu_item['below'])) { - $above[] = $menu_item; - _menutrails_recurse_crumbs($menu_item['below'], $item, $crumbs, $above); - } + if (empty($context['sandbox'])) { + watchdog('menutrails', 'Starting to build the Menu Trails for nodes.'); + + $context['sandbox']['progress'] = 0; + $context['sandbox']['current_node'] = 0; + $context['sandbox']['max'] = db_result(db_query("SELECT COUNT(nid) FROM {node} WHERE type IN (". db_placeholders($types, 'varchar') .")", $types)); } -} -/** - * Determine the menu location of a node. - * - * Inspired by _menu_get_active_trail(). - */ -function menutrails_node_location($node) { - // This should only fire if the menu isn't already active. - $item = menu_get_item(); - if (db_result(db_query("SELECT count(mlid) FROM {menu_links} WHERE link_path = '%s' AND module = 'menu'", $item['href'])) == 0) { - $type_trails = variable_get('menutrails_node_types', array()); - $href = $type_trails[$node->type] ? $type_trails[$node->type] : FALSE; - $term_trails = variable_get('menutrails_terms', array()); - if (!empty($node->taxonomy)) { - foreach ($node->taxonomy as $term) { - if ($term_trails[$term->tid]) { - $href = $term_trails[$term->tid]; - } - } - } + // Process the next set of nodes. + $limit = 50; + $args = array_merge(array($context['sandbox']['current_node']), $types); + $result = db_query_range("SELECT nid, type, title FROM {node} WHERE nid > %d AND type IN (". db_placeholders($types, 'varchar') .") ORDER BY nid ASC", $args, 0, $limit); + while ($row = db_fetch_object($result)) { + menutrails_save_node_link($row, $mapping); + $context['sandbox']['progress']++; + $context['sandbox']['current_node'] = $row->nid; } - else { - // We may want to do some breadcrumbing. - return $item; + + // Multistep processing: report progress. + if ($context['sandbox']['progress'] < $context['sandbox']['max']) { + $context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max']; } - // Organic groups support. - if (module_exists('og') && !empty($node->og_groups)) { - // We can only do one, so we take the first. - $group = array_shift($node->og_groups); - if (variable_get('menutrails_og_group_menu', FALSE) != FALSE) { - if (db_result(db_query("SELECT count(mlid) FROM {menu_links} WHERE link_path = '%s'", $item['href'])) == 0) { - $href = 'node/'. $group; - } - } - else { - $group_trails = variable_get('menutrails_og_node', FALSE); - if ($group_trails[$group] > 0) { - $href = 'node/'. $group; - } - elseif (variable_get('menutrails_og_post_default', FALSE)) { - $href = variable_get('menutrails_og_post_default', FALSE); - } - } +} + +function _menutrails_batch_finished($success, $results, $operations) { + if ($success) { + watchdog('menutrails', 'Sucessfully created the Menu Trails menu items.'); + drupal_set_message(t('The the Menu Trails menu items were created.')); } - if (isset($href)) { - $item['href'] = $href; - return $item; + else { + watchdog('menutrails', 'There was an error that prevented the Menu Trails from building the menu items.', array(), WATCHDOG_ERROR); + drupal_set_message(t('The the Menu Trails menu items were not created.'), 'error'); } - return FALSE; + + cache_clear_all(NULL, 'cache_menu'); } /** - * This implements the same functionality as the nodeapi, but for comment urls. + * Implementation of hook_nodeapi(). */ -function menutrails_comment($comment, $op) { - if ($op == 'form' && arg(0) == 'comment') { - $node = node_load($comment['nid']['#value']); - $item = menutrails_node_location($node); - if ($item) { - menu_set_item(NULL, $item); - } +function menutrails_nodeapi(&$node, $op, $a3 = NULL, $page = FALSE) { + switch ($op) { + case 'update': + case 'insert': + menutrails_save_node_link($node, variable_get('menutrails_mapping', array())); + break; + + case 'delete': + menu_link_delete(NULL, 'node/'. $node->nid); + break; } } @@ -224,7 +177,16 @@ function menutrails_settings_form() { ); $form = array_merge($form, module_invoke_all('menutrails_settings', $options)); - return system_settings_form($form); + $form = system_settings_form($form); + $form['#submit'][] = 'menutrails_settings_form_submit'; + return $form; +} + +/** + * Submit handler for the settings form so we can triger the batch update. + */ +function menutrails_settings_form_submit($form, &$form_state) { + menutrails_rebuild_menu_links(); } /** @@ -242,11 +204,13 @@ function menutrails_settings_form() { * A form element (or array) for the menutrails system settings form. */ function menutrails_menutrails_settings($options) { - $form = array(); $node_types = node_get_types('names'); - $node_trails = variable_get('menutrails_node_types', array()); $vocabs = module_exists('taxonomy') ? taxonomy_get_vocabularies() : array(); + + $node_trails = variable_get('menutrails_node_types', array()); $term_trails = variable_get('menutrails_terms', array()); + + $form = array(); $form['menutrails_node_types'] = array( '#tree' => TRUE, '#type' => 'fieldset', @@ -331,43 +295,6 @@ function menutrails_menutrails_settings( return $form; } -function menutrails_token_values($type, $object = NULL, $options = array()) { - if ($type == 'node') { - $node = $object; - $mlid = db_result(db_query("SELECT mlid FROM {menu_links} WHERE link_path = '%s'", 'node/'. $node->nid)); - if (!empty($mlid) || !empty($node->menu['mlid']) || !empty($node->menu['plid'])) { - $menu_link = menu_link_load($mlid); - $trail_raw = _menu_titles($menu_link, $node->nid); - // Remove the node itself. - array_pop($trail_raw); - } - $trail = array(); - if (!empty($trail_raw)) { - foreach ($trail_raw as $title) { - $trail[] = check_plain($title); - } - $tokens['menu-trail-parents-raw'] = implode('/', $trail_raw); - $tokens['menu-trail-parents'] = implode('/', $trail); - } - // Return NULL in case there is no trail. - if (!isset($tokens['menu-trail-parents-raw'])) { - $tokens['menu-trail-parents-raw'] = NULL; - } - if (!isset($tokens['menu-trail-parents'])) { - $tokens['menu-trail-parents'] = NULL; - } - return $tokens; - } -} - -function menutrails_token_list($type = 'all') { - if ($type == 'node' || $type == 'all') { - $tokens['menutrails']['menu-trail-parents-raw'] = t("The menu trail leading up to but NOT including the node -- RAW"); - $tokens['menutrails']['menu-trail-parents'] = t("The menu trail leading up to but NOT including the node"); - return $tokens; - } -} - /** * Inspired by _menu_parents_recurse(). * @@ -391,82 +318,4 @@ function _menutrails_parents_recurse($tr } } -/** - * Recursion to find the top tree. - */ -function _menutrails_recurse($tree, $href) { - foreach ($tree as $link) { - if ($link['link']['link_path'] == $href) { - $found = $link; - break; - } - if (is_array($link['below'])) { - $found = _menutrails_recurse($link['below'], $href); - } - } - return $found; -} - -/** - * Theme override for theme_links(). - * - * The important difference is that we use the in_active_trail bit here to set - * an "active" CSS class, which is what most themes (e.g. garland) use to - * denote an active/open menu item. You should alter/override this as your - * design needs dictate. - */ -function phptemplate_links($links, $attributes = array('class' => 'links')) { - $output = ''; - - if (count($links) > 0) { - $output = ''; - - $num_links = count($links); - $i = 1; - - foreach ($links as $key => $link) { - $class = $key; - - // Add first, last and active classes to the list of links to help out themers. - if ($i == 1) { - $class .= ' first'; - } - if ($i == $num_links) { - $class .= ' last'; - } - if (isset($link['href']) && ($link['href'] == $_GET['q'] || ($link['href'] == '' && drupal_is_front_page()))) { - $class .= ' active'; - } - - if (isset($link['href'])) { - // add active class for containing
  • and if active-trail is set on the link itself - if (isset($link['attributes']['class']) && strpos($link['attributes']['class'], 'active-trail') !== FALSE && strpos($class, 'active') === FALSE) { - $class .= ' active'; - $link['attributes']['class'] .= ' active'; - } - // Pass in $link as $options, they share the same keys. - $link = l($link['title'], $link['href'], $link); - } - else if (!empty($link['title'])) { - // Some links are actually not links, but we wrap these in for adding title and class attributes - if (empty($link['html'])) { - $link['title'] = check_plain($link['title']); - } - $span_attributes = ''; - if (isset($link['attributes'])) { - $span_attributes = drupal_attributes($link['attributes']); - } - $link = ''. $link['title'] .''; - } - - $i++; - $output .= ' $class)) .'>'; - $output .= $link; - $output .= "
  • \n"; - } - - $output .= ''; - } - return $output; -}