Index: wikitools.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/wikitools/wikitools.module,v
retrieving revision 1.4.2.1
diff -u -p -r1.4.2.1 wikitools.module
--- wikitools.module	22 Feb 2008 16:46:14 -0000	1.4.2.1
+++ wikitools.module	23 Feb 2008 22:12:34 -0000
@@ -35,14 +35,21 @@ function wikitools_menu() {
     'page arguments' => array('wikitools_admin_settings'),
     'type' => MENU_NORMAL_ITEM
   );
-  $wiki_path = wikitools_wiki_path();
-  if ($wiki_path) {
+  if ($wiki_path = wikitools_wiki_path()) {
     $items[$wiki_path] = array(
       'page callback' => 'wikitools_handle_request',
       'access arguments' => array('access content'),
       'type' => MENU_CALLBACK
     );
   }
+  if (module_exists('freelinking') && wikitools_hijack_freelinking()) {
+    // Add a new path under the freelinking path.
+    $callbacks['freelinking/%'] = array(
+      'page callback' => 'wikitools_handle_request',
+      'access arguments' => array('access content'),
+      'type' => MENU_CALLBACK
+    );
+  }
   return $items;
 }
 
@@ -56,14 +63,6 @@ function wikitools_menu_alter(&$callback
     $callbacks['node/%node/delete']['page callback'] = 'wikitools_delete_protection_delete_confirm';
     $callbacks['node/%node/delete']['page arguments'] = array(1);
   }
-  // Only hijack freelinking path if an argument is specified, otherwise let the freelinking page show.
-  if (wikitools_hijack_freelinking()) {
-    $callbacks['freelinking/%'] = array(
-      'page callback' => 'wikitools_handle_request',
-      'access arguments' => array('access content'),
-      'type' => MENU_CALLBACK
-    );
-  }
 }
 
 /**
@@ -86,10 +85,9 @@ function wikitools_admin_settings() {
     '#description' => t('The main page is shown if you type in the wiki path. Leave empty to disable the main page.'),
   );
   $form['wikitools_node_types'] = array(
-    '#type' => 'select',
+    '#type' => 'checkboxes',
     '#title' => t('Wiki node types'),
     '#options' => node_get_types('names'),
-    '#size' => count(node_get_types('names')),
     '#default_value' => wikitools_node_types(),
     '#multiple' => TRUE,
     '#description' => t('Select the node types which will be affected by the specified options. If you select multiple node types, all nodes of these types will be searched for when a wikipath is entered. If a wikipage doesn\'t exist, an option to create any of these types will be given.'),
@@ -101,7 +99,7 @@ function wikitools_admin_settings() {
       'node creation' => t('Node Creation: Let users create new nodes when they type in a node name which does not exist.'),
       'node search' => t('Node Search: Let users search for nodes when they type in a node name which does not exist.'),
       'auto redirect' => t('Automatic Redirect: If a title of a moved page is entered, redirect automatically.'),
-      'unique titles' => t('Unique Titles: Enforce that titles are unique over all wiki node types'),
+      'unique titles' => t('Unique Titles: Enforce that titles of new nodes are different from existing ones.'),
       'move protection' => t('Move Protection: Disallow change of node titles for users without <em>administer nodes</em> permission.'),
       'delete protection' => t('Delete Protection: Disallow deletion of nodes for users without <em>administer nodes</em> permission.'),
       'underscore as space' => t('Treat underscores as spaces when looking for node titles.'),
@@ -114,7 +112,7 @@ function wikitools_admin_settings() {
       t('The option <em>Automatic Redirect</em> works only if node revisions are created.') .'</li></ul>',
   );
   $form['wikitools_404_type'] = array(
-    '#type' => 'select',
+    '#type' => 'checkboxes',
     '#title' => t('Wiki 404 type'),
     '#description' => t('Select the 404 (page not found) type for all pages under the wiki path.'),
     '#multiple' => TRUE,
@@ -123,21 +121,44 @@ function wikitools_admin_settings() {
       'Link to creation' => t('Link to creation'),
       'Creation form' => t('Creation form'),
     ),
-    '#size' => 3,
     '#default_value' => wikitools_404(),
   );
   $form['wikitools_disallowed_characters'] = array(
     '#type' => 'textfield',
     '#title' => t('Disallowed characters in titles'),
-    '#description' => t('A list of characters which are not allowed in the title of a wiki page. This setting is important for the wikilink feature to work. Set it so that your input syntax will not be confused by titles. Make sure you don\'t enter a space character unless you really want to disallow spaces in titles. Leave empty to disable this feature.'),
+    '#description' => t('Leave empty to disable this feature. Specify a list of characters which are not allowed in the title of a wiki page.'),
     '#default_value' => wikitools_disallowed_characters(),
   );
-  $form['wikitools_hijack_freelinking'] = array(
-    '#type' => 'checkbox',
-    '#title' => t('Hijack freelinking filter'),
-    '#default_value' => wikitools_hijack_freelinking(),
-    '#description' => t('If you activate this option, the links of the freelinking filter will be processed by the wikitools module rather than the freelinking module. When active, a link to <em>freelinking/Page Name</em> behaves exactly as a link to <em>wikipath/Page Name</em>.'),
+  if (module_exists('freelinking')) {
+    $form['wikitools_hijack_freelinking'] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Hijack freelinking filter'),
+      '#default_value' => wikitools_hijack_freelinking(),
+      '#description' => t('If you activate this option, the links of the freelinking filter will be processed by the wikitools module rather than the freelinking module. When active, a link to <em>freelinking/Page Name</em> behaves exactly as a link to <em>wikipath/Page Name</em>.'),
+    );
+  }
+  $form['subpages'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Subpages'),
+    '#description' => t('Subpages can be appended to a URL (either directly or via a query string) and will redirect the user to the named subpage.'),
   );
+  $form['subpages']['wikitools_subpages_handling'] = array(
+    '#type' => 'radios',
+    '#title' => t('Activation'),
+    '#options' => array(
+      'disabled' => t('Disabled'),
+      'url' => t('Enable url suffixes: With url suffixes, you can append the subpage to the URL. For example  <em>wikipath/Page/edit</em>.'),
+      'query' => t('Enable query string: With query strings, you can append the subpage as a query. For example <em>wikipath/Page?action=edit</em>.'),
+    ),
+    '#default_value' => wikitools_subpages_handling(),
+  );
+  $form['subpages']['wikitools_subpages'] = array(
+    '#type' => 'textfield',
+    '#title' => t('URL subpages'),
+    '#description' => t('A list of available subpages. Only these subpages can be used as url suffixes or with the query string.'),
+    '#default_value' => implode(", ", wikitools_subpages()),
+  );
+
   $form = system_settings_form($form);
   // Rebuild the menu after updating the settings.
   $form['#submit'][] = 'menu_rebuild';
@@ -214,7 +235,7 @@ function wikitools_disallowed_characters
  */
 function wikitools_options($value = NULL) {
   if (is_null($value)) {
-    return variable_get('wikitools_options', array('node creation' => FALSE, 'node search' => FALSE, 'delete protection' => FALSE, 'move protection' => FALSE, 'unique titles' => FALSE, 'auto redirect' => FALSE, 'underscore as space' => FALSE, 'dash as space' => FALSE));
+    return variable_get('wikitools_options', array('node creation', 'node search', 'unique titles', 'underscore as space'));
   }
   return variable_set('wikitools_options', $value);
 }
@@ -284,6 +305,35 @@ function wikitools_treat_dash_as_space()
 }
 
 /**
+ * The subpage handling used?
+ * @return
+ *   'disabled', 'url' or 'query'
+ */
+function wikitools_subpages_handling($value = NULL) {
+  if (is_null($value)) {
+    return variable_get('wikitools_subpages_handling', 'disabled');
+  }
+  variable_set('wikitools_subpages_handling', $value);
+}
+
+/**
+ * The query string used to specify subpages.
+ */
+function wikitools_subpages_query_string() {
+  return 'wt_action';
+}
+
+/**
+ * Array of URL subpages.
+ */
+function wikitools_subpages($value = NULL) {
+  if (is_null($value)) {
+    return preg_split("/[\s,]+/", variable_get('wikitools_subpages', 'edit, delete, view, revisions'));
+  }
+  variable_set('wikitools_subpages', implode(", ", $value));
+}
+
+/**
  * Is the freelinking path hijacked?
  */
 function wikitools_hijack_freelinking($value = NULL) {
@@ -298,40 +348,67 @@ function wikitools_hijack_freelinking($v
  */
 
 /**
+ * Decode page name given via URL.
+ */
+function wikitools_decode_page_name($encoded_page_name) {
+  $page_name = trim(urldecode($encoded_page_name));
+  if (wikitools_treat_underscore_as_space()) {
+    $page_name = str_replace('_', ' ', $page_name);
+  }
+  if (wikitools_treat_dash_as_space()) {
+    $page_name = str_replace('-', ' ', $page_name);
+  }
+  return $page_name;
+}
+
+/**
  * Menu callback for wiki path.
  * This function is called if a page without an alias is called below the wiki path.
  */
 function wikitools_handle_request() {
-  // Calculate index of first path argument after wiki path if specific position wasn't passed in.
+  $output = '';
+
+  // Create list of path parts.
+  $args = explode('/', $_GET['q']);
+
+  // Calculate index of first path argument after wiki path.
   if (arg(0) != 'freelinking') {
     $i = count(explode('/', wikitools_wiki_path()));
   }
   else {
     $i = 1;
   }
-  if (arg($i)) {
-    // Save the path arguments after the wiki path as page name and put the slashes back.
-    $page_name = arg($i++);
-    while (arg($i)) {
-      $page_name .= '/'. arg($i);
-      $i++;
+
+  // Determine subpage.
+  $subpage = NULL;
+  if (wikitools_subpages_handling() == 'query') {
+    // Check if a query string is in the URL with a valid subpage
+    if (isset($_GET[wikitools_subpages_query_string()])) {
+      $subpage = $_GET[wikitools_subpages_query_string()];
+      if (!in_array($subpage, wikitools_subpages())) {
+        $subpage = NULL;
+      }
+    }
+  }
+  elseif (wikitools_subpages_handling() == 'url') {
+    // Check if there are more than one part, and if the last one is a valid subpage.
+    if (count($args)-$i > 1 && in_array(end($args), wikitools_subpages())) {
+      $subpage = end($args);
+      array_pop($args);
     }
   }
+
+  // Determine page name.
+  if (isset($args[$i])) {
+    $page_name = wikitools_decode_page_name(implode('/', array_slice($args, $i)));
+  }
   else {
     // Use default page title if only wiki path is entered.
     $page_name = wikitools_main_page_title();
   }
-  // Decode page name and remove white space.
-  $page_name = trim(urldecode($page_name));
-  if (wikitools_treat_underscore_as_space()) {
-    $page_name = str_replace('_', ' ', $page_name);
-  }
-  if (wikitools_treat_dash_as_space()) {
-    $page_name = str_replace('-', ' ', $page_name);
-  }
-  $node_types = wikitools_node_types();
-  $output = '';
+
   // Don't do anything if no node types are active or no page name is available
+  $node_types = wikitools_node_types();
   if (count($node_types) && $page_name) {
     // Try to find the current page with this name.
     $result = db_query("SELECT nid, type FROM {node} WHERE LOWER(title) = LOWER('%s')", $page_name);
@@ -344,7 +421,12 @@ function wikitools_handle_request() {
     if (count($found_nodes) == 1) {
       // Single match for title.
       $node = current($found_nodes);
-      drupal_goto("node/$node->nid");
+      if ($subpage) {
+        drupal_goto("node/$node->nid/$subpage");
+      }
+      else {
+        drupal_goto("node/$node->nid");
+      }
     }
     else if (count($found_nodes) > 1) {
       // Multiple match for title.
@@ -394,6 +476,7 @@ function wikitools_nodeapi(&$node, $op, 
  */
 function wikitools_node_validate($node) {
   if (wikitools_type_affected($node->type)) {
+    // Check for unique titles.
     if (wikitools_enforce_unique_titles()) {
       // Build node type condition.
       $types_clause = NULL;
@@ -420,8 +503,8 @@ function wikitools_node_validate($node) 
         form_set_error('title', t('A <a href="@page_url">page</a> with this name alredy exists.', array('@page_url' => url("node/$nid"))));
       }
     }
-    $disallowed_characters = wikitools_disallowed_characters();
-    if ($disallowed_characters) {
+    // Check for disallowed characters in title.
+    if ($disallowed_characters = wikitools_disallowed_characters()) {
       for ($i = 0; $i < strlen($node->title); $i++) {
         if (strpos($disallowed_characters, $node->title[$i]) !== FALSE) {
           form_set_error('title', t('The character %c is not allowed in a title', array('%c' => $node->title[$i])));
@@ -429,6 +512,13 @@ function wikitools_node_validate($node) 
         }
       }
     }
+    // Check for invalid title names if url subpages are enabled and "/" is allowed in titles.
+    if (wikitools_subpages_handling() == 'url' && strpos("/", $disallowed_characters) === FALSE) {
+      $title_parts = explode('/', $node->title);
+      if (count($title_parts) > 1 && in_array(end($title_parts), wikitools_subpages())) {
+        form_set_error('title', t('The title is not allowed to end in: %string', array('%string' => '/' . implode(', /', wikitools_subpages()))));
+      }
+    }
   }
 }
 
