### Eclipse Workspace Patch 1.0
#P faq_ask
Index: faq_ask.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/faq_ask/faq_ask.module,v
retrieving revision 1.17.2.23.2.14
diff -u -r1.17.2.23.2.14 faq_ask.module
--- faq_ask.module	22 Oct 2009 04:11:46 -0000	1.17.2.23.2.14
+++ faq_ask.module	25 Feb 2010 11:51:42 -0000
@@ -61,7 +61,7 @@
   else {
 //    return user_access('answer question') || user_access('edit_own_faq');
     // We don't include "edit own" because the intent is they can edit their own until it's published.
-    return user_access('answer question') || $account->uid == $node->uid; 
+    return user_access('answer question') || $account->uid == $node->uid;
   }
 }
 
@@ -158,11 +158,11 @@
 }
 
 /**
- * Implementation of hook_form_alter().
+ * Implementation of hook_form_FORM_ID_alter().
  *  This is how we build the "ask question" form.
  */
-function faq_ask_form_alter(&$form, $form_state, $form_id) {
-  if ($form_id != 'faq_node_form' || !isset($_GET['ask'])) {
+function faq_ask_form_faq_node_form_alter(&$form, $form_state) {
+  if (!isset($_GET['ask'])) {
       return;
     }
   if ($_GET['ask'] != 1 && $_GET['ask'] != 'true') {
@@ -183,9 +183,140 @@
   }
   $form['body'] = array('#type' => 'value', '#value' => variable_get('faq_ask_unanswered', t('Not answered yet.')));
 
+  // if we're supposed to notify asker on answer, add form item for this
+  if (variable_get('faq_ask_notify_asker', FALSE)) {
+
+    global $user;
+
+    // If asker is anonymous, add an optional e-mail field that may be used for notification when question is answered
+    if ($user->uid == 0) {
+      // Form field for e-mail.
+      $form['faq-email'] = array(
+        '#type' => 'textfield',
+        '#title' => t('Notification E-mail (optional)'),
+        '#default_value' => '',
+        '#weight' => 0,
+        '#description' => t('Write your e-mail here if you would like to be notified when the question is answered.')
+        );
+    }
+    else {
+      // Checkbox for notification
+      $form['faq-notify'] = array(
+        '#type' => 'checkbox',
+        '#title' => t('Notify by E-mail (optional)'),
+        '#default_value' => false,
+        '#weight' => 0,
+        '#description' => t('Check this box if you would like to be notified when the question is answered.'),
+        );
+    }
+  }
+
+  // Add validation of the e-mail field
+  if (isset($form['#validate'])) {
+    $temp_val = $form['#validate'];
+    $form['#validate'] = array($temp_val);
+  }
+  else {
+    $form['#validate'] = array();
+  }
+  $form['#validate'][] = 'faq_ask_form_validate';
+
   // Make sure we know we came from here.
   $form['faq_ask'] = array('#type' => 'value', '#value' => TRUE);
-  $form['#submit'][] = 'faq_ask_submit';
+  $form['buttons']['submit']['#submit'][] = 'faq_ask_submit';
+
+  // Sean Corales: Redirect to faq page if user is anonymous or cannot edit own faq nodes
+  global $user;
+  if ((!user_access('edit own faq') && !user_access('edit faq')) || ($user->uid == 0)) {
+    $form['#redirect'] = 'faq';
+  }
+
+  // Handle special cases if this is a block form
+  if (isset($_GET['block'])) {
+    if($_GET['block']) {
+
+      // Shorten the description text on taxonomy field
+      if (!variable_get('faq_ask_categorize', FALSE) && isset($form['taxonomy']['tags'])) {
+        $tags = array_keys($form['taxonomy']['tags']);
+        $form['taxonomy']['tags'][$tags[0]]['#description'] = t('A comma-separated list of terms.');
+      }
+
+      // Shorter description on Qestion field + move it higher
+      $form['title']['#description'] = t('Question to be answered.');
+      $form['title']['#weight'] = '-5';
+
+      // Shorter description on detailed question field
+      $form['detailed_question']['#description'] = t('Longer question text.');
+
+    }
+  }
+}
+
+/**
+ * Validation form for the FAQ Ask form
+ * Thanks to http://hokuten.net/2010/drupal-creating-an-e-mail-subscription-block/
+ */
+function faq_ask_form_validate($form, &$form_state) {
+
+  if (isset($form_state['values']['faq-email'])) {
+    $email = $form_state['values']['faq-email'];
+    if (strlen($email) > 1 && !eregi('^[a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.([a-zA-Z]{2,4})$', $email)) {
+      form_set_error('email', t('That is not a valid e-mail address.'));
+    }
+  }
+}
+
+/**
+ * Implementation of hook_nodeapi()
+ * Checks if the node being updated is a question that has been answered
+ */
+function faq_ask_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
+  if($node->type == 'faq') {
+    switch ($op) {
+      case 'update':
+
+        // return if the asker notification should be done by cron
+        if (variable_get('faq_ask_notify_by_cron', true)) {
+          return;
+        }
+        // Check if the node is published
+        $email = _faq_ask_get_faq_notification($node->nid);
+        if ($node->status == '1') {
+
+          // Get the asker account
+          $account = user_load(array('mail' => $email));
+          // If the account is not anonymous
+          if ($account) {
+            $params['account'] = $account;
+          }
+          else {
+            $params['account'] = null;
+          }
+
+          // Send the e-mail to the asker. Drupal calls hook_mail() via this
+          $mail_sent = drupal_mail('faq_ask', 'notify_asker', $email, user_preferred_language($params['account']), $params);
+
+          // Handle sending result
+          if ($mail_sent) {
+            watchdog('FAQ_Ask', 'Asker notification email sent to @to for question @quest',
+              array('@to' => $email, '@quest' => check_plain($node->title)), WATCHDOG_NOTICE);
+              // If email sent, remove the notification from the queue
+              _faq_ask_delete_faq_notification($node->nid);
+          }
+          else {
+            watchdog('FAQ_Ask', 'Asker notification email to @to failed for the "@quest" question.',
+              array('@to' => $email, '@quest' => check_plain($node->title)), WATCHDOG_ERROR);
+            drupal_set_message(  t(  'Asker notification email to @to failed for the "@quest" question.',
+                           array('@to' => $email, '@quest' => check_plain($node->title))
+                        )
+                      );
+          }
+        }
+        break;
+      default:
+        break;
+    }
+  }
 }
 
 function faq_ask_submit($form, &$form_state) {
@@ -202,12 +333,13 @@
   else {
     $category = 0;  // 0 is default expert.
   }
+
   // Are we notifying the expert(s)?
   if (variable_get('faq_ask_notify', FALSE)) {
     $params = array(
       'category' => $category ? $category : -1,
-      'question' => $node->title,
-      'nid' => $node->nid,
+      'question' => $form_state['title'],
+      'nid' => $form_state['nid'],
       'creator' => theme('username', $node, array('plain' => TRUE)),
       );
     // Find out who the experts are.
@@ -228,10 +360,157 @@
     }
   }
 
-  drupal_set_message(t('Your question has been submitted. It will appear in the FAQ listing as soon as it has been answered.'), 'status');
+  // Handle the notification of asker
+  if (isset($form_state['values']['faq-email'])) {
+    _faq_ask_set_faq_notification($form_state['nid'], $form_state['values']['faq-email']);
+    drupal_set_message(t('Your question has been submitted. An e-mail will be sent to <i>@mail</i> when answered.', array('@mail' => $form_state['values']['faq-email'])), 'status');
+  }
+  else if (isset($form_state['values']['faq-notify'])) {
+    if ($form_state['values']['faq-notify']) {
+      global $user;
+      $email = $user->mail;
+      _faq_ask_set_faq_notification($form_state['nid'], $email);
+      drupal_set_message(t('Your question has been submitted. An e-mail will be sent to <i>@mail</i> when answered.', array('@mail' => $email)), 'status');
+    }
+  }
+  else {
+    drupal_set_message(t('Your question has been submitted. It will appear in the FAQ listing as soon as it has been answered.'), 'status');
+  }
 }
 
 /**
+ * Implementation of hook_cron()
+ * Checks the que for asker notifications and sends a notification to the asker when the question is published
+ *
+ */
+function faq_ask_cron() {
+
+  // If the asker notification should be done by cron
+  if (!variable_get('faq_ask_notify_by_cron', true)) {
+    return;
+  }
+  // Get all the waiting notifications
+  $notifications = _faq_ask_get_faq_notifications();
+  foreach ($notifications as $nid => $email) {
+    // With the notification record, check if status of the question is published
+    if ($result = db_query('SELECT title,status FROM {node} WHERE nid=%d', $nid)) {
+      $notification = db_fetch_array($result);
+      if ($notification['status'] == '1') {
+
+      $params = array(
+        'question' => $notification['title'],
+        'nid' => $nid,
+        'account' => user_load(array('mail' => $email)),
+        );
+
+        // Send the e-mail to the asker. Drupal calls hook_mail() via this
+        $mail_sent = drupal_mail('faq_ask', 'notify_asker', $email, user_preferred_language($params['account']), $params);
+
+        // Handle sending result
+        if ($mail_sent) {
+          watchdog('FAQ_Ask', 'Asker notification email sent to @to for question: "@quest"',
+            array('@to' => $email, '@quest' => check_plain($notification['title'])), WATCHDOG_NOTICE);
+            // If email sent, remove the notification from the queue
+            _faq_ask_delete_faq_notification($nid);
+        }
+        else {
+          watchdog('FAQ_Ask', 'Asker notification email to @to failed for the "@quest" question.',
+            array('@to' => $email, '@quest' => check_plain($notification['title'])), WATCHDOG_ERROR);
+          drupal_set_message(t('Asker notification email to @to failed for the "@quest" question.', array('@to' => $email, '@quest' => check_plain($notification['title']))));
+        }
+      }
+    }
+
+  }
+}
+/**
+ * Helper function to fetch an email for notification assigned to an faq node
+ *
+ */
+function _faq_ask_get_faq_notification_email($nid) {
+  $result = db_query('SELECT email FROM {faq_ask_notify} WHERE nid=%d', $nid);
+  return db_fetch_array($result);
+}
+
+/**
+ * Helper function fetching all notifications
+ * returns: Array containing all outstanding notifications
+ */
+function _faq_ask_get_faq_notifications() {
+  $notifications = array();
+
+  $result = db_query('SELECT nid, email FROM {faq_ask_notify}');
+  while ($row = db_fetch_array($result)) {
+    $notifications[$row['nid']] = $row['email'];
+  }
+  return $notifications;
+
+}
+function _faq_ask_set_faq_notification($nid, $email) {
+
+ $data = array(
+    'nid' => $nid,
+    'email' => $email
+  );
+  drupal_write_record('faq_ask_notify', $data);
+}
+
+function _faq_ask_delete_faq_notification($nid) {
+  $delete = db_query("DELETE FROM {faq_ask_notify} WHERE nid=%d", $nid);
+  if ($delete === FALSE) {
+    drupal_set_message(t('Attempt to delete email notification failed.'), 'error');
+  }
+}
+
+
+
+/**
+ * Block "Ask a Question" form implementation
+ * This implements the form displayed in a block where the user may ask a question
+ *
+ */
+function faq_ask_a_question_blockform() {
+
+  // Include page handler for node_add()
+  module_load_include('inc', 'node', 'node.pages');
+
+  // If user is allowed to create a faq content type
+  if (node_access('create', 'faq')) {
+
+    // Fool the hook_form_alter function to think we're in an faq-ask page
+    $saved_get = '';
+    if (isset($_GET['ask'])) {
+      $saved_get = $_GET['ask'];
+    }
+    $_GET['ask'] = '1';
+    $_GET['block'] = 'true';
+
+    // Note title before rendering of form.
+    $title = drupal_get_title();
+    // Create the form
+    $form = node_add('faq');
+    // Restore title, which will have been overridden.
+    drupal_set_title($title);
+
+    // Restore the $_GET['ask'] variable status
+    if ($saved_get != '') {
+      $_GET['ask'] = $saved_get;
+    }
+    else {
+      unset($_GET['ask']);
+    }
+    unset($_GET['block']);
+
+    return $form;
+  }
+  else {
+    return '';
+  }
+
+}
+
+
+/**
  * Implementation of hook_mail().
  * This function completes the email, allowing for placeholder substitution.
  * @TODO: notify_asker.
@@ -264,6 +543,24 @@
       $body[] = t('In order to answer it you will first need to <a href="!login_uri">login</a> to the site.', $variables, $language->language);
       $body[] = t('Once logged in, you may proceed <a href="!answer_uri">directly to the question</a> to answer it.', $variables, $language->language);
       break;
+
+    case 'notify_asker':
+      $variables = array_merge($variables, array(
+        '!cat' => $params['category'],
+        '@question' => $params['question'],
+        '!question_uri' => url('node/'. $params['nid'], array('absolute' => TRUE)),
+        ));
+
+      if ($variables['!username'] == '') {
+        $variables['!username'] = t('user');
+      }
+
+      $subject = t('A question you asked has been answered on !site', $variables, $language->language);
+      $body[] = t('Dear !username,', $variables, $language->language);
+      $body[] = t('The question: "@question" you asked on !site has been answered. ', $variables, $language->language);
+      $body[] = t('To view the answer, please visit the question you created on !question_uri.', $variables, $language->language);
+      $body[] = t('Thank you for visiting.', $variables, $language->language);
+      break;
   }
   $message['body'] = drupal_wrap_mail(implode($newline, $body));
   $message['subject'] = $subject;
@@ -276,6 +573,7 @@
  * so it can "flip" based on whether there are more categories or experts.
  */
 function faq_ask_settings_form(&$form_state, $op = NULL, $aid = NULL) {
+
   $form = array();
   // Set a basic message that will be unset once we pass the error checking.
   $form['error'] = array('#value' => t('Errors were found, please correct them before proceeding.'), '#weight' => -10);
@@ -296,9 +594,9 @@
   // Get the admin's name.
   $admin = ucwords(db_result(db_query('SELECT name FROM {users} WHERE uid=1')));
 
-  $form['notification'] = array(
+  $form['notification'] = Array(
     '#type' => 'fieldset',
-    '#title' => t('Notifications'),
+    '#title' => T('Notifications'),
     '#collapsible' => TRUE,
     '#collapsed' => FALSE,
     );
@@ -310,6 +608,28 @@
     '#default_value' => variable_get('faq_ask_notify', 0),
     );
 
+  $form['notification']['notify_asker'] = Array(
+    '#type' => 'fieldset',
+    '#title' => T('Asker notification'),
+    '#collapsible' => FALSE,
+    '#collapsed' => FALSE,
+    );
+
+  $form['notification']['notify_asker']['faq_ask_asker_notify'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Notify askers'),
+    '#description' => t('If this box is checked, the asker creating the question will be notified via email that their question is answered.'),
+    '#default_value' => variable_get('faq_ask_notify_asker', 0),
+    );
+
+  $form['notification']['notify_asker']['faq_ask_asker_notify_cron'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Use cron for asker notification'),
+    '#description' => t('If this box is checked, the asker notifications will be sendt via cron.'),
+    '#default_value' => variable_get('faq_ask_notify_by_cron', true),
+    '#disabled' =>  !variable_get('faq_ask_notify_asker', 0),
+    );
+
   $form['options'] = array(
     '#type' => 'fieldset',
     '#title' => t('Options'),
@@ -345,7 +665,7 @@
     '#description' => t('This text will be inserted into the body of questions when they are asked. This helps make editing easier'),
     '#default_value' => variable_get('faq_ask_unanswered', t('Not answered yet.')),
     );
- 
+
   $form['options']['faq_ask_expert_advice'] = array(
     '#type' => 'textarea',
     '#title' => t('Answer advice for the expert'),
@@ -434,7 +754,7 @@
   //$vocabs = variable_get('faq_ask_vocabularies', $def_vid);
   $vocabs_array = array();
   foreach ($vocabs as $vocab) {
-    $vocabs_array[$vocab->vid] = $vocab->vid;  
+    $vocabs_array[$vocab->vid] = $vocab->vid;
   }
 
   $result = db_query('SELECT td.tid, td.name, td.description FROM {term_data} td WHERE td.vid IN ('. db_placeholders($vocabs_array) .') ORDER BY td.weight ASC, td.name ASC', $vocabs_array);
@@ -566,7 +886,7 @@
     else {
       // Expert 0 means default expert; overlook it.
       if ($expert['tid'] != 0) {
-        drupal_set_message(t("!name doesn't exist. If you have just changed your role selections this may be okay.", array('!name' => $box_name)), 'warning'); 
+        drupal_set_message(t("!name doesn't exist. If you have just changed your role selections this may be okay.", array('!name' => $box_name)), 'warning');
       }
     }
   }
@@ -590,7 +910,7 @@
   }
 
   // Get rid of error element.
-  unset($form['error']);  
+  unset($form['error']);
   $form['submit'] = array(
     '#type' => 'submit',
     '#value' => t('Save configuration'),
@@ -615,6 +935,8 @@
   variable_set('faq_ask_categorize', $form_state['values']['faq_ask_categorize']);
   variable_set('faq_ask_expert_own', $form_state['values']['faq_ask_expert_own']);
   variable_set('faq_ask_notify', $form_state['values']['faq_ask_notify']);
+  variable_set('faq_ask_notify_asker', $form_state['values']['faq_ask_asker_notify']);
+  variable_set('faq_ask_notify_by_cron', $form_state['values']['faq_ask_asker_notify_cron']);
   variable_set('faq_ask_unanswered', $form_state['values']['faq_ask_unanswered']);
   variable_set('faq_ask_default_expert', $form_state['values']['faq_ask_default_expert']);
   variable_set('faq_ask_expert_advice', $form_state['values']['faq_ask_expert_advice']);
@@ -652,7 +974,7 @@
   global $user;
   // Validate the request.
   if (!isset($_REQUEST['token']) || !drupal_valid_token($_REQUEST['token'], "faq_ask/answer/$node->nid")) {
-    watchdog('Faq_Ask', 
+    watchdog('Faq_Ask',
       'Received an invalid answer request (@query_string) from @user_ip.',
       array('@query_string' => $_SERVER['QUERY_STRING'], '@user_ip' => $_SERVER['REMOTE_ADDR']),
       WATCHDOG_ALERT);
@@ -849,6 +1171,7 @@
  */
 function faq_ask_block($op = 'list', $delta = 0, $edit = array()) {
   global $user;
+  $block = array();
   switch ($op) {
     case 'list':
       $blocks[0]['info'] = t('Unanswered Questions');
@@ -865,7 +1188,8 @@
         case 1:
           // Ask a question block.
           if (user_access('ask question')) {
-            $block['content'] = faq_ask_page(NULL);
+            $block['title']= t('Ask a Question');
+            $block['content'] = faq_ask_a_question_blockform();
           }
 
       } // end switch($delta).
@@ -912,7 +1236,7 @@
   // What permissions does this user have?
   $can_edit = user_access('administer faq') || user_access('administer nodes');
   $is_expert = user_access('answer question');
-  
+
   $mode = 'edit';
   $output = $extra_msg = NULL;
   // A high limit means we are doing the "unanswered" page.
Index: faq_ask.install
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/faq_ask/faq_ask.install,v
retrieving revision 1.4.2.7
diff -u -r1.4.2.7 faq_ask.install
--- faq_ask.install	24 Nov 2008 20:13:07 -0000	1.4.2.7
+++ faq_ask.install	25 Feb 2010 11:51:41 -0000
@@ -32,6 +32,28 @@
       'tid' => array('tid', 'uid'),
       ),
     );
+
+  $schema['faq_ask_notify'] = array(
+    'description' => t('FAQ node to asker mapping.'),
+    'fields' => array(
+      'nid' => array(
+        'description' => t('Node identifier for notification'),
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        ),
+      'email' => array(
+        'description' => t('Node identifier for notification'),
+        'type' => 'varchar',
+        'length' => '128',
+        'not null' => TRUE,
+        ),
+      ),
+    'primary key' => array('nid', 'email'),
+    'indexes' => array(
+      'nid' => array('nid', 'email'),
+      ),
+    );
   return $schema;
 }
 
@@ -55,11 +77,22 @@
 function faq_ask_update_6100() {
   $ret = array();
 
-  $ret[] = update_sql('INSERT INTO {faq_expert} (uid, tid) VALUES ('. variable_get('faq_ask_default_expert', 1) .', 0)'); 
+  $ret[] = update_sql('INSERT INTO {faq_expert} (uid, tid) VALUES ('. variable_get('faq_ask_default_expert', 1) .', 0)');
+
+  return $ret;
+}
+
+function faq_ask_update_6101() {
+
+  $ret = array();
+  $schema = faq_ask_schema();
+  db_create_table($ret, 'faq_ask_notify', $schema['faq_ask_notify']);
 
   return $ret;
+
 }
 
+
 /**
  * Implementation of hook_uninstall().
  */
@@ -77,6 +110,6 @@
   variable_del('faq_ask_help_text');
   variable_del('faq_ask_categorize');
   variable_del('faq_ask_expert_own');
-  
+
   drupal_set_message(t('faq_ask module uninstalled.'));
 }
