answers.module in Answers 5.2
Same filename and directory in other branches
Enables the creation of question nodes that can be answered by posting answer nodes.
@author Amanuel Tewolde http://ticklespace.com @email myfirstname (at) companydomain above
File
answers.moduleView source
<?php
/**
* @file
* Enables the creation of question nodes that can be answered by posting answer nodes.
*
* @author Amanuel Tewolde http://ticklespace.com
* @email myfirstname (at) companydomain above
*
*/
define('ANSWERS_TYPE', 'answers_type_');
/**
* Implementation of hook_help().
*/
function answers_help($section) {
switch ($section) {
case 'admin/modules#description':
return t('Enables the creation of question and answer service.');
case 'node/add#quest':
return t('This modules provides a way for users to post questions and get answers from other users.');
}
}
/**
* Implementation of hook_node_info().
*/
function answers_node_info() {
return array(
'answers' => array(
'name' => t('Question'),
'module' => 'answers',
'description' => t("Post a question."),
'has_title' => TRUE,
'title_label' => t('Question'),
'has_body' => TRUE,
'body_label' => t('Add details'),
),
);
}
/**
* Implementation of hook_perm().
*/
function answers_perm() {
return array(
'create quests',
'edit own quests',
);
}
/**
* Implementation of hook_access().
*/
function answers_access($op, $node) {
global $user;
if ($op == 'create') {
return user_access('create quests');
}
if ($op == 'update' || $op == 'delete') {
if (user_access('edit own quests') && $user->uid == $node->uid) {
return TRUE;
}
}
}
/**
* Implementation of hook_menu().
*/
function answers_settings() {
$form['answermodules'] = array(
'#type' => 'fieldset',
'#description' => t('Select content types you wish to use to answer the questions posted.'),
'#weight' => -3,
'#title' => t('Answers Modules'),
);
$form['answermodules']['formtypes'] = array();
$form['answermodules']['formtypes'] = array_merge($form['answermodules']['formtypes'], module_invoke_all('answers', 'settings'));
$form['answers_settings'] = array(
'#type' => 'fieldset',
'#weight' => -2,
'#title' => t('General Settings'),
);
$answers_email = "\nHi %name,\n<br />\n%addername has posted a %ansertype on the quest - \" %title \".\n<br />\nView your quest: %url \n<br />\n<hr />\n\nThis is an automatic message from %site.\n<br />\n ";
$answers_subject = '@name an new answer was posted to your question: @subject';
$form['answers_settings']['answernotify'] = array(
'#type' => 'textarea',
'#title' => t('Notify email user of a posted answer'),
'#default_value' => variable_get('answernotify', $answers_email),
'#description' => t('This is the email that is sent to users. Dynamic vars available: %name, %subject, %addername, %title, %url, %ansertype and %site'),
'#weight' => 2,
'#required' => TRUE,
);
$form['answers_settings']['answernotifysubject'] = array(
'#type' => 'textfield',
'#title' => t('Subject of notify email'),
'#default_value' => variable_get('answernotifysubject', $answers_subject),
'#description' => t('This is the subject line of the email sent. Dynamic vars available: @name, @subject'),
'#weight' => 1,
'#required' => TRUE,
);
$form['answers_settings']['allow_answeranon'] = array(
'#type' => 'checkbox',
'#title' => t('Allow anonimization'),
'#options' => array(
'0',
'1',
),
'#default_value' => variable_get('allow_answeranon', 0),
'#description' => t('Allow users to post questions anonymously. NOTE: the question still belongs to the user the name is just hidden from normal users'),
'#required' => FALSE,
);
$form['answers_settings']['questlinks'] = array(
'#type' => 'checkbox',
'#title' => t('Use Drupal\'s links to show answers totals'),
'#options' => array(
'0',
'1',
),
'#default_value' => variable_get('questlinks', ''),
'#description' => t('If you plan to layout the total answers in your theme instead uncheck this box.'),
'#weight' => 3,
);
return system_settings_form($form);
}
/**
* Implementation of hook_menu().
*/
function answers_menu($may_cache) {
$items = array();
$nid = (int) arg(1);
global $user;
if ($may_cache) {
$items[] = array(
'path' => 'quest/list',
'callback' => 'answers_list',
'title' => t('Browse Quests'),
'access' => user_access('access content'),
'type' => MENU_CALLBACK,
);
}
$items[] = array(
'path' => 'admin/settings/answers',
'callback' => 'drupal_get_form',
'callback arguments' => array(
'answers_settings',
),
'title' => t('Answers settings'),
'description' => t('Configure Answers service settings'),
'access' => user_access('administer content types'),
'type' => MENU_NORMAL_ITEM,
);
return $items;
}
/*
* implement hook_load
* this loads our stuff and force disables commenting on quest nodes
* TODO: make the disable comments optional
*
*/
function answers_load($node) {
$questdetails = db_fetch_object(db_query('SELECT * FROM {quests} WHERE vid = %d', $node->vid));
$questdetails->comment = COMMENT_NODE_DISABLED;
return $questdetails;
}
/*
* implement hook_nodeapi
* this allows us to see when answer nodes are added, deleted or updated.
*
*/
function answers_nodeapi(&$node, $op, $teaser, $page) {
global $user;
switch ($op) {
case "insert":
if (variable_get(ANSWERS_TYPE . $node->type, '0')) {
if ($node->questid) {
db_query("INSERT INTO {answers} (qid, nid, uid, Status, relationscore) VALUES ('%d', '{$node->nid}', '{$node->uid}', '%d', '%d')", $node->questid, 0, 0);
$questnode = node_load($node->questid);
if ($questnode->notifyme) {
answers_notify($node->questid, $questnode->title);
}
}
}
break;
case "update":
if (variable_get(ANSWERS_TYPE . $node->type, '0')) {
if ($node->questid) {
db_query("UPDATE {answers} SET qid = '%d' WHERE nid = '%d' AND uid = '%d'", $node->questid, $node->nid, $user->uid);
}
}
break;
case "delete":
if (variable_get(ANSWERS_TYPE . $node->type, '0')) {
db_query('DELETE FROM {answers} WHERE nid = %d', $node->nid);
}
break;
}
}
function answers_notify($nid, $title, $style = 'answer') {
$subj = $title;
global $user;
$result = db_query('SELECT u.uid, u.name, u.mail, u.language FROM {users} u INNER JOIN {node} n ON u.uid = n.uid WHERE n.nid = %d', $nid);
while ($cuser = db_fetch_object($result)) {
if ($user->uid != $cuser->uid) {
$subject = t(variable_get('answernotifysubject', '@name an answer has been posted for yoru question: @subject'), array(
'@name' => $cuser->name,
'@subject' => $subj,
));
$message = variable_get('answernotify', 'drupal');
$body = t($message, array(
'%name' => $cuser->name,
'%addername' => $user->name,
'%ansertype' => $style,
'%title' => $subj,
'%url' => url('node/' . $nid, NULL, NULL, 1),
'%site' => variable_get('site_name', 'drupal'),
));
$headers["MIME-Version"] = '1.0';
$headers["Content-Transfer-Encoding"] = '8bit';
$headers["Content-Type"] = "text/html; charset='utf-8';";
$mail_success = drupal_mail('answers_notify_email', $cuser->mail, $subject, $body, variable_get('site_mail', NULL), $headers);
if (!$mail_success) {
watchdog('error', t('error mailing quest notification: ') . '"' . $cuser->name . '" <' . $cuser->mail . '>');
}
}
}
}
function answers_comment($comment, $op) {
if ($op == 'insert' || $op == 'update' && $comment->status == 1) {
$nid = $comment['nid'];
$cid = $comment['cid'];
$questnode = node_load($nid);
if ($questnode->notifyme) {
answers_notify($node->questid, $questnode->title, 'comment');
}
}
}
function answers_list() {
$ansset = 'active';
if ($_GET['uans'] == 1) {
$ansset = '';
$unanset = 'active';
$filteranswered = TRUE;
}
$tabs = '<h1 class="title">Quests list</h1><div class="tabs"><ul class="tabs primary">
<li ' . $ansset . '>' . l("All Quests", "quest/list", array(
'class' => $ansset,
)) . '</li>
<li ' . $unanset . '>' . l("Show Unanswered Only", "quest/list", array(
'class' => $unanset,
), "&uans=1") . '</li>
</ul></div>';
return $o = $tabs . theme('answers_list', $filteranswered);
}
/*
* TODO: clean this function.
* TODO: change so it accepts list of quests to dress up instead of handling the sql etc.
*/
function theme_answers_list($filterunanswered = FALSE) {
$header[] = array(
'data' => t('Quests'),
'field' => 'n.nid',
'sort' => 'DESC',
);
$sql = 'SELECT n.nid, n.vid FROM {node} n WHERE n.type = "answers" ' . tablesort_sql($header);
$result = pager_query($sql, 30, 0);
if (!$result) {
$output = "No quests available.";
}
$count1 = 0;
$count2 = 0;
while ($qnode = db_fetch_object($result)) {
$nodedata = node_load($qnode->nid);
$nodeview = node_view($nodedata, TRUE, FALSE, TRUE);
$answercount = answers_count_answers($nodedata->nid);
$odd_or_even1 = $count1 & 1;
$odd_or_even2 = $count2 & 1;
if ($filterunanswered) {
if ($answercount < 1) {
if ($odd_or_even1 == '0') {
$output .= "<div class='even'><br>" . $nodeview . "</div>";
}
else {
$output .= "<div class='odd'><br>" . $nodeview . "</div>";
}
$count1++;
}
}
else {
if ($answercount >= 0) {
if ($odd_or_even2 == '0') {
$output .= "<div class='even'><br>" . $nodeview . "</div>";
}
else {
$output .= "<div class='odd'><br>" . $nodeview . "</div>";
}
$count2++;
}
}
}
$output = '<div class="quest-list">' . $output . '</div><br /> ';
$pager = theme('pager', NULL, 30, 0);
if (!empty($pager)) {
$output .= $pager;
}
return $output;
}
function answers_form_alter($form_id, &$form) {
$answertypes = module_invoke_all('answers', 'answersinfo');
foreach ($answertypes as $type => $name) {
if ($form_id == $type . '_node_form' || $form_id == $type . '_form' || $form_id == 'node_form') {
if (arg(0) == 'node' && arg(1) == 'add' && arg(3)) {
$nid = (int) arg(3);
}
else {
$nid = answers_answersapi('question', $form['nid']['#value']);
}
$form['questid'] = array(
'#type' => 'hidden',
'#value' => $nid,
);
$form['#redirect'] = 'node/' . $nid;
}
}
}
/**
* Implementation of hook_form().
*/
function answers_form($form_values = NULL) {
$node = $form_values;
$type = node_get_types('type', 'answers');
$form['title'] = array(
'#type' => 'textfield',
'#title' => check_plain($type->title_label),
'#required' => TRUE,
'#default_value' => $node->title,
'#prefix' => '<div class="container-inline">',
'#suffix' => '</div>',
'#weight' => -5,
);
$form['body_filter']['body'] = array(
'#type' => 'textarea',
'#title' => check_plain($type->body_label),
'#default_value' => $node->body,
'#prefix' => '<div class="container-inline">',
'#suffix' => '</div>',
'#attributes' => array(
'class' => 'mceNoEditor',
),
'#required' => FALSE,
);
$form['body_filter']['filter'] = filter_form($node->format);
if (variable_get('allow_answeranon', 0)) {
$form['answeroptions']['answeranon'] = array(
'#type' => 'checkbox',
'#title' => t('Make this question anonymous (Hide my Profile)'),
'#prefix' => '<div class="questpreview answeranon">',
'#suffix' => '</div>',
'#default_value' => $node->answeranon,
'#weight' => 3,
'#required' => FALSE,
);
}
$form['answeroptions']['notifyme'] = array(
'#type' => 'checkbox',
'#title' => t('Notify me by email when I recieve new answers to this question'),
'#prefix' => '<div class="questpreview notifyme">',
'#suffix' => '</div>',
'#default_value' => $node->notifyme,
'#weight' => 3,
'#required' => FALSE,
);
return $form;
}
function answers_insert($node) {
db_query("INSERT INTO {quests} (vid, nid, notifyme, answeranon) VALUES (%d, %d, '%d', %d)", $node->vid, $node->nid, $node->notifyme, $node->answeranon);
}
function answers_delete($node) {
db_query('DELETE FROM {quests} WHERE nid = %d', $node->nid);
$tresult = db_query('SELECT * FROM {answers} WHERE qid = %d', $node->nid);
while ($answernode = db_fetch_object($tresult)) {
node_delete($answernode->nid);
}
db_query('DELETE FROM {answers} WHERE nid = %d OR qid= %d', $node->nid, $node->nid);
}
function answers_update($node) {
if ($node->revision) {
answers_insert($node);
}
else {
db_query("UPDATE {quests} SET notifyme = '%d', answeranon = %d WHERE vid = %d", $node->notifyme, $node->answeranon, $node->vid);
}
}
function answers_answersapi($op, $nid) {
switch ($op) {
case 'question':
$tresult = db_query('SELECT a.qid FROM {answers} a WHERE a.nid = "%d"', $nid);
while ($res = db_fetch_object($tresult)) {
return $res->qid;
}
break;
case 'answerlink':
$tresult = db_query('SELECT a.qid FROM {answers} a WHERE a.nid = "%d"', $nid);
while ($res = db_fetch_object($tresult)) {
return $res->qid;
}
break;
case 'qtitle':
$tresult = db_query('SELECT n.title FROM {node} n, {answers} a WHERE a.qid = n.nid AND a.nid = "%d"', $nid);
while ($res = db_fetch_object($tresult)) {
return $res->title;
}
break;
case 'theone':
break;
}
}
function answers_view($node, $teaser = FALSE, $page = FALSE) {
$path = drupal_get_path('module', 'answers');
$node = node_prepare($node, $teaser);
$node->answerlist = answers_get_answers($node, $teaser, $page);
$answercount = count($node->answerlist);
$answerbuttons = module_invoke_all('answers', 'answerbuttons', $node->nid, $answercount);
$node->answer_buttons = theme('answer_buttons', $answerbuttons, $answercount);
$node->content['answers'] = array(
'#value' => theme('answers_content', $node, $teaser),
'#weight' => 1,
);
$node->content['ansposter'] = array(
'#value' => '<div id="ansposter" style="padding: 0px; margin: 0px;"></div>',
'#weight' => 2,
);
if ($page) {
// Breadcrumb navigation
$breadcrumb[] = array(
'path' => 'quest/list',
'title' => t('Answers'),
);
$breadcrumb[] = array(
'path' => 'node/' . $node->nid,
);
menu_set_location($breadcrumb);
// TODO: change for 6.x
}
return $node;
}
function answers_get_poster($node) {
// print_r($node);
if ($node->answeranon) {
return theme('username', 0);
//apply a thin veil to hide poster
}
else {
return theme('username', user_load(array(
'uid' => $node->uid,
)));
}
}
function answers_get_answers($node, $teaser = TRUE, $page = FALSE) {
$answers = array();
$tresult = db_query('SELECT * FROM {answers} WHERE qid = %d ORDER BY nid DESC ', $node->nid);
$count = 0;
while ($answernode = db_fetch_object($tresult)) {
$odd_or_even = $count & 1;
$ansnode = node_load($answernode->nid);
if ($teaser) {
$rendered = module_invoke($ansnode->type, 'answers', 'embedded', $ansnode->nid);
if (is_array($rendered)) {
$rendered = implode(' ', $rendered);
}
$answers[$ansnode->type][] = theme('answers_answer', $node, $rendered, '0');
}
else {
$ansnode = node_load($answernode->nid);
$rendered = node_view($ansnode, $teaser, FALSE, TRUE);
$answers[$ansnode->type][] = theme('answers_answer', $node, $rendered, $odd_or_even);
}
$count++;
}
return $answers;
}
function answers_count_answers($nid) {
return db_result(db_query('SELECT count(nid) FROM {answers} WHERE qid = %d ', $nid));
}
function answers_link_alter(&$node, &$links) {
if ($node->type == 'answers' || $node->type == 'simpleresp') {
unset($links['node_read_more']);
}
}
function theme_answer_buttons($buttons) {
return '<div class="answerbuttons">' . implode(' | ', $buttons) . '</div>';
}
function theme_answers_answer($node, $rendered, $odd_or_even) {
if ($odd_or_even == '0') {
return '<div class="questitem oddans ' . $node->type . '">' . $rendered . '<br></div>';
}
else {
return '<div class="questitem evenans ' . $node->type . '">' . $rendered . '<br></div>';
}
}
function theme_answers_content($node, $teaser = FALSE) {
if (!$teaser) {
foreach ($node->answerlist as $type => $data) {
$answers .= implode(' ', $data);
}
if ($answers) {
$output = '<h3 class="title">Posted Answers</h3>';
$output .= '<div class="answers" style="margin: 18px;margin-top: 8px;">' . $answers . '</div>';
}
else {
$output .= '<span class="title">No answers posted yet</span>';
}
}
$output .= $node->answer_buttons;
return $output;
}
function answers_link($type, $node = 0, $teaser = FALSE) {
$questlinks = variable_get('questlinks', '');
if ($questlinks) {
$links = array();
global $user;
if ($user->uid == 0 && $node->type == 'answers') {
// $links['answerlogin']['title'] = t(' ');
$links['loganswers'] = array(
'title' => t('You must be signed in to post <a href="/user/register">Register</a> | <a href="/user/login">Sign In</a>'),
'html' => 'true',
);
}
if ($node->type == 'answers' && $teaser) {
$result = db_query_range("SELECT count(distinct(q.nid)) as items FROM {answers} q WHERE q.qid = %d", $node->nid, 0, 100);
while ($znode = db_fetch_object($result)) {
if ($znode->items == 1) {
$links['qitem']['title'] .= $znode->items . " answer";
}
else {
$links['qitem']['title'] .= $znode->items . " answers";
}
}
}
return $links;
}
}
Functions
Name | Description |
---|---|
answers_access | Implementation of hook_access(). |
answers_answersapi | |
answers_comment | |
answers_count_answers | |
answers_delete | |
answers_form | Implementation of hook_form(). |
answers_form_alter | |
answers_get_answers | |
answers_get_poster | |
answers_help | Implementation of hook_help(). |
answers_insert | |
answers_link | |
answers_link_alter | |
answers_list | |
answers_load | |
answers_menu | Implementation of hook_menu(). |
answers_nodeapi | |
answers_node_info | Implementation of hook_node_info(). |
answers_notify | |
answers_perm | Implementation of hook_perm(). |
answers_settings | Implementation of hook_menu(). |
answers_update | |
answers_view | |
theme_answers_answer | |
theme_answers_content | |
theme_answers_list | |
theme_answer_buttons |
Constants
Name | Description |
---|---|
ANSWERS_TYPE | @file Enables the creation of question nodes that can be answered by posting answer nodes. |