PluginProbe
wpForo Forum / 1.4.12
wpForo Forum v1.4.12
3.1.5 3.1.4 3.1.2 3.1.1 3.1.0 3.0.9 3.0.8 3.0.7 trunk 1.0.0 1.0.1 1.0.2 1.1.0 1.1.1 1.1.2 1.2.0 1.3.0 1.3.1 1.4.0 1.4.1 1.4.10 1.4.11 1.4.12 1.4.13 1.4.2 All 137 releases
wpforo / wpf-includes / class-topics.php

class-topics.php in wpForo Forum 1.4.12, at wpf-includes/class-topics.php

1,230 lines 44.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 // Exit if accessed directly
3 if( !defined( 'ABSPATH' ) ) exit;
4
5 class wpForoTopic{
6 static $cache = array( 'topics' => array(), 'item' => array(), 'topic' => array() );
7
8 function __construct(){}
9
10 public function get_cache( $var ){
11 if( isset(self::$cache[$var]) ) return self::$cache[$var];
12 }
13
14 private function unique_slug($slug){
15 $new_slug = wpforo_text($slug, 250, false);
16 $i = 2;
17 while( WPF()->db->get_var("SELECT `topicid` FROM ".WPF()->tables->topics." WHERE `slug` = '" . esc_sql($new_slug) . "'") ){
18 $new_slug = wpforo_text($slug, 250, false) . '-' . $i;
19 $i++;
20 }
21 return $new_slug;
22 }
23
24 public function add( $args = array() ){
25
26 if( empty($args) && empty($_REQUEST['topic']) ) return FALSE;
27 if( empty($args) && !empty($_REQUEST['topic']) ){ $args = $_REQUEST['topic']; $args['body'] = $_REQUEST['postbody']; }
28 if( !isset($args['body']) || !$args['body'] ){ WPF()->notice->add('Post is empty', 'error'); return FALSE; }
29 $args['name'] = (isset($args['name']) ? strip_tags($args['name']) : '' );
30 $args['email'] = (isset($args['email']) ? sanitize_email($args['email']) : '' );
31
32 if( !isset($args['forumid']) || !$args['forumid'] = intval($args['forumid']) ){
33 WPF()->notice->add('Add Topic error: No forum selected', 'error');
34 return FALSE;
35 }
36
37 if( !WPF()->perm->forum_can( 'ct', $args['forumid']) ){
38 WPF()->notice->add('You don\'t have permission to create topic into this forum', 'error');
39 return FALSE;
40 }
41
42 if( !isset($args['title']) || !$args['title'] = trim(strip_tags($args['title'])) ){
43 WPF()->notice->add('Please insert required fields!', 'error');
44 return FALSE;
45 }
46
47 if( !is_user_logged_in() ){
48 if( !$args['name'] || !$args['email'] ){
49 WPF()->notice->add('Please insert required fields!', 'error');
50 return FALSE;
51 }
52 else{
53 WPF()->member->set_guest_cookies( $args );
54 }
55 }
56
57 do_action( 'wpforo_start_add_topic', $args );
58
59 $args['title'] = wpforo_text($args['title'], 250, false);
60 $args['body'] = (isset($args['body']) ? preg_replace('#</pre>[\r\n\t\s\0]*<pre>#isu', "\r\n", $args['body']) : '' );
61 $args['slug'] = (isset($args['slug']) && $args['slug']) ? sanitize_title($args['slug']) : ((isset($args['title'])) ? sanitize_title($args['title']) : md5(time()));
62 $args['slug'] = $this->unique_slug($args['slug']);
63 $args['created'] = (isset($args['created']) ? sanitize_text_field($args['created']) : current_time( 'mysql', 1 ) );
64 $args['userid'] = (isset($args['userid']) ? intval($args['userid']) : WPF()->current_userid );
65 $args['name'] = (isset($args['name']) ? $args['name'] : '' );
66 $args['email'] = (isset($args['email']) ? $args['email'] : '' );
67
68 $args = apply_filters('wpforo_add_topic_data_filter', $args);
69
70 if(empty($args)) return FALSE;
71
72 extract($args, EXTR_OVERWRITE);
73
74 if(isset($forumid)) $forumid = intval($forumid);
75 if(isset($title)) $title = sanitize_text_field(trim($title));
76 if(isset($slug)) $slug = sanitize_title($slug);
77 if(isset($created)) $created = sanitize_text_field($created);
78 if(isset($userid)) $userid = intval($userid);
79 $type = ( isset($type) && $type ? 1 : 0 );
80 $status = ( isset($status) && $status ? 1 : 0 );
81 $private = ( isset($private) && $private ? 1 : 0 );
82 if(isset($meta_key)) $meta_key = sanitize_text_field($meta_key);
83 if(isset($meta_desc)) $meta_desc = sanitize_text_field($meta_desc);
84 if(isset($name)) $name = strip_tags(trim($name));
85 if(isset($email)) $email = strip_tags(trim($email));
86 if(isset($body)) $body = wpforo_kses(trim($body), 'post');
87 $views = ( isset($views) ? intval($views) : 0 );
88 $meta_key = (isset($meta_key) ? $meta_key : '');
89 $meta_desc = (isset($meta_desc) ? $meta_desc : '');
90 $has_attach = ( isset($has_attach) && $has_attach ) ? 1 : ((strpos($body, '[attach]') !== FALSE) ? 1 : 0);
91 $layout = WPF()->forum->get_layout( $forumid );
92 $posts = ( $layout == 3 ) ? 0 : 1;
93 do_action( 'wpforo_before_add_topic', $args );
94
95 if(
96 WPF()->db->insert(
97 WPF()->tables->topics,
98 array(
99 'title' => stripslashes($title),
100 'slug' => $slug,
101 'forumid' => $forumid,
102 'userid' => $userid,
103 'type' => $type,
104 'status' => $status,
105 'private' => $private,
106 'created' => $created,
107 'modified' => $created,
108 'last_post' => 0,
109 'views' => $views,
110 'posts' => $posts,
111 'meta_key' => $meta_key,
112 'meta_desc' => $meta_desc,
113 'has_attach'=> $has_attach,
114 'name' => $name,
115 'email' => $email
116 ),
117 array('%s','%s','%d','%d','%d','%d','%d','%s','%s','%d','%d','%d','%s','%s','%d','%s','%s')
118 )
119 ){
120 $topicid = WPF()->db->insert_id;
121 if(
122 WPF()->db->insert(
123 WPF()->tables->posts,
124 array(
125 'forumid' => $forumid,
126 'topicid' => $topicid,
127 'userid' => $userid,
128 'title' => stripslashes($title),
129 'body' => stripslashes($body),
130 'created' => $created,
131 'modified' => $created,
132 'is_first_post' => 1,
133 'status' => $status,
134 'private' => $private,
135 'name' => $name,
136 'email' => $email
137 ),
138 array('%d','%d','%d','%s','%s','%s','%s','%d','%d','%d','%s','%s')
139 )
140 ){
141 $first_postid = WPF()->db->insert_id;
142 if( FALSE !== WPF()->db->update(
143 WPF()->tables->topics,
144 array( 'first_postid' => $first_postid, 'last_post' => $first_postid ),
145 array( 'topicid' => $topicid ),
146 array( '%d', '%d' ),
147 array( '%d' )
148 )
149 ){
150 $questions = '';
151 $forum = WPF()->forum->get_forum($forumid);
152 if( isset($forum['cat_layout']) && $forum['cat_layout'] == 3 ) $questions = ', `questions` = `questions` + 1 ';
153
154 WPF()->db->query( "UPDATE ".WPF()->tables->profiles." SET `posts` = `posts` + 1 $questions WHERE `userid` = " . intval($userid) );
155
156 $args['topicid'] = $topicid;
157 $args['first_postid'] = $first_postid;
158 $args['type'] = $type;
159 $args['status'] = $status;
160 $args['private'] = $private;
161 $args['topicurl'] = $this->get_topic_url($topicid);
162
163 if( !$status && !$private) $this->last_topic($args);
164
165 do_action( 'wpforo_after_add_topic', $args );
166
167 wpforo_clean_cache('topic', $topicid, $args);
168 if(!is_user_logged_in() && $status){
169 WPF()->notice->add('Your topic successfully added and awaiting moderation', 'success');
170 }
171 else{
172 WPF()->member->reset($userid);
173 WPF()->notice->add('Your topic successfully added', 'success');
174 }
175 return $topicid;
176 }
177 }
178
179 }
180
181 WPF()->notice->add('Topic add error', 'error');
182 return FALSE;
183 }
184
185 public function edit( $args = array() ){
186
187 if( empty($args) && empty($_REQUEST['topic']) ) return FALSE;
188 if( !isset($args['topicid']) && isset($_GET['id']) ) $args['topicid'] = intval($_GET['id']);
189 if( empty($args) && !empty($_REQUEST['topic']) ){ $args = $_REQUEST['topic']; $args['body'] = $_REQUEST['postbody']; }
190 if( isset($args['name']) ){ $args['name'] = strip_tags($args['name']); }
191 if( isset($args['email']) ){ $args['email'] = sanitize_email($args['email']); }
192
193 do_action( 'wpforo_start_edit_topic', $args );
194
195 if( !$topic = $this->get_topic( $args['topicid'] ) ){
196 WPF()->notice->add('Topic not found.', 'error');
197 return FALSE;
198 }
199
200 if( !is_user_logged_in() ){
201 if( !isset($topic['email']) || !$topic['email'] ){
202 WPF()->notice->add('Permission denied', 'error');
203 return FALSE;
204 }
205 elseif( !wpforo_current_guest( $topic['email'] ) ){
206 WPF()->notice->add('You are not allowed to edit this post', 'error');
207 return FALSE;
208 }
209 if( !$args['name'] || !$args['email'] ){
210 WPF()->notice->add('Please insert required fields!', 'error');
211 return FALSE;
212 }
213 else{
214 WPF()->member->set_guest_cookies( $args );
215 }
216 }
217
218 $args['status'] = $topic['status'];
219 $args['userid'] = $topic['userid'];
220
221 $args = apply_filters('wpforo_edit_topic_data_filter', $args);
222 if(empty($args)) return FALSE;
223
224 extract($args, EXTR_OVERWRITE);
225
226 if(isset($topicid)) $topicid = intval($topicid);
227 if(isset($forumid)) $forumid = intval($forumid);
228 if(isset($title)) $title = sanitize_text_field(trim($title));
229 if(isset($slug)) $slug = sanitize_title($slug);
230 if(isset($created)) $created = sanitize_text_field($created);
231 if(isset($userid)) $userid = intval($userid);
232 if(isset($type)) $type = intval($type);
233 if(isset($status)) $status = intval($status);
234 if(isset($private)) $private = intval($private);
235 if(isset($meta_key)) $meta_key = sanitize_text_field($meta_key);
236 if(isset($meta_desc)) $meta_desc = sanitize_text_field($meta_desc);
237 if(isset($has_attach)) $has_attach = intval($has_attach);
238 if(isset($name)) $name = strip_tags(trim($name));
239 if(isset($email)) $email = strip_tags(trim($email));
240 if(isset($body)) $body = wpforo_kses(trim($body), 'post');
241
242
243 if( !isset($topicid) ){
244 WPF()->notice->add('Topic edit error', 'error');
245 return FALSE;
246 }
247 if( !isset($title) || !$title = trim(strip_tags($title)) ){
248 WPF()->notice->add('Please insert required fields!', 'error');
249 return FALSE;
250 }
251
252 $title = wpforo_text($title, 250, false);
253 if(isset($body)) $body = preg_replace('#</pre>[\r\n\t\s\0]*<pre>#isu', "\r\n", $body);
254
255 $diff = current_time( 'timestamp', 1 ) - strtotime($topic['created']);
256 if( !(WPF()->perm->forum_can('et', $topic['forumid']) ||
257 (WPF()->current_userid == $topic['userid'] &&
258 WPF()->perm->forum_can('eot', $topic['forumid']) )) ){
259 WPF()->notice->add('You have no permission to edit this topic', 'error');
260 return FALSE;
261 }
262
263 if( !WPF()->perm->forum_can('et', $topic['forumid']) &&
264 WPF()->post->options['eot_durr'] !== 0 &&
265 $diff > WPF()->post->options['eot_durr'] ){
266 WPF()->notice->add('The time to edit this topic is expired', 'error');
267 return FALSE;
268 }
269
270 $title = ( isset($title) ? stripslashes($title) : stripslashes($topic['title']) );
271 $type = ( isset($type) ? $type : intval($topic['type']) );
272 $status = ( isset($status) ? $status : intval($topic['status']) );
273 $private = ( isset($private) ? $private : intval($topic['private']) );
274 $has_attach = ( isset($body) ? (strpos($body, '[attach]') !== FALSE ? 1 : 0) : $topic['has_attach'] );
275 $name = ( isset($name) ? stripslashes($name) : stripslashes($topic['name']) );
276 $email = ( isset($email) ? stripslashes($email) : stripslashes($topic['email']) );
277
278 $t_update = WPF()->db->update(
279 WPF()->tables->topics,
280 array(
281 'title' => $title,
282 'type' => $type,
283 'status' => $status,
284 'private' => $private,
285 'has_attach'=> $has_attach,
286 'name' => $name,
287 'email' => $email
288 ),
289 array( 'topicid' => intval($topicid) ),
290 array( '%s','%d','%d','%d','%d','%s','%s' ),
291 array( '%d' )
292 );
293
294 if( isset($topic['first_postid']) ){
295 if( !$post = WPF()->post->get_post( $topic['first_postid'] ) ){
296 WPF()->notice->add('Topic first post data not found.', 'error');
297 return FALSE;
298 }
299 }
300 else{
301 WPF()->notice->add('Topic first post not found.', 'error');
302 return FALSE;
303 }
304
305 $body = ( (isset($body) && $body) ? stripslashes($body) : stripslashes($post['body']) );
306
307 $p_update = WPF()->db->update(
308 WPF()->tables->posts,
309 array(
310 'title' => $title,
311 'body' => $body,
312 'modified' => current_time( 'mysql', 1 ),
313 'status' => $status,
314 'private' => $private,
315 'name' => $name,
316 'email' => $email,
317 ),
318 array( 'postid' => intval($topic['first_postid']) ),
319 array( '%s','%s','%s','%d','%d','%s','%s' ),
320 array( '%d' )
321 );
322
323 if($t_update !== FALSE && $p_update !== FALSE){
324
325 do_action( 'wpforo_after_edit_topic', array( 'userid' => $topic['userid'], 'forumid' => $topic['forumid'], 'topicid' => $topicid, 'postid' => $topic['first_postid'], 'first_postid' => $topic['first_postid'], 'title' => $title, 'body' => $body, 'status' => $status, 'name' => $name, 'email' => $email ) );
326
327 wpforo_clean_cache('topic', $topicid, $topic);
328 WPF()->notice->add('Topic successfully updated', 'success');
329 return $topicid;
330 }
331
332 WPF()->notice->add('Topic edit error', 'error');
333 return FALSE;
334 }
335
336 private function users_stats_incr_minus($topicid){
337 $topicid = intval($topicid);
338 $sql = "SELECT `userid`, IF(`parentid` = 0, 'answers', 'comments') AS `type`, COUNT(*) AS `quantity`
339 FROM `".WPF()->tables->posts."`
340 WHERE `is_first_post` != 1 AND `topicid` IN( $topicid )
341 GROUP BY `userid`, `parentid` = 0
342 ORDER BY `userid`, `type`";
343 if( $users_incr_stats = WPF()->db->get_results($sql, ARRAY_A) ){
344 $prev_userid = 0;
345 $sets = array();
346 foreach( $users_incr_stats as $users_incr_stat ){
347 if( $prev_userid == 0 ) $prev_userid = $users_incr_stat['userid'];
348
349 if( $prev_userid != $users_incr_stat['userid'] && $prev_userid != 0 ){
350 if( !empty($sets) ){
351 $sql = "UPDATE IGNORE `".WPF()->tables->profiles."` SET ".implode(', ', $sets)." WHERE `userid` = " . intval($prev_userid);
352 WPF()->db->query($sql);
353 }
354 $prev_userid = $users_incr_stat['userid'];
355 $sets = array();
356 }
357
358 if( $users_incr_stat['type'] == 'answers' ) $sets[] = "`answers` = IF( (`answers` - " . esc_sql($users_incr_stat['quantity']) . ") < 0, 0, `answers` - " . esc_sql($users_incr_stat['quantity']) . " )";
359 if( $users_incr_stat['type'] == 'comments' ) $sets[] = "`comments` = IF( (`comments` - " . esc_sql($users_incr_stat['quantity']) . ") < 0, 0, `comments` - " . esc_sql($users_incr_stat['quantity']) . " )";
360
361 }
362
363 if( !empty($sets) ){
364 $sql = "UPDATE IGNORE `".WPF()->tables->profiles."` SET ".implode(', ', $sets)." WHERE `userid` = " . intval($users_incr_stat['userid']);
365 WPF()->db->query($sql);
366 }
367 }
368 }
369
370 #################################################################################
371 /**
372 * Delete topic from DB
373 *
374 * Returns true if successfully deleted or false.
375 *
376 * @since 1.0.0
377 *
378 * @param int $topicid
379 * @param bool $delete_cache
380 *
381 * @return bool
382 */
383 function delete($topicid = 0, $delete_cache = true ){
384 $topicid = intval($topicid);
385 if(!$topicid && isset( $_REQUEST['id'] ) ) $topicid = intval($_REQUEST['id']);
386
387 if( !$topic = $this->get_topic($topicid) ) return true;
388
389 do_action( 'wpforo_before_delete_topic', $topic );
390
391 $diff = current_time( 'timestamp', 1 ) - strtotime($topic['created']);
392 if( !(WPF()->perm->forum_can('dt', $topic['forumid']) ||
393 (WPF()->current_userid == $topic['userid'] &&
394 WPF()->perm->forum_can('dot', $topic['forumid']) )) ){
395 WPF()->notice->add('You don\'t have permission to delete topic from this forum.', 'error');
396 return FALSE;
397 }
398
399 if( !WPF()->perm->forum_can('dt', $topic['forumid']) &&
400 WPF()->post->options['dot_durr'] !== 0 &&
401 $diff > WPF()->post->options['dot_durr'] ){
402 WPF()->notice->add('The time to delete this topic is expired.', 'error');
403 return FALSE;
404 }
405
406 if( $forumid = $topic['forumid'] ){
407
408 $questions = '';
409 $forum = WPF()->forum->get_forum($forumid);
410 if( isset($forum['cat_layout']) && $forum['cat_layout'] == 3 ){
411 $questions = ' `questions` = `questions` - 1 ';
412 $this->users_stats_incr_minus($topicid);
413 }
414
415 // START delete topic posts include first post
416 if( $postids = WPF()->db->get_col(
417 WPF()->db->prepare(
418 "SELECT `postid` FROM `".WPF()->tables->posts."` WHERE `topicid` = %d ORDER BY `is_first_post`",
419 $topicid
420 )
421 )){
422 foreach ($postids as $postid) {
423 if( $postid == $topic['first_postid'] ){
424 return WPF()->post->delete($postid, false);
425 }else{
426 WPF()->post->delete($postid, false);
427 }
428 }
429 }
430 // END delete topic posts include first post
431
432 if( WPF()->db->delete(WPF()->tables->topics, array('topicid' => $topicid)) ){
433 WPF()->db->delete(
434 WPF()->tables->views, array( 'topicid' => $topicid ), array( '%d' )
435 );
436 $last_topic = $this->get_topics( array('forumid' => intval($forumid), 'orderby' => 'modified', 'order' => 'DESC', 'row_count' => 1, 'status' => 0, 'private' => 0) );
437 if(is_array($last_topic) && !empty($last_topic)){
438 $last_topic = $last_post[0];
439 if( isset($last_topic['last_post']) ) {
440 $last_post = WPF()->post->get_post($last_topic['last_post']);
441 if( is_array($last_post) && !empty($last_post) ){
442 $last_topic['last_post_userid'] = $last_post['userid'];
443 }
444 else{
445 $last_topic['last_post_userid'] = $last_topic['userid'];
446 }
447 }
448 }else{
449 $last_topic = array( 'topicid' => 0, 'last_post' => 0, 'last_post_userid' => 0, 'modified' => '0000-00-00 00:00:00');
450 }
451
452 if(WPF()->db->query(
453 "UPDATE IGNORE ".WPF()->tables->forums."
454 SET
455 `last_topicid` = " . intval($last_topic['topicid']) . ",
456 `last_postid` = " . intval($last_topic['last_post']) . ",
457 `last_userid` = " . intval($last_topic['last_post_userid']) . ",
458 `last_post_date` = '" . esc_sql($last_topic['modified']) . "',
459 `topics` = IF( (`topics` - 1) < 0, 0, `topics` - 1 )
460 WHERE `forumid` = " . intval($forumid)
461 )
462 ){
463 if($questions) WPF()->db->query(
464 "UPDATE IGNORE `".WPF()->tables->profiles."`
465 SET $questions
466 WHERE `userid` = " . intval($topic['userid'])
467 );
468
469 do_action( 'wpforo_after_delete_topic', $topic );
470
471 if( $delete_cache ) wpforo_clean_cache('topic', $topicid, $topic);
472 WPF()->member->reset($topic['userid']);
473 WPF()->forum->rebuild_last_infos($forumid);
474
475 WPF()->notice->add('This topic successfully deleted', 'success');
476 return TRUE;
477 }
478 }
479 }
480
481 WPF()->notice->add('Topics delete error', 'error');
482 return FALSE;
483 }
484
485 #################################################################################
486 /**
487 * array get_topic(array or id(num))
488 *
489 * Returns array from defined and default arguments.
490 *
491 * @since 1.0.0
492 *
493 * @param mixed defined arguments array for returning
494 *
495 * @return array
496 */
497
498 function get_topic( $args = array() ){
499
500 if( !$args ) return array();
501 $cache = WPF()->cache->on('memory_cashe');
502
503 if(is_array($args)){
504 $default = array(
505 'topicid' => NULL,
506 'slug' => '',
507 );
508 }elseif(is_numeric($args)){
509 $default = array(
510 'topicid' => $args,
511 'slug' => '',
512 );
513 }elseif(!is_numeric($args)){
514 $default = array(
515 'topicid' => NULL,
516 'slug' => $args,
517 );
518 }
519
520 $args = wpforo_parse_args( $args, $default );
521
522 if( $cache && !empty($args['topicid'])){
523 if( !empty(self::$cache['topic'][$args['topicid']]) ){
524 return self::$cache['topic'][$args['topicid']];
525 }
526 }
527
528 if( $cache && !empty($args['slug'])){
529 if( !empty(self::$cache['topic'][addslashes($args['slug'])]) ){
530 return self::$cache['topic'][addslashes($args['slug'])];
531 }
532 }
533
534 if(!empty($args)){
535 extract($args, EXTR_OVERWRITE);
536
537 $sql = "SELECT * FROM `".WPF()->tables->topics."`";
538 $wheres = array();
539 if($topicid != NULL) $wheres[] = "`topicid` = " . intval($topicid);
540 if($slug != '') $wheres[] = "`slug` = '" . esc_sql($slug) . "'";
541
542 if(!empty($wheres)){
543 $sql .= " WHERE " . implode($wheres, " AND ");
544 }
545
546 $topic = WPF()->db->get_row($sql, ARRAY_A);
547
548 if( isset($topic['forumid']) && $topic['forumid'] && !WPF()->perm->forum_can('vf', $topic['forumid']) ){
549 return array();
550 }
551
552 if( isset($topic['private']) && $topic['private'] && !wpforo_is_owner($topic['userid'], $topic['email']) ){
553 if( isset($topic['forumid']) && $topic['forumid'] && !WPF()->perm->forum_can('vp', $topic['forumid']) ){
554 return array();
555 }
556 }
557
558 if( isset($topic['status']) && $topic['status'] && !wpforo_is_owner($topic['userid'], $topic['email'])){
559 if( isset($topic['forumid']) && $topic['forumid'] && !WPF()->perm->forum_can('au', $topic['forumid']) ){
560 WPF()->current_object['status'] = 'unapproved';
561 return array();
562 }
563 }
564
565 if($cache){
566 self::$cache['topic'][addslashes($topic['slug'])] = $topic;
567 return self::$cache['topic'][$topic['topicid']] = $topic;
568 }
569 else{
570 return $topic;
571 }
572 }
573
574 }
575 /**
576 * array get_topic(array or id(num))
577 * Returns merged arguments array from defined and default arguments.
578 *
579 * @since 1.0.0
580 *
581 * @param array defined arguments array for returning
582 *
583 * @return array where count is topic count and other numeric arrays with topic
584 */
585 function get_topics($args = array(), &$items_count = 0 ){
586
587 $cache = WPF()->cache->on('object_cashe');
588
589 $default = array(
590 'include' => array(), // array( 2, 10, 25 )
591 'exclude' => array(), // array( 2, 10, 25 )
592 'forumids' => array(),
593 'forumid' => NULL,
594 'userid' => NULL, // user id in DB
595 'type' => 0, //0, 1, etc . . .
596 'status' => NULL, //0, 1, etc . . .
597 'private' => NULL, //0, 1, etc . . .''
598 'pollid' => NULL,
599 'orderby' => 'type, topicid', // type, topicid, modified, created
600 'order' => 'DESC', // ASC DESC
601 'offset' => NULL, // this use when you give row_count
602 'row_count' => NULL, // 4 or 1 ...
603 'permgroup' => NULL, //Тreat permissions based on attribute value not on current user usergroup
604 'where' => NULL,
605 );
606
607 $args = wpforo_parse_args( $args, $default );
608
609 if(is_array($args) && !empty($args)){
610
611 extract($args, EXTR_OVERWRITE);
612
613 if( $row_count === 0 ) return array();
614
615 $include = wpforo_parse_args( $include );
616 $exclude = wpforo_parse_args( $exclude );
617 $forumids = wpforo_parse_args( $forumids );
618
619 $guest = array();
620 $wheres = array();
621 $table_as_prefix = '`'.WPF()->tables->topics.'`.';
622
623 if(!empty($include)) $wheres[] = "`topicid` IN(" . implode(', ', array_map('intval', $include)) . ")";
624 if(!empty($exclude)) $wheres[] = "`topicid` NOT IN(" . implode(', ', array_map('intval', $exclude)) . ")";
625 if(!empty($forumids)) $wheres[] = "`forumid` IN(" . implode(', ', array_map('intval', $forumids)) . ")";
626 if(!is_null($forumid)) $wheres[] = "`forumid` = " . intval($forumid);
627 if(!is_null($userid)) $wheres[] = "`userid` = " . intval($userid);
628 if(!is_null($where)) $wheres[] = $table_as_prefix . $where;
629
630 if($type != 0) $wheres[] = " `type` = " . intval($type);
631 if(!is_user_logged_in()) $guest = WPF()->member->get_guest_cookies();
632
633 if(empty($forumids)){
634 if( isset($forumid) && !WPF()->perm->forum_can('vf', $forumid, $permgroup) ){
635 return array();
636 }
637 }
638
639 if( isset($forumid) && $forumid ){
640 if( WPF()->perm->forum_can('vp', $forumid, $permgroup) ){
641 if(!is_null($private)) $wheres[] = " `private` = " . intval($private);
642 }
643 elseif( isset(WPF()->current_userid) && WPF()->current_userid ){
644 $wheres[] = " ( `private` = 0 OR (`private` = 1 AND `userid` = " .intval(WPF()->current_userid). ") )";
645 }
646 elseif( wpfval($guest, 'email') ){
647 $wheres[] = " ( `private` = 0 OR (`private` = 1 AND `email` = '" . sanitize_email($guest['email']) . "') )";
648 }
649 else{
650 $wheres[] = " `private` = 0";
651 }
652 }
653 else{
654 if(!is_null($private)) $wheres[] = " `private` = " . intval($private);
655 }
656
657 if( isset($forumid) && $forumid ){
658 if( WPF()->perm->forum_can('au', $forumid, $permgroup) ){
659 if(!is_null($status)) $wheres[] = " `status` = " . intval($status);
660 }
661 elseif( isset(WPF()->current_userid) && WPF()->current_userid ){
662 $wheres[] = " ( `status` = 0 OR (`status` = 1 AND `userid` = " .intval(WPF()->current_userid). ") )";
663 }
664 elseif( wpfval($guest, 'email') ){
665 $wheres[] = " ( `status` = 0 OR (`status` = 1 AND `email` = '" . sanitize_email($guest['email']) . "') )";
666 }
667 else{
668 $wheres[] = " `status` = 0";
669 }
670 }
671 else{
672 if(!is_null($status)) $wheres[] = " `status` = " . intval($status);
673 }
674
675 if( function_exists('WPF_POLL') ){
676 if( !is_null($pollid) ) $wheres[] = " `pollid` <> 0";
677 }
678
679 $sql = "SELECT * FROM `".WPF()->tables->topics."`";
680 if(!empty($wheres)){
681 $sql .= " WHERE " . implode($wheres, " AND ");
682 }
683
684 $item_count_sql = preg_replace('#SELECT.+?FROM#isu', 'SELECT count(*) FROM', $sql);
685 if( $item_count_sql ) $items_count = WPF()->db->get_var($item_count_sql);
686
687 $sql .= " ORDER BY " . str_replace(',', ' ' . esc_sql($order) . ',', esc_sql($orderby)) . " " . esc_sql($order);
688
689 if(!is_null($row_count)){
690 if(!is_null($offset)){
691 $sql .= esc_sql(" LIMIT $offset,$row_count");
692 }else{
693 $sql .= esc_sql(" LIMIT $row_count");
694 }
695 }
696
697 if( $cache ){ $object_key = md5( $sql . WPF()->current_user_groupid ); $object_cache = WPF()->cache->get( $object_key ); if( !empty($object_cache) ){ $items_count = $object_cache['items_count']; return $object_cache['items']; }}
698
699 $topics = WPF()->db->get_results($sql, ARRAY_A);
700 $topics = apply_filters('wpforo_get_topics', $topics);
701
702 if(!empty($forumids) || !$forumid){
703 foreach($topics as $key => $topic){
704 if( !WPF()->perm->forum_can('vf', $topic['forumid'], $permgroup) ){
705 unset($topics[$key]);
706 }
707 if( isset($topics[$key]) && isset($topic['private']) && $topic['private'] && !wpforo_is_owner($topic['userid'], $topic['email']) ){
708 if( !WPF()->perm->forum_can('vp', $topic['forumid'], $permgroup) ){
709 unset($topics[$key]);
710 }
711 }
712 if( isset($topics[$key]) && isset($topic['status']) && $topic['status'] && !wpforo_is_owner($topic['userid'], $topic['email']) ){
713 if( !WPF()->perm->forum_can('au', $topic['forumid'], $permgroup) ){
714 unset($topics[$key]);
715 }
716 }
717 }
718 }
719
720 if($cache && isset($object_key) && !empty($topics)){
721 self::$cache['topics'][$object_key]['items'] = $topics;
722 self::$cache['topics'][$object_key]['items_count'] = $items_count;
723 }
724 return $topics;
725 }
726 }
727
728 function get_topics_filtered( $args = array() ){
729 $topics = array();
730 $topics = $this->get_topics( $args );
731 if( !empty($topics) ){
732 foreach($topics as $key => $topic){
733 if( !WPF()->perm->forum_can('vf', $topic['forumid']) ){
734 unset($topics[$key]);
735 }
736 if( isset($topics[$key]) && isset($topic['private']) && $topic['private'] && !wpforo_is_owner($topic['userid'], $topic['email']) ){
737 if( !WPF()->perm->forum_can('vp', $topic['forumid']) ){
738 unset($topics[$key]);
739 }
740 }
741 if( isset($topics[$key]) && isset($topic['status']) && $topic['status'] && !wpforo_is_owner($topic['userid'], $topic['email']) ){
742 if( !WPF()->perm->forum_can('au', $topic['forumid']) ){
743 unset($topics[$key]);
744 }
745 }
746 }
747 }
748 return $topics;
749 }
750
751 /**
752 *
753 * Search in your chosen column and return array with needles
754 *
755 * @since 1.0.0
756 *
757 * @param string needle
758 *
759 * @param column name in db ( slug, title, body )
760 *
761 * @param $additional if it's true' return multi-dimensional arrays, if false it return simple array
762 *
763 * @return array with matches
764 */
765
766 function search( $needle = '', $fields = array( 'title', 'body' )){
767 if($needle != ''){
768
769 $needle = stripslashes($needle);
770
771 if(!is_array($fields)){
772 $fields = array($fields); // if is it string it will be convert to array
773 }
774
775 $topicids = array();
776 foreach($fields as $field){
777 if($field == 'body'){
778 $matches = WPF()->db->get_col( "SELECT `topicid` FROM ".WPF()->tables->posts." WHERE `".esc_sql($field)."` LIKE '%". esc_sql(sanitize_text_field($needle)) ."%'" );
779 }else{
780 $matches = WPF()->db->get_col( "SELECT `topicid` FROM ".WPF()->tables->topics." WHERE `".esc_sql($field)."`LIKE '%". esc_sql(sanitize_text_field($needle)) ."%'" );
781 }
782 $topicids = array_merge( $topicids, $matches );
783 }
784 return array_unique($topicids);
785 }
786 else{
787 return $matches = array();
788 }
789 }
790
791 function get_sum_answer($forumids){
792 $sum = WPF()->db->get_var("SELECT SUM(`answers`) FROM `".WPF()->tables->topics."` WHERE `forumid` IN(". implode(', ', array_map('intval', $forumids)) .")");
793 if($sum) return $sum;
794 return 0;
795 }
796
797 function get_forumslug($forumid){
798 $slug = WPF()->db->get_var("SELECT `slug` FROM ".WPF()->tables->forums." WHERE `forumid` = " . intval($forumid));
799 if($slug) return $slug;
800 return 0;
801 }
802
803 function get_forumslug_byid($topicid){
804 $slug = WPF()->db->get_var("SELECT `slug` FROM ".WPF()->tables->forums." WHERE `forumid` =(SELECT forumid FROM `".WPF()->tables->topics."` WHERE `topicid` =".intval($topicid).")");
805 if($slug) return $slug;
806 return 0;
807 }
808
809 function is_sticky( $topicid ){
810 if( WPF()->cache->on('object_cashe') ){
811 $type = wpforo_topic($topicid, 'type');
812 }
813 else{
814 $type = WPF()->db->get_var( "SELECT `type` FROM ".WPF()->tables->topics." WHERE `topicid` = " . intval($topicid) );
815 }
816 if( $type == 1 ) return TRUE;
817 return FALSE;
818 }
819
820 function is_private( $topicid ){
821 if( WPF()->cache->on('object_cashe') ){
822 $private = wpforo_topic($topicid, 'private');
823 }
824 else{
825 $private = WPF()->db->get_var( "SELECT `private` FROM ".WPF()->tables->topics." WHERE `topicid` = " . intval($topicid) );
826 }
827 if( $private == 1 ) return TRUE;
828 return FALSE;
829 }
830
831 function is_unapproved( $topicid ){
832 if( WPF()->cache->on('object_cashe') ){
833 $status = wpforo_topic($topicid, 'status');
834 }
835 else{
836 $status = WPF()->db->get_var( "SELECT `status` FROM ".WPF()->tables->topics." WHERE `topicid` = " . intval($topicid) );
837 }
838 if( $status == 1 ) return TRUE;
839 return FALSE;
840 }
841
842 function is_closed( $topicid ){
843 if( WPF()->cache->on('object_cashe') ){
844 $type = wpforo_topic($topicid, 'closed');
845 }
846 else{
847 $type = WPF()->db->get_var( "SELECT `closed` FROM ".WPF()->tables->topics." WHERE `topicid` = " . intval($topicid) );
848 }
849 if( $type == 1 ) return TRUE;
850 return FALSE;
851 }
852
853 function is_solved( $topicid ){
854 $postid = WPF()->db->get_var( "SELECT `postid` FROM ".WPF()->tables->posts." WHERE `is_answer` = 1 AND `topicid` = " . intval($topicid) . " LIMIT 1" );
855 if( $postid ) return TRUE;
856 return FALSE;
857 }
858
859 /**
860 * Move topic to another forum
861 *
862 * @since 1.0.0
863 *
864 * @param int $topicid
865 * @param int $forumid
866 *
867 * @return int|false $topicid on success, otherwise false
868 */
869 function move($topicid, $forumid){
870 $topic = $this->get_topic( $topicid );
871 if( WPF()->db->query( "UPDATE `".WPF()->tables->topics."` SET `forumid` = ". intval($forumid) ." WHERE `topicid` = ". intval($topicid) ) ){
872 WPF()->db->query( "UPDATE `".WPF()->tables->posts."` SET `forumid` = ". intval($forumid) ." WHERE `topicid` = ". intval($topicid) );
873 $post = WPF()->post->get_post($topic['last_post']);
874
875 WPF()->db->query( "UPDATE `".WPF()->tables->forums."` SET `topics` = `topics` - 1, `posts` = `posts` - ".intval($topic['posts'])." WHERE `forumid` = ".intval($topic['forumid']) );
876 WPF()->db->query( "UPDATE `".WPF()->tables->forums."` SET `topics` = `topics` + 1, `posts` = `posts` + ".intval($topic['posts']).", `last_topicid` = ".intval($topicid).", `last_postid` = ".intval($topic['last_post']).", `last_userid` = ".intval($post['userid']).", `last_post_date` = '". esc_sql($post['created']) ."' WHERE `forumid` = ". intval($forumid) );
877
878 WPF()->forum->rebuild_last_infos($topic['forumid']);
879
880 do_action('wpforo_after_move_topic', $topic, $forumid);
881
882 wpforo_clean_cache( 'topic', $topicid, $topic);
883 WPF()->notice->add('Done!', 'success');
884 return $topicid;
885 }
886
887 WPF()->notice->add('Topic Move Error', 'error');
888 return FALSE;
889 }
890
891 /**
892 * merge topic with target topic
893 *
894 * @param array $current current topic array
895 * @param array $target target topic array
896 * @param array $postids current topic postids array
897 * @param int $to_target_title Update post titles with target topic title
898 * @param int $append Update post dates and append to end
899 *
900 * @return true|false true on success, otherwise false
901 */
902 public function merge( $current = array(), $target, $postids = array(), $to_target_title = 0, $append = 0 ){
903 if( !$current ) $current = WPF()->current_object['topic'];
904
905 $sql = "UPDATE `".WPF()->tables->posts."` SET `topicid` = %d, `forumid` = %d, `is_first_post` = 0";
906 $sql = WPF()->db->prepare($sql, $target['topicid'], $target['forumid']);
907
908 if($append){
909 $sql .= ", `modified` = %s, `created` = %s";
910 $sql = WPF()->db->prepare($sql, current_time( 'mysql', 1 ), current_time( 'mysql', 1 ));
911 }
912
913 if ($to_target_title){
914 $layout = WPF()->forum->get_layout( $target['forumid'] );
915 $phrase = ($layout == 3 ? 'Answer to' : 'RE');
916 $title = wpforo_phrase( $phrase, false) . ': ' . $target['title'];
917 $sql .= ", `title` = %s";
918 $sql = WPF()->db->prepare($sql, $title);
919 }
920
921 $sql .= " WHERE `topicid` = %d";
922 $sql = WPF()->db->prepare($sql, $current['topicid']);
923
924 if( $postids ){
925 $postids = (array) $postids;
926 $postids = array_map('wpforo_bigintval', $postids);
927
928 $sql .= " AND `postid` IN(" . implode(',', $postids) . ")";
929 }
930
931 $db_resp = WPF()->db->query($sql);
932
933 if( $db_resp !== false ){
934 $sql = "SELECT COUNT(*) FROM `".WPF()->tables->posts."` WHERE `topicid` = %d";
935 $sql = WPF()->db->prepare($sql, $current['topicid']);
936 if( !WPF()->db->get_var($sql) ){
937 $this->delete($current['topicid']);
938 }else{
939 $this->rebuild_first_last($current);
940 $this->rebuild_stats($current);
941 wpforo_clean_cache('topic', $current['topicid'], $current);
942 }
943
944 $this->rebuild_first_last($target);
945 $this->rebuild_stats($target);
946 WPF()->forum->rebuild_last_infos($current['forumid']);
947 WPF()->forum->rebuild_last_infos($target['forumid']);
948 WPF()->forum->rebuild_stats($current['forumid']);
949 WPF()->forum->rebuild_stats($target['forumid']);
950
951 WPF()->notice->clear();
952 WPF()->notice->add('Done!', 'success');
953
954 wpforo_clean_cache('topic', $target['topicid'], $target);
955 return true;
956 }
957
958 WPF()->notice->add('Data merging error', 'error');
959 return false;
960 }
961
962 public function split($args, $to_target_title = 0){
963 if(!$args) return FALSE;
964
965 $args['name'] = (isset($args['name']) ? strip_tags($args['name']) : '' );
966 $args['email'] = (isset($args['email']) ? sanitize_email($args['email']) : '' );
967
968 if( !isset($args['forumid']) || !$args['forumid'] = intval($args['forumid']) ){
969 WPF()->notice->add('Please select a target forum', 'error');
970 return FALSE;
971 }
972
973 if( !isset($args['title']) || !$args['title'] = trim(strip_tags($args['title'])) ){
974 WPF()->notice->add('Please insert required fields', 'error');
975 return FALSE;
976 }
977
978 if( empty($args['postids']) ){
979 WPF()->notice->add('Please select at least one post to split', 'error');
980 return FALSE;
981 }
982
983 $args['postids'] = array_values($args['postids']);
984
985 if( $fpost = WPF()->post->get_post($args['postids'][0]) ){
986 $args['title'] = wpforo_text($args['title'], 250, false);
987 $args['slug'] = (isset($args['slug']) && $args['slug']) ? sanitize_title($args['slug']) : ((isset($args['title'])) ? sanitize_title($args['title']) : md5(time()));
988 $args['slug'] = $this->unique_slug($args['slug']);
989
990
991 $args['body'] = $fpost['body'];
992 $args['created'] = $fpost['created'];
993 $args['userid'] = $fpost['userid'];
994 $args['name'] = $fpost['name'];
995 $args['email'] = $fpost['email'];
996
997 extract($args);
998
999 if(isset($forumid)) $forumid = intval($forumid);
1000 if(isset($title)) $title = sanitize_text_field(trim($title));
1001 if(isset($slug)) $slug = sanitize_title($slug);
1002 if(isset($created)) $created = sanitize_text_field($created);
1003 if(isset($userid)) $userid = intval($userid);
1004 $type = ( isset($type) && $type ? 1 : 0 );
1005 $status = ( isset($status) && $status ? 1 : 0 );
1006 $private = ( isset($private) && $private ? 1 : 0 );
1007 if(isset($name)) $name = strip_tags(trim($name));
1008 if(isset($email)) $email = strip_tags(trim($email));
1009 $has_attach = ( isset($has_attach) && $has_attach ) ? 1 : ((strpos($body, '[attach]') !== FALSE) ? 1 : 0);
1010
1011 if(
1012 WPF()->db->insert(
1013 WPF()->tables->topics,
1014 array(
1015 'title' => stripslashes($title),
1016 'slug' => $slug,
1017 'forumid' => $forumid,
1018 'userid' => $userid,
1019 'type' => $type,
1020 'status' => $status,
1021 'private' => $private,
1022 'created' => $created,
1023 'modified' => $created,
1024 'last_post' => 0,
1025 'views' => 0,
1026 'posts' => 1,
1027 'has_attach'=> $has_attach,
1028 'name' => $name,
1029 'email' => $email
1030 ),
1031 array('%s','%s','%d','%d','%d','%d','%d','%s','%s','%d','%d','%d','%d','%s','%s')
1032 )
1033 ){
1034 $args['topicid'] = $topicid = WPF()->db->insert_id;
1035
1036 if( $this->merge( WPF()->current_object['topic'], $args, $args['postids'], $to_target_title, 0 ) ){
1037 WPF()->notice->clear();
1038 WPF()->notice->add('Done!', 'success');
1039 return $topicid;
1040 }
1041 }
1042 }
1043
1044 WPF()->notice->add('Topic splitting error', 'error');
1045 return FALSE;
1046 }
1047
1048 function get_topic_url($topic, $forum = array()){
1049
1050 if( !is_array($topic) ) $topic = $this->get_topic( $topic );
1051
1052 if( is_array($topic) && !empty($topic) ){
1053
1054 if( is_array($forum) && !empty($forum)){
1055 $forum_slug = $forum['slug'];
1056 }
1057 else{
1058
1059 if( isset($topic['forumid']) && !$topic['forumid'] ){
1060 if( isset(self::$cache['forum_slug'][$topic['forumid']]) ){
1061 $forum_slug = self::$cache['forum_slug'][$topic['forumid']];
1062 }
1063 else{
1064 $forum_slug = $this->get_forumslug($topic['forumid']);
1065 }
1066 self::$cache['forum_slug'][$topic['forumid']] = $forum_slug;
1067 }
1068 else{
1069 $forum_slug = $this->get_forumslug_byid($topic['topicid']);
1070 }
1071
1072 }
1073
1074 return wpforo_home_url( $forum_slug . '/' . $topic['slug'] );
1075
1076 }else{
1077 return wpforo_home_url();
1078 }
1079 }
1080
1081
1082 function get_count( $args = array() ){
1083 $sql = "SELECT COUNT(*) FROM `".WPF()->tables->topics."`";
1084 if( !empty($args) ){
1085 $wheres = array();
1086 foreach ($args as $key => $value) $wheres[] = "`$key` = " . intval($value);
1087 if($wheres) $sql .= " WHERE " . implode(' AND ', $wheres);
1088 }
1089 return WPF()->db->get_var($sql);
1090 }
1091
1092 public function status( $topicid, $status ){
1093 if( !$topicid = wpforo_bigintval($topicid) ) return false;
1094
1095 if( false !== WPF()->db->update(
1096 WPF()->tables->topics,
1097 array( 'status' => intval($status) ),
1098 array( 'topicid' => $topicid ),
1099 array( '%d' ),
1100 array( '%d' )
1101 )){
1102 if( false !== WPF()->db->update(
1103 WPF()->tables->posts,
1104 array( 'status' => intval($status) ),
1105 array( 'topicid' => $topicid ),
1106 array( '%d' ),
1107 array( '%d' )
1108 )){
1109 if($status) {
1110 $this->last_topic($topicid, 'remove');
1111 } else {
1112 $this->last_topic($topicid, 'add');
1113 }
1114 do_action( 'wpforo_topic_status_update', $topicid, $status );
1115 wpforo_clean_cache('topic', $topicid);
1116 WPF()->notice->add('Done!', 'success');
1117 return true;
1118 }
1119 }
1120
1121 WPF()->notice->add('Status changing error', 'error');
1122 return false;
1123 }
1124
1125 public function delete_attachments( $topicid ){
1126 $args = array( 'topicid' => $topicid );
1127 $posts = WPF()->post->get_posts( $args );
1128 if(!empty($posts)){
1129 foreach( $posts as $post ){
1130 WPF()->post->delete_attachments( $post['postid'] );
1131 }
1132 }
1133 }
1134
1135 public function rebuild_stats($topic){
1136 if(!$topic) return false;
1137 if(is_numeric($topic)) $topic = $this->get_topic($topic);
1138 if( !is_array($topic) || !$topic ) return false;
1139
1140 $posts = WPF()->post->get_count( array('topicid' => $topic['topicid'], 'status' => 0) );
1141
1142 $data = array('posts' => $posts);
1143 $data_format = array('%d');
1144
1145 $layout = WPF()->forum->get_layout($topic['forumid']);
1146 if($layout == 3){
1147 $data['answers'] = WPF()->post->get_count( array('topicid' => $topic['topicid'], 'status' => 0, 'parentid' => 0, 'is_first_post' => 0) );
1148 $data_format[] = '%d';
1149 $data['posts'] = $posts - 1;
1150 }
1151
1152 if( false !== WPF()->db->update(
1153 WPF()->tables->topics,
1154 $data,
1155 array('topicid' => $topic['topicid']),
1156 $data_format,
1157 array('%d')
1158 ) ) {
1159 wpforo_clean_cache('topic', $topic['topicid'], $topic);
1160 return true;
1161 }
1162 return false;
1163 }
1164
1165 public function rebuild_first_last($topic){
1166 if(!$topic) return false;
1167 if(is_numeric($topic)) $topic = $this->get_topic($topic);
1168 if( !is_array($topic) || !$topic ) return false;
1169
1170 $sql = "SELECT `postid` FROM `".WPF()->tables->posts."` WHERE `topicid` = %d ORDER BY `is_first_post` DESC, `created` ASC, `postid` ASC LIMIT 1";
1171 if( $first_postid = WPF()->db->get_var( WPF()->db->prepare($sql, $topic['topicid']) ) ){
1172 $sql = "UPDATE `".WPF()->tables->posts."` SET `is_first_post` = 1 WHERE `postid` = %d";
1173 WPF()->db->query( WPF()->db->prepare($sql, $first_postid) );
1174 }else{
1175 $first_postid = 0;
1176 }
1177
1178 $sql = "SELECT `postid`, `created` FROM `".WPF()->tables->posts."` WHERE `topicid` = %d ORDER BY `is_first_post` ASC, `created` DESC, `postid` DESC LIMIT 1";
1179 if( !$last_post = WPF()->db->get_row( WPF()->db->prepare($sql, $topic['topicid']), ARRAY_A ) ) $last_post = array( 'postid' => 0, 'created' => $topic['modified']);
1180
1181 if( false !== WPF()->db->update(
1182 WPF()->tables->topics,
1183 array('first_postid' => $first_postid, 'last_post' => $last_post['postid'], 'modified' => $last_post['created']),
1184 array('topicid' => $topic['topicid']),
1185 array('%d','%d','%s'),
1186 array('%d')
1187 ) ) {
1188 wpforo_clean_cache('topic');
1189 return true;
1190 }
1191 return false;
1192 }
1193
1194 public function last_topic($topic, $action = 'add'){
1195 if(is_numeric($topic)){
1196 $topic = $this->get_topic($topic);
1197 }
1198 if( !empty($topic) && isset($topic['first_postid']) && isset($topic['topicid']) && isset($topic['forumid']) && isset($topic['userid']) && isset($topic['created']) ){
1199 extract($topic, EXTR_OVERWRITE);
1200 if( $action == 'add' ){
1201 WPF()->db->query( "UPDATE ".WPF()->tables->forums." SET `last_post_date` = '" . esc_sql($created). "', `last_userid` = " . intval($userid). ", `last_topicid` = " . intval($topicid) . ", `last_postid` = " . intval($first_postid) . ", `topics` = `topics` + 1 , `posts` = `posts` + 1 WHERE `forumid` = " . intval($forumid) );
1202 }
1203 elseif($action == 'remove'){
1204 //rebuild forum last topic info, don't include unapproved and private topics.
1205 }
1206 }
1207 }
1208
1209 public function members( $topicid, $limit = 0 ){
1210 if( !$topicid ) return;
1211 $members = array();
1212 $args = array(
1213 'topicid' => $topicid,
1214 'orderby' => 'created',
1215 'order' => 'ASC',
1216 'private' => 0,
1217 'status' => 0,
1218 'cache_type' => 'args'
1219 );
1220 $posts = WPF()->post->get_posts( $args );
1221 foreach($posts as $post){
1222 if( wpfval($post, 'userid') ){
1223 $members[$post['userid']] = wpforo_member($post['userid']);
1224 if($limit && count($members) >= $limit ) break;
1225 }
1226 }
1227 $members = array_filter($members);
1228 if(!empty($members)) return $members;
1229 }
1230 }