1 |
85ad3d82
|
Assos Assos
|
<?php
|
2 |
|
|
|
3 |
|
|
/**
|
4 |
|
|
* @file
|
5 |
|
|
* Enables the look and feel of other popular forum software.
|
6 |
|
|
*/
|
7 |
|
|
// DRUPAL HOOKS **************************************************************/
|
8 |
|
|
|
9 |
|
|
/**
|
10 |
|
|
* Implementation of hook_perm().
|
11 |
|
|
*/
|
12 |
|
|
function advanced_forum_permission() {
|
13 |
|
|
return array(
|
14 |
|
|
'administer advanced forum' => array(
|
15 |
|
|
'title' => t('Administer Advanced Forum')
|
16 |
|
|
),
|
17 |
|
|
'view forum statistics' => array(
|
18 |
|
|
'title' => t('View Advanced Forum statistics')
|
19 |
|
|
),
|
20 |
|
|
'view last edited notice' => array(
|
21 |
|
|
'title' => t('View last edited notice')
|
22 |
|
|
)
|
23 |
|
|
);
|
24 |
|
|
}
|
25 |
|
|
|
26 |
|
|
/**
|
27 |
|
|
* Implementation of hook_menu().
|
28 |
|
|
*/
|
29 |
|
|
function advanced_forum_menu() {
|
30 |
|
|
$items['admin/config/content/advanced-forum'] = array(
|
31 |
|
|
'access arguments' => array('administer advanced forum'),
|
32 |
|
|
'description' => 'Configure Advanced Forum with these settings.',
|
33 |
|
|
'page arguments' => array('advanced_forum_settings_page'),
|
34 |
|
|
'page callback' => 'drupal_get_form',
|
35 |
|
|
'title' => 'Advanced Forum',
|
36 |
|
|
'file' => 'includes/settings.inc'
|
37 |
|
|
);
|
38 |
|
|
|
39 |
|
|
$items['forum/markasread'] = array(
|
40 |
|
|
'access callback' => 'advanced_forum_markasread_access',
|
41 |
|
|
'page callback' => 'advanced_forum_markasread',
|
42 |
|
|
'type' => MENU_CALLBACK,
|
43 |
|
|
);
|
44 |
|
|
|
45 |
|
|
if (variable_get('advanced_forum_add_local_task', TRUE)) {
|
46 |
|
|
$items['forum/view'] = array(
|
47 |
|
|
'title' => 'View Forums',
|
48 |
|
|
'page callback' => 'advanced_forum_page',
|
49 |
|
|
'type' => MENU_DEFAULT_LOCAL_TASK,
|
50 |
|
|
'weight' => -100,
|
51 |
|
|
);
|
52 |
|
|
}
|
53 |
|
|
|
54 |
|
|
return $items;
|
55 |
|
|
}
|
56 |
|
|
|
57 |
|
|
/**
|
58 |
|
|
* Implementation of hook_cron().
|
59 |
|
|
*/
|
60 |
|
|
function advanced_forum_cron() {
|
61 |
|
|
// ensure the reply stats are up-to-date
|
62 |
|
|
advanced_forum_statistics_replies(NULL, TRUE);
|
63 |
|
|
}
|
64 |
|
|
|
65 |
|
|
/**
|
66 |
|
|
* Implementation of hook_menu_alter().
|
67 |
|
|
*/
|
68 |
|
|
function advanced_forum_menu_alter(&$items) {
|
69 |
|
|
// Take over the forum page creation so we can add more information.
|
70 |
|
|
$items['forum']['page callback'] = 'advanced_forum_page';
|
71 |
|
|
$items['forum']['module'] = 'advanced_forum';
|
72 |
|
|
unset($items['forum']['file']);
|
73 |
|
|
|
74 |
|
|
|
75 |
|
|
// Take over forum/%forum_forum page because we want advanced_forum_forum_load
|
76 |
|
|
// is called instead of core forum_forum_load
|
77 |
|
|
$items['forum/%advanced_forum_forum'] = $items['forum/%forum_forum'];
|
78 |
|
|
$items['forum/%advanced_forum_forum']['page callback'] = 'advanced_forum_page';
|
79 |
|
|
$items['forum/%advanced_forum_forum']['module'] = 'advanced_forum';
|
80 |
|
|
unset($items['forum/%advanced_forum_forum']['file']);
|
81 |
|
|
unset($items['forum/%forum_forum']);
|
82 |
|
|
}
|
83 |
|
|
|
84 |
|
|
/**
|
85 |
|
|
* Implements hook_menu_local_tasks_alter().
|
86 |
|
|
*
|
87 |
|
|
* Unset all items set in core forum_menu_local_tasks_alter
|
88 |
|
|
*/
|
89 |
|
|
function advanced_forum_menu_local_tasks_alter(&$data, $router_item, $root_path) {
|
90 |
|
|
if ($root_path == 'forum' || $root_path == 'forum/%') {
|
91 |
|
|
$data['actions']['output'] = array();
|
92 |
|
|
}
|
93 |
|
|
}
|
94 |
|
|
|
95 |
|
|
/**
|
96 |
|
|
* Implementation of hook_module_implements_alter().
|
97 |
|
|
*
|
98 |
|
|
* We don't want forum_menu_local_tasks_alter() to be called and mess with our links.
|
99 |
|
|
*
|
100 |
|
|
*/
|
101 |
|
|
function advanced_forum_module_implements_alter(&$implementations, $hook) {
|
102 |
|
|
if ($hook == 'menu_local_tasks_alter') {
|
103 |
|
|
unset($implementations['forum']);
|
104 |
|
|
}
|
105 |
|
|
}
|
106 |
|
|
|
107 |
|
|
/**
|
108 |
|
|
* Implementation of hook_theme().
|
109 |
|
|
*/
|
110 |
|
|
function advanced_forum_theme() {
|
111 |
|
|
advanced_forum_load_style_includes();
|
112 |
|
|
|
113 |
|
|
// Bulk read all available (active) style templates
|
114 |
|
|
$existing_items = advanced_forum_find_style_templates();
|
115 |
|
|
|
116 |
|
|
$items['advanced_forum_l'] = array(
|
117 |
|
|
'variables' => array(
|
118 |
|
|
'text' => NULL,
|
119 |
|
|
'path' => NULL,
|
120 |
|
|
'options' => array(),
|
121 |
|
|
'button_class' => NULL,
|
122 |
|
|
)
|
123 |
|
|
);
|
124 |
|
|
|
125 |
|
|
$items['advanced_forum_topic_header'] = array(
|
126 |
|
|
'variables' => array(
|
127 |
|
|
'node' => NULL,
|
128 |
|
|
'comment_count' => NULL,
|
129 |
|
|
)
|
130 |
|
|
);
|
131 |
|
|
|
132 |
|
|
$items['advanced_forum_active_poster'] = array(
|
133 |
|
|
'variables' => array(
|
134 |
|
|
'forum' => NULL,
|
135 |
|
|
'account' => NULL,
|
136 |
|
|
'posts' => NULL,
|
137 |
|
|
'topics' => NULL,
|
138 |
|
|
'last_post' => NULL,
|
139 |
|
|
)
|
140 |
|
|
);
|
141 |
|
|
|
142 |
|
|
$items['advanced_forum_user_picture'] = array(
|
143 |
|
|
'variables' => array(
|
144 |
|
|
'account' => NULL,
|
145 |
|
|
)
|
146 |
|
|
);
|
147 |
|
|
|
148 |
|
|
$items['advanced_forum_reply_link'] = array(
|
149 |
|
|
'variables' => array(
|
150 |
|
|
'node' => NULL,
|
151 |
|
|
)
|
152 |
|
|
);
|
153 |
|
|
|
154 |
|
|
$items['advanced_forum_topic_pager'] = array(
|
155 |
|
|
'variables' => array(
|
156 |
|
|
'pagecount' => NULL,
|
157 |
|
|
'topic' => NULL,
|
158 |
|
|
)
|
159 |
|
|
);
|
160 |
|
|
|
161 |
|
|
$items['advanced_forum_shadow_topic'] = array(
|
162 |
|
|
'variables' => array(
|
163 |
|
|
'title' => NULL,
|
164 |
|
|
'nid' => NULL,
|
165 |
|
|
'new_forum' => NULL,
|
166 |
|
|
)
|
167 |
|
|
);
|
168 |
|
|
|
169 |
|
|
$items['advanced_forum_subforum_list'] = array(
|
170 |
|
|
'variables' => array(
|
171 |
|
|
'subforum_list' => NULL,
|
172 |
|
|
)
|
173 |
|
|
);
|
174 |
|
|
|
175 |
|
|
$items['advanced_forum_subcontainer_list'] = array(
|
176 |
|
|
'variables' => array(
|
177 |
|
|
'subcontainer_list' => NULL,
|
178 |
|
|
)
|
179 |
|
|
);
|
180 |
|
|
|
181 |
|
|
$items['advanced_forum_simple_author_pane'] = array(
|
182 |
|
|
'variables' => array(
|
183 |
|
|
'context' => NULL,
|
184 |
|
|
)
|
185 |
|
|
);
|
186 |
|
|
|
187 |
|
|
$items['advanced_forum_post_edited'] = array(
|
188 |
|
|
'variables' => array(
|
189 |
|
|
'who' => NULL,
|
190 |
|
|
'when' => NULL,
|
191 |
|
|
'why' => NULL,
|
192 |
|
|
)
|
193 |
|
|
);
|
194 |
|
|
|
195 |
|
|
$items['advanced_forum_node_type_create_list'] = array(
|
196 |
|
|
'variables' => array(
|
197 |
|
|
'forum_id' => NULL,
|
198 |
|
|
)
|
199 |
|
|
);
|
200 |
|
|
/*
|
201 |
|
|
// Templates for features added by Views
|
202 |
|
|
|
203 |
|
|
// style
|
204 |
|
|
$items['views_view_forum_topic_list__advanced_forum_topic_list'] = array(
|
205 |
|
|
'variables' => array('view' => NULL, 'options' => NULL, 'rows' => NULL, 'title' => NULL),
|
206 |
|
|
'template' => 'advanced-forum-topic-list-view',
|
207 |
|
|
//'base hook' => 'views_view_forum_topic_list',
|
208 |
|
|
);
|
209 |
|
|
*/
|
210 |
|
|
//display
|
211 |
|
|
$items['views_view__advanced_forum_topic_list'] = array(
|
212 |
|
|
'variables' => array('view' => NULL),
|
213 |
|
|
'template' => 'advanced-forum-topic-list-outer-view',
|
214 |
|
|
//'base hook' => 'views_view',
|
215 |
|
|
);
|
216 |
|
|
|
217 |
|
|
//display group
|
218 |
|
|
$items['views_view__advanced_forum_group_topic_list'] = array(
|
219 |
|
|
'variables' => array('view' => NULL),
|
220 |
|
|
'template' => 'advanced-forum-group-topic-list-outer-view',
|
221 |
|
|
//'base hook' => 'views_view',
|
222 |
|
|
);
|
223 |
|
|
|
224 |
|
|
// Return merged items found in style folder with new ones
|
225 |
|
|
// array_merge_recursive doesn't work as desired
|
226 |
|
|
foreach ($items as $key => $item) {
|
227 |
|
|
if (array_key_exists($key, $existing_items)) {
|
228 |
|
|
$existing_items[$key] += $item;
|
229 |
|
|
}
|
230 |
|
|
else {
|
231 |
|
|
$existing_items[$key] = $item;
|
232 |
|
|
}
|
233 |
|
|
}
|
234 |
|
|
|
235 |
|
|
return $existing_items;
|
236 |
|
|
}
|
237 |
|
|
|
238 |
|
|
/**
|
239 |
|
|
* Implementation of hook_theme_registry_alter().
|
240 |
|
|
*/
|
241 |
|
|
function advanced_forum_theme_registry_alter(&$theme_registry) {
|
242 |
|
|
advanced_forum_load_style_includes();
|
243 |
|
|
|
244 |
|
|
// Don't let core do its basic preprocess for forums, as we want to do
|
245 |
|
|
// other stuff now.
|
246 |
c169e7c4
|
Assos Assos
|
if (isset($theme_registry['forums']['preprocess functions'])) {
|
247 |
|
|
foreach ($theme_registry['forums']['preprocess functions'] as $key => $value) {
|
248 |
|
|
if ($value == 'template_preprocess_forums') {
|
249 |
|
|
unset($theme_registry['forums']['preprocess functions'][$key]);
|
250 |
|
|
}
|
251 |
85ad3d82
|
Assos Assos
|
}
|
252 |
|
|
}
|
253 |
|
|
|
254 |
|
|
// We duplicate all of core's forum list preprocessing so no need to run
|
255 |
|
|
// it twice. Running twice also causes problems with & in forum name.
|
256 |
c169e7c4
|
Assos Assos
|
if (isset($theme_registry['forum_list']['preprocess functions'])) {
|
257 |
|
|
foreach ($theme_registry['forum_list']['preprocess functions'] as $key => $value) {
|
258 |
|
|
if ($value == 'template_preprocess_forum_list') {
|
259 |
|
|
unset($theme_registry['forum_list']['preprocess functions'][$key]);
|
260 |
|
|
}
|
261 |
85ad3d82
|
Assos Assos
|
}
|
262 |
|
|
}
|
263 |
|
|
|
264 |
|
|
// Views handles the topic list pages so remove the core template preprocess.
|
265 |
c169e7c4
|
Assos Assos
|
if (isset($theme_registry['forum_topic_list']['preprocess functions'])) {
|
266 |
|
|
foreach ($theme_registry['forum_topic_list']['preprocess functions'] as $key => $value) {
|
267 |
|
|
if ($value == 'template_preprocess_forum_topic_list') {
|
268 |
|
|
unset($theme_registry['forum_topic_list']['preprocess functions'][$key]);
|
269 |
|
|
}
|
270 |
85ad3d82
|
Assos Assos
|
}
|
271 |
|
|
}
|
272 |
|
|
|
273 |
|
|
// --- The following section manipulates the theme registry so the .tpl files
|
274 |
|
|
// --- for the given templates can be found first in the (sub)theme directory
|
275 |
|
|
// --- then in ancestor themes, if any, then in the active style directory
|
276 |
|
|
// --- for advanced forum or any ancestor styles.
|
277 |
|
|
// Affected templates
|
278 |
|
|
$templates = array(
|
279 |
|
|
'node',
|
280 |
|
|
'comment',
|
281 |
|
|
'comment_wrapper',
|
282 |
|
|
'forums',
|
283 |
|
|
'forum_list',
|
284 |
|
|
'forum_topic_list',
|
285 |
|
|
'forum_icon',
|
286 |
|
|
'forum_submitted',
|
287 |
|
|
'author_pane',
|
288 |
|
|
/*
|
289 |
|
|
'advanced_forum_statistics',
|
290 |
|
|
'advanced_forum_topic_list_view',
|
291 |
|
|
'advanced_forum_topic_legend',
|
292 |
|
|
'advanced_forum_forum_legend',
|
293 |
|
|
'advanced_forum_topic_header',
|
294 |
|
|
'advanced_forum_active_poster', */
|
295 |
|
|
);
|
296 |
|
|
|
297 |
|
|
// Get the sequence of styles to look in for templates
|
298 |
|
|
$lineage = advanced_forum_style_lineage();
|
299 |
|
|
|
300 |
|
|
if (!array_key_exists('naked', $lineage)) {
|
301 |
|
|
// Add naked in at the end of the line to prevent problems if a style
|
302 |
|
|
// doesn't include all needed templates.
|
303 |
|
|
$lineage['naked'] = drupal_get_path('module', 'advanced_forum') . '/styles/naked';
|
304 |
|
|
}
|
305 |
|
|
|
306 |
|
|
// Get theme engine extension
|
307 |
|
|
global $theme_engine;
|
308 |
|
|
$extension = '.tpl.php';
|
309 |
|
|
if (isset($theme_engine)) {
|
310 |
|
|
$extension_function = $theme_engine . '_extension';
|
311 |
|
|
if (function_exists($extension_function)) {
|
312 |
|
|
$extension = $extension_function();
|
313 |
|
|
}
|
314 |
|
|
}
|
315 |
|
|
|
316 |
|
|
foreach ($templates as $template) {
|
317 |
|
|
// Sanity check in case the template is not being used.
|
318 |
|
|
if (!empty($theme_registry[$template])) {
|
319 |
|
|
// There are preprocess functions to add, so figure out where we want to add
|
320 |
|
|
// them.
|
321 |
|
|
if (!empty($preprocess)) {
|
322 |
|
|
$position = 0;
|
323 |
|
|
foreach ($theme_registry[$template]['preprocess functions'] as $function) {
|
324 |
|
|
$position++;
|
325 |
|
|
// If we see either of these items, that means we can place our
|
326 |
|
|
// preprocess functions after this.
|
327 |
|
|
if (substr($function, 0, 25) == 'advanced_forum_preprocess' || substr($function, 0, 34) == 'template_preprocess_advanced_forum') {
|
328 |
|
|
break;
|
329 |
|
|
}
|
330 |
|
|
}
|
331 |
|
|
// Add in our new preprocess functions:
|
332 |
c169e7c4
|
Assos Assos
|
if (isset($theme_registry[$template]['preprocess functions'])) {
|
333 |
|
|
array_splice($theme_registry[$template]['preprocess functions'], $position, 0, $preprocess);
|
334 |
|
|
}
|
335 |
85ad3d82
|
Assos Assos
|
}
|
336 |
|
|
}
|
337 |
|
|
}
|
338 |
|
|
|
339 |
|
|
|
340 |
|
|
// temp workaround
|
341 |
c169e7c4
|
Assos Assos
|
if (isset($theme_registry['views_view__advanced_forum_topic_list']['preprocess functions'])) {
|
342 |
|
|
array_splice($theme_registry['views_view__advanced_forum_topic_list']['preprocess functions'], 1, 0, 'template_preprocess_views_view');
|
343 |
|
|
}
|
344 |
|
|
if (isset($theme_registry['views_view__advanced_forum_group_topic_list']['preprocess functions'])) {
|
345 |
|
|
array_splice($theme_registry['views_view__advanced_forum_group_topic_list']['preprocess functions'], 1, 0, 'template_preprocess_views_view');
|
346 |
|
|
}
|
347 |
85ad3d82
|
Assos Assos
|
//array_splice($theme_registry['views_view_forum_topic_list__advanced_forum_topic_list']['preprocess functions'], 1, 0, 'template_preprocess_views_view_forum_topic_list');
|
348 |
|
|
}
|
349 |
|
|
|
350 |
|
|
/**
|
351 |
|
|
* Own link alteration implementaion because there are no
|
352 |
|
|
* hook_link nor hook_link_alter in D7
|
353 |
|
|
*
|
354 |
|
|
* Name changed intentionally to avoid confusion with hook_link_alter!
|
355 |
|
|
*/
|
356 |
|
|
function advanced_forum_links_alter(&$object, $view_mode, $object_type = 'node') {
|
357 |
|
|
// Don't alter anything if in preview mode
|
358 |
|
|
if (!empty($object->in_preview)) {
|
359 |
|
|
return;
|
360 |
|
|
}
|
361 |
|
|
|
362 |
|
|
if (!advanced_forum_is_styled($object, ($view_mode == 'teaser'), $object_type)) {
|
363 |
|
|
return;
|
364 |
|
|
}
|
365 |
|
|
|
366 |
|
|
if (!empty($object->content['links']['comment'])) {
|
367 |
|
|
$comment_links = $object->content['links']['comment'];
|
368 |
|
|
$links = empty($comment_links['#links']) ? array() : $comment_links['#links'];
|
369 |
|
|
}
|
370 |
|
|
else {
|
371 |
|
|
$comment_links = array();
|
372 |
|
|
$links = array();
|
373 |
|
|
}
|
374 |
|
|
|
375 |
|
|
if ($object_type == 'node') {
|
376 |
|
|
|
377 |
|
|
$node = $object;
|
378 |
|
|
// Add edit / delete links to the node links to match replies.
|
379 |
|
|
if (node_access('update', $node)) {
|
380 |
|
|
$links['post-edit'] = array(
|
381 |
|
|
'title' => t('edit'),
|
382 |
|
|
'href' => 'node/' . $node->nid . '/edit',
|
383 |
|
|
'query' => drupal_get_destination(),
|
384 |
|
|
);
|
385 |
|
|
}
|
386 |
|
|
|
387 |
|
|
if (node_access('delete', $node)) {
|
388 |
|
|
$links['post-delete'] = array(
|
389 |
|
|
'title' => t('delete'),
|
390 |
|
|
'href' => 'node/' . $node->nid . '/delete',
|
391 |
|
|
);
|
392 |
|
|
}
|
393 |
|
|
}
|
394 |
|
|
|
395 |
|
|
// Change first post from "add comment" to "reply" if it isn't already.
|
396 |
|
|
if (!empty($links['comment-add'])) {
|
397 |
|
|
$links['comment-add']['title'] = t('reply');
|
398 |
|
|
$links['comment-add']['href'] = "comment/reply/$node->nid";
|
399 |
|
|
}
|
400 |
|
|
|
401 |
|
|
|
402 |
|
|
// List the keys we are interested in.
|
403 |
|
|
$affected_keys = array('post-edit', 'comment-edit', 'post-delete', 'comment-delete', 'quote', 'comment-add', 'comment-reply');
|
404 |
|
|
|
405 |
|
|
// Add extra span tags for image replacement.
|
406 |
|
|
foreach ($links AS $key => $link) {
|
407 |
|
|
if (in_array($key, $affected_keys)) {
|
408 |
|
|
$links[$key]['attributes']['class'][] = "af-button-small";
|
409 |
|
|
$links[$key]['title'] = '<span>' . $links[$key]['title'] . '</span>';
|
410 |
|
|
$links[$key]['html'] = TRUE;
|
411 |
|
|
}
|
412 |
|
|
}
|
413 |
|
|
|
414 |
|
|
// Put the links in a consistent order.
|
415 |
|
|
foreach ($affected_keys as $key) {
|
416 |
|
|
if (isset($links[$key])) {
|
417 |
|
|
$temp = $links[$key];
|
418 |
|
|
unset($links[$key]);
|
419 |
|
|
$links[$key] = $temp;
|
420 |
|
|
}
|
421 |
|
|
}
|
422 |
|
|
|
423 |
|
|
// we want to put comment links last
|
424 |
|
|
unset($object->content['links']['comment']);
|
425 |
|
|
$object->content['links']['comment'] = $comment_links;
|
426 |
|
|
|
427 |
|
|
// put links back
|
428 |
|
|
$object->content['links']['comment']['#links'] = $links;
|
429 |
|
|
}
|
430 |
|
|
|
431 |
|
|
/**
|
432 |
|
|
* Implementation of hook_node_view().
|
433 |
|
|
*
|
434 |
|
|
* hook_link() and hook_link_alter() functionalty implemented here
|
435 |
|
|
*/
|
436 |
|
|
function advanced_forum_node_view($node, $view_mode, $langcode) {
|
437 |
|
|
advanced_forum_links_alter($node, $view_mode, 'node');
|
438 |
|
|
}
|
439 |
|
|
|
440 |
|
|
/**
|
441 |
|
|
* Implementation of hook_comment_view().
|
442 |
|
|
*/
|
443 |
|
|
function advanced_forum_comment_view($comment, $view_mode, $langcode) {
|
444 |
|
|
advanced_forum_links_alter($comment, $view_mode, 'comment');
|
445 |
|
|
}
|
446 |
|
|
|
447 |
|
|
/**
|
448 |
|
|
* Implementation of hook_comment_delete().
|
449 |
|
|
*/
|
450 |
|
|
function advanced_forum_comment_delete($comment) {
|
451 |
|
|
if (!empty($comment->node_type) && ($comment->node_type == "comment_node_forum")) {
|
452 |
|
|
advanced_forum_statistics_replies(-1);
|
453 |
|
|
}
|
454 |
|
|
}
|
455 |
|
|
|
456 |
|
|
/**
|
457 |
|
|
* Implementation of hook_comment_update().
|
458 |
|
|
*/
|
459 |
|
|
function advanced_forum_comment_update($comment) {
|
460 |
|
|
if (!empty($comment->node_type) && ($comment->node_type == "comment_node_forum")) {
|
461 |
|
|
// comment unpublished?
|
462 |
|
|
if (!$comment->status) {
|
463 |
|
|
advanced_forum_statistics_replies(-1);
|
464 |
|
|
}
|
465 |
|
|
}
|
466 |
|
|
}
|
467 |
|
|
|
468 |
|
|
/**
|
469 |
|
|
* Implementation of hook_comment_publish().
|
470 |
|
|
*/
|
471 |
|
|
function advanced_forum_comment_publish($comment) {
|
472 |
|
|
if (!empty($comment->node_type) && ($comment->node_type == "comment_node_forum")) {
|
473 |
|
|
advanced_forum_statistics_replies(1);
|
474 |
|
|
}
|
475 |
|
|
}
|
476 |
|
|
|
477 |
|
|
/**
|
478 |
|
|
* Implementation of hook_form_alter().
|
479 |
|
|
*/
|
480 |
|
|
function advanced_forum_form_alter(&$form, &$form_state, $form_id) {
|
481 |
|
|
if (!empty($form['#node']->type) && advanced_forum_type_is_in_forum($form['#node']) && isset($form['body_field']) && isset($form['body_field']['#after_build'])) {
|
482 |
|
|
// Remove the teaser splitter.
|
483 |
|
|
$teaser_js_build = array_search('node_teaser_js', $form['body_field']['#after_build']);
|
484 |
|
|
unset($form['body_field']['#after_build'][$teaser_js_build]);
|
485 |
|
|
$form['body_field']['teaser_js']['#access'] = FALSE;
|
486 |
|
|
$form['body_field']['teaser_include']['#access'] = FALSE;
|
487 |
|
|
}
|
488 |
|
|
|
489 |
|
|
// Add our OG view as a potential RON for organic groups.
|
490 |
|
|
if (!empty($form['og_settings']['group_details']['og_home_page_view'])) {
|
491 |
|
|
$form['og_settings']['group_details']['og_home_page_view']['#options']['advanced_forum_group_topic_list'] = 'advanced_forum_group_topic_list';
|
492 |
|
|
}
|
493 |
|
|
}
|
494 |
|
|
|
495 |
|
|
// MAKE VIEWS BITS WORK *****************************************************/
|
496 |
|
|
function advanced_forum_views_api() {
|
497 |
|
|
return array(
|
498 |
|
|
'api' => '3.0-alpha1',
|
499 |
|
|
'path' => drupal_get_path('module', 'advanced_forum') . '/includes/views',
|
500 |
|
|
);
|
501 |
|
|
}
|
502 |
|
|
|
503 |
|
|
// MAKE CTOOLS BITS WORK *****************************************************/
|
504 |
|
|
/**
|
505 |
|
|
* Tell CTools about what plugins we support.
|
506 |
|
|
*/
|
507 |
|
|
function advanced_forum_ctools_plugin_directory($module, $plugin) {
|
508 |
|
|
if ($module == 'advanced_forum') {
|
509 |
|
|
return 'styles';
|
510 |
|
|
}
|
511 |
|
|
|
512 |
|
|
if ($module == 'page_manager' || $module == 'ctools') {
|
513 |
|
|
return 'plugins/' . $plugin;
|
514 |
|
|
}
|
515 |
|
|
}
|
516 |
|
|
|
517 |
|
|
function advanced_forum_ctools_plugin_api($module, $api) {
|
518 |
|
|
if ($module == 'page_manager' && $api = 'pages_default') {
|
519 |
|
|
return array(
|
520 |
|
|
'version' => 1,
|
521 |
|
|
'path' => drupal_get_path('module', 'advanced_forum') . '/includes/panels',
|
522 |
|
|
);
|
523 |
|
|
}
|
524 |
|
|
}
|
525 |
|
|
|
526 |
|
|
// THEME FUNCTIONS AND TEMPLATE PREPROCESSES **********************************/
|
527 |
|
|
module_load_include('inc', 'advanced_forum', 'includes/theme');
|
528 |
|
|
|
529 |
|
|
// STYLE RELATED FUNCTIONS ****************************************************/
|
530 |
|
|
module_load_include('inc', 'advanced_forum', 'includes/style');
|
531 |
|
|
|
532 |
|
|
// CORE FORUM PAGE OVERRIDES **************************************************/
|
533 |
|
|
module_load_include('inc', 'advanced_forum', 'includes/core-overrides');
|
534 |
|
|
|
535 |
|
|
// MARK AS READ ***************************************************************/
|
536 |
|
|
module_load_include('inc', 'advanced_forum', 'includes/mark-read');
|
537 |
|
|
|
538 |
|
|
// VIEWS RELATED GOODIES ******************************************************/
|
539 |
|
|
|
540 |
|
|
/**
|
541 |
|
|
* Post render a view and replace any advanced forum tokens.
|
542 |
|
|
*/
|
543 |
|
|
function advanced_forum_views_post_render(&$view, &$output) {
|
544 |
|
|
if (empty($view->style_plugin) || !$view->style_plugin->uses_row_plugin()) {
|
545 |
|
|
return;
|
546 |
|
|
}
|
547 |
|
|
|
548 |
|
|
$plugin = $view->display_handler->get_option('row_plugin');
|
549 |
|
|
if ($plugin == 'node') {
|
550 |
|
|
// Look for token matches in the output:
|
551 |
|
|
$matches = array();
|
552 |
|
|
$tokens = array();
|
553 |
|
|
|
554 |
|
|
// We want to change the look of the 'new' marker from the default, slightly:
|
555 |
|
|
$tokens['<span class="new">' . t('new') . '</span>'] = '<span class="new">(' . t('new') . ')</span>';
|
556 |
|
|
|
557 |
|
|
// Replace the Author Pane token with the actual Author Pane.
|
558 |
|
|
if (preg_match_all('/<!--post:author-pane-([\d]+)-->/us', $output, $matches)) {
|
559 |
|
|
foreach ($matches[1] as $match => $uid) {
|
560 |
|
|
$token = $matches[0][$match]; // This is the exact string that matched.
|
561 |
|
|
if (!isset($tokens[$token])) {
|
562 |
|
|
$account = user_load($uid);
|
563 |
|
|
$tokens[$token] = theme('author_pane', array(
|
564 |
|
|
'account' => $account,
|
565 |
|
|
'caller' => 'advanced_forum',
|
566 |
|
|
'picture_preset' => variable_get('advanced_forum_user_picture_preset', ''),
|
567 |
|
|
'context' => NULL,
|
568 |
|
|
'disable_css' => TRUE,
|
569 |
|
|
'join_date_type' => variable_get('advanced_forum_author_pane_join_date_type', 'short'),
|
570 |
|
|
));
|
571 |
|
|
}
|
572 |
|
|
}
|
573 |
|
|
}
|
574 |
|
|
|
575 |
|
|
// Replace the Post edited token.
|
576 |
|
|
if (preg_match_all('/<!--post:post-edited-([\d]+)-->/us', $output, $matches)) {
|
577 |
|
|
foreach ($matches[1] as $match => $nid) {
|
578 |
|
|
$token = $matches[0][$match]; // This is the exact string that matched.
|
579 |
|
|
if (!isset($tokens[$token])) {
|
580 |
|
|
if (user_access('view last edited notice')) {
|
581 |
|
|
$sql = 'SELECT uid, log, timestamp FROM {node_revision} WHERE nid = %d ORDER BY timestamp DESC';
|
582 |
|
|
$row = db_fetch_object(db_query($sql, $nid));
|
583 |
|
|
$tokens[$token] = theme('advanced_forum_post_edited', array(
|
584 |
|
|
'who' => $row->uid,
|
585 |
|
|
'when' => $row->timestamp,
|
586 |
|
|
'why' => $row->log
|
587 |
|
|
));
|
588 |
|
|
}
|
589 |
|
|
else {
|
590 |
|
|
// No access; remove token.
|
591 |
|
|
$tokens[$token] = '';
|
592 |
|
|
}
|
593 |
|
|
}
|
594 |
|
|
}
|
595 |
|
|
}
|
596 |
|
|
|
597 |
|
|
// Replace the core Signature token.
|
598 |
|
|
if (preg_match_all('/<!--post:signature-core-([\d]+)-->/us', $output, $matches)) {
|
599 |
|
|
foreach ($matches[1] as $match => $uid) {
|
600 |
|
|
$token = $matches[0][$match]; // This is the exact string that matched.
|
601 |
|
|
if (!isset($tokens[$token])) {
|
602 |
|
|
$account = user_load($uid);
|
603 |
|
|
if ($account->signature) {
|
604 |
|
|
$tokens[$token] = check_markup($account->signature, $account->signature_format, FALSE);
|
605 |
|
|
}
|
606 |
|
|
}
|
607 |
|
|
}
|
608 |
|
|
}
|
609 |
|
|
|
610 |
|
|
// Perform replacements.
|
611 |
|
|
$output = strtr($output, $tokens);
|
612 |
|
|
}
|
613 |
|
|
}
|
614 |
|
|
|
615 |
|
|
/**
|
616 |
|
|
* Display the "sort" widget. This is a specially hacked widget that only
|
617 |
|
|
* works with tablesorting. Tablesorting MUST be on for these widgets
|
618 |
|
|
* to appear.
|
619 |
|
|
*/
|
620 |
|
|
function advanced_forum_forum_topic_list_sort() {
|
621 |
|
|
$form_state = array(
|
622 |
|
|
'method' => 'get',
|
623 |
|
|
'no_redirect' => TRUE,
|
624 |
|
|
'rerender' => TRUE,
|
625 |
|
|
'input' => $_GET,
|
626 |
|
|
'drop tokens' => TRUE,
|
627 |
|
|
);
|
628 |
|
|
|
629 |
|
|
$form = drupal_build_form('advanced_forum_forum_topic_list_sort_form', $form_state);
|
630 |
|
|
return drupal_render($form);
|
631 |
|
|
}
|
632 |
|
|
|
633 |
|
|
function advanced_forum_forum_topic_list_sort_form($form_state) {
|
634 |
|
|
$view = views_get_view('advanced_forum_topic_list');
|
635 |
|
|
$view->set_display('default');
|
636 |
|
|
$view->init_handlers();
|
637 |
|
|
$view->init_style();
|
638 |
|
|
|
639 |
|
|
// Work up a list of possible fields.
|
640 |
|
|
$handler = &$view->style_plugin;
|
641 |
|
|
$fields = &$view->field;
|
642 |
|
|
$columns = $handler->sanitize_columns($handler->options['columns'], $fields);
|
643 |
|
|
|
644 |
|
|
$options = array();
|
645 |
|
|
foreach ($columns as $field => $column) {
|
646 |
|
|
if ($field == $column && empty($fields[$field]->options['exclude'])) {
|
647 |
|
|
if (empty($handler->options['info'][$field]['sortable']) || !$fields[$field]->click_sortable()) {
|
648 |
|
|
continue;
|
649 |
|
|
}
|
650 |
|
|
$label = check_plain(!empty($fields[$field]) ? $fields[$field]->label() : '');
|
651 |
|
|
$options[$field] = $label;
|
652 |
|
|
}
|
653 |
|
|
}
|
654 |
|
|
|
655 |
|
|
$form['inline'] = array(
|
656 |
|
|
'#prefix' => '<div class="container-inline">',
|
657 |
|
|
'#suffix' => '</div>',
|
658 |
|
|
);
|
659 |
|
|
$form['inline']['order'] = array(
|
660 |
|
|
'#type' => 'select',
|
661 |
|
|
'#title' => t('Order by'),
|
662 |
|
|
'#title_display' => 'invisible',
|
663 |
|
|
'#options' => $options,
|
664 |
|
|
'#default_value' => $handler->options['default'],
|
665 |
|
|
);
|
666 |
|
|
|
667 |
|
|
$form['inline']['sort'] = array(
|
668 |
|
|
'#type' => 'select',
|
669 |
|
|
'#title' => t('Sort'),
|
670 |
|
|
'#title_display' => 'invisible',
|
671 |
|
|
'#options' => array(
|
672 |
|
|
'asc' => t('Up'),
|
673 |
|
|
'desc' => t('Down'),
|
674 |
|
|
),
|
675 |
|
|
'#default_value' => 'desc',
|
676 |
|
|
);
|
677 |
|
|
|
678 |
|
|
$form['inline']['submit'] = array(
|
679 |
|
|
'#id' => 'sort-topic-submit',
|
680 |
|
|
'#name' => '',
|
681 |
|
|
'#type' => 'submit',
|
682 |
|
|
'#value' => t('Sort'),
|
683 |
|
|
);
|
684 |
|
|
|
685 |
|
|
if (isset($_GET['page'])) {
|
686 |
|
|
$form['page'] = array(
|
687 |
|
|
'#type' => 'hidden',
|
688 |
|
|
'#default_value' => $_GET['page'],
|
689 |
|
|
);
|
690 |
|
|
}
|
691 |
|
|
|
692 |
|
|
if (!variable_get('clean_url', FALSE)) {
|
693 |
|
|
$form['q'] = array(
|
694 |
|
|
'#type' => 'hidden',
|
695 |
|
|
'#value' => $_GET['q'],
|
696 |
|
|
);
|
697 |
|
|
}
|
698 |
|
|
|
699 |
|
|
$view->destroy();
|
700 |
|
|
return $form;
|
701 |
|
|
}
|
702 |
|
|
|
703 |
|
|
// STATISTICS *****************************************************************/
|
704 |
|
|
|
705 |
|
|
/**
|
706 |
|
|
* Count total amount of forum threads.
|
707 |
|
|
*/
|
708 |
|
|
function advanced_forum_statistics_topics() {
|
709 |
|
|
return db_query('SELECT COUNT(DISTINCT(nid)) FROM {forum}')->fetchField();
|
710 |
|
|
}
|
711 |
|
|
|
712 |
|
|
/**
|
713 |
|
|
* Counts total amount of replies. Initial posts are added to this total
|
714 |
|
|
* in the calling function.
|
715 |
|
|
*
|
716 |
|
|
* @param $delta
|
717 |
|
|
* if not NULL, a numerical delta which should be applied to the count
|
718 |
|
|
* @param $refresh
|
719 |
|
|
* @param $refresh
|
720 |
|
|
* TRUE if the stored count should be updated.
|
721 |
|
|
* @return
|
722 |
|
|
* Total number of replies in the forum.
|
723 |
|
|
*/
|
724 |
|
|
function advanced_forum_statistics_replies($delta = NULL, $refresh = FALSE) {
|
725 |
|
|
|
726 |
|
|
if ($refresh || !($cache = cache_get('advanced_forum_stats_replies'))) {
|
727 |
|
|
$total_replies = db_query('SELECT SUM(comment_count) FROM {forum_index}')->fetchField();
|
728 |
|
|
cache_set('advanced_forum_stats_replies', $total_replies);
|
729 |
|
|
}
|
730 |
|
|
else {
|
731 |
|
|
$total_replies = $cache->data;
|
732 |
|
|
}
|
733 |
|
|
|
734 |
|
|
|
735 |
|
|
if (!empty($delta) && is_numeric($delta)) {
|
736 |
|
|
$total_replies += $delta;
|
737 |
|
|
cache_set('advanced_forum_stats_replies', $total_replies);
|
738 |
|
|
}
|
739 |
|
|
|
740 |
|
|
return $total_replies;
|
741 |
|
|
}
|
742 |
|
|
|
743 |
|
|
/**
|
744 |
|
|
* Count total amount of active users.
|
745 |
|
|
*/
|
746 |
|
|
function advanced_forum_statistics_users() {
|
747 |
|
|
return db_query('SELECT COUNT(uid) FROM {users} WHERE status = 1')->fetchField();
|
748 |
|
|
}
|
749 |
|
|
|
750 |
|
|
/**
|
751 |
|
|
* Return the newest X active (not blocked) users, linked to their profiles.
|
752 |
|
|
*/
|
753 |
|
|
function advanced_forum_statistics_latest_users() {
|
754 |
|
|
$number_to_fetch = 5; // @TODO: Make this a setting.
|
755 |
|
|
|
756 |
|
|
$query = db_select("users", "u")
|
757 |
|
|
->fields("u", array("uid", "name"))
|
758 |
|
|
->condition("status", 0, "<>")
|
759 |
|
|
->condition("access", 0, "<>")
|
760 |
|
|
->orderBy("created", "DESC");
|
761 |
|
|
|
762 |
|
|
$latest_users = $query->range(NULL, $number_to_fetch)->execute();
|
763 |
|
|
while ($account = $latest_users->fetchObject()) {
|
764 |
|
|
$list[] = theme('username', array('account' => $account));
|
765 |
|
|
}
|
766 |
|
|
|
767 |
|
|
return $list;
|
768 |
|
|
}
|
769 |
|
|
|
770 |
|
|
function advanced_forum_session_count($anonymous = TRUE) {
|
771 |
|
|
|
772 |
|
|
$interval = REQUEST_TIME - variable_get('user_block_seconds_online', 900);
|
773 |
|
|
|
774 |
|
|
$query = db_select("sessions", "s")
|
775 |
|
|
->fields("s", array("uid"))
|
776 |
|
|
->distinct()
|
777 |
|
|
->condition('s.timestamp', $interval, '>=')
|
778 |
|
|
->condition('s.uid', 0, $anonymous ? '=' : '>')
|
779 |
|
|
->countQuery();
|
780 |
|
|
|
781 |
|
|
return $query->execute()->fetchField();
|
782 |
|
|
}
|
783 |
|
|
|
784 |
|
|
/**
|
785 |
|
|
* Return an array of online usernames, linked to their profiles.
|
786 |
|
|
*/
|
787 |
|
|
function advanced_forum_statistics_online_users() {
|
788 |
|
|
$list = array();
|
789 |
|
|
|
790 |
|
|
$interval = REQUEST_TIME - variable_get('user_block_seconds_online', 900);
|
791 |
|
|
|
792 |
|
|
$query = db_select("users", "u")->distinct()->fields("u", array("uid", "name"));
|
793 |
|
|
$s_alias = $query->join("sessions", "s", "u.uid = s.uid");
|
794 |
|
|
|
795 |
|
|
$query->addExpression("MAX({$s_alias}.timestamp)", "maxtime");
|
796 |
|
|
$query
|
797 |
|
|
->condition("{$s_alias}.timestamp", $interval, ">=")
|
798 |
|
|
->condition("{$s_alias}.uid", "0", ">")
|
799 |
|
|
->groupBy("u.uid, u.name")
|
800 |
|
|
->orderBy("maxtime", "DESC");
|
801 |
|
|
|
802 |
|
|
$authenticated_users = $query->execute();
|
803 |
|
|
|
804 |
|
|
while ($account = $authenticated_users->fetchObject()) {
|
805 |
|
|
$list[] = theme('username', array('account' => $account));
|
806 |
|
|
}
|
807 |
|
|
|
808 |
|
|
return $list;
|
809 |
|
|
}
|
810 |
|
|
|
811 |
|
|
// CALCULATING LINKS - New, Last, Etc *****************************************/
|
812 |
|
|
|
813 |
|
|
function advanced_forum_get_reply_link($node) {
|
814 |
|
|
$reply_link = array();
|
815 |
|
|
|
816 |
|
|
$comment_setting = $node->comment;
|
817 |
|
|
$fragment = 'comment-form';
|
818 |
|
|
|
819 |
|
|
if ($comment_setting == COMMENT_NODE_OPEN) {
|
820 |
|
|
|
821 |
|
|
$allowed = FALSE;
|
822 |
|
|
if (module_exists('forum_access')) {
|
823 |
|
|
// get tid
|
824 |
|
|
if (!empty($node->taxonomy_forums)) {
|
825 |
|
|
reset($node->taxonomy_forums);
|
826 |
|
|
$langcode = key($node->taxonomy_forums);
|
827 |
|
|
if (!empty($node->taxonomy_forums[$langcode])) {
|
828 |
|
|
$tid = $node->taxonomy_forums[$langcode][0]['tid'];
|
829 |
|
|
if (forum_access_access('create', $tid)) {
|
830 |
|
|
$allowed = TRUE;
|
831 |
|
|
}
|
832 |
|
|
}
|
833 |
|
|
}
|
834 |
|
|
}
|
835 |
|
|
else {
|
836 |
|
|
$allowed = user_access('post comments');
|
837 |
|
|
}
|
838 |
|
|
|
839 |
|
|
if ($allowed) {
|
840 |
|
|
if (variable_get('comment_form_location_' . $node->type, COMMENT_FORM_SEPARATE_PAGE) == COMMENT_FORM_SEPARATE_PAGE) {
|
841 |
|
|
// Reply form is on separate page. Grab the href from the node links
|
842 |
|
|
// so it's automatically corrected for Node Comments if needed.
|
843 |
|
|
$reply_link['href'] = "comment/reply/$node->nid";
|
844 |
|
|
$reply_link['options']['fragment'] = $fragment;
|
845 |
|
|
|
846 |
|
|
$reply_link['class'] = 'reply-allowed';
|
847 |
|
|
$reply_link['title'] = t('Post reply');
|
848 |
|
|
|
849 |
|
|
return $reply_link;
|
850 |
|
|
}
|
851 |
|
|
else {
|
852 |
|
|
// Reply form is on same page. The reply button should jump down to it
|
853 |
|
|
// rather than going to a new page.
|
854 |
|
|
$reply_link['href'] = $_GET['q'];
|
855 |
|
|
$reply_link['options']['fragment'] = $fragment;
|
856 |
|
|
$current_page = isset($_GET['page']) ? $_GET['page'] : 0;
|
857 |
|
|
if ($current_page)
|
858 |
|
|
$reply_link['options']['query'] = array('page' => $current_page);
|
859 |
|
|
|
860 |
|
|
$reply_link['class'] = 'reply-allowed';
|
861 |
|
|
$reply_link['title'] = t('Quick reply');
|
862 |
|
|
|
863 |
|
|
return $reply_link;
|
864 |
|
|
}
|
865 |
|
|
}
|
866 |
|
|
else {
|
867 |
|
|
// User does not have access to post replies on this node.
|
868 |
|
|
return 'reply-forbidden';
|
869 |
|
|
}
|
870 |
|
|
}
|
871 |
|
|
else {
|
872 |
|
|
// Topic is locked.
|
873 |
|
|
return 'reply-locked';
|
874 |
|
|
}
|
875 |
|
|
}
|
876 |
|
|
|
877 |
|
|
/**
|
878 |
|
|
* Get a link to the last post in a topic.
|
879 |
|
|
*
|
880 |
|
|
* @param $node
|
881 |
|
|
* Node object
|
882 |
|
|
* @return
|
883 |
|
|
* Text linking to the last post in a topic.
|
884 |
|
|
*/
|
885 |
|
|
function advanced_forum_last_post_link($node) {
|
886 |
|
|
$last_comment_id = advanced_forum_last_post_in_topic($node->nid);
|
887 |
|
|
// Return empty link if post doesn't have comments.
|
888 |
|
|
if (empty($last_comment_id))
|
889 |
|
|
return '';
|
890 |
|
|
|
891 |
|
|
$last_page = advanced_forum_get_last_page($node);
|
892 |
|
|
|
893 |
|
|
if ($last_page > 0)
|
894 |
|
|
$query = array('page' => $last_page);
|
895 |
|
|
|
896 |
|
|
$options = array(
|
897 |
|
|
'html' => TRUE,
|
898 |
|
|
'query' => empty($query) ? array() : $query,
|
899 |
|
|
'fragment' => "comment-$last_comment_id",
|
900 |
|
|
);
|
901 |
|
|
|
902 |
|
|
return theme('advanced_forum_l', array(
|
903 |
|
|
'text' => t('Last post'),
|
904 |
|
|
'path' => "node/$node->nid",
|
905 |
|
|
'options' => $options,
|
906 |
|
|
'button_class' => 'large'
|
907 |
|
|
));
|
908 |
|
|
}
|
909 |
|
|
|
910 |
|
|
/**
|
911 |
|
|
* Returns a link directly to the first new post in a topic.
|
912 |
|
|
*
|
913 |
|
|
* @param $node
|
914 |
|
|
* Node object
|
915 |
|
|
* @param $comment_count
|
916 |
|
|
* Number of comments on passed node.
|
917 |
|
|
* @return
|
918 |
|
|
* Link to the first unread post.
|
919 |
|
|
*/
|
920 |
|
|
function advanced_forum_first_new_post_link($node, $comment_count) {
|
921 |
|
|
$nid = $node->nid;
|
922 |
|
|
|
923 |
|
|
$current_page = isset($_GET['page']) ? $_GET['page'] : 0;
|
924 |
|
|
$number_new_comments = advanced_forum_reply_num_new($nid);
|
925 |
|
|
|
926 |
|
|
if ($number_new_comments > 0) {
|
927 |
|
|
$page_of_first_new = advanced_forum_page_first_new($comment_count, $number_new_comments, $node);
|
928 |
|
|
|
929 |
|
|
// Note that we are linking to the cid anchor rather than "new" because
|
930 |
|
|
// the new links will be gone if we go to another page.
|
931 |
|
|
$cid_of_first_new = advanced_forum_first_new_comment($nid);
|
932 |
|
|
|
933 |
|
|
$number_new = t("(!new new)", array('!new' => $number_new_comments));
|
934 |
|
|
|
935 |
|
|
$options = array(
|
936 |
|
|
'html' => TRUE,
|
937 |
|
|
'query' => $page_of_first_new,
|
938 |
|
|
'fragment' => "comment-$cid_of_first_new"
|
939 |
|
|
);
|
940 |
|
|
|
941 |
|
|
return theme('advanced_forum_l', array(
|
942 |
|
|
'text' => t('First unread'),
|
943 |
|
|
'path' => "node/$nid",
|
944 |
|
|
'options' => $options,
|
945 |
|
|
'button_class' => 'large'
|
946 |
|
|
));
|
947 |
|
|
}
|
948 |
|
|
}
|
949 |
|
|
|
950 |
|
|
/**
|
951 |
|
|
* Get the page number with the first new post.
|
952 |
|
|
*/
|
953 |
|
|
function advanced_forum_page_first_new($comment_count, $new_replies, $node) {
|
954 |
|
|
return comment_new_page_count($comment_count, $new_replies, $node);
|
955 |
|
|
}
|
956 |
|
|
|
957 |
|
|
/**
|
958 |
|
|
* Get the number of new posts on a topic.
|
959 |
|
|
*/
|
960 |
|
|
function advanced_forum_reply_num_new($nid, $timestamp = 0) {
|
961 |
|
|
// Make a static cache because this function is called twice from the topic
|
962 |
|
|
// header. Once to display the number and once to make the link to first new.
|
963 |
|
|
static $number_new_for_node = array();
|
964 |
|
|
|
965 |
|
|
// $nid is empty if new topic in preview.
|
966 |
|
|
if (empty($nid))
|
967 |
|
|
return 0;
|
968 |
|
|
|
969 |
|
|
if (empty($number_new_for_node[$nid])) {
|
970 |
|
|
global $user;
|
971 |
|
|
|
972 |
|
|
$node = node_load($nid);
|
973 |
|
|
|
974 |
|
|
// We must also check the forum post itself to see if we have viewed it
|
975 |
|
|
$viewed = 0; // If not told otherwise, it has been viewed before
|
976 |
|
|
if ($user->uid) {
|
977 |
|
|
$viewed = node_last_viewed($nid);
|
978 |
|
|
// Set it to 1 if it has not been viewed before.
|
979 |
|
|
$viewed = ($viewed == 0 ? 1 : 0);
|
980 |
|
|
}
|
981 |
|
|
|
982 |
|
|
$number_new_for_node[$nid] = comment_num_new($nid, $timestamp) + $viewed;
|
983 |
|
|
}
|
984 |
|
|
|
985 |
|
|
return $number_new_for_node[$nid];
|
986 |
|
|
}
|
987 |
|
|
|
988 |
|
|
/**
|
989 |
|
|
* Get the comment id of the last post in a topic.
|
990 |
|
|
*
|
991 |
|
|
* @param $node
|
992 |
|
|
* Node object
|
993 |
|
|
* @return
|
994 |
|
|
* cid of last post.
|
995 |
|
|
*/
|
996 |
|
|
function advanced_forum_last_post_in_topic($nid) {
|
997 |
|
|
// $nid is empty if new topic in preview.
|
998 |
|
|
if (empty($nid))
|
999 |
|
|
return NULL;
|
1000 |
|
|
|
1001 |
|
|
$node = node_load($nid);
|
1002 |
|
|
|
1003 |
|
|
// Comment module version
|
1004 |
|
|
$query = 'SELECT c.cid
|
1005 |
|
|
FROM {comment} c
|
1006 |
|
|
WHERE c.nid = :nid AND c.status = :status
|
1007 |
|
|
ORDER BY c.cid DESC';
|
1008 |
|
|
$result = db_query_range($query, 0, 1, array(':nid' => $nid, ':status' => COMMENT_PUBLISHED))->fetchField();
|
1009 |
|
|
|
1010 |
|
|
return $result;
|
1011 |
|
|
}
|
1012 |
|
|
|
1013 |
|
|
/**
|
1014 |
|
|
* Returns the page number of the last page starting at 0 like the pager does.
|
1015 |
|
|
*/
|
1016 |
|
|
function advanced_forum_get_last_page($node) {
|
1017 |
|
|
$comments_per_page = variable_get('comment_default_per_page_' . $node->type, 50);
|
1018 |
|
|
$comment_count = isset($node->comment_count) ? $node->comment_count : 0;
|
1019 |
|
|
$last_page = ceil($comment_count / $comments_per_page) - 1;
|
1020 |
|
|
return $last_page;
|
1021 |
|
|
}
|
1022 |
|
|
|
1023 |
|
|
/**
|
1024 |
|
|
* Returns the ID of the first unread comment.
|
1025 |
|
|
*
|
1026 |
|
|
* @param $nid
|
1027 |
|
|
* Node ID
|
1028 |
|
|
* @param $timestamp
|
1029 |
|
|
* Date/time used to override when the user last viewed the node.
|
1030 |
|
|
* @return
|
1031 |
|
|
* Comment ID
|
1032 |
|
|
*/
|
1033 |
|
|
function advanced_forum_first_new_comment($nid, $timestamp = 0) {
|
1034 |
|
|
global $user;
|
1035 |
|
|
|
1036 |
|
|
if ($user->uid) {
|
1037 |
|
|
// Retrieve the timestamp at which the current user last viewed the
|
1038 |
|
|
// specified node.
|
1039 |
|
|
if (!$timestamp) {
|
1040 |
|
|
$timestamp = node_last_viewed($nid);
|
1041 |
|
|
}
|
1042 |
|
|
|
1043 |
|
|
// Set the timestamp to the limit if the node was last read past the cutoff
|
1044 |
|
|
$timestamp = ($timestamp > NODE_NEW_LIMIT ? $timestamp : NODE_NEW_LIMIT);
|
1045 |
|
|
|
1046 |
|
|
// Use the timestamp to retrieve the oldest new comment.
|
1047 |
|
|
$query = db_select('comment', 'c')
|
1048 |
|
|
->fields('c', array('cid'))
|
1049 |
|
|
->condition('nid', $nid)
|
1050 |
|
|
->condition('changed', $timestamp, '>')
|
1051 |
|
|
->condition('status', COMMENT_PUBLISHED)
|
1052 |
|
|
->range(0, 1)
|
1053 |
|
|
->execute();
|
1054 |
|
|
return $query->fetchField();
|
1055 |
|
|
}
|
1056 |
|
|
else {
|
1057 |
|
|
return 0;
|
1058 |
|
|
}
|
1059 |
|
|
}
|
1060 |
|
|
|
1061 |
|
|
// GENERAL UTILITY FUNCTIONS *************************************************/
|
1062 |
|
|
|
1063 |
|
|
/**
|
1064 |
|
|
* Return an array of node types allowed in a given vocabulary or term ID.
|
1065 |
|
|
*/
|
1066 |
|
|
function advanced_forum_allowed_node_types($tid = 0) {
|
1067 |
|
|
if (module_exists('forum_access')) {
|
1068 |
|
|
// Check with forum access to see if this forum allows node creation.
|
1069 |
|
|
// If it doesn't, send back an empty list.
|
1070 |
|
|
if (!forum_access_access('create', $tid)) {
|
1071 |
|
|
return array();
|
1072 |
|
|
}
|
1073 |
|
|
}
|
1074 |
|
|
|
1075 |
|
|
$field = field_info_field('taxonomy_forums');
|
1076 |
|
|
if (!empty($field['bundles']['node'])) {
|
1077 |
|
|
return $field['bundles']['node'];
|
1078 |
|
|
}
|
1079 |
|
|
else {
|
1080 |
|
|
return array();
|
1081 |
|
|
}
|
1082 |
|
|
}
|
1083 |
|
|
|
1084 |
|
|
/**
|
1085 |
|
|
* Return whether a given node type is allowed in the whole forum or given forum.
|
1086 |
|
|
*/
|
1087 |
|
|
function advanced_forum_type_is_in_forum($node, $tid = 0) {
|
1088 |
|
|
$vid = (empty($vid)) ? variable_get('forum_nav_vocabulary', 0) : $vid;
|
1089 |
|
|
if (!empty($node->taxonomy_forums)) {
|
1090 |
|
|
// Check for language used
|
1091 |
|
|
if (!isset($node->taxonomy_forums[$node->language])) {
|
1092 |
|
|
$langcode = LANGUAGE_NONE;
|
1093 |
|
|
}
|
1094 |
|
|
else {
|
1095 |
|
|
$langcode = $node->language;
|
1096 |
|
|
}
|
1097 |
|
|
|
1098 |
|
|
foreach ($node->taxonomy_forums[$langcode] as $tforum) {
|
1099 |
|
|
if (!isset($tforum['taxonomy_term'])) {
|
1100 |
|
|
continue;
|
1101 |
|
|
}
|
1102 |
|
|
if (($tforum['taxonomy_term']->vid == $vid) || ($tforum['taxonomy_term']->tid == $tid))
|
1103 |
|
|
return TRUE;
|
1104 |
|
|
}
|
1105 |
|
|
}
|
1106 |
|
|
return FALSE;
|
1107 |
|
|
}
|
1108 |
|
|
|
1109 |
|
|
/**
|
1110 |
|
|
* Generate a list of node creation links for a forum.
|
1111 |
|
|
*
|
1112 |
|
|
* This is used on the forum list, allowing us to have direct
|
1113 |
|
|
* links to create new nodes in the forum.
|
1114 |
|
|
*/
|
1115 |
|
|
function advanced_forum_node_type_create_list($tid) {
|
1116 |
|
|
$allowed_types = advanced_forum_allowed_node_types($tid);
|
1117 |
|
|
|
1118 |
|
|
// Ensure "new topic" is first.
|
1119 |
|
|
if (isset($allowed_types['forum'])) {
|
1120 |
|
|
unset($allowed_types['forum']);
|
1121 |
|
|
array_unshift($allowed_types, 'forum');
|
1122 |
|
|
}
|
1123 |
|
|
// Loop through all node types allowed in this forum.
|
1124 |
|
|
foreach ($allowed_types as $type) {
|
1125 |
|
|
// Check if this node type can be created by current user.
|
1126 |
|
|
if (node_access('create', $type)) {
|
1127 |
|
|
// Fetch the "General" name of the content type.
|
1128 |
|
|
$node_type = t(node_type_get_name($type));
|
1129 |
|
|
|
1130 |
|
|
// Remove the word "Forum" out of "Forum topic" to shorten it.
|
1131 |
|
|
// @TODO: this is a little dodgy and may not work right with
|
1132 |
|
|
// translations. Should be replaced if there's a better way.
|
1133 |
|
|
$node_type = str_replace('Forum', '', $node_type);
|
1134 |
|
|
|
1135 |
|
|
// Push the link with title and url to the array.
|
1136 |
|
|
$forum_types[$type] = array(
|
1137 |
|
|
'name' => $node_type,
|
1138 |
|
|
'href' => 'node/add/' . str_replace('_', '-', $type) . '/' . $tid,
|
1139 |
|
|
);
|
1140 |
|
|
}
|
1141 |
|
|
}
|
1142 |
|
|
|
1143 |
|
|
if (empty($forum_types)) {
|
1144 |
|
|
// The user is logged-in; but denied access to create any new forum content type.
|
1145 |
|
|
global $user;
|
1146 |
|
|
if ($user->uid) {
|
1147 |
|
|
return t('You are not allowed to post new content in the forum.');
|
1148 |
|
|
}
|
1149 |
|
|
// The user is not logged-in; and denied access to create any new forum content type.
|
1150 |
|
|
else {
|
1151 |
|
|
return t('<a href="@login">Log in</a> to post new content in the forum.', array(
|
1152 |
|
|
'@login' => url('user/login', array('query' => drupal_get_destination())),
|
1153 |
|
|
));
|
1154 |
|
|
}
|
1155 |
|
|
}
|
1156 |
|
|
else {
|
1157 |
|
|
return $forum_types;
|
1158 |
|
|
}
|
1159 |
|
|
}
|
1160 |
|
|
|
1161 |
|
|
/**
|
1162 |
|
|
* Create a drop down list of forum actions.
|
1163 |
|
|
*/
|
1164 |
|
|
function advanced_forum_forum_tools($tid = 0) {
|
1165 |
|
|
global $user;
|
1166 |
|
|
$options = array();
|
1167 |
|
|
|
1168 |
|
|
ctools_include('jump-menu');
|
1169 |
|
|
if ($tid > 0) {
|
1170 |
|
|
$select[url("forum/active", array('query' => array('forum[]' => $tid)))] = t("View active posts in this forum");
|
1171 |
|
|
$select[url("forum/unanswered", array('query' => array('forum[]' => $tid)))] = t("View unanswered posts in this forum");
|
1172 |
|
|
|
1173 |
|
|
if ($user->uid) {
|
1174 |
|
|
$select[url("forum/new", array('query' => array('forum[]' => $tid)))] = t("View new posts in this forum");
|
1175 |
|
|
}
|
1176 |
|
|
}
|
1177 |
|
|
else {
|
1178 |
|
|
$select[url("forum/active")] = t("View active forum posts");
|
1179 |
|
|
$select[url("forum/unanswered")] = t("View unanswered forum posts");
|
1180 |
|
|
|
1181 |
|
|
if ($user->uid) {
|
1182 |
|
|
$select[url("forum/new")] = t("View new forum posts");
|
1183 |
|
|
}
|
1184 |
|
|
}
|
1185 |
|
|
|
1186 |
|
|
// Add mark as read to the jump list.
|
1187 |
|
|
// This code is a little odd and needs explaining. The return value of
|
1188 |
|
|
// the mark_as_read function is already formed HTML and so is unsuitable
|
1189 |
|
|
// for the jump list. The function already has built in the ability
|
1190 |
|
|
// to add to an existing $links array, which has the URL and title text
|
1191 |
|
|
// separated. Rather than add a third method just for the jump menu, I
|
1192 |
|
|
// reused that functionality here.
|
1193 |
|
|
$mark_as_read = array();
|
1194 |
|
|
advanced_forum_get_mark_read_link($tid, $mark_as_read);
|
1195 |
|
|
if (!empty($mark_as_read['mark-read']['href'])) {
|
1196 |
|
|
$select[url($mark_as_read['mark-read']['href'])] = $mark_as_read['mark-read']['title'];
|
1197 |
|
|
}
|
1198 |
|
|
|
1199 |
|
|
$options['choose'] = t("- Forum Tools -");
|
1200 |
|
|
|
1201 |
|
|
// Create and return the jump menu.
|
1202 |
|
|
$form = drupal_get_form('ctools_jump_menu', $select, $options);
|
1203 |
|
|
return drupal_render($form);
|
1204 |
|
|
}
|
1205 |
|
|
|
1206 |
|
|
/**
|
1207 |
|
|
* Creates a pager to place on each multi-page topic of the topic listing page.
|
1208 |
|
|
*
|
1209 |
|
|
* @param $max_pages_to_display
|
1210 |
|
|
* Number of pages to include on the pager.
|
1211 |
|
|
* @param $topic
|
1212 |
|
|
* Topic object to create a pager for.
|
1213 |
|
|
* @return
|
1214 |
|
|
* Object containing the linked pages ready assembly by the theme function.
|
1215 |
|
|
*/
|
1216 |
|
|
function advanced_forum_create_topic_pager($max_pages_to_display, $topic) {
|
1217 |
|
|
// Find the number of comments per page for the node type of the topic.
|
1218 |
|
|
$comments_per_page = variable_get('comment_default_per_page_' . $topic->type, 50);
|
1219 |
|
|
|
1220 |
|
|
if ($max_pages_to_display > 0 && $topic->comment_count > $comments_per_page) {
|
1221 |
|
|
// Topic has more than one page and a pager is wanted. Start off the
|
1222 |
|
|
// first page because that doesn't have a query.
|
1223 |
|
|
$pager_array = array();
|
1224 |
|
|
$current_display_page = 1;
|
1225 |
|
|
$pager_array[0] = l('1', "node/$topic->nid");
|
1226 |
|
|
|
1227 |
|
|
// Find the ending point. The pager URL is always 1 less than
|
1228 |
|
|
// the number being displayed because the first page is 0.
|
1229 |
|
|
$last_display_page = ceil($topic->comment_count / $comments_per_page);
|
1230 |
|
|
$last_pager_page = $last_display_page - 1;
|
1231 |
|
|
|
1232 |
|
|
// Add pages until we run out or until we hit the max to show.
|
1233 |
|
|
while (($current_display_page < $last_display_page) && ($current_display_page < $max_pages_to_display)) {
|
1234 |
|
|
// Move to the next page
|
1235 |
|
|
$current_display_page++;
|
1236 |
|
|
|
1237 |
|
|
// The page number we link to is 1 less than what's displayed
|
1238 |
|
|
$link_to_page = $current_display_page - 1;
|
1239 |
|
|
|
1240 |
|
|
// Add the link to the array
|
1241 |
|
|
$pager_array[$link_to_page] = l($current_display_page, "node/$topic->nid", array('query' => array('page' => $link_to_page)));
|
1242 |
|
|
}
|
1243 |
|
|
|
1244 |
|
|
// Move to the next page
|
1245 |
|
|
$current_display_page++;
|
1246 |
|
|
|
1247 |
|
|
if ($current_display_page == $last_display_page) {
|
1248 |
|
|
// We are one past the max to display, but it's the last page,
|
1249 |
|
|
// so putting the ...last is silly. Just display it normally.
|
1250 |
|
|
$link_to_page = $current_display_page - 1;
|
1251 |
|
|
$pager_array[$link_to_page] = l($current_display_page, "node/$topic->nid", array('query' => array('page' => $link_to_page)));
|
1252 |
|
|
}
|
1253 |
|
|
|
1254 |
|
|
if ($current_display_page < $last_display_page) {
|
1255 |
|
|
// We are one past the max to display and still aren't
|
1256 |
|
|
// on the last page, so put in ... Last Page(N)
|
1257 |
|
|
$text = t('Last Page');
|
1258 |
|
|
$pager_last_text = l($text, "node/$topic->nid", array('query' => array('page' => $last_pager_page)));
|
1259 |
|
|
$pager_last_number = l($last_display_page, "node/$topic->nid", array('query' => array('page' => $last_pager_page)));
|
1260 |
|
|
// Create last page array to enable more customization for themers.
|
1261 |
|
|
$pager_last = array(
|
1262 |
|
|
'number' => $last_display_page,
|
1263 |
|
|
'link' => "node/$topic->nid",
|
1264 |
|
|
'options' => array('query' => array('page' => $last_pager_page)),
|
1265 |
|
|
);
|
1266 |
|
|
}
|
1267 |
|
|
|
1268 |
|
|
$topic_pager = new stdClass();
|
1269 |
|
|
$topic_pager->initial_pages = (empty($pager_array)) ? array() : $pager_array;
|
1270 |
|
|
$topic_pager->last_page_text = (empty($pager_last_text)) ? '' : $pager_last_text;
|
1271 |
|
|
$topic_pager->last_page_number = (empty($pager_last_number)) ? '' : $pager_last_number;
|
1272 |
|
|
$topic_pager->last_page = (empty($pager_last)) ? array() : $pager_last;
|
1273 |
|
|
|
1274 |
|
|
return $topic_pager;
|
1275 |
|
|
}
|
1276 |
|
|
}
|
1277 |
|
|
|
1278 |
|
|
/**
|
1279 |
|
|
* Create a drop down list of forum hierarchy
|
1280 |
|
|
*/
|
1281 |
|
|
function advanced_forum_forum_jump($tid = 0) {
|
1282 |
|
|
global $user;
|
1283 |
|
|
ctools_include('jump-menu');
|
1284 |
|
|
$select = array();
|
1285 |
|
|
$options = array();
|
1286 |
|
|
$vid = variable_get('forum_nav_vocabulary', 0);
|
1287 |
|
|
if ($tid > 0) {
|
1288 |
|
|
$forum_tree = taxonomy_get_tree($vid);
|
1289 |
|
|
foreach ($forum_tree as $forum) {
|
1290 |
|
|
$select[url("forum/" . $forum->tid)] = str_repeat("-", $forum->depth) . $forum->name;
|
1291 |
|
|
}
|
1292 |
|
|
}
|
1293 |
|
|
else {
|
1294 |
|
|
// nothing
|
1295 |
|
|
}
|
1296 |
|
|
|
1297 |
|
|
$options['choose'] = t("- Select a forum -");
|
1298 |
|
|
|
1299 |
|
|
// Create and return the jump menu.
|
1300 |
|
|
$form = drupal_get_form('ctools_jump_menu', $select, $options);
|
1301 |
|
|
return drupal_render($form);
|
1302 |
|
|
}
|
1303 |
|
|
|
1304 |
|
|
/**
|
1305 |
|
|
* Calculates the number of unread replies for each forum and returns the
|
1306 |
|
|
* count for the requested forum.
|
1307 |
|
|
*/
|
1308 |
|
|
function advanced_forum_unread_replies_in_forum($tid, $uid) {
|
1309 |
|
|
static $result_cache = NULL;
|
1310 |
|
|
|
1311 |
|
|
if (is_null($result_cache)) {
|
1312 |
|
|
$result_cache = array();
|
1313 |
|
|
|
1314 |
|
|
$query = db_select("comment", "c");
|
1315 |
|
|
$f_alias = $query->join("forum", "f", "c.nid = f.nid");
|
1316 |
|
|
//$n_alias = $query->join("node", "n", "f.vid = n.vid");
|
1317 |
|
|
$h_alias = $query->leftJoin("history", "h", "c.nid = h.nid AND h.uid = :uid", array(":uid" => $uid));
|
1318 |
|
|
$query->addExpression("COUNT(DISTINCT(c.cid))", "count");
|
1319 |
|
|
$query->addField($f_alias, "tid");
|
1320 |
|
|
|
1321 |
|
|
$query->condition("c.status", COMMENT_PUBLISHED)
|
1322 |
|
|
->condition("c.changed", NODE_NEW_LIMIT, ">")
|
1323 |
|
|
->condition(db_or()->where("c.changed > {$h_alias}.timestamp")->isNull("h.timestamp"))
|
1324 |
|
|
->groupBy("{$f_alias}.tid")
|
1325 |
|
|
->addTag("node_access");
|
1326 |
|
|
|
1327 |
|
|
$result = $query->execute();
|
1328 |
|
|
foreach ($result as $row) {
|
1329 |
|
|
$result_cache[$row->tid] = $row->count;
|
1330 |
|
|
}
|
1331 |
|
|
}
|
1332 |
|
|
|
1333 |
|
|
return (isset($result_cache[$tid])) ? $result_cache[$tid] : 0;
|
1334 |
|
|
}
|
1335 |
|
|
|
1336 |
|
|
/**
|
1337 |
|
|
* Returns the display position of a given reply post ID on a given node.
|
1338 |
|
|
*/
|
1339 |
|
|
function advanced_forum_post_position($node, $comment) {
|
1340 |
|
|
static $post_order = array();
|
1341 |
|
|
|
1342 |
|
|
if (empty($node) || empty($comment)) {
|
1343 |
|
|
return 0;
|
1344 |
|
|
}
|
1345 |
|
|
|
1346 |
|
|
$node_id = $node->nid;
|
1347 |
c169e7c4
|
Assos Assos
|
$post_id = $comment->cid;
|
1348 |
85ad3d82
|
Assos Assos
|
|
1349 |
|
|
if (!isset($post_order[$node_id])) {
|
1350 |
|
|
// Initialize the spot for this node's list.
|
1351 |
|
|
$post_order[$node_id] = array();
|
1352 |
|
|
|
1353 |
|
|
$mode = variable_get('comment_default_mode_' . $node->type, COMMENT_MODE_THREADED);
|
1354 |
|
|
|
1355 |
|
|
// Get the list of CIDs from the database in order of oldest first.
|
1356 |
|
|
// We are going to make that assumption for now for simplicity but may
|
1357 |
|
|
// revisit in the future if there are requests for newest first.
|
1358 |
|
|
$query = db_select('comment', 'c')
|
1359 |
|
|
->fields('c', array('cid'))
|
1360 |
|
|
->condition('c.nid', $node_id)
|
1361 |
|
|
->addTag('node_access')
|
1362 |
|
|
->addTag('comment_filter');
|
1363 |
|
|
|
1364 |
|
|
if ($mode === COMMENT_MODE_FLAT) {
|
1365 |
|
|
$query->orderBy('c.cid', 'ASC');
|
1366 |
|
|
}
|
1367 |
|
|
else {
|
1368 |
|
|
$query->addExpression('SUBSTRING(c.thread, 1, (LENGTH(c.thread) - 1))', 'torder');
|
1369 |
|
|
$query->orderBy('torder', 'ASC');
|
1370 |
|
|
}
|
1371 |
|
|
|
1372 |
|
|
$query = $query->execute();
|
1373 |
|
|
// Cycle through the results and fill in the array.
|
1374 |
|
|
while ($post = $query->fetchAssoc()) {
|
1375 |
|
|
$post_order[$node_id][] = reset($post);
|
1376 |
|
|
}
|
1377 |
|
|
}
|
1378 |
|
|
|
1379 |
|
|
// Find the position of the passed in post ID.
|
1380 |
|
|
$post_position = 0;
|
1381 |
|
|
if (is_array($post_order[$node_id])) {
|
1382 |
|
|
if (($index = array_search($post_id, $post_order[$node_id])) !== FALSE) {
|
1383 |
|
|
$post_position = $index;
|
1384 |
|
|
|
1385 |
|
|
// We need to add 2 because the array starts at 0 and also because the topic
|
1386 |
|
|
// node is post #1 on display but is not included in the index.
|
1387 |
|
|
$post_position = $post_position + 2;
|
1388 |
|
|
}
|
1389 |
|
|
}
|
1390 |
|
|
|
1391 |
|
|
return $post_position;
|
1392 |
|
|
} |