? 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'), '<front>'));
-  _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 = '<ul'. drupal_attributes($attributes) .'>';
-
-    $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'] == '<front>' && drupal_is_front_page()))) {
-        $class .= ' active';
-      }
-
-      if (isset($link['href'])) {
-        // add active class for containing <li> and <a> 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 <span> 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 = '<span'. $span_attributes .'>'. $link['title'] .'</span>';
-      }
-
-      $i++;
-      $output .= '<li'. drupal_attributes(array('class' => $class)) .'>';
-      $output .= $link;
-      $output .= "</li>\n";
-    }
-
-    $output .= '</ul>';
-  }
-  return $output;
-}
 
