Index: feedback/feedback.admin.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/feedback/feedback.admin.inc,v
retrieving revision 1.1.2.2
diff -u -r1.1.2.2 feedback.admin.inc
--- feedback/feedback.admin.inc	20 Feb 2010 22:30:53 -0000	1.1.2.2
+++ feedback/feedback.admin.inc	8 Apr 2010 17:40:35 -0000
@@ -29,33 +29,10 @@
   if (count(explode(',', $_GET['page'])) < 2) {
     $_GET['page'] .= ',0';
   }
-
-  $form['feedback-messages'] = array('#tree' => TRUE);
-  foreach (array(0, 1) as $status) {
-    $sql = "SELECT f.*, u.name FROM {feedback} f INNER JOIN {users} u ON f.uid = u.uid WHERE f.status = %d";
-    $count_query = "SELECT COUNT(fid) FROM {feedback} WHERE status = %d";
-    $tablesort = tablesort_sql($form['#feedback_header']);
-    $result = pager_query($sql . $tablesort, 50, $status, $count_query, $status);
-
-    $form['feedback-messages'][$status] = array(
-      '#type' => 'fieldset',
-      '#title' => $status_headings[$status],
-      '#collapsible' => TRUE,
-      '#collapsed' => $status,
-      '#attributes' => array('class' => 'feedback-messages'),
-    );
-    while ($entry = db_fetch_object($result)) {
-      $form['feedback-messages'][$status][$entry->fid] = array(
-        '#type' => 'checkbox',
-        '#return_value' => 1,
-        '#default_value' => FALSE,
-      );
-      $form['feedback-messages'][$status][$entry->fid]['location'] = array('#value' => l(truncate_utf8($entry->location, 32, FALSE, TRUE), $entry->url));
-      $form['feedback-messages'][$status][$entry->fid]['date'] = array('#value' => format_date($entry->timestamp, 'small'));
-      $form['feedback-messages'][$status][$entry->fid]['user'] = array('#value' => theme('username', $entry));
-      $form['feedback-messages'][$status][$entry->fid]['message'] = array('#value' => feedback_format_message($entry));
-    }
-  }
+  $tablesort = tablesort_sql($form['#feedback_header']);
+  // Fetch the actual messages to display.
+  $form['feedback-messages'] = feedback_admin_view_feedback($tablesort, $status_headings);
+  
   $form['submit'] = array('#type' => 'submit', '#value' => t('Submit'));
   return $form;
 }
@@ -120,3 +97,42 @@
   }
 }
 
+/**
+ * Manage feedback module settings.
+ */
+function feedback_admin_settings_form() {
+  $form = array();
+  $implementations = array();
+  $options = array();
+  // Get available storage options.
+  $implementations = module_invoke_all('feedback_storage');
+  // Build options for the storage selector.
+  foreach ($implementations['module'] as $key => $module) {
+    $options[$module] = $implementations['name'][$key];
+  }
+  // Build the storage type selector.
+  $form['feedback_storage_settings'] = array(
+    '#title' => t('Storage settings'),
+    '#description' => t('Select where the Feedback module should save data.'),
+    '#type' => 'select',
+    // Disable by default, enable later if there's more than one option.
+    '#disabled' => TRUE,
+    '#options' => $options,
+    // Value is the module name to be used for storage.
+    '#default_value' => variable_get('feedback_storage_settings', 'feedback'),
+  );
+  if (count($options) > 1) {
+    $form['feedback_storage_settings']['#disabled'] = FALSE;
+  }
+  return system_settings_form($form);
+}
+
+/**
+ * Build the entries on the Feedback messages page.
+ */
+function feedback_admin_view_feedback($tablesort, $status_headings) {
+  // Check the module being used for storage.
+  $module = variable_get('feedback_storage_settings', 'feedback');
+  // Pass the act of fetching the entries off to the appropriate module.
+  return module_invoke($module, 'feedback_storage_view', $tablesort, $status_headings); 
+}
Index: feedback/feedback.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/feedback/feedback.module,v
retrieving revision 1.75.2.4
diff -u -r1.75.2.4 feedback.module
--- feedback/feedback.module	20 Feb 2010 23:59:32 -0000	1.75.2.4
+++ feedback/feedback.module	8 Apr 2010 17:40:35 -0000
@@ -10,7 +10,7 @@
  * Implementation of hook_perm().
  */
 function feedback_perm() {
-  return array('access feedback form', 'view feedback messages');
+  return array('access feedback form', 'view feedback messages', 'administer feedback');
 }
 
 /**
@@ -36,6 +36,14 @@
     'access arguments' => array('view feedback messages'),
     'file' => 'feedback.admin.inc',
   );
+  $items['admin/settings/feedback'] = array(
+    'title' => 'Feedback settings',
+    'description' => 'Administer feedback settings.',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('feedback_admin_settings_form'),
+    'access arguments' => array('administer feedback'),
+    'file' => 'feedback.admin.inc',
+  );
   return $items;
 }
 
@@ -122,27 +130,23 @@
       );
     }
   }
-  $form['message'] = array(
-    '#type' => 'textarea',
-    '#attributes' => array('class' => 'feedback-message'),
-    '#cols' => 20,
-    '#title' => t('Message'),
-    '#required' => TRUE,
-    '#wysiwyg' => FALSE,
-  );
+  // Submit button is always there.
   $form['submit'] = array(
     '#type' => 'submit',
     '#value' => t('Send'),
     '#id' => 'feedback-submit',
     '#prefix' => '<div id="feedback-throbber">',
     '#suffix' => '</div>',
+    '#weight' => 50,
   );
 
-  return $form;
+  // Go fetch the feedback data entry fields.
+  return feedback_fields($form);
 }
 
 function feedback_form_submit($form, &$form_state) {
-  feedback_add_entry($form_state['values']['message'], $form_state['values']['location']);
+  // Pass all the form values because we don't know what they will be.
+  feedback_add_entry($form_state['values']);
   $message = t('Thanks for your feedback!');
   if ($form_state['values']['ajax']) {
     echo drupal_to_js(array('message' => $message));
@@ -154,6 +158,17 @@
 }
 
 /**
+ * Build the form fields for the feedback form.
+ */
+function feedback_fields($form) {
+  // Check the module being used for storage.
+  $module = variable_get('feedback_storage_settings', 'feedback');
+  // Pass building the data entry fields to the appropriate module.
+  $form = module_invoke($module, 'feedback_storage_fields', $form);
+  return $form;
+}
+
+/**
  * Format a feedback entry.
  *
  * @param $entry
@@ -181,6 +196,58 @@
  *   A keyed array of optional where clause conditions.
  */
 function feedback_load($array) {
+  // Check the module being used for storage.
+  $module = variable_get('feedback_storage_settings', 'feedback');
+  // Pass the act of loading off to the appropriate module.
+  return module_invoke($module, 'feedback_storage_load', $array);
+}
+
+/**
+ * 'Mask' a path, i.e. replace all numeric arguments in a path with '%' placeholders.
+ *
+ * Please note that only numeric arguments with a preceding slash will be
+ * replaced.
+ *
+ * @param $path
+ *   An internal Drupal path, f.e. 'user/123/edit'.
+ * @return
+ *   A 'masked' path, for above example 'user/%/edit'.
+ */
+function feedback_mask_path($path) {
+  return preg_replace('@/\d+@', '/%', $path);
+}
+
+/**
+ * Store a new feedback entry in the database.
+ *
+ * @param string $form_values
+ *   The posted form values from feedback_form.
+ *   In default 'basic storage' mode the main values are:
+ *     $form_values['message']
+ *     $form_values['location']
+ */
+function feedback_add_entry($form_values) {
+  global $user;
+
+  // Check the module being used for storage.
+  $module = variable_get('feedback_storage_settings', 'feedback');
+  // Pass the act of storage off to the appropriate module.
+  module_invoke($module, 'feedback_storage_insert', $form_values, $user);
+}
+
+/**
+ * Implementation of hook_feedback_storage_insert().
+ */
+function feedback_feedback_storage_insert($form_values, $user) {
+  db_query("INSERT INTO {feedback} (uid, message, location, location_masked, url, timestamp, useragent) VALUES (%d, '%s', '%s', '%s', '%s', %d, '%s')", $user->uid, trim($form_values['message']), $form_values['location'], feedback_mask_path($form_values['location']), url($form_values['location'], array('absolute' => TRUE)), time(), $_SERVER['HTTP_USER_AGENT']);
+}
+
+/**
+ * Implementation of hook_feedback_storage_load().
+ */
+function feedback_feedback_storage_load($array) {
+  // Was the feedback_load() function.
+  // Load feedback for use in the feedback form.
   $where = $args = array();
   if (!empty($array)) {
     foreach ($array as $column => $value) {
@@ -201,32 +268,64 @@
 }
 
 /**
- * 'Mask' a path, i.e. replace all numeric arguments in a path with '%' placeholders.
- *
- * Please note that only numeric arguments with a preceding slash will be
- * replaced.
- *
- * @param $path
- *   An internal Drupal path, f.e. 'user/123/edit'.
- * @return
- *   A 'masked' path, for above example 'user/%/edit'.
+ * Implementation of hook_feedback_storage_view().
  */
-function feedback_mask_path($path) {
-  return preg_replace('@/\d+@', '/%', $path);
+function feedback_feedback_storage_view($tablesort, $status_headings) {
+  // Was in feedback_admin_view_form().
+  // Load feedback for use on the Feedback messages page in admin.
+  $messages = array('#tree' => TRUE);
+
+  foreach (array(0, 1) as $status) {
+    $sql = "SELECT f.*, u.name FROM {feedback} f INNER JOIN {users} u ON f.uid = u.uid WHERE f.status = %d";
+    $count_query = "SELECT COUNT(fid) FROM {feedback} WHERE status = %d";
+    $result = pager_query($sql . $tablesort, 50, $status, $count_query, $status);
+
+    $messages[$status] = array(
+      '#type' => 'fieldset',
+      '#title' => $status_headings[$status],
+      '#collapsible' => TRUE,
+      '#collapsed' => $status,
+      '#attributes' => array('class' => 'feedback-messages'),
+    );
+    while ($entry = db_fetch_object($result)) {
+      $messages[$status][$entry->fid] = array(
+        '#type' => 'checkbox',
+        '#return_value' => 1,
+        '#default_value' => FALSE,
+      );
+      $messages[$status][$entry->fid]['location'] = array('#value' => l(truncate_utf8($entry->location, 32, FALSE, TRUE), $entry->url));
+      $messages[$status][$entry->fid]['date'] = array('#value' => format_date($entry->timestamp, 'small'));
+      $messages[$status][$entry->fid]['user'] = array('#value' => theme('username', $entry));
+      $messages[$status][$entry->fid]['message'] = array('#value' => feedback_format_message($entry));
+    }
+  }
+  return $messages;
 }
 
 /**
- * Store a new feedback entry in the database.
- *
- * @param string $message
- *   A feedback message text entered by an user.
- * @param string $location
- *   The path on which the feedback message was entered.
+ * Implementation of hook_feedback_storage_fields().
  */
-function feedback_add_entry($message, $location) {
-  global $user;
+function feedback_feedback_storage_fields($form) {
+  // Build the feedback form fields.
+  $form['message'] = array(
+    '#type' => 'textarea',
+    '#attributes' => array('class' => 'feedback-message'),
+    '#title' => t('Message'),
+    '#required' => TRUE,
+    '#wysiwyg' => FALSE,
+  );
+  return $form;
+}
 
-  db_query("INSERT INTO {feedback} (uid, message, location, location_masked, url, timestamp, useragent) VALUES (%d, '%s', '%s', '%s', '%s', %d, '%s')", $user->uid, trim($message), $location, feedback_mask_path($location), url($location, array('absolute' => TRUE)), time(), $_SERVER['HTTP_USER_AGENT']);
+/**
+ * Implementation of hook_feedback_storage().
+ */
+function feedback_feedback_storage() {
+  // Return storage type name and module name for Feedback settings.
+  return array(
+    'name' => 'basic storage',
+    'module' => 'feedback',
+  );
 }
 
 /**

