### Eclipse Workspace Patch 1.0
#P faq_ask
Index: faq_ask.module
===================================================================
RCS file: /cvs/drupal/contributions/modules/faq_ask/faq_ask.module,v
retrieving revision 1.43
diff -u -r1.43 faq_ask.module
--- faq_ask.module	28 Feb 2009 19:48:41 -0000	1.43
+++ faq_ask.module	9 Mar 2010 12:01:45 -0000
@@ -1,5 +1,5 @@
 <?php
-// $Id: faq_ask.module,v 1.43 2009/02/28 19:48:41 nancyw Exp $
+// $Id: faq_ask.module,v 1.17.2.23.2.14 2009/10/22 04:11:46 nancyw Exp $
 
 /**
  * @file
@@ -8,167 +8,196 @@
  */
 
 /**
- * Implementation of hook_help().
+ * Display help and module information
+ * @param string $path
+ *   section which section of the site we're displaying help
+ *
+ * @return string
+ *   help text for section
  */
-function faq_ask_help($section='') {
+function faq_ask_help($path, $arg) {
   $output = '';
 
-  switch ($section) {
+  switch ($path) {
     case 'admin/help#faq_ask':
-      $output .= '<p>'. t("This module is an add-on to the FAQ module that allows users with the 'ask question' permission to create a question which will be queued for an 'expert' to answer.") .'</p>'.
-        '<p>'. t("The module shows an abbreviated version of the FAQ form without an answer field. The node is created without the 'published' attribute. There is a block that will show the unanswered questions to the 'expert' (generally, this requires a separate role).") .'</p>'.
-        '<p>'. t("Viewing of the completed question and answer pair is done by the FAQ module.") .'</p>'.
-        '<p>'. t("Simply adding the 'FAQ' content type to a vocabulary will not make it eligible for experts; you must go to the settings page and add it there.") .'</p>';
+      $output .= '<p>' . t("This module is an add-on to the FAQ module that allows users with the 'ask question' permission to create a question which will be queued for an 'expert' to answer.") . '</p>' .
+        '<p>' . t("The module shows an abbreviated version of the FAQ form without an answer field. The node is created without the 'published' attribute. There is a block that will show the unanswered questions to the 'expert' (generally, this requires a separate role).") . '</p>' .
+        '<p>' . t("Viewing of the completed question and answer pair is done by the FAQ module.") . '</p>' .
+        '<p>' . t("Simply adding the 'FAQ' content type to a vocabulary will not make it eligible for experts; you must go to the settings page and add it there.") . '</p>';
       return $output;
 
     case 'admin/settings/faq/ask':
-      return theme('box', NULL, '<big>'. t('In order for the Faq_Ask module to operate, you must, at the least,: 1) select one or more roles as experts (and you may have to "Save configuration"); 2) select at least one category and expert combination; 3) click the "Save configuration" button.') .'</big>');
-    
-    case 'faq_ask/more':
-      $output = '<p>'. variable_get('faq_ask_expert_advice', _faq_ask_advice_default('expert')) .'</p>';
-      
+      return theme('box', NULL, '<big>' . t('In order for the Faq_Ask module to operate, you must, at the least,: 1) Define at least one vocabulary for use with the "faq" content type; 2) select one or more roles as experts (and you may have to "Save configuration"); 3) select at least one category and expert combination; 4) click the "Save configuration" button.') . '</big>');
+
+    case 'faq_ask/unanswered':
+      $output = '<p>' . filter_xss_admin(variable_get('faq_ask_expert_advice', _faq_ask_advice_default('expert'))) . '</p>';
       if (user_access('administer blocks')) {
-        $output .= '<p><em>'. t('You may go <a href="!setting">here</a> to change the block limit.', array('!setting' => url('admin/build/block/configure/faq_ask/0'))) .'</em></p>';
+        $output .= '<p><em>' . t('You may go <a href="!setting">here</a> to change the block limit.', array('!setting' => url('admin/build/block/configure/faq_ask/0'))) . '</em></p>';
       }
-
       return $output;
-  
-    case 'faq_ask/'. arg(1):
+
+    case 'faq_ask/%':
     case 'faq_ask':
-      return variable_get('faq_ask_help_text', _faq_ask_help_default());  }
+      return filter_xss_admin(variable_get('faq_ask_help_text', _faq_ask_help_default()));
+  }
 }
 
 /**
- * Implementation of hook_perm().
+ * Implements hook_permission().
+ *
  * Define the permissions this module uses
+ *
+ * @return array
+ *   permissions defined for the faq_ask module
  */
-function faq_ask_perm() {
-  return array('ask question', 'answer question');
+function faq_ask_permission() {
+  return array(
+    'ask question' => array(
+      'title' => t('Ask a question'),
+      'description' => t('Ask a question to be submitted to an expert.'),
+      ),
+    'answer question' => array(
+      'title' => t('Answer a question'),
+      'description' => t('Answer a question submitted by someone asking.'),
+      ),
+    );
 }
 
 /**
- * Implementation of hook_access().
+ * Implements hook_node_access().
+ *
+ * @param string $op
+ *   The type of node access we are handling
+ * @param object $node
+ *   Node object we are checking the access to
+ * @param obhect $account
+ *   Account object of the current user
+ *
+ * @return boolean
+ *   TRUE if access is granted, FALSE if not.
  */
-function faq_ask_access($op, $node) {
-  global $user;
+function faq_ask_node_access($op, $node, $account) {
   // If node is already published, it's not ours any more.
   if ($node->status == 1) {
-    drupal_set_message('Already published.');
     return NULL;
   }
-  else {
-    drupal_set_message('Not published yet.');
-  }
   if ($op == 'create') {
-    return user_access(t('ask_question')) || user_access('answer question');
+    return user_access('ask question') || user_access('answer question');
   }
   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') || ($user->uid == $node->uid && $node->status == 0); 
+    return user_access('answer question') || $account->uid == $node->uid;
   }
 }
 
 /**
- * Implementation of hook_enable().
- *  This function reminds the user to configure the module.
+ * Determines whether the current user has one of the given permissions.
+ *
+ * @param string $string1
+ *   first permission string
+ * @param string $string2
+ *   second permission string
+ *
+ * @return boolean
+ *   TRUE if user has one of the given permissions, FALSE otherwise
  */
-function faq_ask_enable() {
-  if (_faq_ask_check_dependencies()) {
-    drupal_set_message(t('The Faq_Ask module has been enabled.') .' '. t('Please go to the <a href="!url">settings page</a> to configure this module.', array('!url' => url('admin/settings/faq/ask'))), 'notice');
-  }
+function faq_ask_user_access_or($string1, $string2) {
+  return user_access($string1) || user_access($string2);
 }
 
 /**
- * Implementation of hook_menu().
+ * Implements hook_menu().
+ *
+ * @return array
+ *   Menu structure for the various menus defined for the faq_ask module
+ *
  */
-function faq_ask_menu($may_cache) {
-  if (!_faq_ask_check_dependencies()) {
-    return array();
-  }
-
+function faq_ask_menu() {
   $items = array();
 
-  if ($may_cache) {
-    $items[] = array(
-      'path' => 'admin/settings/faq/ask', 
-      'title' => t('Experts'),
-      'callback' => 'drupal_get_form',
-      'callback arguments' => array('faq_ask_settings_form'),
-      'access' => user_access('administer faq'),
-      'description' => t('Allows the user to configure the Ask_FAQ module.'),
-      'type' => MENU_LOCAL_TASK,
-      'weight' => -2,
+  $items['admin/settings/faq/ask'] = array(
+    'title' => 'Experts',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('faq_ask_settings_form'),
+    'access arguments' => array('administer faq'),
+    'description' => 'Allows the user to configure the Ask_FAQ module.',
+    'type' => MENU_LOCAL_TASK,
+    'weight' => -2,
     );
 
-    $items[] = array(
-      'path' => 'faq_ask',
-      'title' => t('Ask a question'),
-      'callback' => 'faq_ask_page',
-      'access' => user_access('ask question'),
-      );
-  }
-  else {
-    $items[] = array(
-      'path' => 'faq_ask/answer',
-      'title' => t('Answer a question'),
-      'callback' => 'faq_ask_answer',
-      'access' => user_access('answer question'),
-      'type' => MENU_CALLBACK,
-      );
+  $items['faq_ask'] = array(
+    'title' => 'Ask a question',
+    'page callback' => 'faq_ask_page',
+    'access callback' => 'user_access',
+    'access arguments' => array('ask question'),
+    'weight' => 1,
+    );
 
-    $items[] = array(
-      'path' => 'faq_ask/edit',
-      'title' => t('Edit a question'),
-      'callback' => 'faq_ask_edit',
-//      'access' => user_access('answer question'),
-      'access' => user_access('access content'),
-      'type' => MENU_CALLBACK,
-      );
+  $items['faq_ask/%'] = array(
+    'page arguments' => array(1),
+    'access arguments' => array('ask question'),
+    'type' => MENU_CALLBACK,
+    );
 
-    $items[] = array(
-      'path' => 'faq_ask/more',
-      'title' => t('List more unanswered questions'),
-      'callback' => 'faq_ask_list_more',
-      'access' => user_access('answer question') || user_access('ask question'),
-      'type' => MENU_CALLBACK,
-      );
-  }
+  $items['faq_ask/answer/%node'] = array(
+    'title' => 'Answer a question',
+    'page callback' => 'faq_ask_answer',
+    'page arguments' => array(2),
+    'access arguments' => array('answer question'),
+    'type' => MENU_CALLBACK,
+    );
+
+  $items['faq_ask/edit/%node'] = array(
+    'title' => 'Edit a question',
+    'page callback' => 'faq_ask_edit',
+    'page arguments' => array(2),
+    'access arguments' => array('access content'),
+    'type' => MENU_CALLBACK,
+    );
+
+  $items['faq_ask/unanswered'] = array(
+    'title' => 'List more unanswered questions',
+    'page callback' => 'faq_ask_list_more',
+    'access callback' => 'faq_ask_user_access_or',
+    'access arguments' => array('answer question', 'ask question'),
+    'type' => MENU_CALLBACK,
+    );
 
   return $items;
 }
 
 /**
  * Get the ask question form.
+ *
+ * Obsolete? Doesn not seem to be called anywhere
+ *
+ * @return void
  */
 function faq_ask_page($tid = NULL) {
-  $output = NULL;
-  if ($tid) {
-    $term = taxonomy_get_term($tid);
-    $taxo_image = NULL;
-    if (module_exists('taxonomy_image')) {
-      $taxo_image = taxonomy_image_display($tid, 'align="left"');
-    }
-    $output .= '<table id="faq_ask_description"><tr><td>'. $taxo_image . filter_xss($term->description) .'</td></tr></table>';
-    $output .= '<div class="clear-block"></div>';
-  }
-  $output .= drupal_get_form('faq_ask_form', $tid, NULL);
-  return $output;
+  drupal_goto('node/add/faq', 'ask=TRUE');
 }
 
 /**
  * Get the edit question form.
+ *
+ * Checks for the permissions of the current user and redirects to the appropriate edit form.
+ *
+ * @param object $node
+ *   Node object of the node we are editing
+ *
+ * @return void
  */
-function faq_ask_edit($nid = NULL) {
+function faq_ask_edit($node) {
   global $user;
-  $node = node_load($nid);
   if ($node->status == 1) {
     drupal_set_message(t('That question has already been answered.'), 'status');
   }
   else {
     if ($user->uid == $node->uid) {
-      $form = drupal_get_form('faq_ask_form', NULL, $nid);
-      return $form;
+//      $form = drupal_get_form('faq_ask_form', NULL, $node);
+//      return $form;
+      drupal_goto("node/$node->nid/edit", 'ask=TRUE');
     }
     else {
       drupal_set_message(t('You are not allowed to edit that question.'), 'error');
@@ -178,296 +207,536 @@
 }
 
 /**
- * Implementation of hook_form().
- *  This is the "ask question" form.
+ * Implements hook_form_FORM_ID_alter().
+ *
+ * This is how we build the "ask question" form.
+ * @TODO: Make sure this is called after the taxonomy is added, so that we may delete or modify the taxonomy part of the form if we want to.
+ *
+ * @param array $form
+ *   The edit form to modify.
+ * @param array $form_state
+ *   Form state information
+ *
+ * @return array $form
+ *   Modified form as called by reference
  */
-function faq_ask_form($tid, $nid, $form_values = NULL) {
-  $form = array();
-  
-  // Find all the categories for which we have experts.
-  $cat_sql = db_rewrite_sql('SELECT DISTINCT(t.name), e.tid FROM {term_data} t JOIN {faq_expert} e USING (tid)', 't', 'tid');
-  $cat_list = array_flip(db_result_array(db_query($cat_sql)));
-  if (count($cat_list) == 0) {
-    $msg = t('Currently, there are no categories defined. ') .' ';
-    if (user_access('administer faq')) {
-      $msg .= t('Please go to the <a href="!url">settings page</a> to configure this module.', array('!url' => url('admin/settings/faq/ask')));
-    }
-    else {
-      $msg .= t('Please <a href="!url">ask your site administrator</a> to set up this feature.', array('!url' => url('user/1/contact')));
+function faq_ask_form_faq_node_form_alter(&$form, $form_state) {
+  if (!isset($_GET['ask'])) {
+      return;
     }
-    drupal_set_message($msg, 'error');
+  if ($_GET['ask'] != 1 && $_GET['ask'] != 'TRUE') {
+    return;
   }
 
-  // We will allow term suggestions only if the setting is chosen
-  //  AND there is a vocabulary named "FAQ."
-  $vid = db_result(db_query_range("SELECT vid FROM {vocabulary} WHERE name='FAQ'", 0, 1));
-  $suggest = variable_get('faq_ask_suggest', FALSE) && $vid;
-  
-  if ($suggest) {
-    $cat_list[0] = t('<suggest a category>');
-    $form['#multistep'] = TRUE;
-    $form['#redirect'] = FALSE;
-    $form['faq_vid'] = array(
-      '#type' => 'value',
-      '#value' => $vid,
-      );
-    if (!$tid) {
-      $default_tid = 0;
+  drupal_set_title(t('Ask a Question'));
+  // Set the published field off and make sure they can't override it.
+  $form['options']['status']['#default_value'] = FALSE;
+  $form['options']['status']['#disabled'] = TRUE;
+
+  // Get rid of the body elements (we'll dummy one later) and the menu elements.
+  unset($form['body_field'], $form['menu']);
+
+  // Check if only experts can categorize the question.
+  if (variable_get('faq_ask_categorize', FALSE)) {
+    unset($form['taxonomy']);
+  }
+  $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.'),
+        );
     }
   }
 
-  // If a nid exists, then get the existing values.
-  if ($nid) {
-    $node = node_load($nid);
-    $title = $node->title;
-    $taxo = array_keys($node->taxonomy);
-    $default_tid = $taxo[0];
-    $detailed_question = $node->detailed_question;
+  // Add validation of the e-mail field
+  if (isset($form['#validate'])) {
+    $temp_val = $form['#validate'];
+    $form['#validate'] = array($temp_val);
   }
   else {
-    $default_tid = $tid;
-    $title = NULL;
-    $detailed_question = NULL;
+    $form['#validate'] = array();
   }
+  $form['#validate'][] = 'faq_ask_form_validate';
 
-  $form['nid'] = array(
-    '#type' => 'value',
-    '#value' => $nid,
-  );
+  // Make sure we know we came from here.
+  $form['faq_ask'] = array('#type' => 'value', '#value' => TRUE);
+  $form['buttons']['submit']['#submit'][] = 'faq_ask_submit';
 
-  // Category.
-  $expert_categorize = variable_get('faq_ask_categorize', FALSE);
-  // Check if only experts can categorize the question.
-//  if (!$expert_categorize && user_access('answer question')) {
-  if (!$expert_categorize) {
-    $form['category'] = array(
-      '#title' => t('Category'),
-      '#type' => 'select',
-      '#options' => $cat_list,
-      '#default_value' => $default_tid,
-      '#required' => TRUE,
-      '#weight' => -3,
-      '#description' => t('Please select the correct category for your question.'),
-      );
-  }
-  else {
-    $form['category'] = array(
-      '#type' => 'value',
-      '#value' => -1,
-      );
+  // 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';
   }
 
-  if (isset($form_values)) {
-    if ($form_values['category'] == 0) {
-      $form['new_cat'] = array(
-        '#title' => t('Suggested Category'),
-        '#type' => 'textfield',
-        '#weight' => -1,
-        '#default_value' => NULL,
-        '#description' => t('Please enter your suggested category for the question.'),
-        );
-    }
-  }
+  // 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.');
+      }
+      else {
+        unset($form['taxonomy']);
+      }
 
-  // Question.
-  $question_length = variable_get('faq_question_length', 'short');
-   $cols = variable_get('faq_ask_title_len', 60);
-  // Long questions enabled.
-  $form['title'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Question Summary'),
-    '#required' => TRUE,
-    '#default_value' => $title,
-    '#weight' => 0,
-    '#cols' => $cols,
-    '#rows' => 5,
-    '#maxlength' => 256,
-    '#weight' => -1,
-    '#description' => t('Summarize your question here. It will be answered as soon as possible.'),
-    );
-  $form['detailed_question'] = array(
-    '#type' => 'textarea',
-    '#title' => t('Details'),
-    '#required' => true,
-    '#default_value' => $detailed_question,
-    '#weight' => 0,
-    '#cols' => $cols,
-    '#rows' => 5,
-    '#description' => t('Enter your question here. It will be answered as soon as possible.'),
-    );
+      // Shorter description on Qestion field + move it higher
+      $form['title']['#description'] = t('Question to be answered.');
+      $form['title']['#weight'] = '-5';
 
-  $form['send'] = array(
-    '#type' => 'submit',
-    '#value' => t('Send my question'),
-    '#weight' => 3,
-    );
+      // Shorter description on detailed question field
+      $form['detailed_question']['#description'] = t('Longer question text.');
 
-  return $form;
+    }
+  }
 }
 
 /**
- * Implementation of hook_form_submit().
- * This function gets the entered question and category and creates an unpublished FAQ node.
+ * Validation form for the FAQ Ask form
+ *
+ * Verifies that the e-mail entered seems to be a valid e-mail.
+ * Thanks to http://hokuten.net/2010/drupal-creating-an-e-mail-subscription-block/
+ *
+ * @param array $form
+ *   The edit form to validate.
+ * @param array $form_state
+ *   Form state information
+ *
+ * @return void
+ *
  */
-function faq_ask_form_submit($form_id, $form_values) {
-  global $user;
-  
-  $category = $form_values['category'];
-  if ($category == 0 && empty($form_values['new_cat'])) {
-    // Can only be 0 if allowing category suggestion.
+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.'));
+    }
   }
-  else {
-    if ($category == 0) {
-      // We have a new category to process.
-      $new_cat = $form_values['new_cat'];
-      $term = array('name' => $new_cat,
-        'description' => 'suggested by '. $user->name .' ('. $user->uid .') on '. date('F j, Y'),
-        'vid' => $form_values['faq_vid'],
-        'weight' => 0,
-        'parent' => 0,
-        'tid' => NULL,
-        );
-      taxonomy_save_term($term);
-      $term = (object)$term;
-      // Setting up the expert will be done in hook_taxonomy.
-    }
-    $term = taxonomy_get_term($category);
-
-    $node = array(
-      'type' => 'faq',
-      'body' => '',    /* Empty string rather than NULL. */
-      'title' => $form_values['title'],
-      'taxonomy' => $category >= 0 ? array($category => $term) : NULL,
-      'created' => time(),
-      'uid' => $user->uid,
-      'name' => $user->uid ? $user->name : variable_get('anonymous', t('Anonymous')),
-      'status' => 0,   /* Unpublished. */
-      'format' => 1,   /* Default filter (filtered HTML) */
-      'comment' => variable_get('comment_faq', 0),
-      'detailed_question' => (isset($form_values['detailed_question']) ? $form_values['detailed_question'] : ''),
-      );
-    $node_options = variable_get('node_options_'. $node['type'], array('status', 'promote'));
-    foreach (array('promote', 'sticky', 'revision') as $key) {
-      $node[$key] = in_array($key, $node_options) ? 1 : 0;
-    }
-
-    if ($form_values['nid']) {
-      $node['nid'] = $form_values['nid'];
-    }
-
-    // Okay, let's get it done. Node_submit will prepare it and make it an object.
-    $node = node_submit($node);
-    node_save($node);
-  
-    // Are we notifying the expert(s)?
-    if (variable_get('faq_ask_notify', FALSE)) {
-      // Find out who the experts are.
-      $result = db_query("SELECT u.mail FROM {faq_expert} e JOIN {users} u USING (uid) WHERE e.tid=%d", $category);
-      $to_addresses = array();
-      while ($expert = db_fetch_array($result)) {
-        $to_addresses[] = $expert['mail'];
-      }
-      $to = implode(', ', $to_addresses);
-
-      $from = variable_get('site_name', 'Drupal') .'<'. variable_get('site_mail', ini_get('sendmail_from')) .'>';
-      // Let's make this HTML mail because of the links we'll use.
-      $header = array(
-        'MIME-Version' => '1.0',
-        'Content-Type' => 'text/html; charset=UTF-8; format=flowed',
-        'Content-Transfer-Encoding' => '8Bit',
-        'X-Mailer' => 'Drupal'
-        );
+}
 
-      if ($category == -1) {
-        $body = t('The following question has been posted.');
+/**
+ * Implements hook_node_update().
+ *
+ * Checks if the node being updated is a question that has been answered
+ *
+ * @param object $node
+ *   Node object to update
+ *
+ */
+function faq_ask_node_update($node) {
+  if ($node->type == 'faq') {
+    // 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 and asker notified
+    $email = _faq_ask_get_faq_notification_email($node->nid);
+    if ($node->status == '1' && $email != '') {
+      // Get the asker account
+      $params['account'] = user_load_by_mail($email);
+      $params['question'] = $node->title;
+      $params['nid'] = $node->nid;
+
+      // 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 {
-        $body = t('The following question has been posted in the "!cat" category.', array('!cat' => filter_xss($term->name)));
+        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))
+            )
+          );
+      }
+    }
+  }
+}
+
+/**
+ * Handles the ask form submission
+ *
+ * @param array $form
+ *   The form being posted
+ *
+ * @param array $form_state
+ *   Array containing the posted values
+ *
+ */
+function faq_ask_submit($form, &$form_state) {
+  // Use only the first term entered in the correct vocabulary.
+  $vocabs = variable_get('faq_ask_vocabularies', 0);
+  if (isset($form_state['values']['taxonomy']['tags'])) {
+    foreach ($form_state['values']['taxonomy']['tags'] as $vid => $term_name) {
+      if (in_array($vid, $vocabs)) {
+        $term = taxonomy_get_term_by_name($term_name);
+        $category = $term->tid;
       }
-      $body .= "\n<br/><br/>". $form_values['title'];
-      // The URLs in the following are contructed as absolute addresses.
-      $body .= "\n<br/><br/>". t('In order to answer it you will first need to <a href="!url">login</a> to the site.', array('!url' => url('user', NULL, NULL, TRUE)));
-      $body .= "\n<br/>". t('Once logged in, you may proceed <a href="!url">directly to the question</a> to answer it.', array('!url' => url('faq_ask/answer/'. $node->nid, NULL, NULL, TRUE)));
-    
-      $mail_sent = drupal_mail('expert-notify', $to, t('You have a question waiting'), $body, $from, $header);
+    }
+  }
+  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' => $form_state['title'],
+      'nid' => $form_state['nid'],
+      'creator' => theme('username', $node, array('plain' => TRUE)),
+      );
+    // Find out who the experts are.
+//    $result = db_query('SELECT uid FROM {faq_expert} WHERE tid=%d', $category);
+    $experts = db_select('faq_expert')->addField('faq_expert', 'uid')->condition('tid', $category)->execute()->fetchAll();
+    foreach ($experts as $expert) {
+      $account = user_load($expert['uid']);
+      $params['account'] = $account;
+      $mail_sent = drupal_mail('faq_ask', 'notify_expert', $account->mail, user_preferred_language($account), $params);
       if ($mail_sent) {
-        watchdog('FAQ_Ask', t('Expert notification email sent.') .' '. $to, WATCHDOG_NOTICE);
+        watchdog('FAQ_Ask', 'Expert notification email sent to @to',
+          array('@to' => $account->mail), WATCHDOG_NOTICE);
       }
       else {
-        $msg = t('Expert notification email failed for the "!cat" category.', array('!cat' => filter_xss($term->name)));
-        watchdog('FAQ_Ask', $msg .' '. $to, WATCHDOG_ERROR);
-        drupal_set_message($msg, 'notice');
+        watchdog('FAQ_Ask', 'Expert notification email to @to failed for the "@cat" category.',
+          array('@to' => $account->mail, '@cat' => check_plain($term->name)), WATCHDOG_ERROR);
+        drupal_set_message(t('Expert notification email failed for the "!cat" category.', array('!cat' => check_plain($term->name))));
       }
     }
+  }
 
-    // Quick detour to see if the block is enabled.
-    // Slight flaw here: There may be more than one theme enabled, but this just gets the first one,
-    // which may not be the current theme.
-    if (user_access('answer question')) {
-      $region = db_result(db_query_range("SELECT region FROM {blocks} WHERE module='faq_ask' AND delta=0 AND status=1", 0, 1));
+  // 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');
+
+    // If this user is not registered as a user before - check if all asking anonymous users should be added to the newsletter list
+    if (module_exists('simplenews') && $tid = variable_get('faq_ask_notify_asker_simplenews_tid', '0')) {
+      // If we have selected a newsletter to add
+      if (function_exists('simplenews_subscribe_user')) {
+        simplenews_subscribe_user($form_state['values']['faq-email'], $tid,  variable_get('faq_ask_notify_asker_simplenews_confirm', 1), 'FAQ-Ask');
+      }
     }
-    else {
-      $region = NULL;
+  }
+  elseif (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');
     }
-    if ($region) {
-        switch ($region) {
-          case 'left':
-            $region_name = t('left side');
-            break;
-          case 'right':
-            $region_name = t('right side');
-            break;
-          case 'header':
-            $region_name = t('top');
-            break;
-          case 'footer':
-            $region_name = t('bottom');
-            break;
-          default:
-            $region_name = '';
-            break;
-        }
-        if ($region_name) {
-          $msg = t('It should appear in the list at the @region of the screen momentarily.', array('@region' => $region_name));
+  }
+  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');
+  }
+}
+
+/**
+ * Implements 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 ($notification = db_select('node')->fields(array('title', 'status'))->condition('nid', $nid)->execute()->fetchAssoc()) {
+
+      if ($notification['status'] == '1') {
+
+      $params = array(
+        'question' => $notification['title'],
+        'nid' => $nid,
+        'account' => user_load_by_email($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 {
-          $msg = t('It should appear in the list momentarily.');
+          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
+ *
+ * @param integer $nid
+ *   The node Id where the e-mail is assoiciated
+ *
+ * @return string
+ *   Email associated with the node given by $nid
+ *
+ */
+function _faq_ask_get_faq_notification_email($nid) {
+
+  return db_select('faq_ask_notify')->fields('email')->condition('nid', $nid)->execute()->fetchField();
+}
+
+/**
+ * Helper function fetching all notifications
+ *
+ * @TODO: optimise to query for all the relevant notifications = those who have a node that is published
+ *
+ * @return array
+ *   Array containing all outstanding notifications
+ */
+function _faq_ask_get_faq_notifications() {
+
+  return db_select('faq_ask_notify')->fields(array('nid', 'email'))->execute()->fetchAllAssoc('nid');
+
+}
+
+/**
+ * Helper function to set a notification associated with a node
+ *
+ * @param integer $nid
+ *   Node Id of the question to associate an e-mail address to
+ * @param string $email
+ *   Email address to associate with the question and to send the notification to when answered
+ *
+ */
+function _faq_ask_set_faq_notification($nid, $email) {
+
+  $inserted = db_insert('faq_ask_notify')
+    ->fields(array( 'nid' => $nid, 'email' => $email))
+    ->execute();
+
+  if ($inserted == 0) {
+    drupal_set_message(t('Attempt to insert email notification failed.'), 'error');
+  }
+
+}
+
+/**
+ * Helper function to remove a notification from a question
+ *
+ * @param integer $nid
+ *   The Node Id to remove the notification from
+ *
+ */
+function _faq_ask_delete_faq_notification($nid) {
+  $deleted = db_delete('faq_ask_notify')->condition('nid', $nid)->execute();
+  if ($deleted == 0) {
+    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
+ *
+ * @return array
+ *   Block content
+ *
+ */
+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 {
-      $msg = NULL;
+      unset($_GET['ask']);
     }
-    drupal_set_message(t('Your question has been submitted.') .' '. $msg, 'notice');
-  
-    drupal_goto('faq/'. $category);
+    unset($_GET['block']);
+
+    return $form;
+  }
+  else {
+    return '';
+  }
+
+}
+
+
+/**
+ * Implements hook_mail().
+ *
+ * This function completes the email, allowing for placeholder substitution.
+ * Done: notify_asker. stenjo
+ * @TODO: define messages & subjects on settings page, with list of tokens. how to handle newlines?
+ *
+ * @param string $key
+ *   What type of e-mail are we sending?
+ * @param array $message
+ *   The message array to be sendt
+ * @param array $params
+ *   Additional parameters for placeholders in e-mail text.
+ *
+ * @return array $message
+ *   As passed by reference
+ *
+ */
+function faq_ask_mail($key, &$message, $params) {
+  $newline = "\n<br/><br/>";
+  $body = array();
+  $message['headers']['Content-Type'] = 'text/html; charset=UTF-8; format=flowed';
+  $language = $message['language'];
+  $variables = user_mail_tokens($params['account'], $language);
+  switch ($key) {
+    case 'notify_expert':
+      $variables = array_merge($variables, array(
+        '!cat' => $params['category'],
+        '@question' => $params['question'],
+        '!answer_uri' => url('faq_ask/answer/' . $params['nid'], array('absolute' => TRUE)),
+        '!asker' => $params['creator'],
+        ));
+
+      $subject = t('You have a question waiting on !site', $variables, $language->language);
+      $body[]= t('Dear !username,', $variables, $language->language);
+      if ($params['category'] == -1) {
+        $body[] = t('The following question has been posted.', NULL, $language->language);
+      }
+      else {
+        $body[] = t('The following question has been posted in the "!cat" category by !asker.', $variables, $language->language);
+      }
+      $body[] = t('<i>@question</i>', $variables, $language->language);
+      $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;
 }
 
 /**
- * Implementation of hook_form().
+ * Implements hook_form().
+ *
  * This form allows the users to select the expert roles and to which categories the users in those roles are assigned.
  * Note, the expert/category table attempts to use the least horizontal space,
- *  so it can "flip" based on whether there are more categories or experts. 
+ * so it can "flip" based on whether there are more categories or experts.
+ *
+ * @param array $form_state
+ *
  */
-function faq_ask_settings_form($op = NULL, $aid = NULL) {
+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);
 
-  if (!variable_get('faq_use_categories', FALSE)) {
-    drupal_set_message(t('The Faq_Ask module requires that FAQ "Categorize questions." Please go to the <a href="!url">settings page</a> to configure this module.', array('!url' => url('admin/settings/faq/categories'))), 'error');
+  $faq_use_categories = variable_get('faq_use_categories', FALSE);
+  if (!$faq_use_categories) {
+    drupal_set_message(t('The Faq_Ask module requires that FAQ "Categorize questions."') . ' ' . t('Please go to the <a href="!url">settings page</a> to configure this module.', array('!url' => url('admin/settings/faq/categories'))), 'error');
     return $form;
     }
 
   // Get the list of vocabularies that apply to FAQ s.
   $vocabs = taxonomy_get_vocabularies('faq');
   if (count($vocabs) == 0) {
-    drupal_set_message(t('The Faq_Ask module requires that at least one vocabulary apply to the "faq" content type.'), 'error');
+    drupal_set_message(t('The Faq_Ask module requires that at least one vocabulary apply to the "faq" content type. Please go to the Taxonomy <a href="!taxo_uri">configuration page</a> to do this.', array('!taxo_uri' => url('admin/content/taxonomy'))), 'error');
     return $form;
   }
-  
+
   // Get the admin's name.
-  $admin = ucwords(db_result(db_query('SELECT name FROM {users} WHERE uid=1')));
+  //$admin = ucwords(db_result(db_query('SELECT name FROM {users} WHERE uid=1')));
+  $admin = ucwords(db_select('users')->addField('users', 'name')->condition('uid', 1)->execute()->fetchField());
+
+  // Get the Simplenews newsletters if they exists
+  $newsletters = array('0' => t('No newsletter'));
+
+  if (module_exists('simplenews')) {
+    if (!function_exists('simplenews_get_newsletters')) {
+      drupal_set_message(t('The Simplenews integration is not compatible with this version of Simplenews. Please download a later version.'), 'error');
+    }
+    else {
+      $list = simplenews_get_newsletters(variable_get('simplenews_vid', ''));
+      foreach ($list as $key => $object) {
+        $list[$key] = $object->name;
+      }
+      $newsletters += $list;
+    }
+  }
 
   $form['notification'] = array(
     '#type' => 'fieldset',
@@ -483,6 +752,46 @@
     '#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),
+    );
+
+  // If the Simplenews module is loaded we can add functionality to add anonymous askers to a newsletter
+  $form['notification']['notify_asker']['faq_ask_notify_asker_simplenews'] = array(
+    '#type' => 'select',
+    '#title' => t('Add anonymous asker to newsletter'),
+    '#default_value' => variable_get('faq_ask_notify_asker_simplenews_tid', '0'),
+    '#options' => $newsletters,
+    '#description' => (module_exists('simplenews') ? t('Select a newsletter you want anonymous askers to be assigned to.') : t('This functionality needs the <a href="http://drupal.org/project/simplenews">Simplenews module</a> to be activated.')),
+    '#disabled' => !module_exists('simplenews'),
+    );
+
+  $form['notification']['notify_asker']['faq_ask_notify_asker_simplenews_confirm'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Confirm subscription to newsletter'),
+    '#description' => t('If this box is checked, the asker creating the question will be asked to confirm the subscription of the newsletter.'),
+    '#default_value' => variable_get('faq_ask_notify_asker_simplenews_confirm', 1),
+    '#disabled' => !module_exists('simplenews'),
+    );
+
   $form['options'] = array(
     '#type' => 'fieldset',
     '#title' => t('Options'),
@@ -510,27 +819,22 @@
     '#default_value' => variable_get('faq_ask_expert_own', 0),
     );
 
-  $form['options']['faq_ask_suggest'] = array(
-    '#type' => 'checkbox',
-    '#title' => t('Allow "Suggest a category"'),
-    '#description' => t('If this box is checked, the person asking a question will have an option to enter a new category. It will have the default expert assigned to it until you return here to correct the assignment.'),
-    '#default_value' => variable_get('faq_ask_suggest', FALSE),
-    );
-
-  $form['options']['advice'] = array(
-    '#type' => 'fieldset',
-    '#title' => t('Advice'),
-    '#description' => t('This text will be shown at the bottom of the "Unanswered questions" block.'),
-    '#collapsible' => TRUE,
-    '#collapsed' => FALSE,
+  $form['options']['faq_ask_unanswered'] = array(
+    '#type' => 'textarea',
+    '#title' => t('Default unanswered body text'),
+    '#cols' => 60,
+    '#rows' => 1,
+    '#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']['advice']['faq_ask_expert_advice'] = array(
+  $form['options']['faq_ask_expert_advice'] = array(
     '#type' => 'textarea',
-    '#title' => t('Advice for the expert'),
+    '#title' => t('Answer advice for the expert'),
     '#cols' => 60,
     '#rows' => 1,
-    '#default_value' => variable_get('faq_ask_expert_advice', _faq_ask_advice_default('expert')),
+    '#description' => t('This text will be shown at the bottom of the "Unanswered questions" block.'),
+    '#default_value' => variable_get('faq_ask_expert_advice', _faq_ask_advice_default()),
     );
 
     $form['options']['advice']['faq_ask_admin_advice'] = array(
@@ -543,7 +847,7 @@
 
     $form['options']['advice']['faq_ask_asker_advice'] = array(
     '#type' => 'textarea',
-    '#title' => t('Advice for an administrator/editor'),
+    '#title' => t('Advice for an asker'),
     '#cols' => 60,
     '#rows' => 1,
     '#default_value' => variable_get('faq_ask_asker_advice', _faq_ask_advice_default('asker')),
@@ -559,15 +863,6 @@
     '#default_value' => $help_default,
     );
 
-  $title_opts = drupal_map_assoc(array(20, 30, 40, 50, 60, 70, 80, 90, 100, 128));
-  $form['options']['faq_ask_title_len'] = array(
-    '#type' => 'select',
-    '#options' => $title_opts,
-    '#title' => t('Question Box Length'),
-    '#description' => t('This sets the length of the question box (not the question itself). This affects only the FAQ_Ask module, not the FAQ display. The recommendation is to set it as wide as your theme will allow it. Note: If resizable textareas are enabled, this setting will have no effect.'),
-    '#default_value' => variable_get('faq_ask_title_len', 60),
-    );
-
   $form['experts'] = array(
     '#type' => 'fieldset',
     '#title' => t('Experts'),
@@ -575,10 +870,11 @@
     '#collapsed' => FALSE,
     );
 
-  // Use list of vocabularies gotten above.
+  // Use the list of vocabularies from above.
   if (count($vocabs) == 1) {
     // Single vocabulary, don't bother with a selection box, just set it.
     $vid = key($vocabs);
+    $def_vid = $vid;
     variable_set('faq_ask_vocabularies', array($vid => $vid));
     $vobj = $vocabs[$vid];
     $free = $vobj->tags;
@@ -586,14 +882,12 @@
   else {
     // Multiple vocabs available.
     $voc_list = array();
-    $def_vid = 0;
-    $free = FALSE;
+    $def_vid = 0;  // variable_get('faq_ask_vocabularies', 0)?
     foreach ($vocabs as $vid => $vobj) {
       $voc_list[$vid] = $vobj->name;
       if ($vobj->name == 'FAQ') {
         $def_vid = $vid;
       }
-      $free = $free || ($vobj->tags);
     }
     $form['experts']['faq_ask_vocabularies'] = array(
       '#type' => 'select',
@@ -602,51 +896,59 @@
       '#multiple' => TRUE,
       '#default_value' => variable_get('faq_ask_vocabularies', $def_vid),
       '#description' => t('Only the terms from the selected vocabularies will be included in the list below.')
-        .' '. t("Simply adding the 'FAQ' content type to a vocabulary will not make it eligible for experts; you must return to here to add it.")
-        .'<br/><big>'. t('If you select different vocabularies, you must save the configuration BEFORE selecting users below.') .'</big>',
+        . ' ' . t("Simply adding the 'FAQ' content type to a vocabulary will not make it eligible for experts; you must return to here to add it.")
+        . '<br/><big>' . t('If you select different vocabularies, you must save the configuration BEFORE selecting users below.') . '</big>',
       );
   } // End multiple vocabs.
 
-  if ($free) {
-    $msg = t('Free tagging vocabularies are not allowed for Faq_Ask.');
-    drupal_set_message($msg, 'error');
-    $form['experts']['error'] = array(
-      '#type' => 'item',
-      '#value' => '<big><big>'. $msg .'</big></big>'
-      );
-    return $form;
-  }
-
   // Changed query and loop because it failed if 'answer' was the first perm in list.
   // This should be faster any way.
-  $role_list = db_result_array(db_query("SELECT r.rid, r.name FROM {role} r JOIN {permission} p USING (rid) WHERE p.perm LIKE '%%answer question%%'"));
+  //$r_res = db_query("SELECT r.rid, r.name FROM {role} r JOIN {permission} p USING (rid) WHERE p.perm LIKE '%%answer question%%'");
+  $role_list = db_select('role', 'r')
+    ->join('permission', 'p', 'r.rid = p.rid')
+    ->condition('p.perm', '%%answer question%%', 'LIKE' )
+    ->fields('r', array('rid', 'name'))
+    ->execute()
+    ->fetchAllAssoc('r.rid');
+
   if (empty($role_list)) {
-    drupal_set_message(t('No roles with "answer question" permission were found; only !admin is currently eligible to be an expert. You may want to go to the <a href="!access">Access Control page</a> to update your permissions.', array('!access' => url('admin/user/access'), '!admin' => $admin)), 'warning');
+    drupal_set_message(t('No roles with "answer question" permission were found; only !admin is currently eligible to be an expert. You may want to go to the <a href="!access">Permissions page</a> to update your permissions.',
+        array('!access' => url('admin/user/permissions'), '!admin' => $admin),
+        array('langcode' => 'en')),
+      'error');
   }
 
   // Get all terms associated with FAQ.
   //$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);
+
+//  $result = db_query('SELECT td.tid, td.name, td.description FROM {taxonomy_term_data} td WHERE td.vid IN (' . db_placeholders($vocabs_array) . ') ORDER BY td.weight ASC, td.name ASC', $vocabs_array);
+  $result = db_select('taxonomy_term_data', 'td')
+    ->condition('td.vid', $vocabs_array, 'IN')
+    ->fields('td', array('tid', 'name'))
+    ->orderBy('td.weight')->orderBy('td.name')
+    ->execute()
+    ->fetchAllAssoc();
 //  $result = db_query("SELECT td.tid, td.name, td.description FROM {term_data} td WHERE td.vid IN (". db_placeholders($vocabs) .") ORDER BY td.weight ASC, td.name ASC", $vocabs);
 
   $faq_terms = array();
-  while ($term = db_fetch_array($result)) {
+  foreach ($result as $term) {
+//  while ($term = db_fetch_array($result)) {
     // Show term hierarchy?
-    $term_name = /* str_repeat('--', $term['depth']) . */ $term['name'];
+    $term_name = /* str_repeat('--', $term['depth']) . */ check_plain($term['name']);
     if (substr($term['description'], 0, 9) == 'suggested') {
-      $faq_terms[$term['tid']] = $term_name .'<br/>--<small>'. strip_tags($term['description']) .'</small>';
+      $faq_terms[$term['tid']] = $term_name . '<br/>--<small>' . strip_tags($term['description']) . '</small>';
     }
     else {
       $faq_terms[$term['tid']] = $term_name;
     }
   }
   if (count($faq_terms) == 0) {
-    drupal_set_message(t('No vocabularies or terms were found for the "faq" content type . Please go to the <a href="!access">Categories page</a> to update your vocabulary.', array('!access' => url('admin/content/taxonomy'))), 'warning');
+    drupal_set_message(t('No vocabularies or terms were found for the "faq" content type . Please go to the <a href="!access">Categories page</a> to update your vocabulary.', array('!access' => url('admin/content/taxonomy'))), 'error');
+    return $form;
   }
 
   // Get all users associated with the roles.
@@ -659,22 +961,29 @@
     if (in_array(DRUPAL_AUTHENTICATED_RID, $rids)) {
       // Authenticated users may be experts, so get all active users.
       // No other roles matter.
-      $result = db_query("SELECT u.uid, u.name FROM {users} u WHERE status=1");
+      //$result = db_query("SELECT u.uid, u.name FROM {users} u WHERE status=1");
+      $result = db_select('users', 'u')->condition('status', 1)->fields('u', array('uid', 'name'))->execute()->fetchAllKeyed();
+
     }
     else {
       // Only specific roles may be experts.
-      $result = db_query("SELECT DISTINCT(u.uid), u.name FROM {users_roles} ur JOIN {users} u USING (uid) WHERE ur.rid IN (". db_placeholders($rids) .")", $rids);
+      //$result = db_query('SELECT DISTINCT(u.uid), u.name FROM {users_roles} ur JOIN {users} u USING (uid) WHERE ur.rid IN (' . db_placeholders($rids) . ')', $rids);
+      $result = db_select('user_roles', 'ur')->join('users', 'u', 'ur.uid = u.uid')->distinct()->condition('ur.rid', $rids, 'IN')->fields('u', 'uid', 'name')->execute()->fetchAllKeyed();
     }
-    while ($user = db_fetch_array($result)) {
-      if ($user['uid'] != 1) {
-        $faq_expert_names[$user['uid']] = ucwords($user['name']);
+    foreach ($result as $uid => $name) {
+      if ($uid != 1) {
+        $faq_expert_names[$uid] = ucwords($name);
       }
     }
-
+    //while ($user = db_fetch_array($result)) {
+    //  if ($user['uid'] != 1) {
+    //    $faq_expert_names[$user['uid']] = ucwords($user['name']);
+    //  }
+    //}
     // Put them in alphabetical order.
     asort($faq_expert_names);
   }
-  
+
   if (!empty($role_list)) {
     $form['experts']['faq_expert_role'] = array(
       '#type' => 'select',
@@ -682,7 +991,7 @@
       '#options' => $role_list,
       '#multiple' => TRUE,
       '#default_value' => variable_get('faq_expert_role', '2'),
-      '#description' => t('User 1 (@admin) will always be in the list, regardless of roles.', array('@admin' => $admin)) .'<br/><big>'. t('If you select different roles, you must save the configuration BEFORE selecting users below.') .'</big>',
+      '#description' => t('User 1 (@admin) will always be in the list, regardless of roles.', array('@admin' => $admin)) . '<br/><big>' . t('If you select different roles, you must save the configuration BEFORE selecting users below.') . '</big>',
       );
   }
 
@@ -691,79 +1000,92 @@
   // If there is only one eligible expert, we might as well preset all categories.
   $expert_msg = NULL;
   $only_one_expert = (count($faq_expert_names) == 1);
-  
+
   $count = 0;
   if ($more_experts_than_terms) {
     // Experts go down the left; terms go across the top.
     $top = NULL;
     if ($only_one_expert) {
-      $top .= '<p>'. t('Note: Even though the check boxes below are checked, you must still click the "Save configuration" button to save the expert settings.') .'</p>';
+      $top .= '<p>' . t('Note: Even though the check boxes below are checked, you must still click the "Save configuration" button to save the expert settings.') . '</p>';
     }
-    $top .= '<table id="faq_experts"><tr><th> </th><th>'. implode('</th><th>', $faq_terms) .'</th></tr>';
+    $top .= '<table id="faq_experts"><tr><th> </th><th>' . implode('</th><th>', $faq_terms) . '</th></tr>';
     if ($only_one_expert) {
-      $top .= '<tr><td colspan="100">'. t('Note: Even though the check boxes below are checked, you must still click the "Save configuration" button to save the expert settings.') .'</td></tr>';
+      $top .= '<tr><td colspan="100">' . t('Note: Even though the check boxes below are checked, you must still click the "Save configuration" button to save the expert settings.') . '</td></tr>';
     }
     foreach ($faq_expert_names as $uid => $name) {
       ++$count;
       $class = $count & 1 ? 'odd' : 'even';
-      $left = '<tr class="'. $class .'"><td><strong>'. $name .'</strong></td>';
+      $left = '<tr class="' . $class . '"><td><strong>' . $name . '</strong></td>';
       foreach ($faq_terms as $tid => $term_name) {
-        $box_name = 'expert_'. $uid .'_'. $tid;
+        $box_name = 'expert_' . $uid . '_' . $tid;
         $form['experts'][$box_name] = array(
           '#type' => 'checkbox',
           '#default_value' => $only_one_expert,
-          '#prefix' => $top . $left .'<td align="center">',
+          '#prefix' => $top . $left . '<td align="center">',
           '#suffix' => '</td>',
           );
         $top = NULL;
-        $left = NULL;  
+        $left = NULL;
       }
-    $form['experts'][$box_name]['#suffix'] .= '</tr>';  
+    $form['experts'][$box_name]['#suffix'] .= '</tr>';
     }
-    $form['experts'][$box_name]['#suffix'] .= '</table>';  
+    $form['experts'][$box_name]['#suffix'] .= '</table>';
   }
   else {
     // Experts go across the top; terms go down the left.
     $top = NULL;
     if ($only_one_expert) {
-      $top .= '<p>'. t('Note: Even though the check boxes below are checked, you must still click the "Save configuration" button to save the expert settings.') .'</p>';
+      $top .= '<p>' . t('Note: Even though the check boxes below are checked, you must still click the "Save configuration" button to save the expert settings.') . '</p>';
     }
-    $top .= '<table id="faq_experts"><tr><th> </th><th>'. implode('</th><th>', $faq_expert_names) .'</th></tr>';
+    $top .= '<table id="faq_experts"><tr><th> </th><th>' . implode('</th><th>', $faq_expert_names) . '</th></tr>';
     foreach ($faq_terms as $tid => $term_name) {
       ++$count;
       $class = $count & 1 ? 'odd' : 'even';
-      $left = '<tr class="'. $class .'"><td><strong>'. $term_name .'</strong></td>';
+      $left = '<tr class="' . $class . '"><td><strong>' . $term_name . '</strong></td>';
       foreach ($faq_expert_names as $uid => $name) {
-        $box_name = 'expert_'. $uid .'_'. $tid;
+        $box_name = 'expert_' . $uid . '_' . $tid;
         $form['experts'][$box_name] = array(
           '#type' => 'checkbox',
           '#default_value' => $only_one_expert,
-          '#prefix' => $top . $left .'<td align="center">',
+          '#prefix' => $top . $left . '<td align="center">',
           '#suffix' => '</td>',
           );
         $top = NULL;
-        $left = NULL;  
+        $left = NULL;
       }
-    $form['experts'][$box_name]['#suffix'] .= '</tr>';  
+    $form['experts'][$box_name]['#suffix'] .= '</tr>';
     }
-    $form['experts'][$box_name]['#suffix'] .= '</table>';  
+    $form['experts'][$box_name]['#suffix'] .= '</table>';
   }
 
   $form['experts'][$box_name]['#suffix'] .= t('Those who will be answering questions will need both "answer question" and "edit faq" permissions.');
 
-  $result = db_query("SELECT * FROM {faq_expert}");
-  while ($expert = db_fetch_array($result)) {
-    $box_name = 'expert_'. $expert['uid'] .'_'. $expert['tid'];
+  //$result = db_query("SELECT * FROM {faq_expert}");
+  $result = db_select('faq_expert')->fields('faq_expert')->execute()->fetchAll();
+  foreach ($result as $expert) {
+    $box_name = 'expert_' . $expert['uid'] . '_' . $expert['tid'];
     if (isset($form['experts'][$box_name])) { // Might not be present any more.
       $form['experts'][$box_name]['#default_value'] = TRUE;
     }
     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');
       }
     }
   }
+  //while ($expert = db_fetch_array($result)) {
+  //  $box_name = 'expert_' . $expert['uid'] . '_' . $expert['tid'];
+  //  if (isset($form['experts'][$box_name])) { // Might not be present any more.
+  //    $form['experts'][$box_name]['#default_value'] = TRUE;
+  //  }
+  //  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');
+  //    }
+  //  }
+  //}
 
   if ($only_one_expert) {
     // Create a form value to set default expert to admin.
@@ -781,9 +1103,9 @@
       '#description' => t('The selected user will be assigned as the expert for all terms that are added to the selected vocabularies until you return to this page and update it.'),
       '#default_value' => variable_get('faq_ask_default_expert', 1),
       );
-  } 
+  }
 
-  // Get rid of generic error message.
+  // Get rid of error element.
   unset($form['error']);
   $form['submit'] = array(
     '#type' => 'submit',
@@ -795,52 +1117,75 @@
 }
 
 /**
- * Implementation of hook_form_submit.
+ * Implements hook_form_submit().
+ *
  * It saves the expert roles that were selected, then rebuilds the expert/category table.
  */
-function faq_ask_settings_form_submit($form_id, $form_values) {
+function faq_ask_settings_form_submit($form, &$form_state) {
   // Save the simple stuff.
-  variable_set('faq_expert_role', $form_values['faq_expert_role']);
-  variable_set('faq_ask_vocabularies', $form_values['faq_ask_vocabularies']);
-  variable_set('faq_ask_title_len', $form_values['faq_ask_title_len']);
-  variable_set('faq_ask_categorize', $form_values['faq_ask_categorize']);
-  variable_set('faq_ask_expert_own', $form_values['faq_ask_expert_own']);
-  variable_set('faq_ask_suggest', $form_values['faq_ask_suggest']);
-  variable_set('faq_ask_notify', $form_values['faq_ask_notify']);
-  variable_set('faq_ask_default_expert', $form_values['faq_ask_default_expert']);
-  variable_set('faq_ask_expert_advice', $form_values['faq_ask_expert_advice']);
-  variable_set('faq_ask_help_text', $form_values['faq_ask_help_text']);
-  variable_set('faq_ask_admin_advice', $form_values['faq_ask_admin_advice']);
-  variable_set('faq_ask_asker_advice', $form_values['faq_ask_asker_advice']);
+  if (isset($form_state['values']['faq_expert_role'])) {
+    variable_set('faq_expert_role', $form_state['values']['faq_expert_role']);
+  }
+  if (isset($form_state['values']['faq_ask_vocabularies'])) {
+    variable_set('faq_ask_vocabularies', $form_state['values']['faq_ask_vocabularies']);
+  }
+  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_asker_simplenews_tid', $form_state['values']['faq_ask_notify_asker_simplenews']);
+  variable_set('faq_ask_notify_asker_simplenews_confirm', $form_state['values']['faq_ask_notify_asker_simplenews_confirm']);
+  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']);
+  variable_set('faq_ask_help_text', $form_state['values']['faq_ask_help_text']);
+  variable_set('faq_ask_admin_advice', $form_state['values']['faq_ask_admin_advice']);
+  variable_set('faq_ask_asker_advice', $form_state['values']['faq_ask_asker_advice']);
 
   // Get all the selected expert/category options.
   // First, we'll include the default expert for tid=0.
-  $values = array('('. $form_values['faq_ask_default_expert'] .', 0)');
-  foreach ($form_values as $name => $value) {
+  $values = array();
+  $values[] = array('nid' => $form_state['values']['faq_ask_default_expert'], 'tid' => 0);
+  foreach ($form_state['values'] as $name => $value) {
     if (substr($name, 0, 7) == 'expert_') {
       list($junk, $uid, $tid) = explode('_', $name);
       if ($value) {
-        $values[] = '('. $uid .', '. $tid .')';
+        $values[] = array('uid' => $uid, 'tid' => $tid);
       }
     }
   }
-  $vals = implode(', ', $values);
-
   // Delete the current values and save the new ones.
   if (!empty($values)) {
-    db_query('TRUNCATE {faq_expert}');
-    db_query("INSERT INTO {faq_expert} (uid, tid) VALUES %s", $vals);
+//    db_query('TRUNCATE {faq_expert}');
+    db_delete('faq_expert')->execute();
+//    db_query("INSERT INTO {faq_expert} (uid, tid) VALUES %s", $vals);
+    db_insert('faq_expert')
+      ->fields('faq_expert', array('uid', 'tid'))
+      ->values($values)
+      ->execute();
   }
 
-  drupal_set_message(t('Configuration has been updated.'), 'notice');
+  drupal_set_message(t('Configuration has been updated.'), 'status');
 }
 
 /**
  * This function is called when an expert selects a question to answer.
+ *
  * It changes the status option to "published" then goes to the regular FAQ edit function.
  */
-function faq_ask_answer($nid) {
-  $node = node_load(array('nid' => $nid));
+function faq_ask_answer($node) {
+  global $user;
+  // Validate the request.
+  if (!isset($_REQUEST['token']) || !drupal_valid_token($_REQUEST['token'], "faq_ask/answer/$node->nid")) {
+    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);
+    drupal_access_denied();
+    return;
+  }
+
   $reassign_opt = variable_get('faq_ask_expert_own', 0);
   // Check if we need to reassign to the expert.
   switch ($reassign_opt) {
@@ -858,10 +1203,11 @@
       break;
   }
   // Change the status to published and the user id, if needed.
-  db_query("UPDATE {node} SET status=1, uid=%d WHERE nid=%d", $node->uid, $node->nid);
-  
+  //db_query("UPDATE {node} SET status=1, uid=%d WHERE nid=%d", $node->uid, $node->nid);
+  db_update('node')->fields('node', array('status' => 1, 'uid' => $node->uid))->conditions('nid', $node->nid)->execute();
+
   // Need to invoke node/##/edit.
-  drupal_goto('node/'. $nid .'/edit');
+  drupal_goto("node/$node->nid/edit");
 }
 
 /**
@@ -874,17 +1220,20 @@
 }
 
 /**
- * Implementation of hook_taxonomy.
- *  @param:
- *    op:  'insert', 'update, 'delete'
- *    type: 'term', 'vocabulary'
- *    array: depends on other two.
+ * Implements hook_taxonomy().
+ *
+ * @param string $op
+ *   the actions to be handled: 'insert', 'update, 'delete'.
+ * @param string $type
+ *   The type of taxonomy to handle: 'term', 'vocabulary'
+ * @param array $edit
+ *    depends on other two.
  */
-function faq_ask_taxonomy($op, $type, $array = NULL) {
+function faq_ask_taxonomy($op, $type, $edit = NULL) {
   global $user;
   $default_expert = variable_get('faq_ask_default_expert', 1);
   $my_vocs = variable_get('faq_ask_vocabularies', array());
-  $vid = $array['vid'];
+  $vid = $edit['vid'];
   // See if it's one of our vocabularies.
   $our_vocab = in_array($vid, $my_vocs);
 
@@ -894,53 +1243,54 @@
         case 'term':
           // term: set default expert.
           if ($our_vocab) {
-            $insert = db_query("INSERT INTO {faq_expert} (uid, tid) VALUES (%d, %d)", $default_expert, $array['tid']);
-            if ($insert === FALSE) {
+            //$insert = db_query("INSERT INTO {faq_expert} (uid, tid) VALUES (%d, %d)", $default_expert, $edit['tid']);
+            $inserted = db_insert('faq_expert')->fields('faq_expert', array('uid' => $default_expert, 'tid' => $edit['tid']))->execute();
+            if ($inserted == 0) {
               drupal_set_message(t('Attempt to assign expert failed.'), 'error');
             }
             else {
-              drupal_set_message(t('Assigned expert @expert to @name (@tid).', array('@expert' => $default_expert, '@name' => $array['name'], '@tid' => $array['tid'])), 'notice');
+              drupal_set_message(t('Assigned expert @expert to @name (@tid).', array('@expert' => $default_expert, '@name' => $edit['name'], '@tid' => $edit['tid'])), 'status');
             }
           }
           break;
-          
+
         case 'vocabulary':
           // New vocabulary created. It will not show on the ask page until the user
           // goes to the settings page, so we don't need to do anything.
           break;
       } // End insert switch type.
       break;
-    
+
     case 'delete':
       switch ($type) {
         case 'term':
           // Delete term: remove experts.
           if ($our_vocab) {
-            _faq_ask_delete_expert($array['tid'], $array['name']);
+            _faq_ask_delete_expert($edit['tid'], $edit['name']);
           }
           break;
-          
+
         case 'vocabulary':
           // Each term gets deleted first, so all we have to do is remove it from our vocab list.
           if ($our_vocab) {
-            _faq_ask_delete_vocabulary($vid, $array, $my_vocs);
+            _faq_ask_delete_vocabulary($vid, $edit, $my_vocs);
           }
           break;
       } // End delete switch type.
       break;
-    
+
     case 'update':
       //  Two cases for vocabulary:
       //    1) FAQ is added to the vocab. -- see insert comment.
       //    2) FAQ is removed from the vocab. -- need to delete all experts for all terms and remove from voc list?
-      //  $array['nodes'] contains an array of content types for the vocab.
+      //  $edit['nodes'] contains an array of content types for the vocab.
       switch ($type) {
         case 'term':
           // Term update: nothing to do.
           break;
-          
+
         case 'vocabulary':
-          if (in_array('faq', $array['nodes'])) {
+          if (in_array('faq', $edit['nodes'])) {
             // If it's there now, we're done.
             break;
           }
@@ -952,7 +1302,7 @@
               $my_tname = $term->name;
               _faq_ask_delete_expert($my_tid, $my_tname);
             } // End foreach tree.
-            _faq_ask_delete_vocabulary($vid, $array, $my_vocs);
+            _faq_ask_delete_vocabulary($vid, $edit, $my_vocs);
           }
 
           break;
@@ -960,58 +1310,48 @@
       break;
 
     default:
-      drupal_set_message(t('Faq_ask_taxonomy: Unknown op (@op) encountered', array('@op' => $op)), 'warning');
-    
+      drupal_set_message(t('Faq_ask_taxonomy: Unknown op (@op) encountered', array('@op' => $op)), 'status');
+
   } // End switch $op
 }
 
 /**
  * Helper function to delete a vocabulary.
+ *
  *  @param.
  *    $vid - the taxonomy vocabulary id.
- *    $array - the array provided in hook_taxonomy.
+ *    $edit - the array provided in hook_taxonomy.
  *    $my_vocs - the array of faq_ask vocabularies.
  *
  *  @return: none.
  */
-function _faq_ask_delete_vocabulary($vid, $array, $my_vocs) {
+function _faq_ask_delete_vocabulary($vid, $edit, $my_vocs) {
   global $user;
-  $name = $array['name'];
+  $name = check_plain($edit['name']);
   $uname = $user->name;
-  drupal_set_message("Vocabulary '$name' is being removed from the Faq_Ask list.", 'notice');
-  watchdog('Faq_Ask', "Vocabulary $name was deleted from Faq_Ask by $uname.", WATCHDOG-NOTICE);
+  drupal_set_message(t("Vocabulary '@name' is being removed from the Faq_Ask list.", array('@name' => $name)), 'status');
+  watchdog('Faq_Ask', 'Vocabulary @voc was deleted from Faq_Ask by @name.', array('@voc' => $name, '@name' => $uname), WATCHDOG-NOTICE);
   unset($my_vocs[$vid]);
   variable_set('faq_ask_vocabularies', $my_vocs);
 }
 
 /**
  * Helper function to delete experts.
- *  @param.
+ *
+ * @param.
  *    $tid - the taxonomy term id for the experts.
  *
  *  @return: none.
  */
 function _faq_ask_delete_expert($tid, $name=NULL) {
-  $delete = db_query("DELETE FROM {faq_expert} WHERE tid=%d", $tid);
-  if ($delete === FALSE) {
+  //$delete = db_query("DELETE FROM {faq_expert} WHERE tid=%d", $tid);
+  $delete = db_delete('faq_expert')->condition('tid', $tid)->execute();
+  if ($delete == 0) {
     drupal_set_message(t('Attempt to delete expert failed.'), 'error');
   }
   else {
-    drupal_set_message(t("Deleted experts for '@name'.", array('@name' => $name)), 'notice');
-  }
-}
-
-/**
- *  Special function to verify new module dependencies.
- */
-function _faq_ask_check_dependencies() {
-// TODO: Rip this code out after a few months.
-  $is_it_here = module_exists('helpers_database');
-  if (!$is_it_here) {
-    drupal_set_message(t('The Helpers_database module is not present or not enabled. It is required for Faq_Ask. Faq_Ask has been disabled to prevent a site outage.'), 'error');
-    module_disable(array('faq_ask'));
+    drupal_set_message(t("Deleted experts for '@name'.", array('@name' => $name)), 'status');
   }
-  return $is_it_here;
 }
 
 /**
@@ -1036,66 +1376,93 @@
 function _faq_ask_help_default() {
   return t("Add a question for our expert to answer. After being answered, your question and the answer will be displayed in the FAQ pages. If the question will not fit in the box below, please try to rephrase it.");
 }
+
 /**
- * Implementation of hook_block().
- *  This creates and populates the "unanswered questions" block.
+ * Implements hook_block_save().
+ *
  */
-function faq_ask_block($op = 'list', $delta = 0, $edit = array()) {
-  global $user;
-  switch ($op) {
-    case 'list':
-      $blocks[0]['info'] = t('Unanswered Questions');
-      $blocks[1]['info'] = t('Ask a Question');
-      return $blocks;
-
-    case 'view':
-      switch ($delta) {
-        case 0:
-          // Unanswered Questions.
-          // First, let's deal with a change in module dependencies.
-          if (_faq_ask_check_dependencies()) {
-            $block['content'] = _faq_ask_list_unanswered(variable_get('faq_unanswered_count', 3));
-          }
-          break;
+function faq_ask_block_save($delta = '', $edit = array()) {
+  switch ($delta) {
+    case 'unanswered':
+      variable_set('faq_unanswered_count', $edit['faq_unanswered_count']);
+      break;
+  } // end switch($delta)
+}
 
-        case 1:
-          // Ask a question block.
-          $block['content'] = faq_ask_page(NULL);
-          break;
 
-      } // end switch($delta).
-      return $block;
+/**
+ * Implements hook_block_configure().
+ *
+ */
+function faq_ask_block_configure($delta = '') {
+  switch ($delta) {
+    case 'unanswered':
+      // Unanswered Questions.
+      $form['faq_unanswered_count'] = array(
+        '#type' => 'select',
+        '#title' => t('Number of questions to show'),
+        '#description' => t("This controls the number of questions that appear in the 'Unanswered Questions' block."),
+        '#options' => array(1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 5, 6 => 6, 7 => 7, 8 => 8, 9 => 9, 10 => 10, 15 => 15, 20 => 20, 25 => 25, 50 => 50, 100 => 100),
+        '#default_value' => variable_get('faq_unanswered_count', 3),
+        );
+      break;
+  } // end switch($delta)
+
+  return $form;
+}
 
-    case 'configure':
-      switch ($delta) {
-        case 0:
-          // Unanswered Questions.
-          $form['faq_unanswered_count'] = array(
-            '#type' => 'select',
-            '#title' => t('Number of questions to show'),
-            '#description' => t("This controls the number of questions that appear in the 'Unanswered Questions' block."),
-            '#options' => array(1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 5, 6 => 6, 7 => 7, 8 => 8, 9 => 9, 10 => 10, 15 => 15, 20 => 20, 25 => 25, 50 => 50, 100 => 100),
-            '#default_value' => variable_get('faq_unanswered_count', 3),
-          );
-          break;
-      } // end switch($delta)
+/**
+ * Implements hook_block_info().
+ *
+ */
+function faq_ask_block_info() {
+  $block = array();
+  $blocks['unanswered'] = array(
+    'info' => t('Unanswered Questions'),
+    'weight' => 0,
+    'status' => 1,
+    'region' => 'sidebar_first',
+    'cache'  => DRUPAL_CACHE_PER_ROLE,
+  );
+  $blocks['ask_a_question'] = array(
+    'info' => t('Ask a Question'),
+    'weight' => -1,  // Set initially above the unanswered questions block
+    'status' => 1,
+    'region' => 'sidebar_first',
+    'cache'  => DRUPAL_CACHE_GLOBAL,
+  );
+  return $blocks;
+}
 
-      return $form;
+/**
+ * Implements hook_block_view().
+ *
+ */
+function faq_ask_block_view($delta = '') {
+  global $user;
+  $block = array();
+  switch ($delta) {
+    case 'unanswered':
+      // Unanswered Questions.
+      $block['content'] = _faq_ask_list_unanswered(variable_get('faq_unanswered_count', 3));
+      break;
 
-    case 'save':
-      switch ($delta) {
-        case 0:
-          variable_set('faq_unanswered_count', $edit['faq_unanswered_count']);
-          break;
+    case 'ask_a_question':
+      // Ask a question block.
+      if (user_access('ask question')) {
+        $block['title']= t('Ask a Question');
+        $block['content'] = faq_ask_a_question_blockform();
+      }
 
-      } // end switch($delta)
-      return;
-  } // end switch($op)
+  } // end switch($delta).
+  return $block;
 }
 
+
+
 /**
  * This is the code to select the Unanswered Questions for the block.
- * It is also used by the "more" page by setting a very high limit.
+ * It is also used by the "unanswered" page by setting a very high limit.
  */
 function _faq_ask_list_unanswered($limit) {
   global $user;
@@ -1107,59 +1474,81 @@
   // What permissions does this user have?
   $can_edit = user_access('administer faq') || user_access('administer nodes');
   $is_expert = user_access('answer question');
-//  $only_own = user_access('edit own faq');
 
   $mode = 'edit';
   $output = $extra_msg = NULL;
-  // A high limit means we are doing the "more" page.
-  if ($limit > 1000) {
-    $order = 'tn.tid ASC, n.created ASC';
-  }
-  else {
-    $order = 'n.created ASC';
-  }
 
   // Note: If the admin is also an expert, the expert-ness prevails.
   if ($is_expert) {
     $mode = 'answer';
     if ($limit < 1000) {
-      $extra_msg = '<p class="faq_ask_expert_advice">'. variable_get('faq_ask_expert_advice', _faq_ask_advice_default('expert')) .'</p>';
+      $extra_msg = '<p class="faq_ask_expert_advice">' . filter_xss_admin(variable_get('faq_ask_expert_advice', _faq_ask_advice_default('expert'))) . '</p>';
     }
-    // Get the expert's terms.
-    $terms = db_result_array(db_query('SELECT tid FROM {faq_expert} WHERE uid=%d', $user->uid));
+
+    // Get all the expert's terms from the database into a keyed array of term indexes keyed by the term index: $terms[tid] = tid
+    $terms = db_select('faq_expert')->condition('uid', $user->uid)->execute()->fetchAllAssoc('tid');
 
     // Check if this expert has any categories.
     if (count($terms) == 0) {
       if ($limit > 1000) {
-        return '<p>'. t("For some strange reason, I couldn't find any categories for you.") .'</p>';
+        return '<p>' . t("For some strange reason, I couldn't find any categories for you.") . '</p>';
       }
       else {
         return NULL;
       }
     }
     // Join the term_data table to select based on tid.
-    $result = db_query("SELECT n.title, n.nid, tn.tid FROM {node} n LEFT JOIN {term_node} tn USING (nid) WHERE n.type='faq' AND n.status=0 AND (tn.tid IN (". db_placeholders($terms) .") OR tn.tid IS NULL) ORDER BY ". $order, $terms);
+    $query = db_select('node', 'n')
+      ->leftJoin('taxonomy_term_node', 'tn', 'n.nid = tn.nid')
+      ->condition('n.type', 'faq')  // n.type = 'faq' (this is a 'faq' node)
+      ->condition('u.status', 0)  // AND n.status = 0 (node is not published)
+      ->condition(db_or()  // AND ( (one of the following is true:)
+        ->condition('tn.tid', $terms, 'IN')  // tn.tid IN (" . db_placeholders($terms) . ") (the term of the node is in the users terms)
+        ->condition('tn.tid')  // OR tn.tid IS NULL) (or there is no terms associated with the node)
+      );
+
   }
   elseif ($can_edit) {
-    $result = db_query("SELECT n.title, n.nid, tn.tid FROM {node} n JOIN {term_node} tn USING (nid) WHERE n.type='faq' AND n.status=0 ORDER BY ". $order, $terms);
+    $query = db_select('node', 'n')
+      ->join('taxonomy_term_node', 'tn', 'n.nid = tn.nid')
+      ->condition('n.type', 'faq')  // n.type = 'faq'
+      ->condition('u.status', 0);  // AND n.status = 0
+
+    // A high limit means we are doing the "unanswered" page.
     if ($limit < 1000) {
-      $extra_msg = '<p class="faq_ask_expert_advice">'. variable_get('faq_ask_admin_advice', _faq_ask_advice_default('admin')) .'</p>';
+      $extra_msg = '<p class="faq_ask_expert_advice">' . filter_xss_admin(variable_get('faq_ask_admin_advice', _faq_ask_advice_default('admin'))) . '</p>';
     }
   }
   else { // Edit own.
-    $result = db_query("SELECT n.title, n.nid, tn.tid FROM {node} n JOIN {term_node} tn USING (nid) WHERE n.type='faq' AND n.status=0 AND n.uid=%d ORDER BY ". $order, $user->uid);
+    $query = db_select('node', 'n')
+      ->join('taxonomy_term_node', 'tn', 'n.nid = tn.nid')
+      ->condition('n.type', 'faq')  // n.type = 'faq'
+      ->condition('u.status', 0)  // AND n.status = 0
+      ->condition('u.uid', $user->uid);  // AND n.uid = $user->uid (the user and the node owner are the same)
+
+    // A high limit means we are doing the "unanswered" page.
     if ($limit < 1000) {
-      $extra_msg = '<p class="faq_ask_expert_advice">'. variable_get('faq_ask_asker_advice', _faq_ask_advice_default('asker')) .'</p>';
+      $extra_msg = '<p class="faq_ask_expert_advice">' . filter_xss_admin(variable_get('faq_ask_asker_advice', _faq_ask_advice_default('asker'))) . '</p>';
     }
   }
 
+  $query->fields('n', array('title', 'nid'))->fields('tn', array('tid'));
+
+  // A high limit means we are doing the "unanswered" page.
+  if ($limit > 1000) {
+    $query->orderBy('tn.tid');
+  }
+  $query->orderBy('n.created');
+
+  $result = $query->execute()->fetchAllAssoc('nid');
+
   // Get unpublished nodes that are type='faq'.
   $items = array();
   $i = 0;
   $prev_cat = -1;
   $voc_list = variable_get('faq_ask_vocabularies', array());
-  
-  while ($node = db_fetch_array($result)) {
+
+  foreach ($result as $nid => $node) {
     ++$i;
     // If we've reached the limit, then quit.
     if ($i > $limit) {
@@ -1168,14 +1557,21 @@
     $tid = $node['tid'];
     if ($tid) {
       // We need to skip terms that are not in our vocabularies.
-      $term = taxonomy_get_term($tid);
+      $term = taxonomy_term_load($tid);
       if (!in_array($term->vid, $voc_list)) {
         --$i;
         continue;
       }
     }
+    $token = drupal_get_token('faq_ask/answer/' . $node['nid']);
+    $options = array('query' => "token=$token");
+    if ($mode == 'edit') {
+      $options['query'] .= '&ask=TRUE';
+    }
     if ($prev_cat == $tid || $limit < 1000) {
-      $items[] = l($node['title'], 'faq_ask/'. $mode .'/'. $node['nid']);
+      $items[] = ($limit < 1000) ?
+        l($node['title'], "faq_ask/$mode/" . $node['nid'], $options)
+        : node_view(node_load($node['nid']));
     }
     else {
       if (count($items) > 0) {
@@ -1183,29 +1579,32 @@
         $items = array();
       }
       if ($tid) {
-        $term = taxonomy_get_term($tid);
-        $output .= '<br/><h3>'. check_plain($term->name) .'</h3>';
+        $term = taxonomy_term_load($tid);
+        $output .= '<br/><h3>' . check_plain(faq_tt("taxonomy:term:$term->tid:name", $term->name)) . '</h3>';
       }
       else {
-        $output .= '<br/><h3>'. t('Uncategorized') .'</h3>';
+        $output .= '<br/><h3>' . t('Uncategorized') . '</h3>';
       }
       $prev_cat = $tid;
-      $items[] = l($node['title'], 'faq_ask/'. $mode .'/'. $node['nid']);
+      $items[] = ($limit < 1000) ?
+        l($node['title'], "faq_ask/$mode/" . $node['nid'], $options)
+        : node_view(node_load($node['nid']));
     }
   }
+
   if ($i) {
     $output .= theme('item_list', $items)
-      . ($i > $limit ? l(t('more...'), 'faq_ask/more', array('class' => 'faq_ask_more_link')) : NULL)
+      . ($i > $limit ? l(t('more...'), 'faq_ask/unanswered', array('class' => 'faq_ask_more_link')) : NULL)
       . ($limit < 1000 ? $extra_msg : NULL);
   }
   elseif ($limit > 1000) {
-    $output .= '<p>'. t('Currently there are no unanswered questions for you to view.') .'</p>';
+    $output .= '<p>' . t('Currently there are no unanswered questions for you to view.') . '</p>';
   }
 
   return $output;
 }
 
-/*
+/**
  *  This function lists all the unanswered questions the user is allowed to see.
  *  It is used by the "more..." link from the block, but can also be called independently.
  */
@@ -1213,4 +1612,4 @@
   drupal_set_title(t('All Unanswered Questions'));
   $output = '<br/>';
   return _faq_ask_list_unanswered(9999999);
-}
\ No newline at end of file
+}
Index: faq_ask.install
===================================================================
RCS file: /cvs/drupal/contributions/modules/faq_ask/faq_ask.install,v
retrieving revision 1.11
diff -u -r1.11 faq_ask.install
--- faq_ask.install	24 Nov 2008 20:13:23 -0000	1.11
+++ faq_ask.install	9 Mar 2010 12:01:44 -0000
@@ -1,5 +1,5 @@
 <?php
-// $Id: faq_ask.install,v 1.11 2008/11/24 20:13:23 nancyw Exp $
+// $Id: faq_ask.install,v 1.4.2.7 2008/11/24 20:13:07 nancyw Exp $
 
 /**
  * @file
@@ -8,20 +8,20 @@
  */
 
 /**
- * Implementation of hook_schema().
+ * Implements hook_schema().
  */
 function faq_ask_schema() {
   $schema['faq_expert'] = array(
-    'description' => t('FAQ expert to term mapping.'),
+    'description' => 'FAQ expert to term mapping.',
     'fields' => array(
       'uid' => array(
-        'description' => t('User identifier for the expert.'),
+        'description' => 'User identifier for the expert.',
         'type' => 'int',
         'unsigned' => TRUE,
         'not null' => TRUE,
         ),
       'tid' => array(
-        'description' => t('Taxonomy identifier of the terms for the expert.'),
+        'description' => 'Taxonomy identifier of the terms for the expert.',
         'type' => 'int',
         'unsigned' => TRUE,
         'not null' => TRUE,
@@ -33,76 +33,71 @@
       ),
     );
 
-  $schema['faq_questions'] = array(
+  $schema['faq_ask_notify'] = array(
+    'description' => 'FAQ node to asker mapping.',
     'fields' => array(
-      'nid' => array('type' => 'int',
-        'unsigned' => TRUE,
-        'not null' => TRUE,
-        'default' => 0,
-        'disp-width' => '10'),
-      'vid' => array(
+      'nid' => array(
+        'description' => 'Node identifier for notification',
         'type' => 'int',
         'unsigned' => TRUE,
         'not null' => TRUE,
-        'default' => 0,
-        'disp-width' => '10'),
-      'question' => array(
-        'type' => 'text',
-        'not null' => TRUE),
+        ),
+      'email' => array(
+        'description' => 'Node identifier for notification',
+        'type' => 'varchar',
+        'length' => '128',
+        'not null' => TRUE,
+        ),
       ),
-    'primary key' => array('nid', 'vid'),
-);
+    'primary key' => array('nid', 'email'),
+    'indexes' => array(
+      'nid' => array('nid', 'email'),
+      ),
+    );
   return $schema;
 }
 
 /**
- * Implementation of hook_install().
+ * Implements hook_install().
  */
 function faq_ask_install() {
-  // Note: I did not specify defaults here because an insert should fail if a value is not supplied.
-  switch ($GLOBALS['db_type']) {
-    case 'mysql':
-    case 'mysqli':
-      $result = db_query("CREATE TABLE IF NOT EXISTS {faq_expert} (
-        uid INT(10) UNSIGNED NOT NULL,
-        tid INT(10) UNSIGNED NOT NULL,
-        PRIMARY KEY (uid, tid),
-        INDEX tid (tid, uid)
-      ) /*!40100 DEFAULT CHARACTER SET UTF8 */ ");
-      break;
-
-    case 'pgsql':
-      $result = db_query("CREATE TABLE {faq_expert} (
-        uid integer NOT NULL,
-        tid integer NOT NULL,
-        PRIMARY KEY (uid, tid)
-      )");
-      db_query("CREATE INDEX {faq_expert}_tid ON {faq_expert} (tid, uid)");
-      break;
-  }
+  $result = drupal_install_schema('faq_ask');
 
-  if ($result) {
-    drupal_set_message(t('faq_ask module installed.'));
+  if (count($result) > 0) {
+    drupal_set_message(st('faq_ask module installed.'));
+  }
+  else {
+    drupal_set_message(st('faq_ask table creation failed. Please "uninstall" the module and retry.'));
   }
-  else { drupal_set_message(t('faq_ask table creation failed. Please "uninstall" the module and retry.')); }
 }
 
 /**
- * Implementation of hook_update_N().
+ * Implements hook_update_N().
  */
-function faq_ask_update_5100() {
+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().
+ * Implements hook_uninstall().
  */
 function faq_ask_uninstall() {
-  db_query('DROP TABLE {faq_expert}');
+  drupal_uninstall_schema('faq_ask');
 
   variable_del('faq_expert_role');
   variable_del('faq_ask_vocabularies');
@@ -115,6 +110,10 @@
   variable_del('faq_ask_help_text');
   variable_del('faq_ask_categorize');
   variable_del('faq_ask_expert_own');
+  variable_del('faq_ask_notify_asker');
+  variable_del('faq_ask_notify_asker_simplenews_tid');
+  variable_del('faq_ask_notify_asker_simplenews_confirm');
+  variable_del('faq_ask_notify_by_cron');
 
-  drupal_set_message(t('faq_ask module uninstalled.'));
+  drupal_set_message(st('faq_ask module uninstalled.'));
 }
Index: faq_ask.info
===================================================================
RCS file: /cvs/drupal/contributions/modules/faq_ask/faq_ask.info,v
retrieving revision 1.3
diff -u -r1.3 faq_ask.info
--- faq_ask.info	6 Feb 2008 17:34:28 -0000	1.3
+++ faq_ask.info	9 Mar 2010 12:01:44 -0000
@@ -1,4 +1,8 @@
-; $Id: faq_ask.info,v 1.3 2008/02/06 17:34:28 nancyw Exp $
+; $Id: faq_ask.info,v 1.2.2.2.2.1 2009/03/30 22:44:27 nancyw Exp $
 name = Faq_Ask
 description = "Allows an unanswered question 'queue' for the FAQ module."
-dependencies = faq helpers_database
+dependencies[] = faq
+core = 7.x
+files[] = faq_ask.module
+files[] = faq_ask.test
+files[] = faq_ask.install
\ No newline at end of file
Index: po/faq_ask.pot
===================================================================
RCS file: po/faq_ask.pot
diff -N po/faq_ask.pot
--- po/faq_ask.pot	20 May 2008 17:15:31 -0000	1.13
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -1,442 +0,0 @@
-# $Id: faq_ask.pot,v 1.13 2008/05/20 17:15:31 nancyw Exp $
-#
-# LANGUAGE translation of Drupal (general)
-# Copyright YEAR NAME <EMAIL@ADDRESS>
-# Generated from files:
-#  faq_ask.module,v 1.32 2008/05/10 14:22:20 nancyw
-#  faq_ask.info,v 1.3 2008/02/06 17:34:28 nancyw
-#  faq_ask.install,v 1.8 2008/05/10 14:22:20 nancyw
-#
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: PROJECT VERSION\n"
-"POT-Creation-Date: 2008-05-20 13:13-0400\n"
-"PO-Revision-Date: YYYY-mm-DD HH:MM+ZZZZ\n"
-"Last-Translator: NAME <EMAIL@ADDRESS>\n"
-"Language-Team: LANGUAGE <EMAIL@ADDRESS>\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=utf-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
-
-#: faq_ask.module:18
-msgid "This module is an add-on to the FAQ module that allows users with the 'ask question' permission to create a question which will be queued for an 'expert' to answer."
-msgstr ""
-
-#: faq_ask.module:19
-msgid "The module shows an abbreviated version of the FAQ form without an answer field. The node is created without the 'published' attribute. There is a block that will show the unanswered questions to the 'expert' (generally, this requires a separate role)."
-msgstr ""
-
-#: faq_ask.module:20
-msgid "Viewing of the completed question and answer pair is done by the FAQ module."
-msgstr ""
-
-#: faq_ask.module:21
-msgid "Simply adding the 'FAQ' content type to a vocabulary will not make it eligible for experts; you must go to the settings page and add it there."
-msgstr ""
-
-#: faq_ask.module:25
-msgid "In order for the Faq_Ask module to operate, you must, at the least,: 1) select one or more roles as experts (and you may have to \"Save configuration\"); 2) select at least one category and expert combination; 3) click the \"Save configuration\" button."
-msgstr ""
-
-#: faq_ask.module:31
-msgid "You may go <a href=\"!setting\">here</a> to change the block limit."
-msgstr ""
-
-#: faq_ask.module:63
-msgid "ask_question"
-msgstr ""
-
-#: faq_ask.module:78
-msgid "The Faq_Ask module has been enabled."
-msgstr ""
-
-#: faq_ask.module:78;192
-msgid "Please go to the <a href=\"!url\">settings page</a> to configure this module."
-msgstr ""
-
-#: faq_ask.module:95;512
-msgid "Experts"
-msgstr ""
-
-#: faq_ask.module:99
-msgid "Allows the user to configure the Ask_FAQ module."
-msgstr ""
-
-#: faq_ask.module:106
-msgid "Ask a question"
-msgstr ""
-
-#: faq_ask.module:114
-msgid "Answer a question"
-msgstr ""
-
-#: faq_ask.module:122
-msgid "Edit a question"
-msgstr ""
-
-#: faq_ask.module:131
-msgid "List more unanswered questions"
-msgstr ""
-
-#: faq_ask.module:166
-msgid "That question has already been answered."
-msgstr ""
-
-#: faq_ask.module:174
-msgid "You are not allowed to edit that question."
-msgstr ""
-
-#: faq_ask.module:190
-msgid "Currently, there are no categories defined. "
-msgstr ""
-
-#: faq_ask.module:195
-msgid "Please <a href=\"!url\">ask your site administrator</a> to set up this feature."
-msgstr ""
-
-#: faq_ask.module:206
-msgid "<suggest a category>"
-msgstr ""
-
-#: faq_ask.module:237
-msgid "Category"
-msgstr ""
-
-#: faq_ask.module:243
-msgid "Please select the correct category for your question."
-msgstr ""
-
-#: faq_ask.module:249
-msgid "Suggested Category"
-msgstr ""
-
-#: faq_ask.module:253
-msgid "Please enter your suggested category for the question."
-msgstr ""
-
-#: faq_ask.module:262
-msgid "Question"
-msgstr ""
-
-#: faq_ask.module:269
-msgid "Enter your question here. It will be answered as soon as possible."
-msgstr ""
-
-#: faq_ask.module:274
-msgid "Send my question"
-msgstr ""
-
-#: faq_ask.module:316
-msgid "Anonymous"
-msgstr ""
-
-#: faq_ask.module:353
-msgid "The following question has been posted in the \"!cat\" category."
-msgstr ""
-
-#: faq_ask.module:356
-msgid "In order to answer it you will first need to <a href=\"!url\">login</a> to the site."
-msgstr ""
-
-#: faq_ask.module:357
-msgid "Once logged in, you may proceed <a href=\"!url\">directly to the question</a> to answer it."
-msgstr ""
-
-#: faq_ask.module:359
-msgid "You have a question waiting"
-msgstr ""
-
-#: faq_ask.module:361
-msgid "Expert notification email sent."
-msgstr ""
-
-#: faq_ask.module:364
-msgid "Expert notification email failed for the \"!cat\" category."
-msgstr ""
-
-#: faq_ask.module:377
-msgid "left side"
-msgstr ""
-
-#: faq_ask.module:380
-msgid "right side"
-msgstr ""
-
-#: faq_ask.module:383
-msgid "top"
-msgstr ""
-
-#: faq_ask.module:386
-msgid "bottom"
-msgstr ""
-
-#: faq_ask.module:393
-msgid "It should appear in the list at the @region of the screen momentarily."
-msgstr ""
-
-#: faq_ask.module:396
-msgid "It should appear in the list momentarily."
-msgstr ""
-
-#: faq_ask.module:400
-msgid "Your question has been submitted."
-msgstr ""
-
-#: faq_ask.module:415
-msgid "Errors were found, please correct them before proceeding."
-msgstr ""
-
-#: faq_ask.module:418
-msgid "The Faq_Ask module requires that FAQ \"Categorize questions.\" Please go to the <a href=\"!url\">settings page</a> to configure this module."
-msgstr ""
-
-#: faq_ask.module:425
-msgid "The Faq_Ask module requires that at least one vocabulary apply to the \"faq\" content type."
-msgstr ""
-
-#: faq_ask.module:434
-msgid "Notifications"
-msgstr ""
-
-#: faq_ask.module:441
-msgid "Notify experts"
-msgstr ""
-
-#: faq_ask.module:442
-msgid "If this box is checked, the expert(s) for the question will be notified via email that a question awaits them. If you do not choose this option, the \"Unanswered Questions\" block will be the only way they will know they have questions to answer."
-msgstr ""
-
-#: faq_ask.module:448
-msgid "Options"
-msgstr ""
-
-#: faq_ask.module:455
-msgid "Allow \"Suggest a category\""
-msgstr ""
-
-#: faq_ask.module:456
-msgid "If this box is checked, the person asking a question will have an option to enter a new category. It will have the default expert assigned to it until you return here to correct the assignment."
-msgstr ""
-
-#: faq_ask.module:462
-msgid "Advice"
-msgstr ""
-
-#: faq_ask.module:463
-msgid "This text will be shown at the bottom of the \"Unanswered questions\" block."
-msgstr ""
-
-#: faq_ask.module:470
-msgid "Advice for the expert"
-msgstr ""
-
-#: faq_ask.module:478;486
-msgid "Advice for an administrator/editor"
-msgstr ""
-
-#: faq_ask.module:494
-msgid "Help text for the asker"
-msgstr ""
-
-#: faq_ask.module:497
-msgid "This text will be shown at the top of the \"Ask a Question\" page."
-msgstr ""
-
-#: faq_ask.module:505
-msgid "Question Box Length"
-msgstr ""
-
-#: faq_ask.module:506
-msgid "This sets the length of the question box (not the question itself). This affects only the FAQ_Ask module, not the FAQ display. The recommendation is to set it as wide as your theme will allow it. Note: If resizable textareas are enabled, this setting will have no effect."
-msgstr ""
-
-#: faq_ask.module:540
-msgid "Use these vocabularies"
-msgstr ""
-
-#: faq_ask.module:543
-msgid "Only the terms from the selected vocabularies will be included in the list below."
-msgstr ""
-
-#: faq_ask.module:544
-msgid "Simply adding the 'FAQ' content type to a vocabulary will not make it eligible for experts; you must return to here to add it."
-msgstr ""
-
-#: faq_ask.module:545
-msgid "If you select different vocabularies, you must save the configuration BEFORE selecting users below."
-msgstr ""
-
-#: faq_ask.module:550
-msgid "Free tagging vocabularies are not allowed for Faq_Ask."
-msgstr ""
-
-#: faq_ask.module:563
-msgid "No roles with \"answer question\" permission were found; only !admin is currently eligible to be an expert. You may want to go to the <a href=\"!access\">Access Control page</a> to update your permissions."
-msgstr ""
-
-#: faq_ask.module:582
-msgid "No vocabularies or terms were found for the \"faq\" content type . Please go to the <a href=\"!access\">Categories page</a> to update your vocabulary."
-msgstr ""
-
-#: faq_ask.module:614
-msgid "Expert Roles"
-msgstr ""
-
-#: faq_ask.module:618
-msgid "User 1 (@admin) will always be in the list, regardless of roles."
-msgstr ""
-
-#: faq_ask.module:618
-msgid "If you select different roles, you must save the configuration BEFORE selecting users below."
-msgstr ""
-
-#: faq_ask.module:633;637;662
-msgid "Note: Even though the check boxes below are checked, you must still click the \"Save configuration\" button to save the expert settings."
-msgstr ""
-
-#: faq_ask.module:685
-msgid "Those who will be answering questions will need both \"answer question\" and \"edit faq\" permissions."
-msgstr ""
-
-#: faq_ask.module:696
-msgid "!name doesn't exist. If you have just changed your role selections this may be okay."
-msgstr ""
-
-#: faq_ask.module:713
-msgid "Default expert"
-msgstr ""
-
-#: faq_ask.module:714
-msgid "The selected user will be assigned as the expert for all terms that are added to the selected vocabularies until you return to this page and update it."
-msgstr ""
-
-#: faq_ask.module:723
-msgid "Save configuration"
-msgstr ""
-
-#: faq_ask.module:766
-msgid "Configuration has been updated."
-msgstr ""
-
-#: faq_ask.module:804
-msgid "Attempt to assign expert failed."
-msgstr ""
-
-#: faq_ask.module:807
-msgid "Assigned expert @expert to @name (@tid)."
-msgstr ""
-
-#: faq_ask.module:868
-msgid "Faq_ask_taxonomy: Unknown op (@op) encountered"
-msgstr ""
-
-#: faq_ask.module:902
-msgid "Attempt to delete expert failed."
-msgstr ""
-
-#: faq_ask.module:905
-msgid "Deleted experts for '@name'."
-msgstr ""
-
-#: faq_ask.module:925
-msgid "Faq_Ask can't determine the correct vocabulary because no FAQ nodes exist yet."
-msgstr ""
-
-#: faq_ask.module:937
-msgid "The Helpers_database module is not present or not enabled. It is required for Faq_Ask. Faq_Ask has been disabled to prevent a site outage."
-msgstr ""
-
-#: faq_ask.module:949
-msgid "If you select a question, you must answer it."
-msgstr ""
-
-#: faq_ask.module:952
-msgid "You are allowed to edit unanswered questions."
-msgstr ""
-
-#: faq_ask.module:955
-msgid "You may edit your own questions until they are answered."
-msgstr ""
-
-#: faq_ask.module:963
-msgid "Add a question for our expert to answer. After being answered, your question and the answer will be displayed in the FAQ pages. If the question will not fit in the box below, please try to rephrase it."
-msgstr ""
-
-#: faq_ask.module:973
-msgid "Unanswered Questions"
-msgstr ""
-
-#: faq_ask.module:995
-msgid "Number of questions to show"
-msgstr ""
-
-#: faq_ask.module:996
-msgid "This controls the number of questions that appear in the 'Unanswered Questions' block."
-msgstr ""
-
-#: faq_ask.module:1054
-msgid "For some strange reason, I couldn't find any categories for you."
-msgstr ""
-
-#: faq_ask.module:1103
-msgid "more..."
-msgstr ""
-
-#: faq_ask.module:1107
-msgid "Currently there are no unanswered questions for you to view."
-msgstr ""
-
-#: faq_ask.module:1118
-msgid "All Unanswered Questions"
-msgstr ""
-
-#: faq_ask.module:361;365
-msgid "FAQ_Ask"
-msgstr ""
-
-#: faq_ask.module:887 faq_ask.info:0
-msgid "Faq_Ask"
-msgstr ""
-
-#: faq_ask.module:46
-msgid "ask question"
-msgstr ""
-
-#: faq_ask.module:46
-msgid "answer question"
-msgstr ""
-
-#: faq_ask.module:0
-msgid "faq_ask"
-msgstr ""
-
-#: faq_ask.install:15
-msgid "FAQ expert to term mapping."
-msgstr ""
-
-#: faq_ask.install:18
-msgid "User identifier for the expert."
-msgstr ""
-
-#: faq_ask.install:24
-msgid "Taxonomy identifier of the terms for the expert."
-msgstr ""
-
-#: faq_ask.install:85
-msgid "faq_ask module installed."
-msgstr ""
-
-#: faq_ask.install:87
-msgid "faq_ask table creation failed. Please \"uninstall\" the module and retry."
-msgstr ""
-
-#: faq_ask.install:117
-msgid "faq_ask module uninstalled."
-msgstr ""
-
-#: faq_ask.info:0
-msgid "Allows an unanswered question 'queue' for the FAQ module."
-msgstr ""
-
Index: po/pl.po
===================================================================
RCS file: po/pl.po
diff -N po/pl.po
--- po/pl.po	30 Jan 2008 22:15:53 -0000	1.1
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -1,367 +0,0 @@
-# $Id: pl.po,v 1.1 2008/01/30 22:15:53 ser Exp $
-#
-# LANGUAGE translation of Drupal (general)
-# Copyright polskie tlumaczenie 2008 Andrzej Niemiec, Olga Stankiewicz <ani@prim.com.pl> GPL
-# Generated from files:
-#  faq_ask.module,v 1.13 2007/12/29 13:49:13 nancyw
-#  faq_ask.info,v 1.1 2007/11/16 15:20:39 nancyw
-#  faq_ask.install,v 1.2 2007/12/27 18:38:45 nancyw
-#
-
-msgid ""
-msgstr ""
-"Project-Id-Version: DRUPAL5\n"
-"POT-Creation-Date: 2008-01-31 21:59-0500\n"
-"PO-Revision-Date: YYYY-mm-DD HH:MM+ZZZZ\n"
-"Last-Translator: Sergiusz Pawłowicz <drupal-translations@pawlowicz.name>\n"
-"Language-Team: PL <EMAIL@ADDRESS>\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=utf-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=3;    plural=n==1 ? 0 :           n%10>=2 && n%10<=4 "
-"&& (n%100<10 || n%100>=20) ? 1 : 2;\n"
-
-#: faq_ask.module:18
-msgid "This module is an add-on to the FAQ module that allows users with the 'ask question' permission to create a question which will be queued for an 'expert' to answer."
-msgstr "Ten moduł jest dodatkiem do modułu FAQ. Pozwala on użytkownikom formułować pytania, które będą oczekiwać na odpowiedź eksperta."
-
-#: faq_ask.module:19
-msgid "The module shows an abbreviated version of the FAQ form without an answer field. The node is created without the 'published' attribute. There is a block that will show the unanswered questions to the 'expert' (generally, this requires a separate role)."
-msgstr  "Moduł wyświetla skróconą wersję FAQ (bez pola odpowiedzi). Ten węzeł jest stworzony bez atrybutu 'opublikowany'. Istnieje blok, który pokaże pytania bez odpowiedzi 'ekspertowi' (w zasadzie wymaga to stworzenia odrębnej roli)."
-
-#: faq_ask.module:20
-msgid "Viewing of the completed question and answer pair is done by the FAQ module."
-msgstr "Wyświetlanie pytania i odpowiedzi jest realizowane poprzed moduł FAQ."
-
-#: faq_ask.module:21
-msgid "Simply adding the 'FAQ' content type to a vocabulary will not make it eligible for experts; you must go to the settings page and add it there."
-msgstr ""
-
-#: faq_ask.module:25
-msgid "Add a question for our expert to answer. After being answered, your question and the answer will be displayed in the FAQ pages. If the question will not fit in the box below, please try to rephrase it."
-msgstr "Zadaj pytanie naszemu ekspertowi. Gdy ekspert odpowie na pytanie, pytanie wraz z uzyskaną odpowiedzią wyświetlać się będą na stronach FAQ. Jeśli pytanie nie będzie pasować do okna poniżej, proszę przekształć je."
-
-#: faq_ask.module:42
-msgid "ask_question"
-msgstr "Postaw pytanie"
-
-#: faq_ask.module:51
-msgid "The Faq_Ask module has been enabled."
-msgstr "Moduł Faq_Ask został uruchomiony"
-
-#: faq_ask.module:51;155;361
-msgid "Please go to the <a href=\"!url\">settings page</a> to configure this module."
-msgstr "Proszę przejść na stronę <a href=\"!url\">z ustawieniami </a> aby zmienić konfiguracje."
-
-#: faq_ask.module:63
-msgid "Experts"
-msgstr "Eksperci"
-
-#: faq_ask.module:67
-msgid "Allows the user to configure the Ask_FAQ module."
-msgstr "Pozwala to użytkownikowi zmienić ustawienia modułu Ask_FAQ"
-
-#: faq_ask.module:74
-msgid "Ask a question"
-msgstr "Zadaj pytanie"
-
-#: faq_ask.module:82
-msgid "Answer a question"
-msgstr "Odpowiedź na pytanie"
-
-#: faq_ask.module:90
-msgid "Edit a question"
-msgstr "Zmień pytanie"
-
-#: faq_ask.module:98
-msgid "List more unanswered questions"
-msgstr "Pokaż pytania bez odpowiedzi"
-
-#: faq_ask.module:137
-msgid "<suggest a category>"
-msgstr "<zaproponuj kategorię>"
-
-#: faq_ask.module:153
-msgid "Currently, there are no categories defined. "
-msgstr "Obecnie nie ma oreślonych kategorii"
-
-#: faq_ask.module:158
-msgid "Please <a href=\"!url\">ask your site administrator</a> to set up this feature."
-msgstr "Przejdź na <a href=\"!url\"> i poproś administratora </a> aby udostępnił tą możliwość"
-
-#: faq_ask.module:182
-msgid "Category"
-msgstr "Kategoria"
-
-#: faq_ask.module:188
-msgid "Please select the correct category for your question."
-msgstr "Wybierz proszę właściwą kategorię dla Twojego pytania"
-
-#: faq_ask.module:194
-msgid "Suggested Category"
-msgstr "Sugerowana kategoria"
-
-#: faq_ask.module:198
-msgid "Please enter your suggested category for the question."
-msgstr "Wprowadź proszę właściwą kategorię dla Twojego pytania"
-
-#: faq_ask.module:208
-msgid "Question"
-msgstr "Pytanie"
-
-#: faq_ask.module:216
-msgid "Enter your question here. It will be answered as soon as possible. The maximum length for the question is !len characters."
-msgstr "Wprowadź swoje pytanie. Odpowiedź pojawi się tak szybko jak to jest możliwe. Najdłuższe pytanie może zawierać !len znaków"
-
-#: faq_ask.module:221
-msgid "Send my question"
-msgstr "Wyślij moje pytanie"
-
-#: faq_ask.module:298
-msgid "The following question has been posted in the \"!cat\" category."
-msgstr "Poniższe pytanie zostało przesłane do kategorii \"!cat\""
-
-#: faq_ask.module:301
-msgid "In order to answer it you will first need to <a href=\"!url\"> login</a> to the site."
-msgstr "W celu udzielenia odpowiedzi musisz się najpierw <a href=\"!url\"> zalogować </a>"
-
-#: faq_ask.module:302
-msgid "Once logged in, you may proceed <a href=\"!url\">directly to the question</a> to answer it."
-msgstr "Po zalogowaniu, możesz udać się bezpośrednio do <a href=\"!url\"> pytania </a> aby udzielić odpowiedzi."
-
-#: faq_ask.module:306
-msgid "Expert notification email sent."
-msgstr "Wysłano list do eksperta"
-
-#: faq_ask.module:309
-msgid "Expert notification email failed for the \"!cat\" category."
-msgstr "Wysyłka list do eksperta kategorii \"!cat\" nie udala się."
-
-#: faq_ask.module:322
-msgid "left side"
-msgstr "Lewa strona"
-
-#: faq_ask.module:325
-msgid "right side"
-msgstr "Prawa strona"
-
-#: faq_ask.module:328
-msgid "top"
-msgstr "góra"
-
-#: faq_ask.module:331
-msgid "bottom"
-msgstr "dół"
-
-#: faq_ask.module:338
-msgid "It should appear in the list at the @region of the screen momentarily."
-msgstr "Powinno się pojawić na liście w @region "
-
-#: faq_ask.module:341
-msgid "It should appear in the list momentarily."
-msgstr "Powinno pojawić się na liście za chwilę"
-
-#: faq_ask.module:345
-msgid "Your question has been submitted."
-msgstr "Twoje pytanie zostało przesłane"
-
-#: faq_ask.module:361
-msgid "The Faq_Ask module requires that FAQ \"Categorize questions.\""
-msgstr "Moduł Faq_Ask wymaga opcji \"Kategoryzuj pytania.\""
-
-#: faq_ask.module:368
-msgid "Notify experts"
-msgstr "Powiadom eksperta"
-
-#: faq_ask.module:369
-msgid "If this box is checked, the expert(s) for the question will be notified via email that a question awaits them. If you do not choose this option, the \"Unanswered Questions\" block will be the only way they will know they have questions to answer."
-msgstr "Jeśli zaznaczono okienko, ekspert/ci zostaną powiadomieni drogą e-mail o oczekującym pytaniu. Jeśli nie wybierzesz tej opcji dział "pytania bez odpowiedzi" będzie jedynym sposobem w jaki eksperci będą mogli się dowiedzieć o oczekującym pytaniu"
-
-#: faq_ask.module:375
-msgid "Allow \"Suggest a category\""
-msgstr "Dopuść \" Wybierz kategorie\""
-
-#: faq_ask.module:376
-msgid "If this box is checked, the person asking a question will have an option to enter a new category. It will have the default expert assigned to it until you return here to correct the assignment."
-msgstr "Po zaznaczeniu tego okienka osoba zadająca pytanie będzie miała możliwość dodania nowej kategorii. Będzie miała przypisanego domyślnego eksperta, aż do czasu gdy wrócisz i poprawisz wpis."
-
-#: faq_ask.module:384
-msgid "Question Box Length"
-msgstr "Długość okna z pytaniem"
-
-#: faq_ask.module:385
-msgid "This sets the length of the question box (not the question itself). This affects only the FAQ_Ask module, not the FAQ display. The recommendation is to set it as wide as your theme will allow it. Note: If resizable textareas are enabled, this setting will have no effect."
-msgstr "Ustala długość okna z pytaniem (nie samego pytania). Dotyczy tylko modułu FAQ_ask. Zaleca się ustawić okno tak szerokie jak twój temat na to pozwala. Uwaga: Jeśli włączona jest opcja dopasowywania wielkości pola tesktu, to ustawienie nie przyniesie efektu."
-
-#: faq_ask.module:411
-msgid "Use these vocabularies"
-msgstr "Użyj tego słownictwa"
-
-#: faq_ask.module:414
-msgid "Only the terms from the selected vocabularies will be included in the list below."
-msgstr "Tylko zwroty z wybranego zasobu słownictwa będą dodane do poniższej listy."
-
-#: faq_ask.module:415
-msgid "Simply adding the 'FAQ' content type to a vocabulary will not make it eligible for experts; you must return to here to add it."
-msgstr ""
-
-#: faq_ask.module:416
-msgid "If you select different vocabularies, you must save the configuration BEFORE selecting users below."
-msgstr "Jeśli wybierzesz różne/inne słownictwo, musisz zapisać ustawienia PRZED dokonaniem wyboru użytkowników."
-
-#: faq_ask.module:423
-msgid "Free tagging vocabularies are not allowed for Faq_Ask."
-msgstr "(...) są niedozwolone w FAQ_Ask."
-
-#: faq_ask.module:436
-msgid "No roles with \"answer question\" permission were found; only !admin is currently eligible to be an expert. You may want to go to the <a href=\"!access\">Access Control page</a> to update your permissions."
-msgstr "Nie znaleziono ról ze zgodą na \"odpowiedz na pytanie\". Obecnie tylko admin może pełnić rolę eksperta. Możesz przejść na  <a href=\"!access\"> stronę z kontrolą dostępu </a> by aktualizować swoje zgody."
-
-#: faq_ask.module:456
-msgid "No vocabularies or terms were found for the \"faq\" content type . Please go to the <a href=\"!access\">Categories page</a> to update your vocabulary."
-msgstr ""
-
-#: faq_ask.module:480
-msgid "Expert Roles"
-msgstr "Rola eksperta"
-
-#: faq_ask.module:484
-msgid "User 1 (@admin) will always be in the list, regardless of roles."
-msgstr "Użytkowni1 1 (@admin) jest zawsze dostępny na liście, niezależnie od roli"
-
-#: faq_ask.module:484
-msgid "If you select different roles, you must save the configuration BEFORE selecting users below."
-msgstr "Jeśli wybierzesz inna/różne role, musisz zapisać ustawienia PRZED dokonaniem wyboru użytkowników"
-
-#: faq_ask.module:498;502;525
-msgid "Note: Even though the check boxes below are checked, you must still click the \"Save configuration\" button to save the expert settings."
-msgstr "Uwaga: Nawet jeśli zaznaczyłeś okienka, aby zapisać ustawienia musisz kliknąc na przycisk \"zapisz ustawienia\"."
-
-#: faq_ask.module:551
-msgid "!name doesn't exist. If you have just changed your role selections this may be okay."
-msgstr "Podana nazwa nie istnieje. Jeśli zmieniłeś swoją rolę zignoruj tą wiadomość."
-
-#: faq_ask.module:566
-msgid "Default expert"
-msgstr "Domyślny ekspert"
-
-#: faq_ask.module:567
-msgid "The selected user will be assigned as the expert for all terms that are added to the selected vocabularies until you return to this page and update it."
-msgstr "Wybrany użytkowanik zostanie przypisany jako ekspert do wszystkich zwrotów, które zostały zaznaczone w słowniku, aż do czasu twojego powrotu na stronę i updatu."
-
-#: faq_ask.module:574
-msgid "Save configuration"
-msgstr "Zapisz ustawienia"
-
-#: faq_ask.module:612
-msgid "Configuration has been updated."
-msgstr "Ustawienia zostały zmienione"
-
-#: faq_ask.module:650
-msgid "Attempt to assign expert failed."
-msgstr "Nieudana próba przypisania eksperta"
-
-#: faq_ask.module:653
-msgid "Assigned expert @expert to @name (@tid)."
-msgstr "Przypisano eksperta @expert do @name (@tid)."
-
-#: faq_ask.module:714
-msgid "Faq_ask_taxonomy: Unknown op (@op) encountered"
-msgstr "Faq_ask_taxonomy Wystąpił nieznany operator (@op)"
-
-#: faq_ask.module:748
-msgid "Attempt to delete expert failed."
-msgstr "Nieudana próba usunięcia eksperta"
-
-#: faq_ask.module:751
-msgid "Deleted experts for '@name'."
-msgstr "Usunięty ekspert dla '@name'."
-
-#: faq_ask.module:771
-msgid "Faq_Ask can't determine the correct vocabulary because no FAQ nodes exist yet."
-msgstr "Faq_Ask nie może określić poprawnego słownictwa ponieważ nie istenieją żadne węzły."
-
-#: faq_ask.module:784
-msgid "Unanswered Questions"
-msgstr "Pytania bez odpowiedzi"
-
-#: faq_ask.module:803
-msgid "Number of questions to show"
-msgstr "Które pytanie mam Ci pokazać (podaj numer)"
-
-#: faq_ask.module:804
-msgid "This controls the number of questions that appear in the 'Unanswered Questions' block."
-msgstr "Kontroluje liczbę pytań wyświetlających się w kategorii "pytania bez odpowiedzi". "
-
-#: faq_ask.module:843
-msgid "If you select a question, you must answer it."
-msgstr "Jeżeli wybierzesz pytanie będziesz musiał na nie odpowiedzieć"
-
-#: faq_ask.module:873
-msgid "more..."
-msgstr "więcej..."
-
-#: faq_ask.module:892
-msgid "All Unanswered Questions"
-msgstr "Wszystkie pytania bez odpowiedzi"
-
-#: faq_ask.module:895
-msgid "You may go <a href=\"!setting\">here</a> to change the block limit."
-msgstr "Możesz przejść do <a href=\"!setting\"> tutaj </a> aby zmienić ograniczenia "
-
-#: faq_ask.module:921
-msgid "For some strange reason, I couldn't find any categories for you."
-msgstr "Z niejasnych powodów, nie mogę znaleźć kategorii właściwej dla Ciebie"
-
-#: faq_ask.module:956
-msgid "Currently there are no unanswered questions for you to view."
-msgstr "W tej chwili nie ma pytań bez odpowiedzi, które mógłbyś zobaczyć"
-
-#: faq_ask.module:306;310
-msgid "FAQ_Ask"
-msgstr "FAQ_Ask"
-
-#: faq_ask.module:733 faq_ask.info:0
-msgid "Faq_Ask"
-msgstr "Faq_Ask"
-
-#: faq_ask.module:34
-msgid "ask question"
-msgstr "zadaj pytanie"
-
-#: faq_ask.module:34
-msgid "answer question"
-msgstr "odpowiedz na pytanie"
-
-#: faq_ask.module:0
-msgid "faq_ask"
-msgstr "faq_ask"
-
-#: faq_ask.install:9
-msgid "Contact form log table."
-msgstr "Kontakt z zapisów dziennika"
-
-#: faq_ask.install:12
-msgid "User identifier for the expert."
-msgstr "Identyfikator użytkownika dla eksperta"
-
-#: faq_ask.install:18
-msgid "Taxonomy identifier of the terms for the expert."
-msgstr "Identyfikator taksonomii w terminach dla eksperta"
-
-#: faq_ask.install:58
-msgid "faq_ask module installed."
-msgstr "moduł faq_ask został zainstalowany"
-
-#: faq_ask.install:59
-msgid "faq_ask table creation failed. Please \"uninstall\" the module and retry."
-msgstr "Nieudana próba stworzenia tabeli FAQ_ASK . Proszę \"odinstaluj\" moduł i spróbuj ponownie."
-
-#: faq_ask.install:76
-msgid "faq_ask module uninstalled."
-msgstr "moduł faq_ask został odinstalowany"
-
-#: faq_ask.info:0
-msgid "Allows an unanswered question 'queue' for the FAQ module."
-msgstr "Zezwala pytaniu na oczekiwanie na moduł FAQ."
-
Index: po/es.po
===================================================================
RCS file: po/es.po
diff -N po/es.po
--- po/es.po	21 Dec 2007 13:03:27 -0000	1.1
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -1,275 +0,0 @@
-# $Id: es.po,v 1.1 2007/12/21 13:03:27 nancyw Exp $
-#
-# LANGUAGE translation of Drupal (general)
-# Copyright YEAR NAME <EMAIL@ADDRESS>
-# Generated from files:
-#  faq_ask.module,v 1.11 2007/12/20 04:19:37 nancyw
-#  faq_ask.install,v 1.1 2007/11/16 15:20:39 nancyw
-#  faq_ask.info,v 1.1 2007/11/16 15:20:39 nancyw
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: PROJECT VERSION\n"
-"POT-Creation-Date: 2007-12-20 13:51+0100\n"
-"PO-Revision-Date: 2007-12-20 21:16+0100\n"
-"Last-Translator: Javier Farreres <farreres at lsi upc edu>\n"
-"Language-Team: España <EMAIL@ADDRESS>\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=utf-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-"X-Poedit-Language: Spanish\n"
-"X-Poedit-Country: SPAIN\n"
-
-#: faq_ask.module:19
-msgid "This module is an add-on to the FAQ module that allows users with the 'ask question' permission to create a question which will be queued for an 'expert' to answer."
-msgstr "Este módulo es un añadido al módulo FAQ que permite a los usuarios con el permiso de 'hacer preguntas' crear una pregunta que quedará en cola para que un 'experto' la responda."
-
-#: faq_ask.module:20
-msgid "The module shows an abbreviated version of the FAQ form without an answer field. The node is created without the 'published' attribute. There is a block that will show the unanswered questions to the 'expert' (generally, this requires a separate role)."
-msgstr "El módulo muestra una versión abreviada del formulario FAQ sin el campo respuesta. El nodo se crea sin el atributo 'publicado'. Hay un bloque que mostrará las preguntas sin responder al 'experto' (generalmente, esto requiere un rol separado)."
-
-#: faq_ask.module:21
-msgid "Viewing of the completed question and answer pair is done by the FAQ module."
-msgstr "El visionado de la pareja completa pregunta/respuesta lo hace el módulo FAQ."
-
-#: faq_ask.module:25
-msgid "Add a question for our expert to answer. After being answered, your question and the answer will be displayed in the FAQ pages. If the question will not fit in the box below, please try to rephrase it."
-msgstr "Añadir una pregunta para que la responda nuestro experto. Despues de responderla, su pregunta y la respuesta se mostrarán en la página de preguntas y respuestas (FAQ). Si la pregunta no cabe en la caja de texto, intente parafrasearla."
-
-#: faq_ask.module:42
-msgid "ask_question"
-msgstr "ask_question"
-
-#: faq_ask.module:51
-msgid "The Faq_Ask module has been enabled."
-msgstr "El módulo Faq_Asl ha sido activado."
-
-#: faq_ask.module:51;135;303
-msgid "Please go to the <a href=\"!url\">settings page</a> to configure this module."
-msgstr "Pof favor, vaya a la  <a href=\"!url\">página de configuración</a> para configurar este módulo."
-
-#: faq_ask.module:63
-msgid "Experts"
-msgstr "Expertos"
-
-#: faq_ask.module:67
-msgid "Allows the user to configure the Ask_FAQ module."
-msgstr "Permite al usuario configurar el módulo Ask_FAQ."
-
-#: faq_ask.module:74
-msgid "Ask a question"
-msgstr "Hacer una pregunta"
-
-#: faq_ask.module:82
-msgid "Answer a question"
-msgstr "Responder una pregunta."
-
-#: faq_ask.module:90
-msgid "Edit a question"
-msgstr "Editar una pregunta"
-
-#: faq_ask.module:98
-msgid "List more unanswered questions"
-msgstr "Listar más preguntas sin responder"
-
-#: faq_ask.module:135
-msgid "Currently, there are no experts defined. "
-msgstr "Actualmente no hay expertos definidos."
-
-#: faq_ask.module:156
-msgid "Category"
-msgstr "Categoría"
-
-#: faq_ask.module:162
-msgid "Please select the correct category for your question."
-msgstr "Por favor, seleccione la categoría correcta para su pregunta."
-
-#: faq_ask.module:170
-msgid "Question"
-msgstr "Pregunta"
-
-#: faq_ask.module:178
-msgid "Enter your question here. It will be answered as soon as possible. The maximum length for the question is !len characters."
-msgstr "Entre su pregunta aquí. La responderemos lo antes posible. La longitud máxima para la pregunta son !len caracteres."
-
-#: faq_ask.module:183
-msgid "Send my question"
-msgstr "Enviar mi pregunta"
-
-#: faq_ask.module:242
-msgid "The following question has been posted in the \"!cat\" category."
-msgstr "La pregunta siguiente se ha enviado a la categoría \"!cat\"."
-
-#: faq_ask.module:245
-msgid "In order to answer it you will first need to <a href=\"!url\">login</a> to the site."
-msgstr "Para responderla tiene primero que <a href=\"!url\">ingresar</a> en el sitio."
-
-#: faq_ask.module:246
-msgid "Once logged in, you may proceed <a href=\"!url\">directly to the question</a> to answer it."
-msgstr "Una vez dentro, puede usted proceder <a href=\"!url\">directamente a la pregunta</a> para responderla."
-
-#: faq_ask.module:250
-msgid "Expert notification email sent."
-msgstr "Correo de notificación enviado al experto."
-
-#: faq_ask.module:253
-msgid "Expert notification email failed for the \"!cat\" category."
-msgstr "Ha fallado el correo de notificación al experto de la categoría \"!cat\"."
-
-#: faq_ask.module:266
-msgid "left side"
-msgstr "izquierda"
-
-#: faq_ask.module:269
-msgid "right side"
-msgstr "derecha"
-
-#: faq_ask.module:272
-msgid "top"
-msgstr "superior"
-
-#: faq_ask.module:275
-msgid "bottom"
-msgstr "inferior"
-
-#: faq_ask.module:282
-msgid "It should appear in the list at the @region of the screen momentarily."
-msgstr "Debería aparecer en la lista en la parte @region de la pantalla momentáneamente."
-
-#: faq_ask.module:285
-msgid "It should appear in the list momentarily."
-msgstr "Debería aparecer en la lista momentáneamente."
-
-#: faq_ask.module:289
-msgid "Your question has been submitted."
-msgstr "Su pregunta ha sido enviada."
-
-#: faq_ask.module:303
-msgid "The Faq_Ask module requires that FAQ \"Categorize questions.\""
-msgstr "El módulo Faq_Ask requiere que FAQ \"Categorice las preguntas.\""
-
-#: faq_ask.module:308
-msgid "Notify experts"
-msgstr "Notificar a los expertos"
-
-#: faq_ask.module:309
-msgid "If this box is checked, the expert(s) for the question will be notified via email that a question awaits them."
-msgstr "Si se activa, se les notificará a los expertos via correo electrónico que hay una pregunta esperándoles."
-
-#: faq_ask.module:317
-msgid "Question Box Length"
-msgstr "Longitud de la caja de pregunta"
-
-#: faq_ask.module:318
-msgid "This sets the length of the question box (not the question itself). This affects only the FAQ_Ask module, not the FAQ display. The recommendation is to set it as wide as your theme will allow it. Note: If resizable textareas are enabled, this setting will have no effect."
-msgstr "Establece la longitud de la de la caja de pregunta (no de la pregunta misma). Esto solamente afecta al módulo FAQ_Ask, no a la visualización de FAQ. La recomendación es ponerlo tan amplio como el tema lo permita. Nota: si están activadas las areas de texto redimensionables, esta configuración no tendrá efecto."
-
-#: faq_ask.module:330
-msgid "No roles with \"answer question\" permission were found. Please go to the <a href=\"!access\">Access Control page</a> to update your permissions."
-msgstr "No se han encontrado roles con permiso para \"responder preguntas\". Por favor, vaya a la <a href=\"!access\">página de Control de Acceso</a> para actualizar los permisos."
-
-#: faq_ask.module:340
-msgid "No vocabularies or terms were found for the \"faq\" content type . Please go to the <a href=\"!access\">Categories page</a> to update your vocabulary."
-msgstr "No se han encontrado vocabularios o términos para el tipo de contenido \"faq\". Por favor, vaya a la <a href=\"!access\">página de Categorías</a> para actualizar su vocabulario."
-
-#: faq_ask.module:369
-msgid "Expert Roles"
-msgstr "Roles de experto"
-
-#: faq_ask.module:373
-msgid "If you select different roles, you must save the configuration BEFORE selecting users below."
-msgstr "Si selecciona diferentes roles, deberá salvar la configuración ANTES de seleccionar a usuarios debajo."
-
-#: faq_ask.module:422
-msgid "!name doesn't exist. If you have just changed your role selections this may be okay."
-msgstr "!name no existe. Si acabe de cambiar sus selecciones de rol ésto podría ser correcto."
-
-#: faq_ask.module:427
-msgid "Save configuration"
-msgstr "Salvar la configuración"
-
-#: faq_ask.module:466
-msgid "Configuration has been updated."
-msgstr "La configuración ha sido actualizada."
-
-#: faq_ask.module:489
-msgid "Unanswered Questions"
-msgstr "Preguntas sin responder"
-
-#: faq_ask.module:508
-msgid "Number of questions to show"
-msgstr "Número de preguntas que mostrar"
-
-#: faq_ask.module:509
-msgid "This controls the number of questions that appear in the 'Unanswered Questions' block."
-msgstr "Ésto controla el número de preguntas que aparecen en el bloque de 'Preguntas sin responder'."
-
-#: faq_ask.module:576
-msgid "more..."
-msgstr "más..."
-
-#: faq_ask.module:595
-msgid "All Unanswered Questions"
-msgstr "Todas las preguntas sin responder"
-
-#: faq_ask.module:598
-msgid "You may go <a href=\"!setting\">here</a> to change the block limit."
-msgstr "Puede usted ir <a href=\"!setting\">aquí</a> para cambiar el límite del bloque."
-
-#: faq_ask.module:624
-msgid "For some strange reason, I couldn't find any categories for you."
-msgstr "Por alguna extraña razón, no pude encontrar categorías para usted."
-
-#: faq_ask.module:659
-msgid "Currently there are no unanswered questions for you to view."
-msgstr "Actualmente no hay preguntas sin responder que mostrarle."
-
-#: faq_ask.module:250;254
-msgid "FAQ_Ask"
-msgstr "FAQ_Ask"
-
-#: faq_ask.module:34
-msgid "ask question"
-msgstr "hacer una pregunta"
-
-#: faq_ask.module:34
-msgid "answer question"
-msgstr "responder una pregunta"
-
-#: faq_ask.module:0
-msgid "faq_ask"
-msgstr "faq_ask"
-
-#: faq_ask.install:9
-msgid "Contact form log table."
-msgstr "Tabla de registro del formulario de contacto."
-
-#: faq_ask.install:12
-msgid "User identifier for the expert."
-msgstr "Usuario identificado para experto."
-
-#: faq_ask.install:18
-msgid "Taxonomy identifier of the terms for the expert."
-msgstr "Identificador de taxonomía de los términos para el experto."
-
-#: faq_ask.install:57
-msgid "faq_ask module installed."
-msgstr "módulo faq_ask instalado."
-
-#: faq_ask.install:58
-msgid "faq_ask table creation failed. Please \"uninstall\" the module and retry."
-msgstr "creación de la tabla faq_ask fallida. Por favor, \"desinstale\" el módulo y reintente."
-
-#: faq_ask.install:70
-msgid "faq_ask module uninstalled."
-msgstr "módulo faq_ask desinstalado."
-
-#: faq_ask.info:0
-msgid "Ask an FAQ"
-msgstr "Preguntar una FAQ"
-
-#: faq_ask.info:0
-msgid "Allows an unanswered question 'queue' for the FAQ module."
-msgstr "Permite una cola de preguntas sin respuesta para el módulo FAQ."
-
Index: .project
===================================================================
RCS file: .project
diff -N .project
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ .project	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>faq_ask</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>net.sourceforge.phpeclipse.parserbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>net.sourceforge.phpeclipse.phpnature</nature>
+	</natures>
+</projectDescription>
Index: faq_ask.test
===================================================================
RCS file: faq_ask.test
diff -N faq_ask.test
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ faq_ask.test	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,603 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ *
+ * Test Faq_Ask functionality Base test class. All tests inherits this one
+ * Hugely based on code from the test file block.test by boombatower
+ */
+
+/**
+ * Base class that is extended by test cases
+ */
+class Faq_AskTestCase extends DrupalWebTestCase {
+
+
+  protected $admin_user, $answer_user, $ask_user;
+  protected $tax;
+  protected $term, $faq1, $faq2;
+
+  /**
+   * Implementation of getInfo().
+   */
+  public static function getInfo() {
+    return array(
+      'name' => t('FAQ-Ask functionality'),
+      'description' => t('Base class. No tests here.'),
+      'group' => t('FAQ-Ask'),
+    );
+  }
+
+  /**
+   * Implementation of setUp().
+   */
+  function setUp() {
+
+    // Install FAQ Module
+    parent::setUp('taxonomy', 'faq', 'faq_ask');
+
+    // Create and log in user with administer taxonomy permissions
+    $this->admin_user = $this->drupalCreateUser(array('administer taxonomy', 'administer faq', 'administer faq order', 'administer blocks'));
+    $this->drupalLogin($this->admin_user);
+
+    $this->ask_user = $this->drupalCreateUser(array('ask question', 'create faq'));
+    $this->answer_user = $this->drupalCreateUser(array('answer question', 'edit faq', 'view faq page', 'access content'));
+
+    // Set up the vocab and terms
+    $this->setupTaxonomy();
+
+    // Categorize questions
+    $this->drupalPost('admin/settings/faq/categories', array('faq_use_categories' => '1'), t('Save configuration'));  // Set the default expert to answer user
+
+    // Set answer_user as default expert
+    $roles = $this->answer_user->roles;
+    end($roles);  // Set to last role (the unique one)
+    // Set expert role
+    $this->drupalPost('admin/settings/faq/ask', array('faq_expert_role[]' => key($roles)), t('Save configuration'));
+    // Set default expert
+    $this->drupalPost('admin/settings/faq/ask', array('faq_ask_default_expert' => $this->answer_user->uid), t('Save configuration'));
+    // $this->pass('<pre>'.var_export($this->answer_user, TRUE).'</pre>');					// Show us the node loaded
+
+
+    // Select the Unanswered questions block to be configured and moved.
+    $block = array();
+    $block['module'] = 'faq_ask';
+    $block['delta'] = 0;  // Unanswered questions
+    $block['title'] = $this->randomName(8);
+
+    // Set block title to confirm that interface works and override any custom titles.
+    $this->drupalPost('admin/build/block/configure/' . $block['module'] . '/' . $block['delta'], array('title' => $block['title'], 'visibility' => '1'), t('Save block'));
+    $this->assertText(t('The block configuration has been saved.'), t('Block title set.'));
+
+  // Enable the block
+
+    // Set the created block to a specific region.
+    $edit = array();
+    $edit[$block['module'] . '_' . $block['delta'] . '[region]'] = 'left';
+    $this->drupalPost('admin/build/block', $edit, t('Save blocks'));
+
+    // Confirm that the block was moved to the proper region.
+    // TODO: Implement full region checking.
+    $this->assertText(t('The block settings have been updated.'), t('Block successfully moved to left region.'));
+
+    // Confirm that the block is being displayed.
+    // $this->assertNoText(t($block['title']), t('Block successfully being displayed on the page.'));
+    // Should not be visible unless there are unanswered questions assigned to the user logged in
+
+    // Start all tests logged out
+    $this->drupalLogout();
+
+  }
+
+  /**
+   * Tear the whole thing down again
+   */
+  function tearDown() {
+
+    // Things to tidy up like vars and stuff
+    parent::tearDown();
+  }
+
+  /**
+   * Local function to switch the Block containing unanswered questions On
+   */
+  function turnUnansQestBlockOn() {
+    $this->drupalLogin($this->admin_user);
+    $this->drupalPost('admin/build/block/configure/faq_ask/0', array('visibility' => '1'), t('Save block'));
+    $this->drupalPost('admin/build/block', array('faq_ask_0[region]' => 'left'), t('Save blocks'));
+    $this->drupalLogout();
+  }
+
+  /**
+   * Local function to switch the Block containing unanswered questions Off
+   */
+  function turnUnansQestBlockOff() {
+    $this->drupalLogin($this->admin_user);
+    $this->drupalPost('admin/build/block/configure/faq_ask/0', array('visibility' => '0'), t('Save block'));
+    $this->drupalPost('admin/build/block', array('faq_ask_0[region]' => '-1'), t('Save blocks'));
+    $this->drupalLogout();
+  }
+
+ /**
+   * Generates a random string of ASCII numeric characters (values 48 to 57).
+   *
+   * @param $length
+   *   Length of random string to generate .
+   * @return
+   *   Randomly generated string.
+   */
+  protected static function randomNumber($length = 8) {
+    $str = '';
+    for ($i = 0; $i < $length; $i++) {
+      $str .= chr(mt_rand(48, 57));
+    }
+    return $str;
+  }
+
+ /**
+   * Verify that current user has no access to page.
+   *
+   * @param $url
+   *   URL to verify.
+   */
+  function faqVerifyNoAccess($url) {
+    // Test that page returns 403 Access Denied
+    $this->drupalGet($url);
+    $this->assertResponse(403);
+  }
+
+  /**
+   * Set up the taxonomy - all vocabularies and stuff
+   * Values also stored in protected variable $tax
+   */
+  function setupTaxonomy() {
+
+  // Create Vocabulary
+  $this->tax = array();
+  $this->tax['name'] = $this->randomName(8);  // Create taxonomy vocabulary name
+  $this->tax['description'] = $this->randomName(64);
+  $this->tax['nodes[faq]'] = '1';  // Assign vocab to FAQ node types
+  $this->tax['tags'] = '1';  // Users may create tags
+  $this->tax['multiple'] = '1';  // may have more than one tag
+  $this->tax['required'] = '1';  // but minimum 1 tag
+  $this->drupalPost('admin/content/taxonomy/add/vocabulary', $this->tax, t('Save'));
+  $this->assertText(t('Created new vocabulary @name', array('@name' => $this->tax['name'])));
+
+  $this->assertText(t('FAQ'));
+
+  // Add term
+  $this->clickLink(t('add terms'), substr_count($this->drupalGetContent(), "add terms")-1); // Click the last occurrance of the link
+  $this->assertText(t('Add term to @name', array('@name' => $this->tax['name']) ));
+
+  $url = parse_url($this->getUrl());
+  if ("" == $url['query']) {
+    $array = split("/", $url['path']);
+    $this->tax['id'] = $array[4];
+  }
+  else {
+    $array = split("/", $url['query']);
+    $this->tax['id'] = $array[3];
+  }
+  $this->pass(var_export($array, TRUE));
+
+  $url = $this->getUrl();
+  $this->term = array();
+  $this->term['name'] = $this->randomName(8);  // Create taxonomy vocabulary name
+  $this->term['description'] = $this->randomName(64);
+  $this->drupalPost($url, $this->term, t('Save'));
+  $this->assertText(t('Created new term @name', array('@name' => $this->term['name'])));
+
+  }
+
+  /**
+   * Test accessing the FAQ page
+   */
+
+}
+
+class FaqAccessTestClass extends Faq_AskTestCase {
+
+  /**
+   * Implementation of getInfo().
+   */
+  public static function getInfo() {
+    return array(
+      'name' => t('Access to FAQ pages'),
+      'description' => t('Access to pages by anonymous user and logged in user with rights.'),
+      'group' => t('FAQ-Ask'),
+    );
+  }
+
+  function testFaqAccess() {
+
+  // Verify that anonymous user has no access to the faq page
+  $this->faqVerifyNoAccess('faq');
+
+    // Create and login user
+    $normal_user = $this->drupalCreateUser();
+    $this->drupalLogin($normal_user);
+  // Verify that logged in user has no access to the faq page
+  $this->faqVerifyNoAccess('faq');
+    $this->drupalLogout();
+
+    $view_faq_user = $this->drupalCreateUser(array('view faq page'));
+    $this->drupalLogin($view_faq_user);
+
+  // Verify that the faq page is visible and available but empty
+    $this->drupalGet('faq');
+  $this->assertText(t('Frequently Asked Questions'), t('FAQ page is available for view faq page permissions.'));
+
+  }
+}
+
+
+class CreateFaqTestCase extends Faq_AskTestCase {
+
+  /**
+   * Implementation of getInfo().
+   */
+  public static function getInfo() {
+    return array(
+      'name' => t('Create FAQ node'),
+      'description' => t('Add, Edit and delete FAQ nodes when FAQ Ask module is enabled.'),
+      'group' => t('FAQ-Ask'),
+    );
+  }
+
+  /**
+   * Test creating a FAQ node
+   */
+  function testFaqCreate() {
+
+    // Create and log in user with create FAQ permissions
+    $this->admin_user = $this->drupalCreateUser(array('create faq', 'view faq page'));
+    $this->drupalLogin($this->admin_user);
+
+    // Verify that the faq page is visible and available but empty
+    $this->drupalGet('faq');
+    $this->assertText(t('Frequently Asked Questions'), t('FAQ page is available for view faq page permissions.'));
+
+    // Fill in the Create FAQ node 1 form and post it
+    $this->faq1 = array();
+    $this->faq1['title'] = $this->randomName(8);
+    $this->faq1['taxonomy[tags][1]'] = $this->term['name'];  // Add existing term
+    $this->faq1['detailed_question'] = $this->randomName(16);
+    $this->faq1['body'] = $this->randomName(16);
+    $this->drupalPost('node/add/faq', $this->faq1, t('Save'));
+
+    // Check that new FAQ node has actually been created
+    $this->assertText(t('FAQ @title has been created.', array('@title' => $this->faq1['title'])));
+
+    // Fill in the Create FAQ node 2 form and post it
+    $this->faq2 = array();
+    $this->faq2['title'] = $this->randomName(8);
+    $this->faq2['taxonomy[tags][1]'] = $this->randomName(8);  // Add new term
+    $this->faq2['detailed_question'] = $this->randomName(16);
+    $this->faq2['body'] = $this->randomName(16);
+    $this->drupalPost('node/add/faq', $this->faq2, t('Save'));
+
+    // Check that new FAQ node has actually been created
+    $this->assertText(t('FAQ @title has been created.', array('@title' => $this->faq2['title'])));
+
+
+    // New user
+    $this->drupalLogout();
+
+
+    // Verify that logged in user has no access to the faq page
+    $this->faqVerifyNoAccess('faq');
+
+    // Check that the FAQ page is available and that the correct term is listed as grouping for the new FAQ node
+    $view_faq_user = $this->drupalCreateUser(array('view faq page'));
+    $this->drupalLogin($view_faq_user);
+    $this->drupalGet('faq');
+    $this->assertText(t('Frequently Asked Questions'), t('FAQ page is available for view faq page permissions.'));
+    $this->assertText($this->faq1['title'], t('Created FAQ node 1 available on FAQ page.'));
+    $this->assertText($this->faq1['taxonomy[tags][1]'], t('Term for node 1  available on FAQ page.'));
+    $this->assertText($this->faq2['title'], t('Created FAQ node 2 available on FAQ page.'));
+    $this->assertText($this->faq2['taxonomy[tags][1]'], t('Term for node 2  available on FAQ page.'));
+
+    // Navigate to FAQ node created on FAQ page
+    $this->clickLink(t($this->faq1['title']));
+    $this->assertText(t($this->faq1['body']));
+
+    // Enable categorisation of FAQ nodes
+    // Create and log in user with create and administer FAQ permissions
+    $this->admin_user = $this->drupalCreateUser(array('create faq', 'view faq page', 'administer faq'));
+    $this->drupalLogin($this->admin_user);
+
+    // faq_use_categories
+    $faqcfg = array();
+    $faqcfg['faq_use_categories'] = '1';  // Enable categorised FAQs
+    $this->drupalPost('admin/settings/faq/categories', $faqcfg, t('Save configuration'));
+    $this->drupalLogout();
+
+    $this->drupalLogin($view_faq_user);
+    $this->drupalGet('faq');
+    $this->assertText(t('Frequently Asked Questions'), t('FAQ page is available for view faq page permissions.'));
+    $this->assertText($this->faq1['title'], t('Created FAQ node 1 available on FAQ page.'));
+    $this->assertText($this->faq1['taxonomy[tags][1]'], t('Term for node 1 not available on FAQ page.'));
+    $this->assertText($this->faq2['title'], t('Created FAQ node 2 available on FAQ page.'));
+    $this->assertText($this->faq2['taxonomy[tags][1]'], t('Term for node 2 not available on FAQ page.'));
+
+    // TODO: Add update and Delete of FAQ nodes
+
+  }
+
+}
+
+
+class FaqExistsFaq_AskTestCase extends Faq_AskTestCase {
+
+  /**
+   * Implementation of getInfo().
+   */
+  public static function getInfo() {
+    return array(
+      'name' => t('Does FAQ page exist?'),
+      'description' => t('Verify that FAQ page exists when FAQ Ask module is enabled.'),
+      'group' => t('FAQ-Ask'),
+    );
+  }
+
+  /**
+   * Check for existing FAQ page and the posibility to create a FAQ by user
+   */
+  public function testFaq_AskExist() {
+
+    // Create and log in user with create FAQ permissions
+    $this->drupalLogin($this->ask_user);
+
+    $this->drupalGet("faq_ask");
+
+    // Verify that all the fields are there
+    $this->assertFieldById('edit-taxonomy-tags-' . $this->tax['id']);
+    $this->assertFieldByName('taxonomy[tags][' . $this->tax['id'] . ']');
+    $this->assertFieldById('edit-title');
+    $this->assertFieldByName('title');
+    $this->assertFieldById('edit-detailed-question');
+    $this->assertFieldByName('detailed_question');
+
+    // The answer field should not be there
+    $this->assertNoFieldByName('body');
+
+    // No published status field
+    // $this->assertNoFieldChecked('status');  // Turns out this one is not accessible for someone asking questions
+
+    // Leave the logged in state
+    $this->drupalLogout();
+  }
+}
+
+
+class CRAUDFaq_AskTestCase extends Faq_AskTestCase {
+
+  /**
+   * Implementation of getInfo().
+   */
+  public static function getInfo() {
+    return array(
+      'name' => t('CRAUD Unanswered Question'),
+      'description' => t('Create, Read, Answer, Update and Delete an Unanswered question'),
+      'group' => t('FAQ-Ask'),
+    );
+  }
+
+  /**
+   * Test creating an unanswered FAQ and verify its status
+   */
+  public function testFaq_AskCreate() {
+
+    // Verify that logged in user has no access to the faq page
+    $this->faqVerifyNoAccess('faq');
+
+    // Log in user with create FAQ permissions
+    $this->drupalLogin($this->ask_user);
+
+    // Create a FAQ Ask node.
+    $edit = array();
+    $edit['title'] = $this->randomName(8);
+    $edit['taxonomy[tags][' . $this->tax['id'] . ']'] = $this->randomName(8);
+    $edit['detailed_question'] = $this->randomName(64);
+    $this->drupalPost('faq_ask', $edit, t('Save'));
+    $this->assertText(t('FAQ @title has been created.', array('@title' => $edit['title'])));
+    $this->assertText(t('Your question has been submitted. It will appear in the FAQ listing as soon as it has been answered.'));
+
+    // Check status for FAQ node - should be not published
+    $node = $this->drupalGetNodeByTitle($edit['title']);
+    //$this->pass('<pre>' . var_export($node, TRUE) . '</pre>');  // Show us the node loaded
+    $this->assertFalse($node->status);
+
+    $this->turnUnansQestBlockOff();
+
+    // FAQ node should not be visible for user with view faq permissions
+    $this->drupalLogin($this->ask_user);
+    $this->drupalGet("faq");  // Load faq page
+    $this->assertNoText($edit['title']);  // Node should not be listed here
+    $this->drupalGet('node/' . $node->nid);  // But should be possible to open the node directly by the author who created it
+    $this->assertResponse(200);
+
+    $this->turnUnansQestBlockOn();
+
+    // Log in user with answer question. Must also have edit faq and view faq page permission
+    $this->drupalLogin($this->answer_user);
+
+    // Open unanswered question
+    // Verify that logged in user has no access to the unanswered node display
+    $this->faqVerifyNoAccess('node/' . $node->nid);
+    $this->drupalGet('node/' . $node->nid . '/edit');  // Open edit page with node
+    $this->assertResponse(200);
+
+    // Select question
+    $this->clickLink($edit['title']);  // Click the node name in unanswered questions box
+
+    // Post an answer to the question
+    $this->drupalPost('node/' . $node->nid . '/edit', array('body' => $this->randomName(64)), t('Save'));
+
+    // Create and log in user with view FAQ permissions
+    $faq_view_user = $this->drupalCreateUser(array('view faq page'));
+    $this->drupalLogin($faq_view_user);
+
+    // Verify visibility on faq page
+    $this->drupalGet("faq");  // Load faq page
+    $this->assertText($edit['title']);  // Node should be listed here
+    $this->drupalGet('node/' . $node->nid);  // It should also be possible to open the node directly
+
+    // Update FAQ
+    // Log in user with answer question. Must also have edit faq and view faq page permission
+    $this->drupalLogin($this->answer_user);
+    $edit2['title'] = 'title-' . $this->randomName(8);
+    $edit2['body']  = 'body-' . $this->randomName(64);
+    $this->drupalPost( 'node/' . $node->nid . '/edit',
+              array( 'title' => $edit2['title'],
+                'body' => $edit2['body']),
+              t('Save'));
+    $this->assertText(t('FAQ @title has been updated.', array('@title' => $edit2['title'])));
+    $this->assertText($edit2['title'], 'Title has changed');
+    $this->assertText($edit2['body'], 'Body has changed');
+
+    // Delete FAQ
+    // Try deleting faq by edit faq permission
+    $this->drupalPost(  'node/' . $node->nid . '/edit', array(), t('Delete'));
+
+    // Log in user with delete FAQ permissions
+    $this->drupalLogin($this->admin_user);
+    $this->drupalPost(  'node/' . $node->nid . '/edit', array(), t('Delete'));
+    $this->assertText(t('Are you sure you want to delete @title?', array('@title' => $edit2['title'])));
+    $this->drupalPost(  'node/' . $node->nid . '/delete', array(), t('Delete'));
+    $this->assertText(t('FAQ @title has been deleted.', array('@title' => $edit2['title'])));
+
+  }
+
+}
+
+
+class BlockFaq_AskTestCase extends Faq_AskTestCase {
+
+  /**
+   * Implementation of getInfo().
+   */
+  public static function getInfo() {
+    return array(
+      'name' => t('Ask a Question Block'),
+      'description' => t('Ask a question via the Ask a Question Block'),
+      'group' => t('FAQ-Ask'),
+    );
+  }
+
+  /**
+   * Ask a question via the block
+   */
+  function testAskQuestionBlock() {
+
+    $this->drupalLogin($this->admin_user);
+
+    // Select the Ask a Question block to be configured and moved.
+    $block = array();
+    $block['module'] = 'faq_ask';
+    $block['delta'] = 1;  // Ask a Question Block
+    $block['title'] = $this->randomName(8);
+
+    // Set block title to confirm that interface works and override any custom titles.
+    $this->drupalPost('admin/build/block/configure/' . $block['module'] . '/' . $block['delta'], array('title' => $block['title']), t('Save block'));
+    $this->assertText(t('The block configuration has been saved.'), t('Block title set.'));
+    $bid = db_result(db_query("SELECT bid FROM {blocks} WHERE module = '%s' AND delta = '%s'", array($block['module'], $block['delta'])));
+
+    // Check to see if the block was created by checking that it's in the database.
+    $this->assertNotNull($bid, t('Block found in database'));
+
+    // Swich off User login block
+    $this->drupalPost('admin/build/block', array('user_0[region]' => '-1'), t('Save blocks'));
+
+    // Set the created block to a specific region.
+    $edit = array();
+    $edit[$block['module'] . '_' . $block['delta'] . '[region]'] = 'left';
+    $this->drupalPost('admin/build/block', $edit, t('Save blocks'));
+
+    // Confirm that the block was moved to the proper region.
+    // TODO: Implement full region checking.
+    $this->assertText(t('The block settings have been updated.'), t('Block successfully moved to left region.'));
+
+    // Confirm that the block is being displayed.
+    // $this->assertText(t($block['title']), t('Block successfully being displayed on the page.'));
+
+    $this->drupalLogout();
+
+    $this->drupalLogin($this->ask_user);
+
+    // Show front page of site
+    $this->drupalGet('/node');
+
+    // Fill in a form and save
+    $edit['question'] = 'Q-' . $this->randomName(8);
+    $edit['question_detailed'] = 'DetailedQ-' . $this->randomName(16);
+    $this->drupalPost('/node/add/faq&ask=true', $edit, t('Save'));
+
+    // Check that the question is posted and unanswered
+    $this->assertText(t('FAQ @title has been created.', array('@title' => $edit['question'])));
+    $this->assertText(t('Your question has been submitted. It will appear in the FAQ listing as soon as it has been answered.'));
+
+    // Check status for FAQ node - should be not published
+    $node = $this->drupalGetNodeByTitle($edit['question']);
+    $this->assertFalse($node->status);
+
+    $this->turnUnansQestBlockOff();
+
+    // FAQ node should not be visible for user with view faq permissions
+    $this->drupalLogin($this->ask_user);
+    $this->drupalGet("faq");  // Load faq page
+    $this->assertNoText($edit['question']);  // Node should not be listed here
+    $this->drupalGet('node/' . $node->nid);  // But should be possible to open the node directly by the author who created it
+    $this->assertResponse(200);
+
+    $this->turnUnansQestBlockOn();
+
+    // Log in user with answer question. Must also have edit faq and view faq page permission
+    $this->drupalLogin($this->answer_user);
+
+    // Open unanswered question
+    // Verify that logged in user has no access to the unanswered node display
+    $this->faqVerifyNoAccess('node/' . $node->nid);
+    $this->drupalGet('node/' . $node->nid . '/edit');  // Open edit page with node
+    $this->assertResponse(200);
+
+    // Select question
+    $this->clickLink($edit['question']); // Click the node name in unanswered questions box
+
+    // Post an answer to the question
+    $this->drupalPost('node/' . $node->nid . '/edit', array('body' => $this->randomName(64)), t('Save'));
+
+    // Create and log in user with view FAQ permissions
+    $faq_view_user = $this->drupalCreateUser(array('view faq page'));
+    $this->drupalLogin($faq_view_user);
+
+    // Verify visibility on faq page
+    $this->drupalGet("faq");  // Load faq page
+    $this->assertText($edit['question']);  // Node should be listed here
+    $this->drupalGet('node/' . $node->nid);  // It should also be possible to open the node directly
+
+
+    // Turn off the block
+
+    // Set the block to the disabled region.
+    $edit = array();
+    $edit[$block['module'] . '_' . $block['delta'] . '[region]'] = '-1';
+    $this->drupalPost('admin/build/block', $edit, t('Save blocks'));
+
+    // Confirm that the block was moved to the proper region.
+    $this->assertText(t('The block settings have been updated.'), t('Block successfully move to disabled region.'));
+    $this->assertNoText(t($block['title']), t('Block no longer appears on page.'));
+
+    // For convenience of developers, put the navigation block back.
+    $edit = array();
+    $edit[$block['module'] . '_' . $block['delta'] . '[region]'] = 'left';
+    $this->drupalPost('admin/build/block', $edit, t('Save blocks'));
+    $this->assertText(t('The block settings have been updated.'), t('Block successfully move to disabled region.'));
+
+    $this->drupalPost('admin/build/block/configure/' . $block['module'] . '/' . $block['delta'], array('title' => 'Navigation'), t('Save block'));
+    $this->assertText(t('The block configuration has been saved.'), t('Block title set.'));
+
+  }
+
+}
