/[drupal]/contributions/modules/faq/faq.module
ViewVC logotype

Contents of /contributions/modules/faq/faq.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.2 - (show annotations) (download) (as text)
Tue Mar 6 20:08:19 2007 UTC (2 years, 8 months ago) by snpower
Branch: MAIN
CVS Tags: HEAD
Changes since 1.1: +510 -278 lines
File MIME type: text/x-php
DRUPAL-5 branch
1 <?php
2 // $Id$
3 /**
4 * Display help and module information
5 * @param section which section of the site we're displaying help
6 * @return help text for section
7 */
8 function faq_help($section='') {
9
10 $output = '';
11
12 switch ($section) {
13 case "admin/help#faq":
14 $output .= '<p>'. t("This module allows users with the 'administer faq' permission to create question and answer pairs which will be displayed on the 'faq' page. The 'faq' page is automatically generated from the FAQ nodes configured and the layout of this page can be modified on the settings page. Users will need the 'access content' permission in order to view the 'faq' page."). '</p>'.
15 '<p>' .t("To create a question and answer, the user must create a 'FAQ' node (Create content >> FAQ). This screen allows the user to edit the question and answer text. If the 'Taxonomy' module is enabled and there are some terms configured for the FAQ node type, it will also be possible to put the questions into different categories when editing."). '</p>'.
16 '<p>' .t("The 'Frequently Asked Questions' settings configuration screen will allow users with 'administer faq' permissions to specify different layouts of the questions and answers."). '</p>'.
17 '<p>' .t("All users with 'access content' permissions will be able to view the generated FAQ page at 'www.example.com/faq'."). '</p>';
18 return $output;
19 case "admin/modules#description":
20 return t("Allows the user to configure the layout of questions and answers on a FAQ page.");
21 case "node/add#faq":
22 return t("Add a question and answer to a FAQ list.");
23 }
24
25 }
26
27 /**
28 * Implementation of hook_perm()
29 * Define the permissions this module uses
30 */
31 function faq_perm() {
32 return array('administer faq');
33 }
34
35
36 /**
37 * Implementation of hook_access()
38 */
39 function faq_access($op, $node) {
40 if ($op == 'create' || $op == 'update' || $op == 'delete') {
41 return user_access('administer faq');
42 }
43 }
44
45 /**
46 * Implementation of hook_menu()
47 */
48 function faq_menu($may_cache) {
49 $access = user_access('administer faq');
50 $items = array();
51
52 if ($may_cache) {
53 $items[] = array('path' => 'admin/settings/faq',
54 'title' => t('Frequently Asked Questions'),
55 'callback' => 'faq_settings_page',
56 'access' => $access,
57 'description' => t('Allows the user to configure the layout of questions and answers on a FAQ page.'),
58 );
59 $items[] = array('path' => 'faq',
60 'title' => t('Frequently Asked Questions'),
61 'callback' => t('faq_page'),
62 'access' => user_access('access content'),
63 'weight' => 1
64 );
65 }
66 else {
67 $items[] = array(
68 'path' => 'admin/settings/faq/configure',
69 'title' => t('Configure'),
70 'description' => t('Allows the user to configure the layout of questions and answers on a FAQ page.'),
71 'callback' => 'drupal_get_form',
72 'callback arguments' => array('faq_settings_form'),
73 'access' => $access,
74 'type' => MENU_DEFAULT_LOCAL_TASK,
75 'weight' => -10,
76 );
77 $items[] = array('path' => 'node/add/faq',
78 'title' => t('FAQ'),
79 'access' => $access,
80 );
81 $items[] = array('path' => 'faq',
82 'title' => t('Frequently Asked Questions'),
83 'callback' => t('faq_page'),
84 'access' => user_access('access content'),
85 'weight' => 1
86 );
87
88 if (arg(0) == 'faq' && is_numeric(arg(1))) {
89 $items[] = array('path' => 'faq/' . arg(1),
90 'title' => t('Frequently Asked Questions'),
91 'callback' => 'faq_page',
92 'callback arguments' => array(arg(1)),
93 'access' => user_access('access content'),
94 'type' => MENU_CALLBACK,
95 );
96 }
97
98 }
99
100 return $items;
101 }
102
103 /**
104 * Implementation of hook_node_info()
105 */
106 function faq_node_info() {
107 return array(
108 'faq' => array(
109 'name' => t('FAQ'),
110 'module' => 'faq',
111 'description' => t('A frequently asked question and the answer.'),
112 )
113 );
114 }
115
116 /**
117 * Implementation of hook_node_name()
118 */
119 function faq_node_name($node) {
120 return t('FAQ');
121 }
122
123 function faq_form(&$node) {
124
125 // question
126 $form['title'] = array(
127 '#type' => 'textfield',
128 '#title' => t('Question'),
129 '#default_value' => $node->title,
130 '#required' => TRUE,
131 '#weight' => 0,
132 '#description' => t('Question to be answered'),
133 );
134
135 // answer
136 $form['body_filter']['body'] = array(
137 '#type' => 'textarea',
138 '#title' => t('Answer'),
139 '#default_value' => $node->body,
140 '#rows' => 10,
141 '#required' => TRUE,
142 );
143 $form['body_filter']['format'] = filter_form($node->format);
144
145 return $form;
146 }
147
148 function faq_settings_page($op = NULL, $aid = NULL) {
149
150 switch ($op) {
151 case 'edit':
152 if (is_numeric($aid)) {
153 $output = drupal_get_form('faq_settings_form');
154 }
155 break;
156 default:
157 $form[] = array(
158 '#type' => 'fieldset',
159 '#title' => t('Add another'),
160 );
161 $output .= drupal_get_form('faq_settings_form');
162 break;
163 }
164 return $output;
165 }
166
167
168 /**
169 * Define a form to upload the avatar images.
170 */
171 function faq_settings_form() {
172
173 $form['questions'] = array('#type' => 'fieldset',
174 '#title' => t('Questions and Answers'),
175 '#weight' => -1,
176 '#collapsible' => 1,
177 '#collapsed' => 0,
178 );
179 $display_options['questions_inline'] = t('Questions inline');
180 $display_options['questions_top'] = t('Clicking on question brings user to answer further down the page');
181 $display_options['hide_answer'] = t('Clicking on question opens/hides answer under question');
182 $display_options['new_page'] = t('Clicking on question opens the answer in a new page');
183
184 $form['questions']['display'] = array('#type' => 'radios',
185 '#options' => $display_options,
186 '#title' => t('Page layout'),
187 '#description' => t('This controls now the questions and answers are displayed on the page and what happens when someone clicks on the question.'),
188 '#default_value' => variable_get('faq_display', 'questions_top'),
189 );
190
191 $form['questions']['back_to_top'] = array('#type' => 'textfield',
192 '#title' => t('"Back to Top" link text'),
193 '#description' => t('This allows the user to change the text displayed for the links which return the user to the top of the page on certain page layouts. Defaults to "Back to Top". Leave blank to have no link.'),
194 '#default_value' => variable_get('faq_back_to_top', t('Back to Top')),
195 );
196
197
198 $form['category'] = array('#type' => 'fieldset',
199 '#title' => t('Categories'),
200 '#weight' => 0,
201 '#collapsible' => 1,
202 '#collapsed' => 0,
203 );
204
205 $form['category']['categories'] = array('#type' => 'checkbox',
206 '#title' => t('Categorize questions'),
207 '#description' => t('This allows the user to display the questions according to the categories configured on the add/edit FAQ page. Use of sub-categories is only recommended for large lists of questions.'),
208 '#default_value' => variable_get('faq_use_categories', FALSE),
209 );
210
211 $category_options['categories_inline'] = t('Categories inline');
212 $category_options['hide_qa'] = t('Clicking on category opens/hides questions and answers under category');
213 $category_options['new_page'] = t('Clicking on category opens the questions/answers in a new page');
214
215 $form['category']['category_display'] = array('#type' => 'radios',
216 '#options' => $category_options,
217 '#title' => t('Categories layout'),
218 '#description' => t('This controls now the categories are displayed on the page and what happens when someone clicks on the category.'),
219 '#default_value' => variable_get('faq_category_display', 'categories_inline'),
220 );
221
222 $form['update']['attach'] = array(
223 '#type' => 'submit',
224 '#value' => t('Update'),
225 '#weight' => 3,
226 );
227
228 return $form;
229 }
230
231 /**
232 * Validate the submission.
233 *
234 * Check whether:
235 * if any of the settings have changed
236 */
237 function faq_settings_form_validate($form_id, $form_values) {
238 if ($form_values['op'] == t('Update')) {
239 variable_set('faq_display', $form_values['display']);
240 variable_set('faq_back_to_top', $form_values['back_to_top']);
241 variable_set('faq_use_categories', $form_values['categories']);
242 variable_set('faq_category_display', $form_values['category_display']);
243 drupal_set_message(t('Configuration has been updated.'));
244
245 if (variable_get('faq_use_categories', FALSE) && !module_exists("taxonomy")) {
246 drupal_set_message(t("warning: Categorization of questions will not work without the 'taxonomy' module."), 'error');
247 }
248
249 }
250 }
251
252 /**
253 * Function to display the faq page
254 */
255 function faq_page($tid = 0) {
256 drupal_add_css(drupal_get_path('module', 'faq') .'/faq.css');
257
258 // get page layout
259 $faq_display = variable_get('faq_display', 'questions_top');
260
261 // get "back to top" link text
262 $back_to_top = variable_get('faq_back_to_top', t('Back to Top'));
263 $back_to_top = '<br><span class="more-link">'
264 . l(check_plain(t($back_to_top)), 'faq') . '</span>';
265
266 // find out if we should categorize the questions, if so get list of
267 // categories
268 $use_categories = variable_get('faq_use_categories', FALSE);
269 if (!module_exists("taxonomy")) $use_categories = FALSE;
270
271
272
273 // non-categorized questions and answers
274 if (!$use_categories) {
275 $result = db_query("SELECT n.title, n.nid, r.body FROM {node} n LEFT JOIN {node_revisions} r ON n.nid = r.nid AND r.vid = n.vid WHERE n.type='faq' AND n.status = 1 ORDER BY n.created DESC");
276
277 switch ($faq_display) {
278 case 'questions_top':
279 while ($node = db_fetch_object($result)) {
280 _questions_top($node, $back_to_top, '', $questions, $answers);
281 }
282 $output .= "<ul>" . $questions . "</ul>";
283 $output .= "<dl>". $answers . "</dl>";
284 break;
285
286
287 case 'hide_answer':
288 drupal_add_js(drupal_get_path('module', 'faq') .'/faq.js', 'module');
289 $output = '<dl class="faq">';
290 while ($node = db_fetch_object($result)) {
291 $output .= _hide_answer($node);
292 }
293 $output .= '</dl>';
294 break;
295
296
297 case 'questions_inline':
298 $output = "<dl>";
299 while ($node = db_fetch_object($result)) {
300 $output .= _questions_inline($node, $back_to_top);
301 }
302 $output .= "</dl>";
303 break;
304
305 case 'new_page':
306 $output = "<ul>";
307 while ($node = db_fetch_object($result)) {
308 $output .= _new_page($node);
309 }
310 $output .= "</ul>";
311 break;
312
313 } // end of switch
314 }
315
316
317
318 // categorize questions
319 else {
320 $category_display=variable_get('faq_category_display', 'categories_inline');
321 $output .= "<br>";
322
323
324 // if we're viewing a specific category/term
325 if ($tid != 0) {
326 $term = taxonomy_get_term($tid);
327 $result = taxonomy_select_nodes(array($term->tid), 'or', 0, FALSE);
328 if ($result) {
329 _display_faq_by_category($faq_display, $category_display, $result,
330 $term, $output, $output_answers);
331 }
332 $output = '<div class="content">'.$output . $output_answers .'</div>';
333 return $output;
334 }
335
336
337 $vocabularies = taxonomy_get_vocabularies("FAQ");
338 $terms = array();
339 foreach ($vocabularies as $vid => $vobj) {
340 $tree = taxonomy_get_tree($vid);
341 foreach ($tree as $term) {
342
343 switch ($category_display) {
344 case 'new_page':
345 $depth = 0;
346 while ($depth < $term->depth) {
347 $indent = '<ul class="category-indent">';
348 $output .= $indent;
349 $depth++;
350 }
351
352 $output .= "<li>" . l(t($term->name), "faq/$term->tid") . "</li>";
353
354 while ($depth > 0) {
355 $output .= '</ul>';
356 $depth--;
357 }
358 break;
359
360 case 'hide_qa':
361 drupal_add_js(drupal_get_path('module','faq').'/faq.js','module');
362
363 case 'categories_inline':
364 $result = taxonomy_select_nodes(array($term->tid), 'or', 0, FALSE);
365 if ($result) {
366 _display_faq_by_category($faq_display, $category_display, $result,
367 $term, $output, $output_answers);
368 }
369 break;
370
371 } // end of switch (category_display)
372 } // end of foreach term
373 } // end of foreach vocab
374 if ($category_display == "new_page") {
375 $output = "\n<ul>" . $output . "</ul>\n";
376 }
377 }
378
379 $output = '<div class="content">'. $output . $output_answers .'</div>';
380
381 return $output;
382 }
383
384
385
386 function _display_faq_by_category($faq_display, $category_display, $result, $term, &$output, &$output_answers) {
387
388 $depth = 0;
389 while ($depth < $term->depth) {
390 $indent = '<div class="category-indent">';
391 $output .= $indent;
392 $depth++;
393 }
394
395 $header = '<h5 class="faq_qa_header">' . t($term->name) . '</h5>';
396 if ($term->depth > 0) {
397 $header = '<h6 class="faq_qa_header">' .t($term->name). '</h6>';
398 }
399
400
401 if ($category_display == "hide_qa") {
402 $faq_qa_div_class = "faq_qa_hide";
403 }
404 else {
405 $faq_qa_div_class = "faq_qa";
406 }
407
408 switch ($faq_display) {
409 case 'questions_top':
410 $questions = NULL;
411 $answers = NULL;
412
413 $output .= $header;
414 $output .= '<div class="'.$faq_qa_div_class.'">';
415 while ($node = db_fetch_object($result)) {
416 $full_node = node_load($node->nid);
417 if ($full_node->type == "faq") {
418 _questions_top($full_node, $back_to_top, $term->tid,
419 $questions, $answers);
420 }
421 }
422 $output .= "<ul>\n" . $questions . "\n</ul>\n";
423
424 if ($category_display == "hide_qa") {
425 $output .= "<dl>\n" .$answers. "\n</dl>\n</div>";
426
427 }
428 else {
429 $output .= "</div>\n";
430 $ans_depth = 0;
431 while ($ans_depth < $term->depth) {
432 $indent = '<div class="category-indent">';
433 $output_answers .= $indent;
434 $ans_depth++;
435 }
436 $output_answers .= $header . "<dl>\n" .$answers. "\n</dl>\n";
437 while ($ans_depth > 0) {
438 $output_answers .= '</div>';
439 $ans_depth--;
440 }
441 }
442 break;
443
444
445 case 'hide_answer':
446 drupal_add_js(drupal_get_path('module','faq').'/faq.js','module');
447 $output .= $header;
448 $output .= '<div class="'.$faq_qa_div_class.'">';
449 $output .= '<dl class="faq">'."\n";
450 while ($node = db_fetch_object($result)) {
451 $full_node = node_load($node->nid);
452 if ($full_node->type == "faq") {
453 $output .= _hide_answer($full_node);
454 }
455 }
456 $output .= "</dl>\n</div>\n";
457 break;
458
459
460 case 'questions_inline':
461 $output .= $header;
462 $output .= '<div class="'.$faq_qa_div_class.'">';
463 $output .= "<dl>\n";
464 while ($node = db_fetch_object($result)) {
465 $full_node = node_load($node->nid);
466 if ($full_node->type == "faq") {
467 $output .= _questions_inline($full_node, $back_to_top);
468 }
469 }
470 $output .= "</dl>\n</div>\n";
471 break;
472
473
474 case 'new_page':
475 $output .= $header;
476 $output .= '<div class="'.$faq_qa_div_class.'">';
477 $output .= "<ul>\n";
478 while ($node = db_fetch_object($result)) {
479 $full_node = node_load($node->nid);
480 if ($full_node->type == "faq") {
481 $output .= _new_page($full_node);
482 }
483 }
484 $output .= "</ul>\n</div>\n";
485 break;
486 } // end of switch (faq_display)
487
488
489 while ($depth > 0) {
490 $output .= '</div>';
491 $depth--;
492 }
493
494 }
495
496 function _questions_top($node, $back_to_top, $tid, &$questions, &$answers) {
497 $anchor = $tid . "n" . $node->nid;
498 $this_page = ltrim(request_uri(), "/");
499 $questions .= "<li>" . l(t($node->title), $this_page, NULL, NULL, $anchor) . "</li>";
500 $answers .= "<dt>" . l(t($node->title), "node/$node->nid", array("name" => "$anchor")) . "</dt>";
501 $answers .= "<dd>" . t($node->body) . $back_to_top . "</dd>";
502 return;
503 }
504
505 function _hide_answer($node) {
506 $output .= '<dt class="faq_question">' . t($node->title) . '</dt>';
507 $output .= '<dd class="faq_answer">' . t($node->body) . '</dd>';
508 return $output;
509 }
510
511 function _questions_inline($node, $back_to_top) {
512 $output .= "<dt>" . l(t($node->title), "node/$node->nid") . "</dt>";
513 $output .= "<dd>" . t($node->body) . $back_to_top . "</dd>";
514 return $output;
515 }
516
517 function _new_page($node) {
518 $output .= "<li>" . l(t($node->title), "node/$node->nid") . "</li>";
519 return $output;
520 }

  ViewVC Help
Powered by ViewVC 1.1.2