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

Contents of /contributions/modules/advanced_forum/advanced_forum.module

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


Revision 1.150 - (show annotations) (download) (as text)
Fri May 22 15:22:24 2009 UTC (6 months ago) by michellec
Branch: MAIN
CVS Tags: HEAD
Changes since 1.149: +2 -2 lines
File MIME type: text/x-php
#445696 by KaleWorsley: Fixed typo that set image titles to null which forced them equal to the alt.
1 <?php
2 // $Id: advanced_forum.module,v 1.149 2009/04/20 02:11:18 michellec Exp $
3
4 /**
5 * @file
6 * Enables the look and feel of other popular forum software.
7 */
8
9 // DRUPAL HOOKS **************************************************************/
10
11 /**
12 * Implementation of hook_perm().
13 */
14 function advanced_forum_perm() {
15 return array('administer advanced forum',
16 'view forum statistics');
17 }
18
19 /**
20 * Implementation of hook_menu().
21 */
22 function advanced_forum_menu() {
23 $items['forum/markasread'] = array(
24 'access callback' => 'advanced_forum_markasread_access',
25 'page callback' => 'advanced_forum_markasread',
26 'type' => MENU_CALLBACK,
27 );
28 $items['admin/settings/advanced-forum'] = array(
29 'access arguments' => array('administer advanced forum'),
30 'description' => 'Configure Advanced Forum with these settings.',
31 'page arguments' => array('advanced_forum_settings_page'),
32 'page callback' => 'drupal_get_form',
33 'title' => 'Advanced Forum',
34 );
35 return $items;
36 }
37
38 /**
39 * Implementation of hook_menu_alter().
40 *
41 * Take over the forum page creation so we can add more information.
42 */
43 function advanced_forum_menu_alter(&$callbacks) {
44 $callbacks['forum']['page callback'] = 'advanced_forum_page';
45 }
46
47 /**
48 * Implementation of hook_theme().
49 */
50 function advanced_forum_theme() {
51 $items['advf_forum_statistics'] = array(
52 'template' => 'advf-forum-statistics',
53 );
54
55 $items['advanced_forum_topic_legend'] = array(
56 'template' => 'advanced_forum-topic-legend',
57 );
58
59 $items['advanced_forum_topic_header'] = array(
60 'template' => 'advanced_forum-topic-header',
61 'arguments' => array(
62 'node' => NULL,
63 'comment_count' => NULL,
64 )
65 );
66
67 $items['advanced_forum_forum_legend'] = array(
68 'template' => 'advanced_forum-forum-legend',
69 );
70
71 $items['advanced_forum_user_picture'] = array(
72 'arguments' => array(
73 'account' => NULL,
74 )
75 );
76
77 $items['advanced_forum_reply_link'] = array(
78 'arguments' => array(
79 'node' => NULL,
80 )
81 );
82
83 return $items;
84 }
85
86 /**
87 * Implementation of hook_theme_registry_alter().
88 */
89 function advanced_forum_theme_registry_alter(&$theme_registry) {
90 // Kill the next/previous forum topic navigation links.
91 if (!variable_get('advanced_forum_use_topic_navigation', FALSE)) {
92 foreach ($theme_registry['forum_topic_navigation']['preprocess functions'] as $key => $value) {
93 if ($value = 'template_preprocess_forum_topic_navigation') {
94 unset($theme_registry['forum_topic_navigation']['preprocess functions'][$key]);
95 }
96 }
97 }
98
99 // --- The following section manipulates the theme registry so the .tpl files
100 // --- for the given templates can be found first in the (sub)theme directory
101 // --- then in ancestor themes, if any, then in the designated styles
102 // --- directory for advanced forum, and finally in the advanced forum naked
103 // --- style as a base style.
104
105 // Affected templates
106 $templates = array('node',
107 'comment',
108 'comment_wrapper',
109 'forums',
110 'forum_list',
111 'forum_topic_list',
112 'forum_icon',
113 'forum_submitted',
114 'author_pane',
115 'advf_forum_statistics',
116 'advanced_forum_topic_legend',
117 'advanced_forum_forum_legend',
118 'advanced_forum_topic_header',
119 );
120
121 // Find all our ancestor themes and put them in an array.
122 global $theme;
123 $themes = list_themes();
124
125 $ancestor_paths = array();
126 $ancestor = $theme;
127 while ($ancestor && isset($themes[$ancestor]->base_theme)) {
128 array_unshift($ancestor_paths, dirname($themes[$themes[$ancestor]->base_theme]->filename));
129 $ancestor = $themes[$ancestor]->base_theme;
130 }
131
132 $current_style = advanced_forum_path_to_style();
133 $naked_path = drupal_get_path('module', 'advanced_forum') . '/styles/naked';
134 foreach ($templates as $template) {
135 // Sanity check in case the template is not being used.
136 if (is_array($theme_registry[$template])) {
137
138 // If there was a path in there, store it.
139 $existing_path = array_shift($theme_registry[$template]['theme paths']);
140
141 // Slide the paths we are adding in before the existing one.
142 if ($naked_path == $current_style) {
143 // The style is already naked, so no need to add it twice.
144 array_unshift($theme_registry[$template]['theme paths'], $existing_path, $current_style);
145 }
146 else {
147 // Style is not naked so slip naked in as a default style.
148 array_unshift($theme_registry[$template]['theme paths'], $existing_path, $naked_path, $current_style);
149 }
150
151 // If there are any ancestor paths (ie: we are in a subtheme, add those)
152 foreach ($ancestor_paths as $ancestor_path) {
153 $theme_registry[$template]['theme paths'][] = $ancestor_path;
154 }
155
156 // Put the active theme's path last since that takes precidence.
157 $theme_registry[$template]['theme paths'][] = advanced_forum_path_to_theme();
158 }
159 }
160 }
161
162 // SETTINGS PAGE *************************************************************/
163
164 /**
165 * Defines the Advanced Forum settings form.
166 */
167 function advanced_forum_settings_page() {
168 /* General settings */
169 $form['advanced_forum_general'] = array(
170 '#type' => 'fieldset',
171 '#title' => t('General'),
172 '#collapsible' => TRUE,
173 '#collapsed' => FALSE,
174 );
175
176 // Choose style
177 $options = array();
178 $available_styles = advanced_forum_get_styles();
179 foreach ($available_styles as $style_name => $style) {
180 $options[$style_name] = $style_name;
181 }
182
183 $form['advanced_forum_general']['advanced_forum_style'] = array(
184 '#type' => 'select',
185 '#title' => t('Advanced forum style'),
186 '#options' => $options,
187 '#description' => t('Choose which style to use for your forums. This will apply independent of site theme.'),
188 '#default_value' => variable_get('advanced_forum_style', 'naked'),
189 );
190
191 // Choose image directory
192 $form['advanced_forum_general']['advanced_forum_image_directory'] = array(
193 '#type' => 'textfield',
194 '#title' => t('Image directory'),
195 '#size' => 50,
196 '#description' => t('Images are assumed to be in the "images" subdirectory of your style. If you need images to be somewhere else, put the full path here.'),
197 '#default_value' => variable_get('advanced_forum_image_directory', ''),
198 );
199
200 // Use buttons for links
201 $form['advanced_forum_general']['advanced_forum_button_links'] = array(
202 '#type' => 'checkbox',
203 '#title' => t('Use graphical buttons for links'),
204 '#default_value' => variable_get('advanced_forum_button_links', 1),
205 '#description' => t('Included buttons are in English. Uncheck this to use translatable links instead.'),
206 );
207
208 // Theme all site comments as forums
209 $form['advanced_forum_general']['advanced_forum_theme_all_comments'] = array(
210 '#type' => 'checkbox',
211 '#title' => t('Treat all site comments like forum posts'),
212 '#default_value' => variable_get('advanced_forum_theme_all_comments', 0),
213 '#description' => t('Choosing yes causes advanced forum to consider every comment a forum comment and attempt to theme it that way. Some changes to your theme may be required.'),
214 );
215
216 /* Forum / topic list settings */
217 $form['advanced_forum_lists'] = array(
218 '#type' => 'fieldset',
219 '#title' => t('Forum and topic lists'),
220 '#collapsible' => TRUE,
221 '#collapsed' => FALSE,
222 );
223
224 // Hide 'created' column
225 $form['advanced_forum_lists']['advanced_forum_hide_created'] = array(
226 '#type' => 'checkbox',
227 '#title' => t('Hide the created column on the topic list'),
228 '#default_value' => variable_get('advanced_forum_hide_created', 0),
229 '#description' => t('This allows you to hide the created column on the topic list. Useful if you want to move the created by information to underneath the topic title.'),
230 );
231
232 // Pager max
233 $form['advanced_forum_lists']['advanced_forum_topic_pager_max'] = array(
234 '#type' => 'textfield',
235 '#title' => t('Maximum number of pages to show on per title pager'),
236 '#size' => 5,
237 '#description' => t('Used on the pager under topic titles in topic list. e.g. entering 5 will get you 1,2,3,4 ... 10'),
238 '#default_value' => variable_get('advanced_forum_topic_pager_max', 5),
239 );
240
241 // Retrieve new comments on forum listing
242 $form['advanced_forum_lists']['advanced_forum_get_new_comments'] = array(
243 '#type' => 'checkbox',
244 '#title' => t('Get the number of new comments per forum on the forum list'),
245 '#default_value' => variable_get('advanced_forum_get_new_comments', 0),
246 '#description' => t('Core forum shows the number of new topics. If checked, Advanced Forum will get the number of new comments as well and show it under "posts" on the forum overview. Slow query not recommended on large forums.'),
247 );
248
249 // Title length max
250 $form['advanced_forum_lists']['advanced_forum_topic_title_length'] = array(
251 '#type' => 'textfield',
252 '#title' => t('Number of characters to display for the topic title'),
253 '#size' => 5,
254 '#description' => t('Used on main forum page. Enter 0 to use the full title.'),
255 '#default_value' => variable_get('advanced_forum_topic_title_length', 15),
256 );
257
258 // Time ago cutoff
259 $form['advanced_forum_lists']['advanced_forum_time_ago_cutoff'] = array(
260 '#type' => 'textfield',
261 '#title' => t('Number of hours before switching to date posted in displays'),
262 '#size' => 5,
263 '#description' => t('Will show "time ago" until this cutoff and then switch to actual date posted .'),
264 '#default_value' => variable_get('advanced_forum_time_ago_cutoff', 48),
265 );
266
267 /* Topic settings */
268 $form['advanced_forum_topics'] = array(
269 '#type' => 'fieldset',
270 '#title' => t('Topics'),
271 '#collapsible' => TRUE,
272 '#collapsed' => FALSE,
273 );
274
275 // Use topic navigation
276 $form['advanced_forum_topics']['advanced_forum_use_topic_navigation'] = array(
277 '#type' => 'checkbox',
278 '#title' => t('Use topic navigation'),
279 '#default_value' => variable_get('advanced_forum_use_topic_navigation', 0),
280 '#description' => t('Core forum gets the next and previous topics and shows links to them under the top post. This is turned off by default as the query has performance issues and the placement of the links is poor.'),
281 );
282
283
284 if (module_exists('imagecache')) {
285 $options = array('' => '');
286 $presets = imagecache_presets();
287 foreach ($presets AS $preset) {
288 $options[$preset['presetname']] = $preset['presetname'];
289 }
290
291 $form['advanced_forum_topics']['advanced_forum_user_picture_preset'] = array(
292 '#type' => 'select',
293 '#title' => t('User picture preset'),
294 '#options' => $options,
295 '#description' => t('Imagecache preset to use for forum avatars. Leave blank to not use this feature.'),
296 '#default_value' => variable_get('advanced_forum_user_picture_preset', ''),
297 );
298 }
299
300 // Send our form to Drupal to make a settings page
301 return system_settings_form($form);
302 }
303
304 // TEMPLATE PREPROCESS *******************************************************/
305
306 /**
307 * Preprocesses template variables for the author pane.
308 */
309 function advanced_forum_preprocess_author_pane(&$variables) {
310 // Author pane is used in various places. The only way to be sure to only
311 // hit it when we are using it is to check the template suggestion.
312 if ($variables['template_suggestion'] == 'advf-author-pane') {
313 // Attempt to override the user picture fetched by Author Pane from core.
314 $sized_picture = theme('advanced_forum_user_picture', $variables['account']);
315 if (!empty($sized_picture)) {
316 $variables['picture'] = $sized_picture;
317 }
318 }
319 }
320
321 /**
322 * Preprocesses template variables for the topic header template.
323 */
324 function advanced_forum_preprocess_advanced_forum_topic_header(&$variables) {
325 $variables['template_files'][] = 'advanced_forum-topic-header';
326
327 // Build the reply link / button
328 $variables['reply_link'] = theme('advanced_forum_reply_link', $variables['node']);
329
330 // Total & new replies
331 if (!empty($variables['comment_count'])) {
332 $variables['total_posts'] = format_plural($variables['comment_count'], '1 reply', '@count replies');
333 $variables['last_post'] = advanced_forum_last_post_link($variables['node']);
334 }
335 else {
336 $variables['total_posts'] = t('No replies');
337 }
338
339 $variables['new_posts'] = advanced_forum_first_new_post_link($variables['node'], $variables['comment_count']);
340 }
341
342 /**
343 * Theme function to format the reply link at the top/bottom of topic.
344 */
345 function theme_advanced_forum_reply_link($node) {
346 if (user_access('post comments')) {
347 if ($node->comment == COMMENT_NODE_READ_WRITE) {
348 if (variable_get('comment_form_location_'. $node->type, COMMENT_FORM_SEPARATE_PAGE) == COMMENT_FORM_SEPARATE_PAGE) {
349 // Comment form on seperate page
350 $links['topic_reply'] = array(
351 'title' => t('Post Reply'),
352 'href' => "comment/reply/$node->nid",
353 'attributes' => array('title' => t('Share your thoughts and opinions related to this posting.')),
354 'fragment' => 'comment-form'
355 );
356
357 }
358 else {
359 // Comment form is already on the page
360 $links['topic_reply'] = array(
361 'title' => t('Post Reply'),
362 'href' => $_GET['q'],
363 'attributes' => array('title' => t('Share your thoughts and opinions related to this posting.')),
364 'fragment' => 'comment-form',
365 'query' => ($_GET['page']) ? "page=" . $_GET['page'] : NULL,
366 );
367 }
368
369 // Change to using a button if so set
370 if (variable_get('advanced_forum_button_links', 1)) {
371 $links['topic_reply']['title'] = advanced_forum_theme_image(t('post-reply.png'), t('Post reply'));
372 $links['topic_reply']['html'] = TRUE;
373 }
374 }
375 else {
376 // Post is locked
377 $links['topic_locked'] = array(
378 'title' => t('Topic Locked'),
379 'attributes' => array('title' => t('This topic is locked')),
380 );
381
382 // Change to using a button if so set
383 if (variable_get('advanced_forum_button_links', 1)) {
384 $links['topic_locked']['title'] = advanced_forum_theme_image(t('locked-topic.png'), t('Locked'));
385 $links['topic_locked']['html'] = TRUE;
386 }
387 }
388 }
389 else {
390 // User does not have rights to post
391 $links['comment_forbidden']['title'] = theme('comment_post_forbidden', $node);
392 $links['comment_forbidden']['html'] = TRUE;
393 }
394
395 return theme('links', $links, array('class' => 'forum-links'));
396 }
397
398 /**
399 * Preprocesses template variables for the node template.
400 */
401 function advanced_forum_preprocess_node(&$variables) {
402 if (!advanced_forum_treat_as_forum_post('node', $variables)) {
403 // We only deal with forum posts.
404 return;
405 }
406
407 // Determine the template file to use for the node.
408 if (isset($_GET['page']) && $_GET['page'] > 0) {
409 // This is the repeated node on the top of subsequent pages.
410 // We send this to a special .tpl so people can adjust it to their needs.
411 $variables['template_files'][] = "advf-forum-repeat-post";
412 }
413 elseif (arg(1) == 'reply') {
414 // Use the preview version
415 $variables['template_files'][] = "advf-forum-preview-post";
416 }
417 else {
418 // Use our combined node/comment template file
419 $variables['template_files'][] = "advf-forum-post";
420 }
421
422 // The node is the first post, aka topic head
423 $variables['top_post'] = TRUE;
424
425 // Build the topic header
426 $variables['topic_header'] = theme('advanced_forum_topic_header', $variables['node'], $variables['comment_count']);
427
428 /* Node links changes */
429 // Change first post from "add comment" to "Reply"
430 if (!empty($variables['node']->links) && !empty($variables['node']->links['comment_add'])) {
431 $variables['node']->links['comment_add']['title'] = t('Reply');
432 }
433
434 // Change links over to buttons when possible and wanted.
435 _advanced_forum_buttonify_links($variables['node']->links);
436
437 // Remake the links with our changes
438 $variables['links'] = theme('links', $variables['node']->links, array('class' => 'links inline forum-links'));
439
440 // Make an array version of $links
441 $variables['links_array'] = $variables['node']->links;
442
443 // User information / author pane
444 $variables['account'] = user_load(array('uid' => $variables['node']->uid));
445 $variables['author_pane'] = theme('author_pane', $variables['account'], advanced_forum_path_to_images(), 'advf-author-pane');
446
447 // Load the signature.
448 if (module_exists('signature_forum')) {
449 // If Signature For Forums is installed, use that
450 $variables['signature'] = signature_forum_get_signature($variables['node']);
451 }
452 elseif (variable_get('user_signatures', 0)) {
453 // Otherwise load Drupal's built in one, if enabled.
454 $variables['signature'] = check_markup($variables['account']->signature, $variables['node']->format);
455 }
456 }
457
458 /**
459 * Preprocesses template variables for the comment template.
460 */
461 function advanced_forum_preprocess_comment(&$variables) {
462 if (advanced_forum_treat_as_forum_post('comment', $variables)) {
463 if (arg(1) == 'reply') {
464 // Use the preview version
465 $variables['template_files'][] = "advf-forum-preview-post";
466 }
467 else {
468 // Use our combined node/comment template file
469 $variables['template_files'][] = 'advf-forum-post';
470 }
471
472 // This is a comment, not the node.
473 $variables['top_post'] = FALSE;
474
475 // Just use the date for the submitted on.
476 $variables['submitted'] = format_date($variables['comment']->timestamp);
477
478 // Assign the comment to the content variable for consistancy with nodes.
479 $variables['content'] = $variables['comment']->comment;
480
481 // User information
482 $account_id = $variables['comment']->uid;
483 if ($account_id == 0) {
484 // Anonymous user. Make a fake user object for theme_username
485 $variables['account']->name = $variables['comment']->name;
486 $variables['account']->homepage = $variables['comment']->homepage;
487 }
488 else {
489 // Load up the real user object
490 $variables['account'] = user_load(array('uid' => $variables['comment']->uid));
491 }
492
493 // Create the author pane
494 $variables['author_pane'] = theme('author_pane', $variables['account'], advanced_forum_path_to_images(), 'advf-author-pane');
495
496 if (arg(1) != 'reply') {
497 // Because the $links array isn't available here, we recreate it
498 $node = node_load($variables['comment']->nid);
499 $links = module_invoke_all('link', 'comment', $variables['comment']);
500 drupal_alter('link', $links, $node);
501 unset($links['comment_parent']);
502
503 // Iconify common links (optional to avoid translation issues)
504 _advanced_forum_buttonify_links($links);
505
506 // Remake the links with our changes
507 $variables['links'] = theme('links', $links, array('class' => 'links forum-links'));
508 $variables['links_array'] = $links;
509 }
510
511 // Since we have to load the node anyway for our links trick, make it avail
512 $variables['node'] = $node;
513
514 // Title
515 if (variable_get('comment_subject_field_' . $node->type, 1) == 0) {
516 // if comment titles are disabled, don't display it.
517 $variables['title'] = '';
518 }
519 else {
520 // Assign the subject to the title variable for consistancy with nodes.
521 $variables['title'] = check_plain($variables['comment']->subject);
522 }
523
524 // Comment number with link
525 if (!isset($post_number)) {
526 static $post_number = 0;
527 }
528 _advanced_forum_topic_nid($variables['node']->nid);
529
530 $post_per_page = _comment_get_display_setting('comments_per_page', $variables['node']);
531 $page_number = $_GET['page'];
532 if (!$page_number) {
533 $page_number = 0;
534 }
535
536 $post_number++;
537 $fragment = 'comment-' . $variables['comment']->cid;
538 $query = ($page_number) ? 'page=' . $page_number : NULL;
539 $linktext = '#' . (($page_number * $post_per_page) + $post_number);
540 $linkpath = 'node/' . _advanced_forum_topic_nid();
541 $variables['comment_link'] = l($linktext, $linkpath, array('query' => $query, 'fragment' => $fragment));;
542
543 // Link to page created by Comment Page module, if it exists
544 $variables['page_link'] = '';
545 if (!empty($variables['comment']->page_url) && !(arg(0) == 'comment' && arg(1) == $variables['comment']->cid)) {
546 $variables['page_link'] = l(t('(permalink)'), $variables['comment']->page_url);
547 }
548
549 // Load the signature.
550 if (module_exists('signature_forum')) {
551 // If Signature For Forums is installed, use that
552 $variables['signature'] = signature_forum_get_signature($variables['comment']);
553 }
554 elseif (variable_get('user_signatures', 0)) {
555 if ($variables['account']->signature) {
556 // Otherwise load Drupal's built in one, if enabled.
557 $variables['signature'] = check_markup($variables['account']->signature, $variables['comment']->format);
558 }
559 }
560 }
561 }
562
563 function advanced_forum_preprocess_comment_wrapper(&$variables) {
564 if (advanced_forum_treat_as_forum_post('comment-wrapper', $variables)) {
565 $variables['template_files'][] = 'advf-comment-wrapper';
566
567 $variables['reply_link'] = '';
568 if ($variables['node']->comment != COMMENT_NODE_READ_WRITE || variable_get('comment_form_location_'. $variables['node']->type, COMMENT_FORM_SEPARATE_PAGE) == COMMENT_FORM_SEPARATE_PAGE) {
569 // If the post is locked or the comment form is on a seperate page, build
570 // the reply/locked link / button
571 $variables['reply_link'] = theme('advanced_forum_reply_link', $variables['node']);
572 }
573 }
574 }
575
576 /**
577 * Preprocesses template variables for the forum template.
578 *
579 * This function adds additional functionality to the core forum preprocess.
580 */
581 function advanced_forum_preprocess_forums($variables) {
582 $variables['template_files'][] = 'advf-forums';
583
584 if (empty($variables['topics'])) {
585 // We don't want the links on the top of the forum overview
586 $variables['links_orig'] = $variables['links'];
587 $variables['links'] = array();
588 $variables['forum_description'] = '';
589 }
590 else {
591 // Grab the forum description and make it available to the template file
592 $forum = taxonomy_get_term($variables['tid']);
593 $variables['forum_description'] = $forum->description;
594
595 // To avoid translation issues, make the button version optional
596 if (variable_get('advanced_forum_button_links', 1)) {
597 if (isset($variables['links']['forum'])) {
598 $title_image = advanced_forum_theme_image(t('new-topic.png'), t('New topic'));
599 $variables['links']['forum']['title'] = $title_image;
600 $variables['links']['forum']['html'] = TRUE;
601 }
602
603 if (isset($variables['links']['poll'])) {
604 $title_image = advanced_forum_theme_image(t('new-poll.png'), t('New poll'));
605 $variables['links']['poll']['title'] = $title_image;
606 $variables['links']['poll']['html'] = TRUE;
607 }
608 }
609 }
610
611 // Add in the mark as read link if user has access
612 if (advanced_forum_markasread_access()) {
613 $tid = $variables['tid'];
614 if ($tid) {
615 $title = t('Mark all topics read');
616 $link = "forum/markasread/$tid";
617 }
618 else {
619 $title = t('Mark all forums read');
620 $link = "forum/markasread";
621 }
622
623 // To avoid translation issues, make the button version optional
624 if (variable_get('advanced_forum_button_links', 1)) {
625 $title_image = advanced_forum_theme_image(t('mark-read.png'), t('Mark read'));
626 $variables['links']['markasread'] = array('title' => $title_image, 'href' => $link, 'html' => TRUE);
627 $variables['links_orig']['markasread'] = array('title' => $title_image, 'href' => $link, 'html' => TRUE);
628 }
629 else {
630 $variables['links']['markasread'] = array('title' => $title, 'href' => $link);
631 $variables['links_orig']['markasread'] = array('title' => $title, 'href' => $link);
632 }
633 }
634 }
635
636 /**
637 * Preprocesses template variables for the forum statistics template.
638 */
639 function advanced_forum_preprocess_advf_forum_statistics(&$variables) {
640 $variables['template_files'][] = 'advf-forum-statistics';
641
642 $variables['topics'] = advanced_forum_statistics_topics();
643 $variables['posts'] = advanced_forum_statistics_comments() + $variables['topics'];
644 $variables['users'] = advanced_forum_statistics_users();
645
646 $authenticated_users = advanced_forum_statistics_online_users();
647 $variables['online_users'] = implode(', ', $authenticated_users);
648 $variables['current_users'] = count($authenticated_users);
649 $variables['current_guests'] = sess_count(time() - variable_get('user_block_seconds_online', 900));
650 $variables['current_total'] = $variables['current_users'] + $variables['current_guests'];
651
652 $latest_user = advanced_forum_statistics_latest_user();
653 $variables['latest_user'] = theme('username', $latest_user);
654 }
655
656 /**
657 * Preprocesses template variables for the forum statistics template.
658 */
659 function advanced_forum_preprocess_advanced_forum_forum_legend(&$variables) {
660 $variables['template_files'][] = 'advanced_forum-forum-legend';
661
662 $variables['folder_new_posts'] = advanced_forum_theme_image(t('forum-folder-new-posts.png'), t('Forum Contains New Posts'));
663 $variables['folder_default'] = advanced_forum_theme_image(t('/forum-folder.png'), t('Forum Contains No New Posts'));
664 $variables['folder_locked'] = advanced_forum_theme_image(t('forum-folder-locked.png'), t('Forum is Locked'));
665 }
666
667 function advanced_forum_preprocess_advanced_forum_topic_legend(&$variables) {
668 $variables['template_files'][] = 'advanced_forum-topic-legend';
669
670 $variables['topic_new'] = advanced_forum_theme_image(t('topic-new.png'), t('New Posts'));
671 $variables['topic_hot_new'] = advanced_forum_theme_image(t('topic-hot-new.png'), t('Hot Thread (New)'));
672 $variables['topic_hot'] = advanced_forum_theme_image(t('topic-hot.png'), t('Hot Thread (No New)'));
673 $variables['topic_default'] = advanced_forum_theme_image(t('topic-default.png'), t('No New Posts'));
674 $variables['topic_sticky'] = advanced_forum_theme_image(t('topic-sticky.png'), t('Sticky Thread'));
675 $variables['topic_closed'] = advanced_forum_theme_image(t('topic-closed.png'), t('Locked Thread'));
676
677 }
678
679 /**
680 * Preprocesses template variables for the forum list template.
681 *
682 * This function adds additional functionality to the core forum preprocess.
683 */
684 function advanced_forum_preprocess_forum_list(&$variables) {
685 $variables['template_files'][] = 'advf-forum-list';
686
687 global $user;
688
689 $number_of_forums = count($variables['forums']);
690 $forum_counter = 0;
691 foreach ($variables['forums'] as $id => $forum) {
692 // Counter to label the rows by position
693 $forum_counter++;
694 switch ($forum_counter) {
695 case "1":
696 $row_classes = 'first-row';
697 break;
698 case $number_of_forums:
699 $row_classes = 'last-row';
700 break;
701 default:
702 $row_classes = 'middle-row';
703 }
704
705 if ($forum->is_container) {
706 $row_classes .= ' container';
707 }
708
709 $variables['forums'][$id]->row_classes = $row_classes;
710
711 $variables['forums'][$id]->new_posts = 0;
712 $variables['forums'][$id]->new_text_posts = '';
713 $variables['forums'][$id]->new_url_posts = '';
714 $variables['forums'][$id]->old_posts = $forum->num_posts;
715
716 $current_container = $current_container_depth = 0;
717 if ($forum->is_container) {
718 $current_container = $forum->tid;
719 $current_container_depth = $forum->depth;
720 $variables['forums'][$id]->container_id = $current_container;
721 }
722 else {
723 if ($forum->depth > $current_container_depth ) {
724 $variables['forums'][$id]->container_id = $current_container;
725 }
726 else {
727 $variables['forums'][$id]->container_id = 0;
728 }
729 }
730
731 if ($user->uid) {
732 // Show number of new posts as well as topics
733 if (variable_get('advanced_forum_get_new_comments', 0)) {
734 // This can cause performance issues, so allow it to be turned off
735 $variables['forums'][$id]->new_posts = advanced_forum_unread_comments_in_forum($forum->tid, $user->uid) + $variables['forums'][$id]->new_topics;
736
737 if ($variables['forums'][$id]->new_posts) {
738 $variables['forums'][$id]->new_text_posts = format_plural($variables['forums'][$id]->new_posts, '1 new', '@count new');
739 $variables['forums'][$id]->new_url_posts = url("forum/$forum->tid", array('fragment' => 'new'));
740 }
741
742 $variables['forums'][$id]->old_posts = $forum->num_posts - $variables['forums'][$id]->new_posts;
743 }
744 }
745
746 // If there are new topics/posts, change the icon
747 if ($forum->new_topics || $forum->new_posts) {
748 $variables['forums'][$id]->icon = advanced_forum_theme_image(t('forum-folder-new-posts.png'), t('new post folder'));
749 }
750 else {
751 $variables['forums'][$id]->icon = advanced_forum_theme_image(t('forum-folder.png'), t('folder'));
752 }
753
754 // Make container description more accessable
755 if (!empty($variables['parents']['0'])) {
756 $variables['container_description'] = $variables['parents']['0']->description;
757 }
758 }
759
760 if (user_access('view forum statistics')) {
761 $variables['forum_statistics'] = theme('advf_forum_statistics');
762 }
763
764 $variables['forum_legend'] = theme('advanced_forum_forum_legend');
765 }
766
767 /**
768 * Preprocesses template variables for the submitted by/in template.
769 *
770 * This function adds additional functionality to the core forum preprocess.
771 */
772 function advanced_forum_preprocess_forum_submitted(&$variables) {
773 $variables['template_files'][] = 'advf-forum-submitted';
774
775 // Avoid E_ALL warning
776 $variables['topic_link'] = '';
777
778 if (isset($variables['topic']->node_title)) {
779 $nid = $variables['topic']->nid;
780
781 // Make a fake node object to avoid the node load
782 $node = new stdClass();
783 $node->nid = $nid;
784 $node->type = $variables['topic']->type;
785
786 // Find the page of the first unread comment, if any
787 $num_comments = db_result(db_query('SELECT COUNT(cid) FROM {comments} WHERE nid = %d', $nid));
788 $new_replies = comment_num_new($nid);
789 $query = comment_new_page_count($num_comments, $new_replies, $node);
790
791 // Format the node title with a link
792 $title_length = variable_get('advanced_forum_topic_title_length', 15);
793 if ($title_length == 0) {
794 $short_topic_title = $variables['topic']->node_title;
795 }
796 else {
797 $short_topic_title = truncate_utf8($variables['topic']->node_title, $title_length, TRUE, TRUE);
798 }
799
800 $fragment = ($new_replies) ? 'new' : NULL;
801 $variables['topic_link'] = l($short_topic_title, "node/$nid", array('query' => $query, 'fragment' => $fragment));
802 }
803
804 // For items posted more than $cutoff hours ago, offer an actual date.
805 $cutoff = variable_get('advanced_forum_time_ago_cutoff', 48) * 60 * 60;
806 if (isset($variables['topic']->timestamp)) {
807 $timestamp = $variables['topic']->timestamp;
808 if (time() - $timestamp > $cutoff) {
809 $variables['date_posted'] = format_date($timestamp, 'small');
810 }
811 }
812 }
813
814 /**
815 * Preprocesses template variables for the topic list template.
816 *
817 * This function adds additional functionality to the core forum preprocess.
818 */
819 function advanced_forum_preprocess_forum_topic_list(&$variables) {
820 // Take control of the template file.
821 $variables['template_files'][] = 'advf-forum-topic-list';
822
823 // Redo the table header so we can make our adjustments. This relies on this
824 // header being unaltered from the forum module or it will be messed up. I
825 // decided to do it this way rather than making it better able to adapt for
826 // perfomance reasons.
827 global $forum_topic_list_header;
828
829 $new_header = array();
830 $forum_topic_list_header[0]['class'] = 'topic-icon';
831 $new_header[] = $forum_topic_list_header[0];
832
833 $forum_topic_list_header[1]['class'] = 'topic-topic';
834 $new_header[] = $forum_topic_list_header[1];
835
836 $forum_topic_list_header[2]['class'] = 'topic-replies';
837 $new_header[] = $forum_topic_list_header[2];
838
839 // Topic views require the statistics module so don't show if it's not enabled
840 if (module_exists('statistics')) {
841 $new_header[] = array('data' => t('Views'), 'class' => 'topic-views');
842 }
843
844 // Allow admins to turn off the created column
845 if (!variable_get('advanced_forum_hide_created', 0)) {
846 $forum_topic_list_header[3]['class'] = 'topic-created';
847 $new_header[] = $forum_topic_list_header[3];
848 }
849
850 $forum_topic_list_header[4]['class'] = 'topic-lreply';
851 $new_header[] = $forum_topic_list_header[4];
852
853 $forum_topic_list_header = $new_header;
854
855 // Create the tablesorting header.
856 $ts = tablesort_init($forum_topic_list_header);
857 $header = '';
858 foreach ($forum_topic_list_header as $cell) {
859 $cell = tablesort_header($cell, $forum_topic_list_header, $ts);
860 $header .= _theme_table_cell($cell, TRUE);
861 }
862 $variables['header'] = $header;
863
864 // Grab the forum description and make it available to the template file
865 $forum = taxonomy_get_term($variables['topic_id']);
866 $variables['forum_description'] = $forum->description;
867
868 // Do our own topic processing.
869 if (!empty($variables['topics'])) {
870 $row = 0;
871 $was_sticky = FALSE;
872
873 // Find out how many pages to show on the topic pager. We do this outside
874 // the loop because it will be the same for all topics.
875 $max_pages_to_display = variable_get('advanced_forum_topic_pager_max', 5);
876
877 foreach ($variables['topics'] as $id => $topic) {
878 // Get a pager to add to the topic, if there is one
879 $variables['topics'][$id]->pager = _advanced_forum_create_topic_pager($max_pages_to_display, $topic);
880
881 // Make shadow copy point to actual thread and tell you new the forum name
882 if ($variables['topics'][$id]->moved == TRUE) {
883 $term = taxonomy_get_term($topic->forum_tid);
884 $variables['topics'][$id]->message = l(t('This topic has been moved to !forum', array('!forum' => $term->name)), "node/$topic->nid");
885 }
886
887 // Send the NID into the icon theme code so it can be linked to the topic
888 $variables['topics'][$id]->icon = theme('forum_icon', $topic->new, $topic->num_comments, $topic->comment_mode, $topic->sticky, $topic->nid);
889
890 // Add in the number of views
891 if (module_exists('statistics')) {
892 $variables['topics'][$id]->views = _advanced_forum_get_topic_views_count($topic->nid);
893 }
894
895 // Set classes based on stickiness. This allows themers to seperate out
896 // all the sticky posts into their own section.
897 if ($topic->sticky) {
898 $sticky_class = 'sticky-topic';
899 $was_sticky = TRUE;
900 }
901 elseif ($was_sticky) {
902 $sticky_class = 'first-not-sticky not-sticky';
903 $was_sticky = FALSE;
904 }
905 else {
906 $sticky_class = 'not-sticky';
907 }
908
909 $topic->sticky_class = $sticky_class;
910
911 }
912
913 // Set a variable for displaying the topic legend.
914 $variables['topic_legend'] = theme('advanced_forum_topic_legend');
915
916 }
917 }
918
919 /**
920 * Preprocesses template variables for the forum icon template.
921 *
922 * This function adds additional functionality to the core forum preprocess.
923 */
924 function advanced_forum_preprocess_forum_icon(&$variables) {
925 $variables['template_files'][] = 'advf-forum-icon';
926 $variables['iconpath'] = advanced_forum_path_to_images();
927 }
928
929 // CORE FORUM PAGE OVERRIDE **************************************************/
930
931 /**
932 * Menu callback; prints a forum listing.
933 *
934 * This is copied from the forum module and adapted.
935 */
936 function advanced_forum_page($tid = 0) {
937 _advanced_forum_add_files();
938
939 $topics = '';
940 $forum_per_page = variable_get('forum_per_page', 25);
941 $sortby = variable_get('forum_order', 1);
942
943 $forums = advanced_forum_get_forums($tid);
944 $parents = taxonomy_get_parents_all($tid);
945 if ($tid && !in_array($tid, variable_get('forum_containers', array()))) {
946 $topics = forum_get_topics($tid, $sortby, $forum_per_page);
947 }
948
949 return theme('forums', $forums, $topics, $parents, $tid, $sortby, $forum_per_page);
950 }
951
952 /**
953 * Returns a list of all forums for a given taxonomy id
954 *
955 * This is copied from the forum module and adapted.
956 *
957 * Forum objects contain the following fields
958 * -num_topics Number of topics in the forum
959 * -num_posts Total number of posts in all topics
960 * -last_post Most recent post for the forum
961 *
962 * @param $tid
963 * Taxonomy ID of the vocabulary that holds the forum list.
964 * @return
965 * Array of object containing the forum information.
966 */
967 function advanced_forum_get_forums($tid = 0) {
968
969 $forums = array();
970 $vid = variable_get('forum_nav_vocabulary', '');
971 $_forums = taxonomy_get_tree($vid, $tid);
972
973 if (count($_forums)) {
974
975 $counts = array();
976
977 $sql = "SELECT r.tid, COUNT(n.nid) AS topic_count, SUM(l.comment_count) AS comment_count
978 FROM {node} n
979 INNER JOIN {node_comment_statistics} l ON n.nid = l.nid
980 INNER JOIN {term_node} r ON n.vid = r.vid
981 WHERE n.status = 1
982 GROUP BY r.tid";
983 $sql = db_rewrite_sql($sql);
984 $_counts = db_query($sql);
985 while ($count = db_fetch_object($_counts)) {
986 $counts[$count->tid] = $count;
987 }
988 }
989
990 foreach ($_forums as $forum) {
991 // Check if this term is a container
992 if (in_array($forum->tid, variable_get('forum_containers', array()))) {
993 $forum->container = 1;
994 }
995
996 if (!empty($counts[$forum->tid])) {
997 $forum->num_topics = $counts[$forum->tid]->topic_count;
998 $forum->num_posts = $counts[$forum->tid]->topic_count + $counts[$forum->tid]->comment_count;
999 }
1000 else {
1001 $forum->num_topics = 0;
1002 $forum->num_posts = 0;
1003 }
1004
1005 // This query does not use full ANSI syntax since MySQL 3.x does not support
1006 // table1 INNER JOIN table2 INNER JOIN table3 ON table2_criteria ON table3_criteria
1007 // used to join node_comment_statistics to users.
1008 $sql = "SELECT n.nid, n.title, n.type,
1009 ncs.last_comment_timestamp,
1010 IF (ncs.last_comment_uid != 0, u2.name, ncs.last_comment_name) AS last_comment_name,
1011 ncs.last_comment_uid
1012 FROM {node} n
1013 INNER JOIN {users} u1 ON n.uid = u1.uid
1014 INNER JOIN {term_node} tn ON n.vid = tn.vid
1015 INNER JOIN {node_comment_statistics} ncs ON n.nid = ncs.nid
1016 INNER JOIN {users} u2 ON ncs.last_comment_uid=u2.uid
1017 WHERE n.status = 1 AND tn.tid = %d
1018 ORDER BY ncs.last_comment_timestamp DESC";
1019 $sql = db_rewrite_sql($sql);
1020 $topic = db_fetch_object(db_query_range($sql, $forum->tid, 0, 1));
1021
1022 $last_post = new stdClass();
1023 if (!empty($topic->last_comment_timestamp)) {
1024 $last_post->timestamp = $topic->last_comment_timestamp;
1025 $last_post->name = $topic->last_comment_name;
1026 $last_post->uid = $topic->last_comment_uid;
1027 $last_post->nid = $topic->nid;
1028 // Note, we call it "node_title" otherwise it gets picked up on the
1029 // topic list as well.
1030 $last_post->node_title = $topic->title;
1031 $last_post->type = $topic->type;
1032 }
1033 $forum->last_post = $last_post;
1034
1035 $forums[$forum->tid] = $forum;
1036 }
1037
1038 return $forums;
1039 }
1040
1041 // MARK AS READ **************************************************************/
1042
1043 /**
1044 * Marks all posts in forums or in a given forum as read by the current user.
1045 */
1046 function advanced_forum_markasread() {
1047 global $user;
1048
1049 // See if we're on a forum or on the forum overview
1050 // Path will be /forum/markasread or /forum/markasread/tid
1051 $current_forum_id = arg(2);
1052
1053 if ($current_forum_id) {
1054 // Delete the current history entries so already visited nodes get updated.
1055 $sql = "DELETE h
1056 FROM {history} AS h
1057 INNER JOIN {term_node} AS tn ON (h.nid = tn.nid)
1058 WHERE h.uid = %d AND tn.tid = %d";
1059 db_query($sql, $user->uid, $current_forum_id);
1060
1061 // Update the history table with all forum nodes newer than the cutoff.
1062 $sql = "INSERT INTO {history} (uid, nid, timestamp)
1063 SELECT DISTINCT %d, n.nid, %d
1064 FROM {node} AS n
1065 INNER JOIN {term_node} AS tn ON n.nid = tn.nid
1066 INNER JOIN {node_comment_statistics} AS ncs ON ncs.nid = n.nid
1067 WHERE (n.created > %d OR ncs.last_comment_timestamp > %d) AND tn.tid = %d";
1068
1069 $args = array($user->uid, time(), NODE_NEW_LIMIT, NODE_NEW_LIMIT, $current_forum_id);
1070 db_query($sql, $args);
1071
1072 // Readpath integration
1073 if (module_exists('readpath')) {
1074 readpath_clear_readpath();
1075 }
1076
1077 drupal_set_message(t('All content in this forum has been marked as read'));
1078 drupal_goto('forum/'. $current_forum_id);
1079 }
1080 else {
1081 // We are on the forum overview, requesting all forums be marked read
1082 $forum_vocabulary_id = variable_get('forum_nav_vocabulary', '');
1083
1084 // Delete the current history entries so already visited nodes get updated.
1085 $sql = "DELETE h
1086 FROM {history} AS h
1087 INNER JOIN {term_node} AS tn ON (h.nid = tn.nid)
1088 INNER JOIN {term_data} AS td ON (td.tid = tn.tid)
1089 WHERE h.uid = %d AND td.vid = %d";
1090 db_query($sql, $user->uid, $forum_vocabulary_id);
1091
1092 // Update the history table with all forum nodes newer than the cutoff.
1093 $sql = "INSERT INTO {history} (uid, nid, timestamp)
1094 SELECT DISTINCT %d, n.nid, %d
1095 FROM {node} AS n
1096 INNER JOIN {term_node} AS tn ON n.nid=tn.nid
1097 INNER JOIN {node_comment_statistics} AS ncs ON ncs.nid = n.nid
1098 INNER JOIN {term_data} AS td ON tn.tid = td.tid
1099 WHERE (n.created > %d OR ncs.last_comment_timestamp > %d) AND td.vid = %d";
1100
1101 $args = array($user->uid, time(), NODE_NEW_LIMIT, NODE_NEW_LIMIT, $forum_vocabulary_id);
1102
1103 db_query($sql, $args);
1104
1105 // Readpath integration
1106 if (module_exists('readpath')) {
1107 readpath_clear_readpath();
1108 }
1109
1110 drupal_set_message(t('All forum content been marked as read'));
1111 drupal_goto('forum');
1112 }
1113 }
1114
1115 /**
1116 * Access callback for menus and link display.
1117 *
1118 * This separate function is needed because the Drupal 6 menu system doesn't
1119 * run hook_menu() every time and the logged-in status of the user can get
1120 * cached and re-used for other users.
1121 */
1122 function advanced_forum_markasread_access() {
1123 global $user;
1124 return user_access('access content') && $user->uid;
1125 }
1126
1127
1128 // STYLE UTILITY FUNCTIONS ***************************************************/
1129
1130 // Include the file that handles the plugin system adapted from panels.
1131 include_once drupal_get_path('module', 'advanced_forum') . '/advf-plugins.inc';
1132
1133 function advanced_forum_advforum_styles() {
1134 $items = array();
1135 $items['naked'] = array(
1136 'directory' => 'styles/naked',
1137 );
1138
1139 $items['naked_stacked'] = array(
1140 'directory' => 'styles/naked_stacked',
1141 );
1142
1143 $items['blue_lagoon'] = array(
1144 'directory' => 'styles/blue_lagoon',
1145 );
1146
1147 $items['blue_lagoon_stacked'] = array(
1148 'directory' => 'styles/blue_lagoon_stacked',
1149 );
1150
1151 $items['boxy'] = array(
1152 'directory' => 'styles/boxy',
1153 );
1154
1155 $items['boxy_stacked'] = array(
1156 'directory' => 'styles/boxy_stacked',
1157 );
1158
1159 $items['flatgrey'] = array(
1160 'directory' => 'styles/flatgrey',
1161 );
1162
1163 return $items;
1164 }
1165
1166 /**
1167 * Returns the name of the forum style to use.
1168 */
1169 function advanced_forum_get_current_style() {