PluginProbe
wpForo Forum / 3.2.0
wpForo Forum v3.2.0
3.2.0 3.1.7 3.1.6 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 All 140 releases
wpforo / classes / Cache.php

Cache.php in wpForo Forum 3.2.0, at classes/Cache.php

618 lines 27.4 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 use FilesystemIterator;
6
7 // Exit if accessed directly
8 if( ! defined( 'ABSPATH' ) ) exit;
9
10 class Cache {
11 public $dir = '';
12 public $locale = '';
13 public $special_key = '';
14 private $touched_postids = [];
15
16 function __construct() {
17 add_action( 'wpforo_after_init_folders', function( $folders ) {
18 $cache_dir = apply_filters('wpforo_cache_dir', $folders['cache']['dir'], $folders);
19 if( ! is_dir( $cache_dir ) ) $this->dir( $cache_dir );
20 if( ! is_dir( $cache_dir . DIRECTORY_SEPARATOR . 'tag' ) ) $this->mkdir( $cache_dir . DIRECTORY_SEPARATOR . 'tag' );
21 if( ! is_dir( $cache_dir . DIRECTORY_SEPARATOR . 'item' . DIRECTORY_SEPARATOR . 'tag' ) ) $this->mkdir( $cache_dir . DIRECTORY_SEPARATOR . 'item' . DIRECTORY_SEPARATOR . 'tag' );
22 if( ! is_dir( $cache_dir . DIRECTORY_SEPARATOR . 'item' . DIRECTORY_SEPARATOR . 'url' ) ) $this->mkdir( $cache_dir . DIRECTORY_SEPARATOR . 'item' . DIRECTORY_SEPARATOR . 'url' );
23 if( ! is_dir( $cache_dir . DIRECTORY_SEPARATOR . 'item' . DIRECTORY_SEPARATOR . 'avatar' ) ) $this->mkdir( $cache_dir . DIRECTORY_SEPARATOR . 'item' . DIRECTORY_SEPARATOR . 'avatar' );
24 if( ! is_dir( $cache_dir . DIRECTORY_SEPARATOR . 'item' . DIRECTORY_SEPARATOR . 'reaction' ) ) $this->mkdir( $cache_dir . DIRECTORY_SEPARATOR . 'item' . DIRECTORY_SEPARATOR . 'reaction' );
25 if( ! is_dir( $cache_dir . DIRECTORY_SEPARATOR . 'item' . DIRECTORY_SEPARATOR . 'option' ) ) $this->mkdir( $cache_dir . DIRECTORY_SEPARATOR . 'item' . DIRECTORY_SEPARATOR . 'option' );
26
27 $this->dir = $cache_dir;
28 } );
29
30 if( apply_filters( 'wpforo_cache_by_usergroup', false ) ){
31 add_action( 'wpforo_after_init_current_user', function (){
32 $this->set_special_key();
33 } );
34 }
35
36 add_action( 'wpforo_after_set_locale', function( $locale ) {
37 $this->locale = $locale;
38 $this->set_special_key();
39 } );
40
41 add_action( 'wpforo_after_add_board', function( $board ){
42 if( $board['status'] ){
43 WPF()->change_board( $board['boardid'] );
44 wpforo_clean_cache();
45 }
46 } );
47
48 add_action( 'wpforo_after_edit_board', function( $boardid ){
49 $board = WPF()->board->_get_board( $boardid );
50 if( wpfval($board, 'status' ) ){
51 WPF()->change_board( $boardid );
52 wpforo_clean_cache();
53 }
54 } );
55
56 add_action( 'wpforo_after_add_reaction', [ $this, 'after_add_reaction' ] );
57 add_action( 'wpforo_after_edit_reaction', [ $this, 'after_edit_reaction' ] );
58 add_action( 'wpforo_before_delete_reaction', [ $this, 'before_delete_reaction' ], 10, 2 );
59 add_action( 'wpforo_after_delete_reaction', [ $this, 'after_delete_reaction' ] );
60 }
61
62 private function set_special_key(): void {
63 $this->special_key = (
64 apply_filters( 'wpforo_cache_by_usergroup', false )
65 ? implode( '-', WPF()->current_user_groupids ) . '-' : ''
66 ) . $this->locale;
67 }
68
69 public function get_key( $type = 'html' ) {
70 if( $type === 'html' ) {
71 $ug = WPF()->current_user_groupid;
72
73 return md5( preg_replace( '#(.+)\#.+?$#is', '$1', (string) $_SERVER['REQUEST_URI'] ) . $ug );
74 }
75 }
76
77 private function dir( $cache_dir ) {
78 $dirs = [
79 $cache_dir,
80 $cache_dir . DIRECTORY_SEPARATOR . 'forum',
81 $cache_dir . DIRECTORY_SEPARATOR . 'topic',
82 $cache_dir . DIRECTORY_SEPARATOR . 'post',
83 $cache_dir . DIRECTORY_SEPARATOR . 'tag',
84 $cache_dir . DIRECTORY_SEPARATOR . 'item',
85 $cache_dir . DIRECTORY_SEPARATOR . 'item' . DIRECTORY_SEPARATOR . 'forum',
86 $cache_dir . DIRECTORY_SEPARATOR . 'item' . DIRECTORY_SEPARATOR . 'topic',
87 $cache_dir . DIRECTORY_SEPARATOR . 'item' . DIRECTORY_SEPARATOR . 'post',
88 $cache_dir . DIRECTORY_SEPARATOR . 'item' . DIRECTORY_SEPARATOR . 'tag',
89 $cache_dir . DIRECTORY_SEPARATOR . 'item' . DIRECTORY_SEPARATOR . 'url',
90 $cache_dir . DIRECTORY_SEPARATOR . 'item' . DIRECTORY_SEPARATOR . 'avatar',
91 $cache_dir . DIRECTORY_SEPARATOR . 'item' . DIRECTORY_SEPARATOR . 'reaction',
92 $cache_dir . DIRECTORY_SEPARATOR . 'item' . DIRECTORY_SEPARATOR . 'option',
93 ];
94 $this->mkdir( $dirs );
95 }
96
97 private function mkdir( $dirs ) {
98 foreach( (array) $dirs as $dir ) {
99 wp_mkdir_p( $dir );
100 wpforo_write_file( $dir . '/index.html', '' );
101 wpforo_write_file( $dir . '/.htaccess', 'deny from all' );
102 }
103 }
104
105 public function on( $type = 'all' ){
106 if( $type !== 'all' ){
107 if( $type === 'forum' && !apply_filters( 'wpforo_cache_forum', true ) ) return false;
108 if( $type === 'topic' && !apply_filters( 'wpforo_cache_topic', true ) ) return false;
109 if( $type === 'post' && !apply_filters( 'wpforo_cache_post', true ) ) return false;
110 if( $type === 'tag' && !apply_filters( 'wpforo_cache_tag', true ) ) return false;
111 if( $type === 'url' && !apply_filters( 'wpforo_cache_url', true ) ) return false;
112 if( $type === 'reaction' && !apply_filters( 'wpforo_cache_reaction', true ) ) return false;
113 if( $type === 'avatar' && !apply_filters( 'wpforo_cache_avatar', true ) ) return false;
114 if( $type === 'option' && !apply_filters( 'wpforo_cache_option', true ) ) return false;
115 }
116 return wpforo_setting( 'board', 'cache' );
117 }
118
119 public function get( $key, $type = 'loop', $template = null ) {
120 $template = ( $template ) ?: WPF()->current_object['template'];
121 $loop_templates = [ 'forum', 'topic', 'post', 'tag' ];
122 if( $type === 'loop' && $template ) {
123 if( $this->exists( $key, $template ) ) {
124 if( in_array( $template, $loop_templates ) ) {
125 $cache_file = $this->dir . '/' . $template . '/' . $key;
126 $array = wpforo_get_file_content( $cache_file );
127
128 return @unserialize( $array, [ 'allowed_classes' => false ] );
129 }
130 }
131 }
132 }
133
134 public function get_item( $id, $type = 'post', $sub_type = '' ) {
135 if( $id ) {
136 $key = $id . '_' . $this->special_key;
137 $domain_path = preg_replace('|https?://|i', '', get_site_url() );
138 if( $this->exists( $key, 'item', $type, $sub_type ) ) {
139 $cache_file = $this->dir . '/item/' . $type . '/' . ( $sub_type ? $sub_type . '_' : '' ) . $key;
140 $array = wpforo_get_file_content( $cache_file );
141 $data = @unserialize( $array, [ 'allowed_classes' => false ] );
142 if( $type === 'url' ) {
143 // Always make sure the cached URLs are pointed to current website
144 if( strpos( (string) $data, $domain_path ) === FALSE ) return null;
145 }
146 return $data;
147 }
148 }
149 return null;
150 }
151
152 public function get_html() {
153 $template = WPF()->current_object['template'];
154 if( $template == 'forum' ) {
155 $key = $this->get_key();
156 if( $this->exists( $key, $template ) ) {
157 $cache_file = $this->dir . '/' . $template . '/' . $key;
158 $html = wpforo_get_file_content( $cache_file );
159
160 return $this->filter( $html );
161 }
162 }
163
164 return false;
165 }
166
167 public function html( $content ) {
168 /*$template = WPF()->current_object['template'];
169 if( $template === 'forum' ){
170 $key = $this->get_key();
171 $this->create_html( $content, $template, $key );
172 }*/
173 }
174
175 public function create( $mode = 'loop', $cache = [], $type = 'post' ) {
176 if( ! $this->on() ) return false;
177 $template = WPF()->current_object['template'];
178 if( $template == 'forum' ) {
179 $this->check( $this->dir . '/item/post' );
180 }
181
182 if( $mode === 'loop' && $template ) {
183 if( wpfval( $cache, 'tags' ) ) {
184 $this->create_files( $cache['tags'], 'tag' );
185 }
186 if( $template === 'forum' || $template === 'topic' || $template === 'post' ) {
187 $cache = WPF()->forum->get_cache( 'forums' );
188 $this->create_files( $cache, $template );
189 $cache = WPF()->topic->get_cache( 'topics' );
190 $this->create_files( $cache, $template );
191 $cache = WPF()->post->get_cache( 'posts' );
192 $this->create_files( $cache, $template );
193 }
194 } elseif( $mode === 'item' && ! empty( $cache ) ) {
195 $this->create_files( $cache, 'item', $type );
196 }
197 }
198
199 public function create_files( $cache = [], $template = '', $type = '' ) {
200 if( ! empty( $cache ) ) {
201 $type = ( $type ) ? $type . '/' : '';
202 foreach( $cache as $key => $object ) {
203 if( $template === 'item' ) $key = $key . '_' . $this->special_key;
204 if( ! $this->exists( $key, $template ) ) {
205 $object = serialize( $object );
206 wpforo_write_file( $this->dir . '/' . $template . '/' . $type . $key, $object );
207 }
208 }
209 }
210 }
211
212 public function create_html( $content, $template = '', $key = '' ) {
213 if( $content ) {
214 if( ! $this->exists( $key, $template ) ) {
215 wpforo_write_file( $this->dir . '/' . $template . '/' . $key, $content );
216 }
217 }
218 }
219
220 public function create_custom( $args = [], $items = [], $template = 'post', $items_count = 0 ) {
221 if( empty( $args ) || ! is_array( $args ) ) return;
222 if( empty( $items ) || ! is_array( $items ) ) return;
223 $cache = [];
224 $hach = serialize( $args );
225 $object_key = md5( $hach . WPF()->current_user_groupid );
226 $cache[ $object_key ]['items'] = $items;
227 $cache[ $object_key ]['items_count'] = $items_count;
228 $this->create_files( $cache, $template );
229 }
230
231 public function filter( $html = '' ) {
232 //exit();
233 $html = preg_replace( '|<div[\s\t]*id=\"wpf-msg-box\"|i', '<div style="display:none;"', (string) $html );
234
235 return $html;
236 }
237
238 #################################################################################
239
240 /**
241 * Cleans forum cache
242 *
243 * @param integer Item ID (e.g.: $topicid or $postid) | (!) ID is 0 on dome actions (e.g.: delete actions)
244 * @param string Item Type (e.g.: 'forum', 'topic', 'post', 'user', 'widget', etc...)
245 * @param array Item data as array
246 *
247 * @return void
248 * @since 1.2.1
249 *
250 */
251
252 public function clean( $id, $template, $item = [] ) {
253
254 $dirs = [];
255 $userid = ( isset( $item['userid'] ) && $item['userid'] ) ? $item['userid'] : 0;
256 $postid = ( isset( $item['postid'] ) && $item['postid'] ) ? $item['postid'] : 0;
257 $topicid = ( isset( $item['topicid'] ) && $item['topicid'] ) ? $item['topicid'] : 0;
258 $forumid = ( isset( $item['forumid'] ) && $item['forumid'] ) ? $item['forumid'] : 0;
259 $parentid = ( isset( $item['parentid'] ) && $item['parentid'] ) ? $item['parentid'] : 0;
260 $root = ( isset( $item['root'] ) && $item['root'] ) ? $item['root'] : 0;
261 $tagid = ( isset( $item['tagid'] ) && $item['tagid'] ) ? $item['tagid'] : 0;
262
263 if( isset( WPF()->forum ) && method_exists(WPF()->forum, 'reset') ) WPF()->forum->reset();
264 if( isset( WPF()->topic ) && method_exists(WPF()->topic, 'reset') ) WPF()->topic->reset();
265 if( isset( WPF()->post ) && method_exists(WPF()->post, 'reset') ) WPF()->post->reset();
266
267 if( $template === 'forum' || $template === 'forum-soft' ) {
268 $id = isset( $id ) ? $id : $forumid;
269 if( $template === 'forum' ) {
270 $dirs = [ $this->dir . '/forum', $this->dir . '/item/forum', $this->dir . '/item/url' ];
271 WPF()->seo->clear_cache();
272 }
273 if( $template === 'forum-soft' ) {
274 $dirs = [ $this->dir . '/forum' ];
275 }
276 if( $id ) {
277 $file = $this->dir . '/item/forum/' . $id . '_' . $this->special_key;
278 $this->clean_file( $file );
279 }
280 } elseif( $template === 'topic' || $template === 'topic-first-post' || $template === 'topic-soft' ) {
281 $id = isset( $id ) ? $id : $topicid;
282 if( $template === 'topic' || $template === 'topic-first-post' ) {
283 WPF()->seo->clear_cache();
284 $dirs = [ $this->dir . '/forum', $this->dir . '/topic', $this->dir . '/post' ];
285 }
286 if( $forumid ) {
287 $file = $this->dir . '/item/forum/' . $forumid . '_' . $this->special_key;
288 $this->clean_file( $file );
289 }
290 if( $id ) {
291 $file = $this->dir . '/item/topic/' . $id . '_' . $this->special_key;
292 $this->clean_file( $file );
293 $file = $this->dir . '/item/url/topic_' . $id . '_' . $this->special_key;
294 $this->clean_file( $file );
295 $postid = ( isset( $item['first_postid'] ) && $item['first_postid'] ) ? $item['first_postid'] : 0;
296 if( $postid ) $file = $this->dir . '/item/post/' . $postid . '_' . $this->special_key;
297 $this->clean_file( $file );
298 if( $template === 'topic' ) $this->clear_topic_posts_urls( $id );
299 }
300 WPF()->statistic_cache_clean();
301 $this->clear_visitor_tracking();
302 } elseif( $template === 'post' || $template === 'post-soft' ) {
303 $id = isset( $id ) ? $id : $postid;
304 if( $template === 'post' ) {
305 $dirs = [ $this->dir . '/forum', $this->dir . '/topic', $this->dir . '/post' ];
306 }
307 if( $forumid ) {
308 $file = $this->dir . '/item/forum/' . $forumid . '_' . $this->special_key;
309 $this->clean_file( $file );
310 }
311 if( $topicid ) {
312 $file = $this->dir . '/item/topic/' . $topicid . '_' . $this->special_key;
313 $this->clean_file( $file );
314 }
315 if( $parentid ) {
316 $file = $this->dir . '/item/post/' . $parentid . '_' . $this->special_key;
317 $this->clean_file( $file );
318 }
319 if( $root ) {
320 $file = $this->dir . '/item/post/' . $root . '_' . $this->special_key;
321 $this->clean_file( $file );
322 }
323 if( $id ) {
324 $file = $this->dir . '/item/post/' . $id . '_' . $this->special_key;
325 $this->clean_file( $file );
326 $file = $this->dir . '/item/url/post_' . $id . '_' . $this->special_key;
327 $this->clean_file( $file );
328 $this->clear_topic_next_posts_urls( $id, $topicid );
329 }
330 WPF()->statistic_cache_clean();
331 $this->clear_visitor_tracking();
332 } elseif( $template === 'tag' ) {
333 if( $id ) {
334 $file = $this->dir . '/item/tag/' . md5( $id ) . '_' . $this->special_key;
335 $this->clean_file( $file );
336 } else {
337 $dirs = [ $this->dir . '/tag' ];
338 }
339 } elseif( $template === 'option' ) {
340 $dirs = [ $this->dir . '/item/option' ];
341 } elseif( $template === 'url' ) {
342 $dirs = [ $this->dir . '/item/url' ];
343 } elseif( $template === 'avatar' ) {
344 if( $id ){
345 $file = $this->dir . '/item/avatar/' . $id . '_' . $this->special_key;
346 $this->clean_file( $file );
347 } else {
348 $dirs = [ $this->dir . '/item/avatar' ];
349 }
350 } elseif( $template === 'reaction' ) {
351 if( $id ){
352 $file = $this->dir . '/item/reaction/' . $id . '_' . $this->special_key;
353 $this->clean_file( $file );
354 $this->clean( $id, 'post' );
355 } else {
356 $dirs = [ $this->dir . '/item/reaction' ];
357 }
358 } elseif( $template === 'user' ) {
359 if( wpforo_setting( 'seo', 'seo_profile' ) ) WPF()->seo->clear_cache();
360 } elseif( $template === 'loop' ) {
361 $dirs = [ $this->dir . '/forum', $this->dir . '/topic', $this->dir . '/post' ];
362 WPF()->seo->clear_cache();
363 } elseif( $template === 'item' ) {
364 $dirs = [ $this->dir . '/item/post', $this->dir . '/item/topic', $this->dir . '/item/forum' ];
365 WPF()->seo->clear_cache();
366 } else {
367 $dirs = [
368 $this->dir . '/forum',
369 $this->dir . '/topic',
370 $this->dir . '/post',
371 $this->dir . '/tag',
372 $this->dir . '/item/post',
373 $this->dir . '/item/topic',
374 $this->dir . '/item/forum',
375 $this->dir . '/item/tag',
376 $this->dir . '/item/url',
377 $this->dir . '/item/avatar',
378 $this->dir . '/item/option',
379 //$this->dir . '/item/reaction',
380 ];
381 WPF()->seo->clear_cache();
382 }
383
384 if( ! empty( $dirs ) ) {
385 foreach( $dirs as $dir ) {
386 $this->clean_files( $dir );
387 }
388 }
389 }
390
391 public function clean_files( $directory ) {
392 $directory = (string) $directory;
393 $directory = wpforo_fix_dir_sep( $directory );
394 $directory_ns = trim( $directory, DIRECTORY_SEPARATOR ) . DIRECTORY_SEPARATOR . '*';
395 $directory_ws = DIRECTORY_SEPARATOR . trim( $directory, DIRECTORY_SEPARATOR ) . DIRECTORY_SEPARATOR . '*';
396 $glob = glob( $directory_ns );
397 if( empty( $glob ) ) $glob = glob( $directory_ws );
398 foreach( $glob as $item ) {
399 if( strpos( (string) $item, 'index.html' ) !== false || strpos( (string) $item, '.htaccess' ) !== false ) continue;
400 if( ! is_dir( $item ) && file_exists( $item ) ) {
401 @unlink( $item );
402 }
403 }
404 }
405
406 public function clean_file( $file ) {
407 if( ! is_dir( $file ) && file_exists( $file ) ) {
408 @unlink( $file );
409 }
410 }
411
412 public function clear_topic_posts_urls( $topicid ){
413 if( !$topicid ) return;
414 $post_ids = WPF()->db->get_results("SELECT `postid` FROM " . WPF()->tables->posts . " WHERE `topicid` = " . intval( $topicid ), ARRAY_A );
415 if( !empty( $post_ids ) ){
416 foreach( $post_ids as $post_id ){
417 $this->clean_file( $this->dir . '/item/post/' . $post_id['postid'] . '_' . $this->special_key );
418 $this->clean_file( $this->dir . '/item/url/post_' . $post_id['postid'] . '_' . $this->special_key );
419 }
420 }
421 }
422
423 public function clear_topic_next_posts_urls( $postid, $topicid ){
424 $topicid = ( $topicid ) ? : wpforo_post( $postid, 'topicid' );
425 $post_ids = WPF()->db->get_results("SELECT `postid` FROM " . WPF()->tables->posts . " WHERE `topicid` = " . intval( $topicid ) . " AND `postid` > " . intval( $postid ), ARRAY_A );
426 if( !empty( $post_ids ) ){
427 foreach( $post_ids as $post_id ){
428 $this->clean_file( $this->dir . '/item/post/' . $post_id['postid'] . '_' . $this->special_key );
429 $this->clean_file( $this->dir . '/item/url/post_' . $post_id['postid'] . '_' . $this->special_key );
430 }
431 }
432 }
433
434 public function exists( $key, $template, $type = '', $sub_type = '' ) {
435 $type = ( $type ) ? $type . '/' : '';
436 if( file_exists( $this->dir . '/' . $template . '/' . $type . ( $sub_type ? $sub_type . '_' : '' ) . $key ) ) {
437 return true;
438 } else {
439 return false;
440 }
441 }
442
443 public function check( $directory ) {
444 $directory = (string) $directory;
445 $directory = wpforo_fix_dir_sep( $directory );
446
447 if( ! class_exists( 'FilesystemIterator' ) || ! is_dir( $directory ) ) return;
448
449 $fi = new FilesystemIterator( $directory, FilesystemIterator::SKIP_DOTS );
450 $filecount = iterator_count( $fi );
451 if( ! $filecount ) return;
452
453 // Dynamic limit based on online members (scales with forum activity)
454 // Use direct call to avoid recursion: statistic() calls post->get_url() which triggers cache->create() -> check() -> statistic()
455 $online = WPF()->member ? intval( WPF()->member->online_members_count() ) : 0;
456 $online = max( 2, $online );
457 $max = $online * 500;
458 $max = max( 1000, min( $max, 50000 ) );
459
460 /**
461 * Filter the maximum cache files allowed per directory.
462 *
463 * @param int $max Maximum files (default: dynamic based on online users)
464 * @param string $directory The cache directory being checked
465 */
466 $max = (int) apply_filters( 'wpforo_cache_dir_max_files', $max, $directory );
467 if( $max === 0 ) return; // 0 = disable cache limit
468
469 if( $filecount > $max ) {
470 $this->clean_old_files( $directory, (int) ceil( $filecount * 0.5 ) );
471 }
472 }
473
474 private function clean_old_files( $directory, $delete_count ) {
475 $directory_ns = trim( $directory, DIRECTORY_SEPARATOR ) . DIRECTORY_SEPARATOR . '*';
476 $directory_ws = DIRECTORY_SEPARATOR . trim( $directory, DIRECTORY_SEPARATOR ) . DIRECTORY_SEPARATOR . '*';
477 $files = glob( $directory_ns );
478 if( empty( $files ) ) $files = glob( $directory_ws );
479 if( empty( $files ) ) return;
480
481 // Sort by modification time (oldest first)
482 usort( $files, function( $a, $b ) {
483 return filemtime( $a ) - filemtime( $b );
484 });
485
486 // Delete oldest 50%
487 foreach( array_slice( $files, 0, $delete_count ) as $file ) {
488 if( strpos( (string) $file, 'index.html' ) !== false || strpos( (string) $file, '.htaccess' ) !== false ) continue;
489 if( ! is_dir( $file ) && file_exists( $file ) ) @unlink( $file );
490 }
491 }
492
493 public function clear_visitor_tracking() {
494 $keep_vistors_data = apply_filters( 'wpforo_keep_visitors_data', 4000 );
495 $time = (int) time() - (int) $keep_vistors_data;
496 $online = (int) time() - (int) wpforo_setting( 'profiles', 'online_status_timeout' );
497 if( $time > 1 ) {
498 WPF()->db->query( "DELETE FROM `" . WPF()->tables->visits . "` WHERE `time` < " . intval( $time ) . " OR (`time` < " . intval( $online ) . " AND `userid` = 0)" );
499 }
500 }
501
502 public function cache_plugins(){
503 $board_paths = [];
504 $cache_plugins = [];
505
506 if( is_wpforo_multiboard() ){
507 $boards = WPF()->board->get_boards();
508 if(!empty($boards)){
509 foreach($boards as $board){
510 $board_paths[] = '/' . $board['slug'] . '/';
511 }
512 }
513 } else {
514 $board_paths[] = '/' . WPF()->board->get_current( 'slug' ) . '/';
515 }
516
517 $board_paths[] = '/' . wpforo_settings_get_slug('member') . '/';
518 $board_paths[] = '/' . wpforo_settings_get_slug('register') . '/';
519 $board_paths[] = '/' . wpforo_settings_get_slug('login') . '/';
520 $board_paths[] = '/' . wpforo_settings_get_slug('lostpassword') . '/';
521
522 if (function_exists("wpsc_init")) {
523 //WP Super Cache
524 $cache_plugins['WPSuper']['name'] = 'WP Super Cache';
525 $cache_plugins['WPSuper']['steps'][] = __('Please navigate in Dashboard to Settings > WP Super Cache', 'wpforo');
526 $cache_plugins['WPSuper']['steps'][] = __('Go to Advanced Tab, scroll down to "Rejected URL Strings" option', 'wpforo');
527 $cache_plugins['WPSuper']['steps'][] = __('Insert the URL path(s) of your forum page(s) one per line in the option textarea:', 'wpforo') . ' <br><code>' . implode('</code> <br> <code>', $board_paths) . '</code>';
528 $cache_plugins['WPSuper']['steps'][] = __('Save it and delete all caches.', 'wpforo');
529 }
530 if (defined("LSCWP_V")) {
531 //LiteSpeed Cache
532 $cache_plugins['LiteSpeed']['name'] = 'LiteSpeed Cache';
533 $cache_plugins['LiteSpeed']['steps'][] = __('Please navigate in Dashboard to LiteSpeed Cache > Cache admin page', 'wpforo');
534 $cache_plugins['LiteSpeed']['steps'][] = __('Go to Exclude Tab, find the "Do Not Cache URIs" option', 'wpforo');
535 $cache_plugins['LiteSpeed']['steps'][] = __('Insert the URL path(s) of your forum page(s) one per line in the option textarea:', 'wpforo') . ' <br><code>' . implode('</code> <br> <code>', $board_paths) . '</code>';
536 $cache_plugins['LiteSpeed']['steps'][] = __('Save it and delete all caches.', 'wpforo');
537 }
538 if (function_exists("rocket_clean_post")) {
539 //WP Rocket Cache
540 $cache_plugins['WPRocket']['name'] = 'WP Rocket Cache';
541 $cache_plugins['WPRocket']['steps'][] = __('Please navigate in Dashboard to WP Rocket > Advanced Rules Tab', 'wpforo');
542 $cache_plugins['WPRocket']['steps'][] = __('Scroll down to "Never cache (URLs)" option', 'wpforo');
543 $cache_plugins['WPRocket']['steps'][] = __('Insert the URL path(s) of your forum page(s) one per line with wildcard (.*) in the option textarea:', 'wpforo') . ' <br><code>' . implode('</code> <br> <code>', array_map( function ( $value ){ return $value . '(.*)'; }, $board_paths)) . '</code>';
544 $cache_plugins['WPRocket']['steps'][] = __('Save it and delete all caches.', 'wpforo');
545 }
546 if (function_exists("wpfc_clear_post_cache_by_id")) {
547 //WP Fastest Cache
548 $cache_plugins['WPFastest']['name'] = 'WP Fastest Cache';
549 $cache_plugins['WPFastest']['steps'][] = __('Please navigate in Dashboard to WP Fastest Cache > Exclude Tab', 'wpforo');
550 $cache_plugins['WPFastest']['steps'][] = __('In the "Exclude Pages" section click the [Add New Rule] button', 'wpforo');
551 $cache_plugins['WPFastest']['steps'][] = __('Select [Start with] option in the drop-down menu and insert the URL path(s) of your forum page(s) one per rule in the next field:', 'wpforo') . ' <br><code>' . implode('</code> <br> <code>', $board_paths) . '</code>';
552 $cache_plugins['WPFastest']['steps'][] = __('If you have more than one forum pages (boards) you should create separate rules for each forum board.', 'wpforo');
553 $cache_plugins['WPFastest']['steps'][] = __('Save rules and delete all caches.', 'wpforo');
554 }
555 if (function_exists("w3tc_flush_post")) {
556 //W3 Total Cache
557 $cache_plugins['W3Total']['name'] = 'W3 Total Cache';
558 $cache_plugins['W3Total']['steps'][] = __('Please navigate in Dashboard to Performance > Page Cache admin page', 'wpforo');
559 $cache_plugins['W3Total']['steps'][] = __('Go to Advanced Tab, scroll down to Rejected URL Strings option', 'wpforo');
560 $cache_plugins['W3Total']['steps'][] = __('Scroll to Advanced section and insert the URL path(s) of your forum page(s) one per line in the "Never cache the following pages" textarea:', 'wpforo') . ' <br><code>' . implode('</code> <br> <code>', $board_paths) . '</code>';
561 $cache_plugins['W3Total']['steps'][] = __('Save it and delete all caches.', 'wpforo');
562 }
563 if (is_callable(["WPO_Page_Cache", "delete_single_post_cache"])) {
564 //WP-Optimize Cache
565 $cache_plugins['WPOptimize']['name'] = 'WP-Optimize Cache';
566 $cache_plugins['WPOptimize']['steps'][] = __('Please navigate in Dashboard to WP-Optimize > Cache admin page', 'wpforo');
567 $cache_plugins['WPOptimize']['steps'][] = __('Go to Advanced Settings Tab, find the "URLs to exclude from caching" option', 'wpforo');
568 $cache_plugins['WPOptimize']['steps'][] = __('Insert the URL path(s) of your forum page(s) one per line with wildcard [*] in the option textarea:', 'wpforo') . ' <br><code>' . implode('</code> <br> <code>', array_map( function ( $value ){ return $value . '*'; }, $board_paths)) . '</code>';
569 $cache_plugins['WPOptimize']['steps'][] = __('Save it and delete all caches.', 'wpforo');
570 }
571 if (class_exists("\SiteGround_Optimizer\Supercacher\Supercacher")) {
572 //SiteGround Optimizer
573 $cache_plugins['SiteGround']['name'] = 'SiteGround Optimizer';
574 $cache_plugins['SiteGround']['steps'][] = __('Please navigate in Dashboard to SG Optimizer > Caching admin page', 'wpforo');
575 $cache_plugins['SiteGround']['steps'][] = __('Scroll to Exclude URLs from Caching section and click the "pencil" button, enable it, and click the button again', 'wpforo');
576 $cache_plugins['SiteGround']['steps'][] = __('Insert the URL path(s) of your forum page(s) with wildcard [*] in the pop-up filed:', 'wpforo') . ' <br><code>' . implode('</code> <br> <code>', array_map( function ( $value ){ return $value . '*'; }, $board_paths)) . '</code>';
577 $cache_plugins['SiteGround']['steps'][] = __('Save it and delete all caches.', 'wpforo');
578 }
579 return $cache_plugins;
580 }
581
582 public function cache_plugins_status(){
583 $not_exluded = [];
584 $cache_plugins = $this->cache_plugins();
585 $excluded = wpforo_get_option( 'wpforo_excluded_cache', '', false );
586 $excluded = explode(',', $excluded );
587 if( ! empty( $cache_plugins ) ){
588 foreach( $cache_plugins as $cache_plugin ){
589 if( ! in_array( $cache_plugin['name'], $excluded ) ){
590 $not_exluded[] = $cache_plugin;
591 }
592 }
593 }
594 return $not_exluded;
595 }
596
597 public function after_add_reaction( $reaction ) {
598 if( wpfval( $reaction, 'postid' ) ) {
599 WPF()->reaction->create_reaction_cache( $reaction['postid'] );
600 }
601 }
602
603 public function after_edit_reaction( $fields ) {
604 if( wpfval( $fields, 'postid' ) ) {
605 wpforo_clean_cache( 'reaction', $fields['postid'] );
606 }
607 }
608
609 public function before_delete_reaction( $args, $operator ) {
610 $this->touched_postids = WPF()->reaction->_get_reactions_col( 'postid', $args, $operator );
611 }
612
613 public function after_delete_reaction(){
614 foreach( array_unique(array_filter( $this->touched_postids )) as $postid ) wpforo_clean_cache( 'reaction', $postid );
615 }
616
617 }
618