? helpinject_help/help/Books-to-Export.html
? helpinject_help/help/Excluding-forms-from-HelpInject.html
? helpinject_help/help/Exporting-Help.html
? helpinject_help/help/Languages.html
? helpinject_help/help/Module-Name.html
? helpinject_help/help/Module-base-name.html
? helpinject_help/help/Package-Name.html
? helpinject_help/help/The-HelpInject-Module.html
? helpinject_help/help/helpinject_help.help.ini
Index: helpinject.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/helpinject/helpinject.module,v
retrieving revision 1.28
diff -u -r1.28 helpinject.module
--- helpinject.module	6 May 2009 04:06:51 -0000	1.28
+++ helpinject.module	6 May 2009 10:07:52 -0000
@@ -8,25 +8,38 @@
   // This tests whether HelpInject should be doing anything on this page.
   if (helpinject_path_visibility()) {
     $help_link = '';
-    // The router path becomes the unique ID for "path" based help.
-    $router_item = menu_get_item();
-    $router_path = $router_item['path'];
-    $help_link = $inject_link = '';
+    $inject_link = '';
+
     // If there help for this path, inject it.
     if (user_access('view advanced help popup')) {
-      if ($values = helpinject_get_from_key('path', $router_path)) {
-        $help_link = theme('helpinject_topic', $values['nid']);
+      if ($values = helpinject_get_from_key('path', helpinject_get_path_ancestors())) {
+        foreach ($values as $value) {
+          $help_link = theme('helpinject_topic', $value['nid']);
+        }
       }
     }
     // If the user is allowed, show the injection icon.
     if (user_access('inject help')) {
-      $inject_link = _helpinject_admin_link('path', $router_path, t('this page'));
+      $inject_link = _helpinject_admin_link('path', $_GET['q'], t('this page'));
     }
     return $help_link . $inject_link;
   }
 }
 
 /**
+ * Helper function to get the ancestor paths from any given path.
+ */
+function helpinject_get_path_ancestors($path = '') {
+  if (empty($path)) {
+    $path = $_GET['q'];
+  }
+  // The paths in $ancestors become the possible IDs for "path" based help.
+  $parts = array_slice(arg(NULL, $path), 0, MENU_MAX_PARTS);
+  list($ancestors, $placeholders) = menu_get_ancestors($parts);
+  return $ancestors;
+}
+
+/**
  * Tests whether HelpInject should be doing anything on this path.
  */
 function helpinject_path_visibility() {
@@ -130,60 +143,123 @@
  */
 function helpinject_injection_form(&$form_state, $type) {
   $form = array();
-  // Get the whole rest of the path
-  $q_paths = explode('/', $_GET['q'], 4);
-  $key = $q_paths[3];
-
-  // TODO: Add the possibility to create a new node right here, either
-  // as an embedded form or as a light box or some other way.
-  // http://drupal.org/node/416068
-
-  // We show every topic (book page) grouped by book title.
-  // Pack the book trees into the form.
-  $trees = array();
-  $books = book_get_books();
-  ksort($books);
-  foreach ($books as $book) {
-    $node = node_load($book['nid']);
-    $trees[$node->nid] = book_menu_subtree_data($node->book);
-  }
-  $form['book_trees'] = array('#type' => 'value', '#value' => $trees);
-
-  // Pack the key into the form for later use.
-  $form['helpkey'] = array('#type' => 'value', '#value' => $key);
   // Pack the type into the form for later use.
   $form['type'] = array('#type' => 'value', '#value' => $type);
-  // Find out if a help topic has already been selected.
-  $defaults = helpinject_get_from_key($type, $key);
-  // Build the options. It's simply a list of nids from the {book} table.
-  $options = array();
-  $result = db_query("SELECT nid FROM {book}");
-  while ($row = db_fetch_object($result)) {
-    $options[$row->nid] = $row->nid;
-  }
-  // Make sure there's an option for NONE (to remove a mapping, for example).
-  $none = t('None');
-  $options[$none] = $none;
-  $attributes = array('attributes' => array('rel' => 'lightframe'),
-    'query' => drupal_query_string_encode(array('destination' => $_GET['q'], 'require-outline' => 'true')),
-  );
-  $book_add_link = l(t('create'), 'node/add/book', $attributes);
-  // The form element for pages radio buttons.
-  $form['page'] = array(
-    '#type' => 'radios',
-    '#title' => t('Available book pages'),
-    '#description' => t('Choose the book page that should be used for this item, or !create a new one.', array('!create' => $book_add_link)),
-    '#options' => $options,
-    '#default_value' => empty($defaults) ? $none : $defaults['nid'],
-  );
-  $form['submit'] = array(
-    '#title' => t('Submit'),
-    '#type' => 'submit',
-    '#value' => t('Submit'),
-  );
+
+  if ($type == 'path' && empty($form_state['storage']['helpkey'])) {
+    // Get the whole rest of the path
+    $q_paths = explode('/', $_GET['q'], 4);
+    $key = $q_paths[3];
+    $ancestors = drupal_map_assoc(helpinject_get_path_ancestors($key));
+    $existing = helpinject_get_from_key($type, $ancestors);
+    foreach ($ancestors as $key => $value) {
+      if ($match = $existing[$key]) {
+        $title = db_result(db_query("SELECT r.title FROM {node_revisions} r INNER JOIN {node} n ON n.vid = r.vid WHERE r.nid = %d", $match['nid']));
+        $ancestors[$key] .= ' (' . t('Currently %title [nid !nid]', array('%title' => check_plain($title), '!nid' => $match['nid'])) . ')';
+      }
+    }
+    // This prevents it from going to the theme function for the injection form.
+    $form['#theme'] = 'theme_form';
+    $form['helpkey'] = array(
+      '#type' => 'radios',
+      '#required' => TRUE,
+      '#title' => t('Path granularity'),
+      '#description' => t('Choose a level of path granularity for this injection rule.'),
+      '#options' => $ancestors,
+      '#default_value' => $key,
+    );
+    $form['next'] = array(
+      '#title' => t('Next'),
+      '#type' => 'submit',
+      '#value' => t('Next'),
+    );
+  }
+  else {
+    if (empty($form_state['storage']['helpkey'])) {
+      // In this case we're injecting into something other than a path, so we
+      // need to get the helpkey from the URL path.
+
+      // Get the whole rest of the path
+      $q_paths = explode('/', $_GET['q'], 4);
+      $key = $q_paths[3];
+      // Pack the helpkey into the form for later use.
+      $form['helpkey'] = array('#type' => 'value', '#value' => $key);
+    }
+
+    // We show every topic (book page) grouped by book title.
+    // Pack the book trees into the form.
+    $trees = array();
+    $books = book_get_books();
+    ksort($books);
+    foreach ($books as $book) {
+      $node = node_load($book['nid']);
+      $trees[$node->nid] = book_menu_subtree_data($node->book);
+    }
+    $form['book_trees'] = array('#type' => 'value', '#value' => $trees);
+
+    // Find out if a help topic has already been selected.
+    $defaults = helpinject_get_from_key($type, $key);
+    // Build the options. It's simply a list of nids from the {book} table.
+    $options = array();
+    $result = db_query("SELECT nid FROM {book}");
+    while ($row = db_fetch_object($result)) {
+      $options[$row->nid] = $row->nid;
+    }
+    // Make sure there's an option for NONE (to remove a mapping, for example).
+    $none = t('None');
+    $options[$none] = $none;
+    $attributes = array('attributes' => array('rel' => 'lightframe'),
+      'query' => drupal_query_string_encode(array('destination' => $_GET['q'], 'require-outline' => 'true')),
+    );
+    $book_add_link = l(t('create'), 'node/add/book', $attributes);
+    // The form element for pages radio buttons.
+    $form['page'] = array(
+      '#type' => 'radios',
+      '#required' => TRUE,
+      '#title' => t('Available book pages'),
+      '#description' => t('Choose the book page that should be used for this item, or !create a new one.', array('!create' => $book_add_link)),
+      '#options' => $options,
+      '#default_value' => empty($defaults) ? $none : $defaults['nid'],
+    );
+    $form['submit'] = array(
+      '#title' => t('Submit'),
+      '#type' => 'submit',
+      '#value' => t('Submit'),
+    );
+  }
   return $form;
 }
 
+
+function helpinject_injection_form_submit($form, &$form_state) {
+  // It's important that we only go into this first block if we're dealing with
+  // 'path' types, and if the helpkey hasn't yet been chosen.
+  if (empty($form_state['storage']['helpkey']) && $form_state['values']['type'] == 'path') {
+    $form_state['storage']['helpkey'] = $form_state['values']['helpkey'];
+    $form_state['storage']['type'] = $form_state['values']['type'];
+    $form_state['rebuild'] = TRUE;
+  }
+  else {
+    $book_id = $form_state['values']['page'];
+    // First look into 'storage' for the helpkey (the case of a multi-step form),
+    // and if not found there. look in 'values' (the case of a single-step form).
+    $helpkey = empty($form_state['storage']['helpkey']) ? $form_state['values']['helpkey'] : $form_state['storage']['helpkey'];
+    $values = array(
+      'type' => $form_state['values']['type'],
+      'helpkey' => $helpkey,
+      'nid' => $book_id,
+    );
+    if ($book_id != t('None') && !@drupal_write_record('helpinject', $values)) {
+      drupal_write_record('helpinject', $values, 'helpkey');
+    }
+    if ($book_id == t('None')) {
+      db_query("DELETE FROM {helpinject} WHERE helpkey = '%s'", $helpkey);
+    }
+    // Unsetting storage allows the form to redirect to "destination".
+    unset($form_state['storage']);
+  }
+}
+
 function helpinject_injection_form_treewalker($tree = NULL, &$rows = NULL) {
   static $column = 0;
   static $max_colspan = 0;
@@ -214,7 +290,7 @@
   $column--;
 }
 
-function theme_helpinject_injection_form($form) {
+function theme_helpinject_injection_form($form, $blah = NULL) {
   drupal_set_title(t("Inject help text for @type %key", array('@type' => $form['type']['#value'], '%key' => $form['helpkey']['#value'])));
 
   $bookrows = array();
@@ -244,21 +320,6 @@
   return $output;
 }
 
-function helpinject_injection_form_submit($form, &$form_state) {
-  $book_id = $form_state['values']['page'];
-  $values = array(
-   'type' => $form_state['values']['type'],
-    'helpkey' => $form_state['values']['helpkey'],
-    'nid' => $book_id,
-  );
-  if ($book_id != t('None') && !@drupal_write_record('helpinject', $values)) {
-    drupal_write_record('helpinject', $values, 'helpkey');
-  }
-  if ($book_id == t('None')) {
-    db_query("DELETE FROM {helpinject} WHERE helpkey = '%s'", $form_state['values']['helpkey']);
-  }
-}
-
 // TODO: The form should be smart enough to know which books are referenced by
 // injected help. http://drupal.org/node/416142
 // TODO: Support exporting sub-books. http://drupal.org/node/416146
@@ -515,7 +576,8 @@
     helpinject_step_form($form, $form_id, 'helpinject_help_link');
     $topic = '';
     if ($values = helpinject_get_from_key('form', $form_id)) {
-      $topic = theme('helpinject_topic', $values['nid']);
+      $value = array_pop($values);
+      $topic = theme('helpinject_topic', $value['nid']);
     }
     // This line displays the help link for the whole form (if one has been injected for it).
     $form['#description'] = isset($form['#description']) ? $topic . ' ' . $form['#description'] : $topic;
@@ -591,7 +653,8 @@
   if (user_access('view advanced help popup')) {
     if (isset($element['#type']) && !in_array($element['#type'], array('button', 'image_button', 'submit', 'markup', 'token', 'hidden', 'form', 'value', 'weight'))) {
       if ($values = helpinject_get_from_key('form', $form_id, $element)) {
-        $link = theme('helpinject_topic', $values['nid']);
+        $value = array_pop($values);
+        $link = theme('helpinject_topic', $value['nid']);
         $element['#description'] = isset($element['#description']) ? $link . ' ' . $element['#description'] : $link;
       }
     }
@@ -599,11 +662,21 @@
 }
 
 function helpinject_get_from_key($type, $key) {
-  if ($values = db_fetch_array(db_query("SELECT h.*, n.title FROM {helpinject} h INNER JOIN {node} n ON h.nid = n.nid WHERE h.type = '%s' AND h.helpkey = '%s'", $type, $key))) {
-    $values['title'] = helpinject_munge_title($values['title']);
-    return $values;
+  if (!is_array($key)) {
+    $key = array($key);
+  }
+  $s = array();
+  foreach ($key as $k) {
+    $s[] = "'%s'";
+  }
+  $values = array();
+  $params = array_merge(array($type), $key);
+  $result = db_query("SELECT h.*, n.title FROM {helpinject} h INNER JOIN {node} n ON h.nid = n.nid WHERE h.type = '%s' AND h.helpkey in (" . implode(',', $s) . ")", $params);
+  while ($row = db_fetch_array($result)) {
+    $row['title'] = helpinject_munge_title($row['title']);
+    $values[$row['helpkey']] = $row;
   }
-  return FALSE;
+  return empty($values) ? FALSE : $values;
 }
 
 function helpinject_step_form(&$element, $form_id, $callback) {
