PluginProbe
wpForo Forum / 3.0.5
wpForo Forum v3.0.5
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 / classes / Logs.php

Logs.php in wpForo Forum 3.0.5, at classes/Logs.php

427 lines 15.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace wpforo\classes;
4
5 // Exit if accessed directly
6 if( ! defined( 'ABSPATH' ) ) exit;
7
8 class Logs {
9 public function read() {
10 $data = WPF()->current_object;
11
12 if( wpforo_setting( 'logging', 'view_logging' ) && wpfval( $data, 'template' ) ) {
13 if( $data['template'] === 'post' ) {
14 if( wpfval( $data, 'topicid' ) && wpfval( $data, 'topic', 'last_post' ) ) {
15 $this->read_item( $data['topicid'], $data['topic']['last_post'], wpforo_prefix( 'read_topics' ) );
16 }
17 if( wpfval( $data, 'forumid' ) ) {
18 $end_date = time() - ( 14 * 24 * 60 * 60 );
19 $items_count = 0;
20 $args = [ 'read' => false, 'forumid' => $data['forumid'], 'orderby' => 'modified', 'order' => 'ASC', 'row_count' => 1, 'where' => "`modified` > '" . gmdate( 'Y-m-d H:i:s', $end_date ) . "'" ];
21 $topics = WPF()->topic->get_topics( $args, $items_count );
22 if( empty( $topics ) ) {
23 if( wpfval( $data, 'forum', 'last_postid' ) ) {
24 $last_postid = $data['forum']['last_postid'];
25 } elseif( wpfval( $data, 'topic', 'last_post' ) ) {
26 $last_postid = $data['topic']['last_post'];
27 }
28 if( ! empty( $last_postid ) ) $this->read_item( $data['forumid'], $last_postid, wpforo_prefix( 'read_forums' ) );
29 } else {
30 foreach( $topics as $topic ) {
31 if( wpfval( $topic, 'last_post' ) ) {
32 if( $items_count == 1 && $topic['topicid'] == $data['topicid'] ) {
33 if( wpfval( $data, 'forum', 'last_postid' ) ) {
34 $last_postid = $data['forum']['last_postid'];
35 } elseif( wpfval( $data, 'topic', 'last_post' ) ) {
36 $last_postid = $data['topic']['last_post'];
37 } elseif( wpfval( $topic, 'last_post' ) ) {
38 $last_postid = $topic['last_post'];
39 }
40 } else {
41 $last_postid = ( $topic['last_post'] - 1 );
42 }
43 if( isset( $last_postid ) ) {
44 $this->read_item( $data['forumid'], $last_postid, wpforo_prefix( 'read_forums' ) );
45 break;
46 }
47 }
48 }
49 }
50 }
51 }
52 }
53 }
54
55 public function read_item( $itemid, $item_last_postid, $key ) {
56
57 $log = false;
58 $logdb = false;
59 $read_ids = [];
60 $read_db_ids = [];
61 $login = is_user_logged_in();
62
63 if( $itemid && $key ) {
64 if( wpforo_setting( 'legal', 'cookies' ) ) $read_ids = wpforo_getcookie( $key, false );
65 if( wpfval( WPF()->current_usermeta, $key ) ) $read_db_ids = wpforo_current_usermeta( $key );
66 if( ! $read_ids || ! is_array( $read_ids ) ) $read_ids = [];
67 if( ! $read_db_ids || ! is_array( $read_ids ) ) $read_db_ids = [];
68
69 if( empty( $read_ids ) || ( $login && empty( $read_db_ids ) ) ) {
70 if( empty( $read_ids ) ) $log = true;
71 if( empty( $read_db_ids ) && $login ) $logdb = true;
72 $read_ids = [ $itemid => $item_last_postid ];
73 } elseif( ! wpfval( $read_ids, $itemid ) || ! wpfval( $read_db_ids, $itemid ) || (int) $read_ids[ $itemid ] < (int) $item_last_postid || (int) $read_db_ids[ $itemid ] < (int) $item_last_postid ) {
74 $log = true;
75 if( $login ) $logdb = true;
76 if( is_array( $read_ids ) && is_array( $read_db_ids ) ) {
77 $keep_guest_read = apply_filters( 'wpforo_keep_guest_read', false );
78 $merge_guest_read = apply_filters( 'wpforo_merge_guest_read', true );
79 if( $merge_guest_read ) {
80 $read_ids = ( $keep_guest_read ) ? $read_ids + $read_db_ids : $read_db_ids + $read_ids;
81 } else {
82 $read_ids = ( $login ) ? $read_db_ids : $read_ids;
83 }
84 }
85 $read_ids[ $itemid ] = $item_last_postid;
86 if( $key === wpforo_prefix( 'read_forums' ) ) {
87 $read_ids = $this->read_parent_items( $read_ids, $itemid, $item_last_postid );
88 }
89 }
90 $this->log_item( $read_ids, $key, $logdb, $log );
91 }
92 }
93
94 public function read_parent_items( $read_ids = [], $itemid = 0, $item_last_postid = 0 ) {
95 if( wpfval( $read_ids, $itemid ) && $item_last_postid ) {
96 $parents = [];
97 WPF()->forum->get_parents( $itemid, $parents );
98 foreach( $parents as $parent ) {
99 $read_ids[ $parent ] = $item_last_postid;
100 }
101 }
102
103 return $read_ids;
104 }
105
106 public function log_item( $read_ids, $key, $logdb = true, $log = true ) {
107 if( $log && wpforo_setting( 'legal', 'cookies' ) ) {
108 wpforo_setcookie( $key, $read_ids, false );
109 }
110 if( $logdb && is_user_logged_in() ) {
111 $max = apply_filters( 'wpforo_max_logged_topics', 100 );
112 $num = count( $read_ids );
113 if( $num > $max ) {
114 $delta = $num - $max;
115 if( $delta > 0 ) $read_ids = array_slice( $read_ids, $delta, null, true );
116 }
117 update_user_meta( WPF()->current_userid, $key, $read_ids );
118 }
119 }
120
121 public function unread( $id, $in = 'forum', $postid = 0 ) {
122
123 $new = false;
124 if( ! wpforo_setting( 'logging', 'view_logging' ) ) return false;
125
126 if( $id ) {
127 if( $in === 'forum' ) {
128 $last_postid = wpforo_forum( $id, 'last_postid' );
129 if( ! $last_postid ) {
130 return false;
131 }
132 //Pass all posts created before "Mark all read" action
133 $last_read_postid = $this->get_all_read( 'post' );
134 if( $last_read_postid ) {
135 if( (int) $last_postid > $last_read_postid ) $new = true;
136 }
137 //Check the last read post of current forum
138 if( ! $last_read_postid || $new ) {
139 $read_forums = $this->get_read_forums();
140 if( wpfkey( $read_forums, $id ) ) {
141 $last_read_postid = $read_forums[ $id ];
142 if( (int) $last_postid > (int) $last_read_postid ) {
143 $new = true;
144 } else {
145 $new = false;
146 }
147 } else {
148 $new = true;
149 }
150 }
151 $new = apply_filters( 'wpforo_new_in_forum', $new, $id );
152 } elseif( $in == 'topic' || $in == 'post' ) {
153 $last_postid = wpforo_topic( $id, 'last_post' );
154 if( ! $last_postid ) {
155 return false;
156 }
157 //Pass all posts created before "Mark all read" action
158 $last_read_postid = $this->get_all_read( 'post' );
159 if( $last_read_postid ) {
160 if( (int) $last_postid > $last_read_postid ) $new = true;
161 }
162 //Check the last read post of current forum
163 if( ! $last_read_postid || $new ) {
164 $read_topics = $this->get_read_topics();
165 if( wpfkey( $read_topics, $id ) ) {
166 $last_read_postid = $read_topics[ $id ];
167 if( (int) $last_postid > (int) $last_read_postid ) {
168 $new = true;
169 } else {
170 $new = false;
171 }
172 } else {
173 $new = true;
174 }
175 }
176 //Check an individual post if it's unread in an unread topic
177 if( $in === 'post' && $postid && (int) $postid > (int) $last_read_postid ) $new = true;
178 $new = apply_filters( 'wpforo_new_in_topic', $new, $id );
179 }
180 }
181
182 return $new;
183 }
184
185 public function get_read( $return = 'topicid' ) {
186 $topic_ids = [];
187 $read_topics = $this->get_read_topics();
188 if( ! empty( $read_topics ) && is_array( $read_topics ) ) {
189 $last_read_postid = $this->get_all_read( 'post' );
190 foreach( $read_topics as $topicid => $postid ) {
191 if( $last_read_postid && (int) $postid <= $last_read_postid ) {
192 unset( $read_topics[ $topicid ] );
193 } else {
194 $current_last_postid = wpforo_topic( $topicid, 'last_post' );
195 if( $current_last_postid ) {
196 if( (int) $current_last_postid <= (int) $postid ) {
197 $topic_ids[] = $topicid;
198 }
199 } else {
200 $topic_ids[] = $topicid;
201 }
202 }
203 }
204 }
205 if( $return == 'topicid' ) {
206 return $topic_ids;
207 } else {
208 return $read_topics;
209 }
210 }
211
212 public function get_read_forums() {
213 if( is_user_logged_in() && wpfval( WPF()->current_usermeta, wpforo_prefix( 'read_forums' ) ) ) {
214 $read_forums = wpforo_current_usermeta( wpforo_prefix( 'read_forums' ) );
215 } else {
216 $read_forums = wpforo_getcookie( wpforo_prefix( 'read_forums' ), false );
217 }
218
219 return $read_forums;
220 }
221
222 public function get_read_topics() {
223 if( is_user_logged_in() && wpfval( WPF()->current_usermeta, wpforo_prefix( 'read_topics' ) ) ) {
224 $read_topics = wpforo_current_usermeta( wpforo_prefix( 'read_topics' ) );
225 } else {
226 $read_topics = wpforo_getcookie( wpforo_prefix( 'read_topics' ), false );
227 }
228
229 return $read_topics;
230 }
231
232 public function last( $item ) {
233 $id = 0;
234
235 if( $item === 'forum' ) {
236 $id = WPF()->db->get_var( "SELECT MAX(`forumid`) FROM " . WPF()->tables->forums );
237 } elseif( $item === 'topic' ) {
238 $id = WPF()->db->get_var( "SELECT MAX(`topicid`) FROM " . WPF()->tables->topics );
239 } elseif( $item === 'post' ) {
240 $id = WPF()->db->get_var( "SELECT MAX(`postid`) FROM " . WPF()->tables->posts );
241 }
242
243 return intval( $id );
244 }
245
246 public function mark_all_read() {
247 $last_forumid = $this->last( 'forum' );
248 $last_topicid = $this->last( 'topic' );
249 $last_postid = $this->last( 'post' );
250 $last = [ 'forum' => $last_forumid, 'topic' => $last_topicid, 'post' => $last_postid ];
251 if( is_user_logged_in() ) {
252 update_user_meta( WPF()->current_userid, wpforo_prefix( 'all_read' ), $last );
253 update_user_meta( WPF()->current_userid, wpforo_prefix( 'read_forums' ), [] );
254 update_user_meta( WPF()->current_userid, wpforo_prefix( 'read_topics' ), [] );
255 }
256 wpforo_setcookie( wpforo_prefix( 'all_read' ), $last );
257 wpforo_setcookie( wpforo_prefix( 'read_forums' ) );
258 wpforo_setcookie( wpforo_prefix( 'read_topics' ) );
259 }
260
261 public function get_all_read( $item ) {
262 if( is_user_logged_in() ) {
263 $last = wpforo_current_usermeta( wpforo_prefix( 'all_read' ) );
264 } else {
265 $last = wpforo_getcookie( wpforo_prefix( 'all_read' ) );
266 }
267 if( $item && wpfval( $last, $item ) ) {
268 return intval( $last[ $item ] );
269 }
270
271 return 0;
272 }
273
274 public function visitors( $item ) {
275 $data = [];
276 $visitors = [];
277 if( wpfval( $item, 'topicid' ) ) {
278 $keep_vistors_data = apply_filters( 'wpforo_keep_visitors_data', 4000 );
279 $time = (int) time() - (int) $keep_vistors_data;
280 $visitors = WPF()->db->get_results( "SELECT * FROM `" . WPF()->tables->visits . "` WHERE `topicid` = " . intval( $item['topicid'] ) . " AND `time` > " . $time . " ORDER BY `id` DESC", ARRAY_A );
281 } elseif( wpfval( $item, 'forumid' ) ) {
282 $keep_vistors_data = apply_filters( 'wpforo_keep_visitors_data', 4000 );
283 $time = (int) time() - (int) $keep_vistors_data;
284 $visitors = WPF()->db->get_results( "SELECT * FROM `" . WPF()->tables->visits . "` WHERE `forumid` = " . intval( $item['forumid'] ) . " AND `time` > " . $time . " ORDER BY `id` DESC", ARRAY_A );
285 }
286 if( ! empty( $visitors ) ) {
287 $online_period = (int) time() - (int) wpforo_setting( 'profiles', 'online_status_timeout' );
288
289 // Batch-fetch the latest visit time per user to avoid N+1 queries
290 $online_user_ids = [];
291 foreach( $visitors as $visitor ) {
292 if( wpfval( $visitor, 'userid' ) && (int) $visitor['time'] >= $online_period ) {
293 $online_user_ids[ intval( $visitor['userid'] ) ] = true;
294 }
295 }
296 $user_max_times = [];
297 if( ! empty( $online_user_ids ) ) {
298 $id_list = implode( ',', array_keys( $online_user_ids ) );
299 $rows = WPF()->db->get_results(
300 "SELECT `userid`, MAX(`time`) as max_time FROM `" . WPF()->tables->visits . "` WHERE `userid` IN (" . $id_list . ") GROUP BY `userid`",
301 ARRAY_A
302 );
303 foreach( $rows as $row ) {
304 $user_max_times[ (int) $row['userid'] ] = (int) $row['max_time'];
305 }
306 }
307
308 foreach( $visitors as $visitor ) {
309 if( wpfval( $visitor, 'userid' ) ) {
310 if( (int) $visitor['time'] < $online_period ) {
311 $data['users']['viewed'][] = $visitor;
312 } else {
313 $uid = intval( $visitor['userid'] );
314 $max_time = isset( $user_max_times[ $uid ] ) ? $user_max_times[ $uid ] : 0;
315 if( $max_time > (int) $visitor['time'] ) {
316 $data['users']['viewed'][] = $visitor;
317 } else {
318 $data['users']['viewing'][] = $visitor;
319 }
320 }
321 } elseif( (int) $visitor['time'] > $online_period ) {
322 $data['guests'][] = $visitor;
323 }
324 }
325 }
326
327 return $data;
328 }
329
330 public function visit() {
331 if( wpforo_setting( 'logging', 'track_logging' ) ) {
332 if( ( wpforo_current_user_is( 'admin' ) || WPF()->current_user_groupid == 1 ) && ! wpforo_setting( 'logging', 'display_admin_viewers' ) ) {
333 return false;
334 }
335 $data = WPF()->current_object;
336 $visitor = WPF()->current_user;
337 $template = ( wpfval( $data, 'template' ) ) ? $data['template'] : '';
338 $templates = [ 'forum', 'topic', 'post' ];
339 $templates = apply_filters( 'wpforo_track_visitors_in_pages', $templates );
340 if( $template ) {
341 if( $template == 'post' && in_array( $template, $templates ) ) {
342 //topic page (post list)
343 if( wpfval( $data, 'topic', 'topicid' ) && wpfval( $data, 'topic', 'forumid' ) ) {
344 $forumid = intval( $data['topic']['forumid'] );
345 $topicid = intval( $data['topic']['topicid'] );
346 $this->add_visit( $visitor, $forumid, $topicid );
347 }
348 } elseif( $template == 'topic' && in_array( $template, $templates ) ) {
349 //forum page (topic list)
350 if( wpfval( $data, 'forum', 'forumid' ) ) {
351 $forumid = intval( $data['forum']['forumid'] );
352 $this->add_visit( $visitor, $forumid );
353 }
354 } elseif( $template == 'forum' && in_array( $template, $templates ) ) {
355 //forum home page
356 $this->add_visit( $visitor );
357 } elseif( in_array( $template, $templates ) ) {
358 //other pages (profile, search, members, etc..)
359 $this->add_visit( $visitor );
360 }
361 }
362 }
363 return false;
364 }
365
366 public function add_visit( $visitor, $forumid = 0, $topicid = 0 ) {
367 $time = esc_sql( time() );
368 if( WPF()->current_userid ) {
369 $userid = ( wpfval( $visitor, 'userid' ) ) ? intval( $visitor['userid'] ) : 0;
370 $name = ( wpfval( $visitor, 'display_name' ) ) ? esc_sql( $visitor['display_name'] ) : '';
371 WPF()->db->query( "INSERT INTO `" . WPF()->tables->visits . "` (`userid`, `name`, `time`, `topicid`, `forumid`) VALUES( " . $userid . ", '" . $name . "', '" . $time . "', " . $topicid . ", " . $forumid . " ) ON DUPLICATE KEY UPDATE `time` = '" . $time . "'" );
372 } elseif( ! wpforo_is_bot() ) {
373 $ip = ( wpfval( $_SERVER, 'REMOTE_ADDR' ) ) ? substr( md5( (string) $_SERVER['REMOTE_ADDR'] ), 0, 32 ) : '-noip-';
374 if( $ip ) {
375 $guest = WPF()->db->get_var( "SELECT `id` FROM `" . WPF()->tables->visits . "` WHERE `ip` = '" . esc_sql( $ip ) . "' LIMIT 1" );
376 if( $guest ) {
377 WPF()->db->query( "UPDATE `" . WPF()->tables->visits . "` SET `topicid` = " . intval( $topicid ) . ", `forumid` = " . intval( $forumid ) . ", `time` = '" . $time . "' WHERE `id` = " . intval( $guest ) );
378 } else {
379 WPF()->db->query( "INSERT IGNORE INTO `" . WPF()->tables->visits . "` (`ip`, `time`, `topicid`, `forumid`) VALUES( '" . esc_sql( $ip ) . "', '" . $time . "', " . $topicid . ", " . $forumid . " )" );
380 }
381 }
382 }
383 }
384
385 /**
386 * do not use, this logic is not tested yet.
387 *
388 * @param int $forumid
389 *
390 * @return int
391 */
392 public function get_forum_unreads_count( $forumid ) {
393 $forumid = intval( $forumid );
394 $read_forums = $this->get_read_forums();
395 $last_read_postid = (int) wpfval( $read_forums, $forumid );
396 $sql = "SELECT SQL_NO_CACHE COUNT(*) FROM `" . WPF()->tables->posts . "`
397 WHERE `status` = 0
398 AND `private` = 0
399 AND `forumid` = $forumid
400 AND `postid` > $last_read_postid";
401 $count = (int) WPF()->db->get_var( $sql );
402
403 return (int) apply_filters( 'wpforo_logs_get_forum_unreads_count', $count, $forumid, $last_read_postid );
404 }
405
406 /**
407 * get unread posts count for topic by giving topicid
408 *
409 * @param int $topicid
410 *
411 * @return int
412 */
413 public function get_topic_unreads_count( $topicid ) {
414 $topicid = intval( $topicid );
415 $read_topics = $this->get_read_topics();
416 $last_read_postid = (int) wpfval( $read_topics, $topicid );
417 $sql = "SELECT SQL_NO_CACHE COUNT(*) FROM `" . WPF()->tables->posts . "`
418 WHERE `status` = 0
419 AND `topicid` = $topicid
420 AND `postid` > $last_read_postid";
421 $count = (int) WPF()->db->get_var( $sql );
422
423 return (int) apply_filters( 'wpforo_logs_get_topic_unreads_count', $count, $topicid, $last_read_postid );
424 }
425
426 }
427