PluginProbe
wpForo Forum / 1.4.11
wpForo Forum v1.4.11
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.11, at wpf-includes/class-topics.php

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