PluginProbe
wpForo Forum / 3.1.6
wpForo Forum v3.1.6
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 1.4.12 1.4.13 All 138 releases
← All changes | wpforo.php +1656 -710 1.4.133.1.6 View file →
@@ -1,710 +1,1656 @@
1 -<?php
2 -/*
3 -* Plugin Name: wpForo
4 -* Plugin URI: https://wpforo.com
5 -* Description: WordPress Forum plugin. wpForo is a full-fledged forum solution for your community. Comes with multiple modern forum layouts.
6 -* Author: gVectors Team (A. Chakhoyan, R. Hovhannisyan)
7 -* Author URI: https://gvectors.com/
8 -* Version: 1.4.13
9 -* Text Domain: wpforo
10 -* Domain Path: /wpf-languages
11 -*/
12 -
13 -//Exit if accessed directly
14 -if( !defined( 'ABSPATH' ) ) exit;
15 -if( !defined( 'WPFORO_VERSION' ) ) define('WPFORO_VERSION', '1.4.13');
16 -
17 -function wpforo_load_plugin_textdomain() { load_plugin_textdomain( 'wpforo', FALSE, basename( dirname( __FILE__ ) ) . '/wpf-languages/' ); }
18 -add_action( 'plugins_loaded', 'wpforo_load_plugin_textdomain' );
19 -
20 -if( !class_exists( 'wpForo' ) ) {
21 -
22 - define('WPFORO_DIR', rtrim( plugin_dir_path( __FILE__ ), '/' ));
23 - define('WPFORO_URL', rtrim( plugins_url( '', __FILE__ ), '/' ));
24 - define('WPFORO_FOLDER', rtrim( plugin_basename(dirname(__FILE__)), '/'));
25 - define('WPFORO_BASENAME', plugin_basename(__FILE__)); //wpforo/wpforo.php
26 -
27 - final class wpForo{
28 - private static $_instance = NULL;
29 -
30 - public $file;
31 - public $basename;
32 - public $error;
33 - public $locale;
34 -
35 - public $tables;
36 - public $blog_prefix;
37 - private $prefix = "wpforo_";
38 - private $_tables = array( 'accesses', 'forums', 'languages', 'likes', 'phrases', 'posts', 'profiles',
39 - 'subscribes', 'topics', 'usergroups', 'views', 'visits', 'votes' );
40 -
41 - public $db;
42 - public $addons = array();
43 - public $current_url;
44 - public $current_object;
45 - public $menu = array();
46 - public $form = array();
47 - public $default;
48 -
49 - public $current_user = array();
50 - public $current_user_groupid = 4;
51 - public $current_userid = 0;
52 - public $current_username = '';
53 - public $current_user_email = '';
54 - public $current_user_display_name = '';
55 - public $current_user_status = '';
56 -
57 - public $use_trailing_slashes;
58 - public $use_home_url;
59 - public $excld_urls;
60 - public $base_permastruct;
61 - public $permastruct;
62 - public $url;
63 - public $pageid;
64 -
65 - public $general_options;
66 - public $features;
67 - public $tools_antispam;
68 - public $tools_cleanup;
69 - public $tools_misc;
70 - public $tools_legal;
71 -
72 - public $cache;
73 - public $phrase;
74 - public $forum;
75 - public $topic;
76 - public $post;
77 - public $usergroup;
78 - public $member;
79 - public $perm;
80 - public $sbscrb;
81 - public $tpl;
82 - public $notice;
83 - public $api;
84 - public $feed;
85 - public $moderation;
86 - public $add;
87 -
88 - public $member_tpls;
89 -
90 - public static function instance(){
91 - if ( is_null(self::$_instance) ) self::$_instance = new self();
92 - return self::$_instance;
93 - }
94 -
95 - private function __construct(){
96 - global $wpdb;
97 - $this->db = $wpdb;
98 - $this->file = __FILE__;
99 - $this->error = NULL;
100 - $this->locale = get_locale();
101 - $this->basename = plugin_basename($this->file);
102 -
103 - $this->init_db_tables();
104 - $this->includes();
105 - $this->init_defaults();
106 - $this->init_options();
107 - $this->setup();
108 - $this->init_hooks();
109 -
110 - $this->cache = new wpForoCache();
111 - $this->phrase = new wpForoPhrase();
112 - $this->forum = new wpForoForum();
113 - $this->topic = new wpForoTopic();
114 - $this->post = new wpForoPost();
115 - $this->usergroup = new wpForoUsergroup();
116 - $this->member = new wpForoMember();
117 - $this->perm = new wpForoPermissions();
118 - $this->sbscrb = new wpForoSubscribe();
119 - $this->tpl = new wpForoTemplate();
120 - $this->notice = new wpForoNotices();
121 - $this->api = new wpForoAPI();
122 - $this->feed = new wpForoFeed();
123 - $this->moderation = new wpForoModeration();
124 - $this->add = new stdClass(); // Integrations
125 - }
126 -
127 - private function init_hooks(){
128 - add_action('admin_init', array($this, 'admin_init'));
129 - add_action('init', array($this, 'init'));
130 - add_action('wp_loaded', 'wpforo_actions');
131 - add_action('wp', array($this, 'init_shortcode_page'));
132 - }
133 -
134 - private function init_db_tables($blog_id = 0){
135 - $blog_id = apply_filters('wpforo_current_blog_id', $blog_id);
136 - $this->tables = new stdClass;
137 - if(!$blog_id) $blog_id = $this->db->blogid;
138 - $this->blog_prefix = $this->db->get_blog_prefix( $blog_id );
139 - $this->_tables = apply_filters('wpforo_init_db_tables', $this->_tables);
140 - foreach ( $this->_tables as $table )
141 - $this->tables->$table = $this->blog_prefix . $this->prefix . $table;
142 - }
143 -
144 - private function includes(){
145 - include( WPFORO_DIR . '/wpf-includes/wpf-hooks.php' );
146 - include( WPFORO_DIR . '/wpf-includes/wpf-actions.php');
147 - include( WPFORO_DIR . '/wpf-includes/functions.php' );
148 - include( WPFORO_DIR . '/wpf-includes/functions-integration.php' );
149 - include( WPFORO_DIR . '/wpf-includes/functions-template.php' );
150 - if(wpforo_is_admin()) {
151 - include( WPFORO_DIR . '/wpf-includes/functions-installation.php' );
152 - include( WPFORO_DIR .'/wpf-admin/admin.php' );
153 - }
154 -
155 - include( WPFORO_DIR . '/wpf-includes/class-cache.php' );
156 - include( WPFORO_DIR . '/wpf-includes/class-forums.php' );
157 - include( WPFORO_DIR . '/wpf-includes/class-topics.php' );
158 - include( WPFORO_DIR . '/wpf-includes/class-posts.php' );
159 - include( WPFORO_DIR . '/wpf-includes/class-usergroups.php' );
160 - include( WPFORO_DIR . '/wpf-includes/class-members.php' );
161 - include( WPFORO_DIR . '/wpf-includes/class-permissions.php' );
162 - include( WPFORO_DIR . '/wpf-includes/class-phrases.php');
163 - include( WPFORO_DIR . '/wpf-includes/class-subscribes.php' );
164 - include( WPFORO_DIR . '/wpf-includes/class-template.php' );
165 - include( WPFORO_DIR . '/wpf-includes/class-notices.php' );
166 - include( WPFORO_DIR . '/wpf-includes/class-api.php' );
167 - include( WPFORO_DIR . '/wpf-includes/class-feed.php' );
168 - include( WPFORO_DIR . '/wpf-includes/class-moderation.php' );
169 - }
170 -
171 - public function admin_init(){
172 - if( wpforo_is_admin() ){
173 - if( !wpforo_feature('user-synch') && get_option('wpforo_version') ){
174 - $users = $this->db->get_var("SELECT COUNT(*) FROM `".$this->db->users."`");
175 - $profiles = $this->db->get_var("SELECT COUNT(*) FROM `" . $this->tables->profiles."`");
176 - $delta = $users - $profiles;
177 - if( $users > 100 && $delta > 2 ){ add_action( 'admin_notices', 'wpforo_profile_notice' ); }
178 - }
179 - $db_version = get_option('wpforo_version_db');
180 - if( !$db_version || version_compare( $db_version, WPFORO_VERSION, '<') ){
181 - add_action( 'admin_notices', 'wpforo_update_db_notice' );
182 - }
183 - }
184 - }
185 -
186 - public function init(){
187 - $this->phrase->init();
188 - $this->member->init_current_user();
189 - $this->perm->init();
190 -
191 - $this->init_current_object();
192 - $this->moderation->init();
193 - $this->tpl->init();
194 - $this->api->hooks();
195 - }
196 -
197 - public function init_shortcode_page(){
198 - if(wpforo_is_admin()) return;
199 -
200 - if( is_wpforo_shortcode_page() ){
201 - $url = wpforo_home_url();
202 -
203 - if( $atts = get_wpforo_shortcode_atts() ){
204 - $args = shortcode_atts( array(
205 - 'item' => 'forum',
206 - 'id' => 0,
207 - 'slug' => '',
208 - ), $atts );
209 -
210 - if( $args['id'] || $args['slug'] ){
211 - $getid = ( $args['slug'] ? $args['slug'] : $args['id'] );
212 - if( $args['item'] == 'topic' ){
213 - $url = $this->topic->get_topic_url($getid);
214 - }elseif( $args['item'] == 'profile' ){
215 - $url = $this->member->get_profile_url($getid);
216 - }else{
217 - $url = $this->forum->get_forum_url($getid);
218 - }
219 - }
220 - }
221 -
222 - $this->init_current_object($url);
223 - $this->tpl->init_nav_menu();
224 - }
225 -
226 - }
227 -
228 - private function init_defaults(){
229 - $this->default = new stdClass;
230 -
231 - $this->default->use_home_url = 0;
232 - $this->default->excld_urls = '';
233 - $this->default->permastruct = 'community';
234 -
235 - $blogname = get_option('blogname', '');
236 - $this->default->general_options = array(
237 - 'title' => $blogname . ' ' . __('Forum', 'wpforo'),
238 - 'description' => $blogname . ' ' . __('Discussion Board', 'wpforo'),
239 - 'lang' => 1
240 - );
241 -
242 - $this->default->features = array(
243 - 'user-admin-bar' => 0,
244 - 'page-title' => 1,
245 - 'top-bar' => 1,
246 - 'top-bar-search' => 1,
247 - 'breadcrumb' => 1,
248 - 'footer-stat' => 1,
249 - 'mention-nicknames' => 1,
250 - 'content-do_shortcode' => 0,
251 - 'view-logging' => 1,
252 - 'author-link' => 0,
253 - 'comment-author-link' => 0,
254 - 'user-register' => 1,
255 - 'user-register-email-confirm' => 1,
256 - 'register-url' => 0,
257 - 'login-url' => 0,
258 - 'resetpass-url' => 0, //In most cases incompatible with security and antispam plugins
259 - 'replace-avatar' => 1,
260 - 'avatars' => 1,
261 - 'custom-avatars' => 1,
262 - 'signature' => 1,
263 - 'rating' => 1,
264 - 'rating_title' => 1,
265 - 'member_cashe' => 1,
266 - 'object_cashe' => 1,
267 - 'html_cashe' => 0,
268 - 'memory_cashe' => 1,
269 - 'seo-title' => 1,
270 - 'seo-meta' => 1,
271 - 'seo-profile' => 1,
272 - 'rss-feed' => 1,
273 - 'font-awesome' => 1,
274 - 'user-synch' => 0,
275 - 'bp_profile' => 0,
276 - 'bp_activity' => 1,
277 - 'bp_notification' => 1,
278 - 'bp_forum_tab' => 1,
279 - 'output-buffer' => 1,
280 - 'wp-date-format' => 0,
281 - 'subscribe_conf' => 1,
282 - 'subscribe_checkbox_on_post_editor' => 1,
283 - 'subscribe_checkbox_default_status' => 0,
284 - 'attach-media-lib' => 1,
285 - 'debug-mode' => 0,
286 - 'copyright' => 1
287 - );
288 -
289 - $this->default->tools_antispam = array(
290 - 'spam_filter' => 1,
291 - 'spam_filter_level_topic' => mt_rand(30, 60),
292 - 'spam_filter_level_post' => mt_rand(30, 60),
293 - 'spam_user_ban' => 0,
294 - 'new_user_max_posts' => 5,
295 - 'spam_user_ban_notification' => 1,
296 - 'min_number_post_to_attach' => 3,
297 - 'min_number_post_to_link' => 0,
298 - 'spam_file_scanner' => 1,
299 - 'limited_file_ext' => 'pdf|doc|docx|txt|htm|html|rtf|xml|xls|xlsx|zip|rar|tar|gz|bzip|7z',
300 - 'exclude_file_ext' => 'pdf|doc|docx|txt',
301 - 'rc_site_key' => '',
302 - 'rc_secret_key' => '',
303 - 'rc_theme' => 'light',
304 - 'rc_login_form' => 0,
305 - 'rc_reg_form' => 0,
306 - 'rc_lostpass_form' => 0,
307 - 'rc_wpf_login_form' => 1,
308 - 'rc_wpf_reg_form' => 1,
309 - 'rc_wpf_lostpass_form' => 1,
310 - 'rc_topic_editor' => 1,
311 - 'rc_post_editor' => 1,
312 - 'html' => 'embed(src width height name pluginspage type wmode allowFullScreen allowScriptAccess flashVars),',
313 - );
314 -
315 - $this->default->tools_cleanup = array(
316 - 'user_reg_days_ago' => 7,
317 - 'auto_cleanup_users' => 0,
318 - 'usergroup' => array ( 1 => '0', 5 => '0', 2 => '1', 3 => '0' )
319 - );
320 -
321 - $this->default->tools_misc = array(
322 - 'dofollow' => '',
323 - 'noindex' => ''
324 - );
325 -
326 - $this->default->tools_legal = array(
327 - 'rules_checkbox' => 0,
328 - 'rules_text' => NULL,
329 - 'page_terms' => '',
330 - 'page_privacy' => '',
331 - 'forum_privacy_text' => NULL,
332 - 'checkbox_terms_privacy' => 0,
333 - 'checkbox_email_password' => 1,
334 - 'checkbox_forum_privacy' => 0,
335 - 'checkbox_fb_login' => 1,
336 - 'contact_page_url' => NULL,
337 - 'cookies' => 1
338 - );
339 -
340 - $this->default->stats = array(
341 - 'forums' => 0,
342 - 'topics' => 0,
343 - 'posts' => 0,
344 - 'members' => 0,
345 - 'online_members_count' => 0,
346 - 'last_post_title' => '',
347 - 'last_post_url' => '',
348 - 'newest_member_dname' => '',
349 - 'newest_member_profile_url' => ''
350 - );
351 - }
352 -
353 - private function init_options(){
354 - $permalink_structure = get_option('permalink_structure');
355 -
356 - $this->use_trailing_slashes = ( '/' == substr($permalink_structure, -1, 1) );
357 -
358 - //OPTIONS
359 - $this->use_home_url = get_wpf_option('wpforo_use_home_url', $this->default->use_home_url);
360 - $this->excld_urls = get_wpf_option('wpforo_excld_urls', $this->default->excld_urls);
361 -
362 - $this->permastruct = trim( get_wpf_option('wpforo_permastruct', $this->default->permastruct), '/' );
363 - $this->permastruct = preg_replace('#^/?index\.php/?#isu', '', $this->permastruct);
364 - $this->permastruct = trim($this->permastruct, '/');
365 -
366 - $this->base_permastruct = (!$this->use_home_url ? $this->permastruct : '');
367 - $this->base_permastruct = rtrim( ( strpos($permalink_structure, 'index.php') !== FALSE ? '/index.php/' . $this->base_permastruct : '/' . $this->base_permastruct ), '/\\' );
368 - $this->url = esc_url( home_url( $this->user_trailingslashit($this->base_permastruct) ) );
369 - $this->pageid = get_wpf_option( 'wpforo_pageid');
370 -
371 - $this->general_options = get_wpf_option( 'wpforo_general_options', $this->default->general_options);
372 - $this->features = get_wpf_option('wpforo_features', $this->default->features);
373 - $this->tools_antispam = get_wpf_option('wpforo_tools_antispam', $this->default->tools_antispam);
374 - $this->tools_cleanup = get_wpf_option('wpforo_tools_cleanup', $this->default->tools_cleanup);
375 - $this->tools_misc = get_wpf_option('wpforo_tools_misc', $this->default->tools_misc);
376 - $this->tools_legal = get_wpf_option('wpforo_tools_legal', $this->default->tools_legal);
377 -
378 - //CONSTANTS
379 - define('WPFORO_BASE_PERMASTRUCT', $this->base_permastruct );
380 - define('WPFORO_BASE_URL', $this->url );
381 - }
382 -
383 - private function setup(){
384 - if( wpforo_is_admin() ){
385 - register_activation_hook($this->basename, 'do_wpforo_activation');
386 - register_deactivation_hook($this->basename, 'do_wpforo_deactivation');
387 - }
388 - }
389 -
390 - public function user_trailingslashit($url) {
391 - $rtrimed_url = '';
392 - $url_append_vars = '';
393 - if( preg_match('#(^.+?)(/?\?.*$|$)#isu', $url, $match) ){
394 - if(isset($match[1]) && $match[1]) $rtrimed_url = rtrim($match[1], '/\\');
395 - if(isset($match[2]) && $match[2]) $url_append_vars = trim($match[2], '/\\');
396 - if( $rtrimed_url ) {
397 - $home_url = rtrim( preg_replace('#/?\?.*$#isu', '', home_url()), '/\\' );
398 - if( $rtrimed_url == $home_url ){
399 - $url = $rtrimed_url . '/';
400 - }else{
401 - $url = ( $this->use_trailing_slashes ? $rtrimed_url . '/' : $rtrimed_url );
402 - }
403 - }
404 - }
405 - return $url . $url_append_vars;
406 - }
407 -
408 - public function statistic( $mode = 'get', $template = 'all' ){
409 -
410 - if( $mode == 'get' ){
411 - if( $cached_stat = get_option('wpforo_stat' ) ){
412 - $cached_stat['online_members_count'] = $this->member->online_members_count();
413 - return $cached_stat;
414 - }
415 - }
416 -
417 - if( $mode == 'get' || $template == 'all' ) {
418 - $stats['forums'] = $this->forum->get_count( array('is_cat' => 0) );
419 - $stats['topics'] = $this->topic->get_count();
420 - $stats['posts'] = $this->post->get_count();
421 - $stats['members'] = $this->member->get_count();
422 - $stats['online_members_count'] = $this->member->online_members_count();
423 -
424 - $posts = $this->topic->get_topics(array('orderby' => 'modified', 'order' => 'DESC', 'row_count' => 20, 'private' => 0, 'status' => 0, 'permgroup' => 4 ));
425 - $first = key($posts);
426 - if ( isset($posts[$first]) && !empty($posts[$first]) && $this->perm->forum_can('vf', $posts[$first]['forumid'], 4) ) {
427 - $stats['last_post_title'] = $posts[$first]['title'];
428 - $stats['last_post_url'] = $this->post->get_post_url($posts[$first]['last_post']);
429 - }
430 -
431 - $members = $this->member->get_members(array('orderby' => 'userid', 'order' => 'DESC', 'row_count' => 1));
432 - if (isset($members[0]) && !empty($members[0])) {
433 - $stats['newest_member_dname'] = wpforo_make_dname($members[0]['display_name'], $members[0]['user_nicename']);
434 - $stats['newest_member_profile_url'] = $this->member->get_profile_url($members[0]['ID']);
435 - }
436 - }else{
437 - $stats = get_wpf_option('wpforo_stat', $this->default->stats);
438 - switch ($template){
439 - case 'forum':
440 - $stats['forums'] = $this->forum->get_count( array('is_cat' => 0) );
441 - break;
442 - case 'topic':
443 - $stats['topics'] = $this->topic->get_count();
444 - $posts = $this->topic->get_topics(array('orderby' => 'modified', 'order' => 'DESC', 'row_count' => 1));
445 - if ( isset($posts[0]) && !empty($posts[0]) && $this->perm->forum_can('vf', $posts[0]['forumid']) ) {
446 - $stats['last_post_title'] = $posts[0]['title'];
447 - $stats['last_post_url'] = $this->post->get_post_url($posts[0]['last_post']);
448 - }
449 - break;
450 - case 'post':
451 - $stats['posts'] = $this->post->get_count();
452 - $posts = $this->topic->get_topics(array('orderby' => 'modified', 'order' => 'DESC', 'row_count' => 1));
453 - if ( isset($posts[0]) && !empty($posts[0]) && $this->perm->forum_can('vf', $posts[0]['forumid']) ) {
454 - $stats['last_post_title'] = $posts[0]['title'];
455 - $stats['last_post_url'] = $this->post->get_post_url($posts[0]['last_post']);
456 - }
457 - break;
458 - case 'user':
459 - $stats['members'] = $this->member->get_count();
460 - $stats['online_members_count'] = $this->member->online_members_count();
461 -
462 - $members = $this->member->get_members(array('orderby' => 'userid', 'order' => 'DESC', 'row_count' => 1));
463 - if (isset($members[0]) && !empty($members[0])) {
464 - $stats['newest_member_dname'] = wpforo_make_dname($members[0]['display_name'], $members[0]['user_nicename']);
465 - $stats['newest_member_profile_url'] = $this->member->get_profile_url($members[0]['ID']);
466 - }
467 - break;
468 - }
469 - }
470 -
471 - $stats = array_merge($this->default->stats, $stats);
472 - $stats = apply_filters('wpforo_get_statistic_array_filter', $stats);
473 - update_option( 'wpforo_stat', $stats );
474 - return $stats;
475 - }
476 -
477 - public function init_current_object($url = ''){
478 - $this->current_object = array('template' => '', 'paged' => 1, 'is_404' => false, 'user_is_same_current_user' => false);
479 - if(!$url) $url = wpforo_get_request_uri();
480 -
481 - if( !is_wpforo_page($url) ) return;
482 -
483 - $this->current_url = $url;
484 - $current_url = wpforo_get_url_query_vars_str($url);
485 -
486 - if( $this->use_home_url ) $this->permastruct = '';
487 -
488 - $current_object = array();
489 - $current_object['template'] = '';
490 - $current_object['is_404'] = false;
491 - $current_object['user_is_same_current_user'] = false;
492 -
493 - if(isset($_GET['wpfs'])) $current_object['template'] = 'search';
494 - if( isset($_GET['wpforo']) ){
495 - switch($_GET['wpforo']){
496 - case 'signup':
497 - if(!is_user_logged_in()) $current_object['template'] = 'register';
498 - break;
499 - case 'signin':
500 - if(!is_user_logged_in()) $current_object['template'] = 'login';
501 - break;
502 - case 'lostpassword':
503 - if(!is_user_logged_in()) $current_object['template'] = 'lostpassword';
504 - break;
505 - case 'resetpassword':
506 - $current_object['template'] = 'resetpassword';
507 - break;
508 - case 'page':
509 - $current_object['template'] = 'page';
510 - break;
511 - case 'logout':
512 - wp_logout();
513 - wp_redirect( wpforo_home_url( preg_replace('#\?.*$#is', '', wpforo_get_request_uri()) ) );
514 - exit();
515 - break;
516 - }
517 - }
518 -
519 - $wpf_url = preg_replace( '#^/?'.preg_quote($this->permastruct).'#isu', '' , $current_url, 1 );
520 - $wpf_url = preg_replace('#/?\?.*$#isu', '', $wpf_url);
521 - $wpf_url_parse = array_filter( explode('/', trim($wpf_url, '/')) );
522 - $wpf_url_parse = array_reverse($wpf_url_parse);
523 -
524 - if(in_array('paged', $wpf_url_parse)){
525 - foreach($wpf_url_parse as $key => $value){
526 - if( $value == 'paged'){
527 - unset($wpf_url_parse[$key]);
528 - break;
529 - }
530 - if(is_numeric($value)) $paged = intval($value);
531 -
532 - unset($wpf_url_parse[$key]);
533 - }
534 - }
535 - if(isset($_GET['wpfpaged']) && intval($_GET['wpfpaged'])) $paged = intval($_GET['wpfpaged']);
536 - $current_object['paged'] = (isset($paged) && $paged) ? $paged : 1;
537 -
538 - $wpf_url_parse = array_values($wpf_url_parse);
539 -
540 - if( !isset($current_object['template']) || !$current_object['template'] )
541 - $current_object = apply_filters('wpforo_before_init_current_object', $current_object, $wpf_url_parse);
542 -
543 - if( !isset($current_object['template']) || !$current_object['template'] ) {
544 - if(in_array('members', $wpf_url_parse) && $wpf_url_parse[0] == 'members'){
545 - $current_object['template'] = 'members';
546 - }elseif(in_array('recent', $wpf_url_parse) && $wpf_url_parse[0] == 'recent'){
547 - $current_object['template'] = 'recent';
548 - }elseif(in_array('profile', $wpf_url_parse)){
549 - $current_object['template'] = 'profile';
550 - foreach($wpf_url_parse as $value){
551 - if( $value == 'profile') break;
552 - if(is_numeric($value)) $current_object['userid'] = $value; else $current_object['user_nicename'] = $value;
553 - }
554 - }elseif(in_array('account', $wpf_url_parse)){
555 - $current_object['template'] = 'account';
556 - foreach($wpf_url_parse as $value){
557 - if( $value == 'account') break;
558 - if(is_numeric($value)) $current_object['userid'] = $value; else $current_object['user_nicename'] = $value;
559 - }
560 - }elseif(in_array('activity', $wpf_url_parse)){
561 - $current_object['template'] = 'activity';
562 - foreach($wpf_url_parse as $value){
563 - if( $value == 'activity') break;
564 - if(is_numeric($value)) $current_object['userid'] = $value; else $current_object['user_nicename'] = $value;
565 - }
566 - }elseif(in_array('subscriptions', $wpf_url_parse)){
567 - $current_object['template'] = 'subscriptions';
568 - foreach($wpf_url_parse as $value){
569 - if( $value == 'subscriptions') break;
570 - if(is_numeric($value)) $current_object['userid'] = $value; else $current_object['user_nicename'] = $value;
571 - }
572 - }else{
573 - $current_object['template'] = 'forum';
574 - if( isset($wpf_url_parse[0]) ){
575 - if( isset($wpf_url_parse[1]) ){
576 - $current_object['topic_slug'] = $wpf_url_parse[0];
577 - $current_object['forum_slug'] = $wpf_url_parse[1];
578 - $current_object['template'] = 'post';
579 - }else{
580 - $current_object['forum_slug'] = $wpf_url_parse[0];
581 - $current_object['template'] = 'topic';
582 - }
583 - }
584 - }
585 - }
586 -
587 - if( in_array( $current_object['template'], array('profile', 'account', 'activity', 'subscriptions') )
588 - && !isset($current_object['user_nicename']) && !isset($current_object['userid']) ){
589 - $current_object = wpforo_find_current_user_data( $current_object );
590 - }
591 -
592 - if( isset($current_object['userid']) || isset($current_object['user_nicename']) ){
593 - $args = array();
594 - if(isset($current_object['userid'])) $args['userid'] = $current_object['userid'];
595 - if(isset($current_object['user_nicename'])) $args['user_nicename'] = $current_object['user_nicename'];
596 - $selected_user = $this->member->get_member($args);
597 - if(isset($current_object['userid']) && empty($selected_user)) $selected_user = $this->member->get_member(array('user_nicename' => $current_object['userid']));
598 - if(!empty($selected_user)){
599 - $current_object['user'] = $selected_user;
600 - $current_object['userid'] = $selected_user['ID'];
601 - $current_object['user_nicename'] = $selected_user['user_nicename'];
602 - $current_object['user_is_same_current_user'] = !empty($this->current_userid) && $selected_user['ID'] == $this->current_userid;
603 -
604 - switch($current_object['template']){
605 - case 'activity':
606 - $args = array(
607 - 'offset' => ($current_object['paged'] - 1) * $this->post->options['posts_per_page'],
608 - 'row_count' => $this->post->options['posts_per_page'],
609 - 'userid' => $current_object['userid'],
610 - 'orderby' => '`created` DESC, `postid` DESC',
611 - 'check_private' => true
612 - );
613 - $current_object['items_count'] = 0;
614 - $current_object['activities'] = $this->post->get_posts( $args, $current_object['items_count']);
615 - break;
616 - case 'subscriptions':
617 - $args = array(
618 - 'offset' => ($current_object['paged'] - 1) * $this->post->options['posts_per_page'],
619 - 'row_count' => $this->post->options['posts_per_page'],
620 - 'userid' => $current_object['userid'],
621 - 'order' => 'DESC'
622 - );
623 - $current_object['items_count'] = 0;
624 - $current_object['subscribes'] = $this->sbscrb->get_subscribes( $args, $current_object['items_count']);
625 - break;
626 - }
627 -
628 - }else{
629 - $current_object['is_404'] = true;
630 - $current_object['user'] = array();
631 - $current_object['userid'] = 0;
632 - $current_object['user_nicename'] = '';
633 - }
634 - }
635 -
636 - if(isset($current_object['forum_slug']) && $current_object['forum_slug']){
637 - $forum = $this->forum->get_forum( array('slug' => $current_object['forum_slug']) );
638 - if(!empty($forum)){
639 - $current_object['forum'] = $forum;
640 - $current_object['forumid'] = $forum['forumid'];
641 - $current_object['forum_desc'] = $forum['description'];
642 - $current_object['forum_meta_key'] = $forum['meta_key'];
643 - $current_object['forum_meta_desc'] = $forum['meta_desc'];
644 - $current_object['og_text'] = $forum['title'];
645 - }else{
646 - $current_object['is_404'] = true;
647 - $current_object['forum'] = array();
648 - $current_object['forumid'] = 0;
649 - $current_object['forum_desc'] = '';
650 - $current_object['forum_meta_key'] = '';
651 - $current_object['forum_meta_desc'] = '';
652 - $current_object['og_text'] = '';
653 - }
654 - }
655 -
656 - if(isset($current_object['topic_slug']) && $current_object['topic_slug']){
657 - $topic = $this->topic->get_topic(array('slug' => $current_object['topic_slug']));
658 - if(!empty($topic)){
659 - $current_object['topic'] = $topic;
660 - $current_object['topicid'] = $topic['topicid'];
661 - $current_object['og_text'] = ( wpfval($topic, 'title') ? $topic['title'] : '' );
662 - }elseif( $this->current_object['status'] == 'unapproved' && !is_user_logged_in() ){
663 - wp_redirect( wpforo_login_url() );
664 - exit();
665 - }else{
666 - $current_object['is_404'] = true;
667 - $current_object['topic'] = array();
668 - $current_object['topicid'] = 0;
669 - }
670 - }
671 -
672 - $this->current_object = apply_filters('wpforo_after_init_current_object', $current_object, $wpf_url_parse);
673 - }
674 -
675 - public function is_installed(){
676 - return (bool) get_option('wpforo_version');
677 - }
678 - }
679 -
680 - /**
681 - * Main instance of wpForo.
682 - *
683 - * Returns the main instance of WPF to prevent the need to use globals.
684 - *
685 - * @since 1.4.3
686 - * @return wpForo
687 - */
688 - if ( !function_exists('WPF') ){
689 - function WPF() {
690 - return wpForo::instance();
691 - }
692 - }
693 -
694 - // Global for backwards compatibility.
695 - $GLOBALS['wpforo'] = WPF();
696 -
697 - //ADDONS/////////////////////////////////////////////////////
698 - WPF()->addons = array(
699 - 'embeds' => array('version' => '1.0.4', 'requires' => '1.4.0', 'class' => 'wpForoEmbeds', 'title' => 'Embeds', 'thumb' => WPFORO_URL . '/wpf-assets/addons/' . 'embeds' . '/header.png', 'desc' => __('Allows to embed hundreds of video, social network, audio and photo content providers in forum topics and posts.', 'wpforo'), 'url' => 'https://gvectors.com/product/wpforo-embeds/'),
700 - 'polls' => array('version' => '1.0.0', 'requires' => '1.4.3', 'class' => 'wpForoPoll', 'title' => 'Polls', 'thumb' => WPFORO_URL . '/wpf-assets/addons/' . 'polls' . '/header.png', 'desc' => __('wpForo Polls is a complete addon to help forum members create, vote and manage polls effectively. Comes with poll specific permissions and settings.', 'wpforo'), 'url' => 'https://gvectors.com/product/wpforo-polls/'),
701 - 'mycred' => array('version' => '1.0.0', 'requires' => '1.4.3', 'class' => 'myCRED_Hook_wpForo', 'title' => 'MyCRED Integration', 'thumb' => WPFORO_URL . '/wpf-assets/addons/' . 'mycred' . '/header.png', 'desc' => __('Awards myCRED points for forum activity. Integrates myCRED Badges and Ranks. Converts wpForo topic and posts, likes to myCRED points.', 'wpforo'), 'url' => 'https://gvectors.com/product/wpforo-mycred/'),
702 - 'ucf' => array('version' => '1.0.0', 'requires' => '1.4.0', 'class' => 'WpforoUcf', 'title' => 'User Custom Fields', 'thumb' => WPFORO_URL . '/wpf-assets/addons/' . 'ucf' . '/header.png', 'desc' => __('Advanced user profile builder system. Allows to add new fields and manage profile page. Creates custom Registration, Account, Member Search forms.', 'wpforo'), 'url' => 'https://gvectors.com/product/wpforo-user-custom-fields/'),
703 - 'attachments' => array('version' => '1.1.2', 'requires' => '1.4.0', 'class' => 'wpForoAttachments', 'title' => 'Advanced Attachments', 'thumb' => WPFORO_URL . '/wpf-assets/addons/' . 'attachments' . '/header.png', 'desc' => __('Adds an advanced file attachment system to forum topics and posts. AJAX powered media uploading and displaying system with user specific library.', 'wpforo'), 'url' => 'https://gvectors.com/product/wpforo-advanced-attachments/'),
704 - 'pm' => array('version' => '1.0.3', 'requires' => '1.4.0', 'class' => 'wpForoPMs', 'title' => 'Private Messages', 'thumb' => WPFORO_URL . '/wpf-assets/addons/' . 'pm' . '/header.png', 'desc' => __('Provides a safe way to communicate directly with other members. Messages are private and can only be viewed by conversation participants.', 'wpforo'), 'url' => 'https://gvectors.com/product/wpforo-private-messages/'),
705 - 'cross' => array('version' => '1.0.3', 'requires' => '1.4.0', 'class' => 'wpForoCrossPosting', 'title' => '"Forum - Blog" Cross Posting', 'thumb' => WPFORO_URL . '/wpf-assets/addons/' . 'cross' . '/header.png', 'desc' => __('Blog to Forum and Forum to Blog content synchronization. Blog posts with Forum topics and Blog comments with Forum replies.', 'wpforo'), 'url' => 'https://gvectors.com/product/wpforo-cross-posting/'),
706 - 'ad-manager' => array('version' => '1.0.0', 'requires' => '1.4.0', 'class' => 'wpForoAD', 'title' => 'Ads Manager', 'thumb' => WPFORO_URL . '/wpf-assets/addons/' . 'ad-manager' . '/header.png', 'desc' => __('Ads Manager is a powerful yet simple advertisement management system, that allows you to add adverting banners between forums, topics and posts.', 'wpforo'), 'url' => 'https://gvectors.com/product/wpforo-ad-manager/'),
707 - );
708 - $wp_version = get_bloginfo('version'); if (version_compare($wp_version, '4.2.0', '>=')) { add_action('wp_ajax_dismiss_wpforo_addon_note', array(WPF()->notice, 'dismissAddonNote')); add_action('admin_notices', array(WPF()->notice, 'addonNote'));}
709 - /////////////////////////////////////////////////////////////
710 -}
1 +<?php
2 +/*
3 +* Plugin Name: wpForo
4 +* Plugin URI: https://wpforo.com
5 +* Description: WordPress Forum plugin. wpForo is the only AI powered forum solution for your community. Modern design and 5 forum layouts.
6 +* Author: gVectors Team
7 +* Author URI: https://gvectors.com/
8 +* Version: 3.1.6
9 +* Requires at least: 5.2
10 +* Requires PHP: 7.1
11 +* Text Domain: wpforo
12 +* Domain Path: /languages
13 +*/
14 +
15 +namespace wpforo;
16 +
17 +define( 'WPFORO_VERSION', '3.1.6' );
18 +
19 +//Exit if accessed directly
20 +if( ! defined( 'ABSPATH' ) ) exit;
21 +
22 +define( 'WPFORO_DIR', rtrim( plugin_dir_path( __FILE__ ), '/' ) );
23 +define( 'WPFORO_URL', rtrim( plugins_url( '', __FILE__ ), '/' ) );
24 +define( 'WPFORO_BASENAME', plugin_basename( __FILE__ ) ); //wpforo/wpforo.php
25 +
26 +require_once WPFORO_DIR . "/autoload.php";
27 +
28 +use stdClass;
29 +use wpdb;
30 +use wpforo\classes\Actions;
31 +use wpforo\classes\Activity;
32 +use wpforo\classes\AIChatbot;
33 +use wpforo\classes\AIClient;
34 +use wpforo\classes\AIContentModeration;
35 +use wpforo\classes\AILogs;
36 +use wpforo\classes\AIWordPressIndexer;
37 +use wpforo\classes\API;
38 +use wpforo\classes\Blocks;
39 +use wpforo\classes\Boards;
40 +use wpforo\classes\Cache;
41 +use wpforo\classes\Feed;
42 +use wpforo\classes\Forms;
43 +use wpforo\classes\Forums;
44 +use wpforo\classes\Logs;
45 +use wpforo\classes\Members;
46 +use wpforo\classes\Moderation;
47 +use wpforo\classes\Notices;
48 +use wpforo\classes\Permissions;
49 +use wpforo\classes\Phrases;
50 +use wpforo\classes\PostMeta;
51 +use wpforo\classes\Posts;
52 +use wpforo\classes\RamCache;
53 +use wpforo\classes\SEO;
54 +use wpforo\classes\Settings;
55 +use wpforo\classes\TaskManager;
56 +use wpforo\classes\EmailQueue;
57 +use wpforo\classes\Template;
58 +use wpforo\classes\Topics;
59 +use wpforo\classes\VectorStorageManager;
60 +use wpforo\classes\UserGroups;
61 +use wpforo\modules\bookmarks\Bookmarks;
62 +use wpforo\modules\reactions\Reactions;
63 +use wpforo\modules\revisions\Revisions;
64 +use wpforo\modules\subscriptions\Subscriptions;
65 +
66 +final class wpforo {
67 + private static $_instance = null;
68 +
69 + /** @var wpdb * */
70 + public $db;
71 + public $default;
72 +
73 + public $blog_prefix = "wp_";
74 + public $base_prefix = "wpforo_";
75 + public $prefix = "wpforo_";
76 + public $_base_tables = [
77 + 'boards',
78 + 'usergroups',
79 + 'profiles',
80 + 'logs',
81 + 'follows',
82 + 'bookmarks',
83 + 'accesses',
84 + 'email_queue',
85 + ];
86 + public $_tables = [
87 + 'activity',
88 + 'ai_cache',
89 + 'ai_chat_conversations',
90 + 'ai_chat_messages',
91 + 'ai_embeddings',
92 + 'ai_embeddings_cache',
93 + 'ai_logs',
94 + 'ai_moderation',
95 + 'ai_tasks',
96 + 'ai_task_logs',
97 + 'forums',
98 + 'languages',
99 + 'phrases',
100 + 'postmeta',
101 + 'posts',
102 + 'post_revisions',
103 + 'subscribes',
104 + 'topics',
105 + 'tags',
106 + 'visits',
107 + 'reactions',
108 + ];
109 + public $tables;
110 + private $_folders = [
111 + 'assets',
112 + 'attachments',
113 + 'avatars',
114 + 'covers',
115 + 'cache',
116 + 'default_attachments',
117 + 'emoticons',
118 + ];
119 + public $folders = [];
120 +
121 + public $current_url;
122 + public $canonical_url;
123 + public $GET = [];
124 + public $current_object;
125 +
126 + public $wp_current_user = null;
127 + public $current_user = [];
128 + public $current_usermeta = [];
129 + public $current_user_groupid = 4;
130 + public $current_user_groupids = [ 4 ];
131 + public $current_user_secondary_groupids = [];
132 + public $current_userid = 0;
133 + public $current_user_login = '';
134 + public $current_user_email = '';
135 + public $current_user_display_name = '';
136 + public $current_user_status = '';
137 + public $current_user_accesses = [];
138 + public $session_token = '';
139 +
140 + public $tools_cleanup;
141 + public $tools_misc;
142 + public $locale = 'en_US';
143 +
144 + public $dissmissed;
145 +
146 + /** @var Settings */
147 + public $settings;
148 + /** @var Actions */
149 + public $action;
150 + /** @var Activity */
151 + public $activity;
152 + /** @var API */
153 + public $api;
154 + /** @var AIClient */
155 + public $ai_client;
156 + /** @var AIChatbot */
157 + public $ai_chatbot;
158 + /** @var VectorStorageManager */
159 + public $vector_storage;
160 + /** @var TaskManager */
161 + public $task_manager;
162 + /** @var AIContentModeration */
163 + public $ai_content_moderation;
164 + /** @var AILogs */
165 + public $ai_logs;
166 + /** @var AIWordPressIndexer */
167 + public $ai_wp_indexer;
168 + /** @var Boards */
169 + public $board;
170 + /** @var Cache */
171 + public $cache;
172 + /** @var Feed */
173 + public $feed;
174 + /** @var Forms */
175 + public $form;
176 + /** @var Forums */
177 + public $forum;
178 + /** @var Logs */
179 + public $log;
180 + /** @var Members */
181 + public $member;
182 + /** @var Moderation */
183 + public $moderation;
184 + /** @var Notices */
185 + public $notice;
186 + /** @var Permissions */
187 + public $perm;
188 + /** @var Phrases */
189 + public $phrase;
190 + /** @var PostMeta */
191 + public $postmeta;
192 + /** @var Posts */
193 + public $post;
194 + /** @var Blocks */
195 + public $blocks;
196 + /** @var RamCache */
197 + public $ram_cache;
198 + /** @var Revisions */
199 + public $revision;
200 + /** @var Reactions */
201 + public $reaction;
202 + /** @var Bookmarks */
203 + public $bookmark;
204 + /** @var SEO */
205 + public $seo;
206 + /** @var Subscriptions */
207 + public $sbscrb;
208 + /** @var EmailQueue */
209 + public $email_queue;
210 + /** @var Template */
211 + public $tpl;
212 + /** @var Topics */
213 + public $topic;
214 + /** @var UserGroups */
215 + public $usergroup;
216 +
217 + public static function instance() {
218 + if( is_null( self::$_instance ) ) self::$_instance = new self();
219 +
220 + return self::$_instance;
221 + }
222 +
223 + private function init_db() {
224 + global $wpdb;
225 + $this->db = $wpdb;
226 + }
227 +
228 + public function is_db_mysql8() {
229 + if( preg_match( '#([\d.]+)-MariaDB#iu', (string) $this->db->get_var( "SELECT VERSION()" ), $match ) ) {
230 + $use_mysql8 = version_compare( $match[1], '10.2.6', '>=' );
231 + } else {
232 + $use_mysql8 = version_compare( $this->db->db_version(), '8.0.0', '>=' );
233 + }
234 +
235 + return apply_filters( 'wpforo_use_mysql8', $use_mysql8 );
236 + }
237 +
238 + private function __construct() {
239 + $this->init_db();
240 + $this->init_hooks();
241 + }
242 +
243 + public function generate_prefix( $boardid ) {
244 + $boardid = intval( $boardid );
245 +
246 + return $this->base_prefix . ( $boardid ? $boardid . '_' : '' );
247 + }
248 +
249 + private function init_prefix() {
250 + $boardid = $this->board->get_current( 'boardid' );
251 + $this->prefix = $this->generate_prefix( $boardid );
252 + }
253 +
254 + public function change_board( $args = [] ) {
255 + if( is_null( $this->board ) ) return;
256 +
257 + do_action( 'wpforo_before_change_board', $args );
258 +
259 + $boardid = $this->board->get_current( 'boardid' );
260 + $is_inited = (bool) wpfval( $this->board->is_inited, $boardid );
261 + $this->board->init_current( $args );
262 +
263 + if( ! $is_inited || $boardid !== $this->board->get_current( 'boardid' ) ) {
264 + $this->ram_cache->reset();
265 +
266 + $this->init_prefix();
267 + $this->init_tables();
268 + $this->init_folders();
269 + $this->init_options();
270 +
271 + do_action( 'wpforo_after_change_board', $args );
272 + }
273 + }
274 +
275 + private function init_base_classes() {
276 + $this->requires();
277 + $this->init_defaults();
278 + $this->reset_current_object();
279 + $this->init_base_tables();
280 + $this->init_folders();
281 +
282 + do_action( 'wpforo_before_init_base_classes' );
283 +
284 + $this->settings = new Settings();
285 + $this->tpl = new Template();
286 + $this->ram_cache = new RamCache();
287 + $this->cache = new Cache();
288 + $this->action = new Actions();
289 + $this->board = new Boards();
290 + $this->usergroup = new UserGroups();
291 + $this->member = new Members();
292 + $this->perm = new Permissions();
293 + $this->notice = new Notices();
294 +
295 + $this->moderation = new Moderation();
296 + $this->phrase = new Phrases();
297 + $this->blocks = new Blocks();
298 +
299 + do_action( 'wpforo_after_init_base_classes' );
300 + }
301 +
302 + private function init_classes() {
303 + do_action( 'wpforo_before_init_classes' );
304 +
305 + $this->activity = new Activity();
306 + $this->api = new API();
307 + // AIClient: Initialize globally for both admin and front-end features
308 + // (semantic search, antispam, auto-translation, etc.)
309 + $this->ai_client = new AIClient();
310 + // AIChatbot: AI-powered chat functionality in AI Assistant widget
311 + $this->ai_chatbot = new AIChatbot();
312 + // VectorStorageManager: Unified abstraction for vector storage (local/cloud)
313 + $this->vector_storage = new VectorStorageManager();
314 + // TaskManager: Initialize for AI task scheduling and execution
315 + $this->task_manager = new TaskManager();
316 + // AIContentModeration: Central class for AI-powered content moderation
317 + $this->ai_content_moderation = AIContentModeration::get_instance();
318 + // AILogs: Logging of all AI actions for admin visibility
319 + $this->ai_logs = new AILogs();
320 + // AIWordPressIndexer: WordPress content type indexing for AI search
321 + $this->ai_wp_indexer = new AIWordPressIndexer();
322 + $this->feed = new Feed();
323 + $this->form = new Forms();
324 + $this->forum = new Forums();
325 + $this->log = new Logs();
326 + $this->postmeta = new PostMeta();
327 + $this->post = new Posts();
328 + $this->seo = new SEO();
329 + $this->topic = new Topics();
330 + $this->reaction = new Reactions();
331 + $this->bookmark = new Bookmarks();
332 + $this->sbscrb = new Subscriptions();
333 + $this->email_queue = new EmailQueue();
334 + if( wpforo_is_module_enabled( 'revisions' ) ) $this->revision = new Revisions();
335 +
336 + do_action( 'wpforo_after_init_classes' );
337 + }
338 +
339 + public function set_locale( $locale ) {
340 + $this->locale = $locale;
341 + do_action( 'wpforo_after_set_locale', $locale );
342 + }
343 +
344 + private function init_hooks() {
345 + add_action( 'wpforo_after_init_folders', function( $folders ) {
346 + $this->create_folders( $folders );
347 + }, 9999 );
348 + add_action(
349 + 'after_setup_theme',
350 + function() {
351 + do_action( 'wpforo_before_base_init' );
352 + $this->init_base_classes();
353 + if( ! $this->is_installed() ) $this->init();
354 + },
355 + 0
356 + );
357 + add_action( 'change_locale', [ $this, 'set_locale' ] );
358 + add_action( 'init', function() { $this->set_locale( get_locale() ); } );
359 + add_action( 'widgets_init', function() {
360 + $boards = $this->board->get_boards( [ 'status' => true ] );
361 + foreach( $boards as $board ) {
362 + register_sidebar(
363 + [
364 + 'id' => sprintf(
365 + 'wpforo_%1$ssidebar',
366 + $board['boardid'] ? $board['boardid'] . '_' : ''
367 + ),
368 + 'name' => __( 'wpForo Sidebar', 'wpforo' ) . ' - ( ' . $board['title'] . ' )',
369 + 'description' => __( "NOTE: If you're going to add widgets in this sidebar, please use 'Full Width' template for wpForo index page to avoid sidebar duplication.", 'wpforo' ),
370 + 'before_widget' => '<aside id="%1$s" class="footer-widget-col %2$s clearfix">',
371 + 'after_widget' => '</aside>',
372 + 'before_title' => '<h3 class="widget-title">',
373 + 'after_title' => '</h3>',
374 + ]
375 + );
376 + }
377 +
378 + register_widget( 'wpforo\widgets\Forums' );
379 + register_widget( 'wpforo\widgets\Profile' );
380 + register_widget( 'wpforo\widgets\Search' );
381 + register_widget( 'wpforo\widgets\OnlineMembers' );
382 + register_widget( 'wpforo\widgets\RecentTopics' );
383 + register_widget( 'wpforo\widgets\RecentPosts' );
384 + register_widget( 'wpforo\widgets\Tags' );
385 + } );
386 + add_filter( 'plugin_locale', function( $locale, $domain ) {
387 + if( $domain === 'wpforo' && defined( 'DOING_AJAX' ) && DOING_AJAX ) $locale = $this->locale;
388 +
389 + return $locale;
390 + }, 10, 2 );
391 + add_action( 'wpforo_after_init_classes', function() {
392 + if( wpforo_setting( 'email', 'disable_new_user_admin_notification' ) ) {
393 + remove_action( 'after_password_reset', 'wp_password_change_notification' );
394 +
395 + remove_action( 'register_new_user', 'wp_send_new_user_notifications' );
396 + add_action( 'register_new_user', 'wpforo_send_new_user_notifications' );
397 +
398 + remove_action( 'edit_user_created_user', 'wp_send_new_user_notifications' );
399 + add_action( 'edit_user_created_user', 'wpforo_send_new_user_notifications', 10, 2 );
400 +
401 + remove_action( 'network_site_new_created_user', 'wp_send_new_user_notifications' );
402 + add_action( 'network_site_new_created_user', 'wpforo_send_new_user_notifications' );
403 +
404 + remove_action( 'network_site_users_created_user', 'wp_send_new_user_notifications' );
405 + add_action( 'network_site_new_created_user', 'wpforo_send_new_user_notifications' );
406 +
407 + remove_action( 'network_user_new_created_user', 'wp_send_new_user_notifications' );
408 + add_action( 'network_user_new_created_user', 'wpforo_send_new_user_notifications' );
409 + }
410 + } );
411 +
412 + // WP Cron: Ensure classes are initialized early for cron hook callbacks
413 + if ( wp_doing_cron() || isset( $_GET['doing_wp_cron'] ) ) {
414 + add_action( 'init', [ $this, 'init' ], 1 ); // Priority 1 - before cron runs
415 + } elseif( is_admin() || strpos( (string) $_SERVER['REQUEST_URI'], '/peepsoajax/' ) === 0 || preg_match(
416 + '#^/?(?:([^\s/?&=<>:\'\"*\\\|]*/)(?1)*)?[^\s/?&=<>:\'\"*\\\|]+\.(?:php|js|css|jpe?g|png|gif|bmp|webp|svg|tiff)/?(?:\?[^/]*)?$#iu',
417 + (string) $_SERVER['REQUEST_URI']
418 + ) ) {
419 + add_action( 'init', [ $this, 'init' ], 99 );
420 + add_action( 'admin_init', [ $this, 'admin_init' ] );
421 + } elseif( strpos( (string) $_SERVER['REQUEST_URI'], '/wp-json/' ) !== false ) {
422 + add_filter( 'rest_authentication_errors', function( $r ) {
423 + $this->init();
424 +
425 + return $r;
426 + }, 9999 );
427 + } else {
428 + add_action( 'wp', [ $this, 'init' ], 99 );
429 + }
430 + add_action( 'switch_blog', [ $this, 'after_switch_blog' ], 10, 2 );
431 + add_action( 'wpforo_before_init', [ $this, 'change_board' ] );
432 + add_action( 'wpforo_after_init_current_url', [ $this, 'change_board' ] );
433 + }
434 +
435 + public function after_switch_blog( $new_blog_id, $prev_blog_id ) {
436 + if( intval( $new_blog_id ) !== intval( $prev_blog_id ) ) {
437 + $this->init_base_tables();
438 + $this->init_tables();
439 + $this->init_folders();
440 + }
441 + }
442 +
443 + private function init_base_tables() {
444 + $this->db->query( "SET SESSION group_concat_max_len = 1000000" );
445 + $blog_id = apply_filters( 'wpforo_current_blog_id', 0 );
446 + $this->tables = new stdClass;
447 + if( ! $blog_id ) $blog_id = $this->db->blogid;
448 + $this->blog_prefix = $this->db->get_blog_prefix( $blog_id );
449 + $this->_base_tables = apply_filters( 'wpforo_init_base_tables', $this->_base_tables );
450 + foreach( $this->_base_tables as $table ) $this->tables->$table = $this->fix_table_name( $table );
451 + }
452 +
453 + private function init_tables() {
454 + $this->_tables = apply_filters( 'wpforo_init_tables', $this->_tables );
455 + foreach( $this->_tables as $table ) $this->tables->$table = $this->fix_table_name( $table );
456 + }
457 +
458 + public function get_active_boards_tables( $basename ) {
459 + $tables = [];
460 + if( $boardids = $this->board->get_active_boardids() ) {
461 + foreach( $boardids as $boardid ) $tables[] = $this->fix_table_name( $basename, $this->generate_prefix( $boardid ) );
462 + }
463 +
464 + return array_unique( $tables );
465 + }
466 +
467 + /**
468 + * @param string $basename
469 + *
470 + * @return string
471 + */
472 + public function fix_table_name( $basename, $prefix = null ) {
473 + return $this->blog_prefix . ( in_array( $basename, $this->_base_tables, true ) ? $this->base_prefix : ( is_null( $prefix ) ? $this->prefix : $prefix ) ) . $basename;
474 + }
475 +
476 + public function fix_dir_sep( $dir ) {
477 + $dir = str_replace( [ '/', '\\', '\\\\' ], DIRECTORY_SEPARATOR, $dir );
478 +
479 + return rtrim( trim( (string) $dir ), DIRECTORY_SEPARATOR );
480 + }
481 +
482 + public function fix_url_sep( $url ) {
483 + return trim( str_replace( [ '/', '\\', '\\\\' ], '/', (string) $url ) );
484 + }
485 +
486 + private function init_folders() {
487 + $this->_folders = apply_filters( 'wpforo_init_folders', $this->_folders );
488 + $boardid = ( is_callable( [ $this->board, 'get_current' ] ) ? $this->board->get_current( 'boardid' ) : 0 );
489 + $upload_dir = wp_get_upload_dir();
490 +
491 + // In many cases people leave the website URL protocol as http, but website works with https
492 + // In this case colors.css and phrases.js are not loaded because of http blocking by browser
493 + $upload_dir['baseurl'] = is_ssl() ? str_replace( 'http://', 'https://', $upload_dir['baseurl'] ) : $upload_dir['baseurl'];
494 +
495 + $this->folders['wp_upload'] = [
496 + 'dir' => $this->fix_dir_sep( $upload_dir['basedir'] ),
497 + 'url' => $this->fix_url_sep( $upload_dir['baseurl'] ),
498 + ];
499 + $this->folders['wp_upload']['url//'] = preg_replace( '#^https?:#i', '', (string) $this->folders['wp_upload']['url'] );
500 + $this->folders['upload'] = [
501 + 'dir' => $this->folders['wp_upload']['dir'] . DIRECTORY_SEPARATOR . "wpforo" . ( $boardid ? '_' . $boardid : '' ),
502 + 'url' => $this->folders['wp_upload']['url'] . "/wpforo" . ( $boardid ? '_' . $boardid : '' ),
503 + 'url//' => $this->folders['wp_upload']['url//'] . "/wpforo" . ( $boardid ? '_' . $boardid : '' ),
504 + ];
505 + foreach( $this->_folders as $folder ) {
506 + $this->folders[ $folder ] = [
507 + 'dir' => $this->folders['upload']['dir'] . DIRECTORY_SEPARATOR . trim( $this->fix_dir_sep( (string) $folder ), DIRECTORY_SEPARATOR ),
508 + 'url' => $this->folders['upload']['url'] . "/" . trim( $this->fix_url_sep( (string) $folder ), '/' ),
509 + 'url//' => $this->folders['upload']['url//'] . "/" . trim( $this->fix_url_sep( (string) $folder ), '/' ),
510 + ];
511 + }
512 +
513 + $this->folders = apply_filters( 'wpforo_working_folders', $this->folders );
514 +
515 + do_action( 'wpforo_after_init_folders', $this->folders );
516 + }
517 +
518 + private function create_folders( array $folders = [] ): void {
519 + if( ! $folders ) $folders = WPF()->folders;
520 + foreach( $folders as $folder ) {
521 + $dir = ( is_scalar( $folder ) ? $folder : ( array_key_exists( 'dir', $folder ) ? (string) $folder['dir'] : '' ) );
522 + if( $dir && ! is_dir( $dir ) ) {
523 + if( wp_mkdir_p( $dir ) ) {
524 + wpforo_write_file( "$dir/index.html", "" );
525 + wpforo_write_file( "$dir/robots.txt", "User-agent: *\nDisallow: /" );
526 + }
527 + }
528 + }
529 + }
530 +
531 + private function requires() {
532 + require_once WPFORO_DIR . '/includes/functions.php';
533 + require_once WPFORO_DIR . '/includes/functions-template.php';
534 + require_once WPFORO_DIR . '/includes/hooks.php';
535 + require_once WPFORO_DIR . '/includes/installation.php';
536 + require_once WPFORO_DIR . '/integrations/functions.php';
537 + if( wpforo_is_admin() ) require_once WPFORO_DIR . '/admin/index.php';
538 + }
539 +
540 + public function admin_init() {
541 + if( wpforo_is_admin() ) {
542 + $this->change_board();
543 +
544 + $this->check_issues();
545 +
546 + if( strpos( wpforo_get_request_uri(), 'user-new.php' ) === false ) {
547 + if( ! $this->member->get_groupid( $this->current_userid ) ) {
548 + $this->member->synchronize_user( $this->current_userid );
549 + }
550 + }
551 +
552 + if( ! $this->usergroup->can_manage_forum() && wpforo_current_user_is( 'admin' ) ) {
553 + $this->member->set_groupid( $this->current_userid, 1 );
554 + }
555 + }
556 + }
557 +
558 + public function check_issues() {
559 + //Make sure all users profiles are created
560 + if( $this->is_installed() ) {
561 + if( apply_filters( 'wpforo_profile_synchronization_notice', true ) ) {
562 + if( is_multisite() ) {
563 + $sql = "SELECT COUNT(`user_id`) FROM `" . WPF()->db->usermeta . "` WHERE `meta_key` LIKE '" . WPF(
564 + )->blog_prefix . "capabilities' AND `user_id` NOT IN( SELECT `userid` FROM `" . WPF()->tables->profiles . "` )";
565 + } else {
566 + $sql = "SELECT COUNT(`ID`) as user_id FROM `" . WPF()->db->users . "` WHERE `ID` NOT IN( SELECT `userid` FROM `" . WPF()->tables->profiles . "` )";
567 + }
568 + if( (int) $this->db->get_var( $sql ) ) add_action( 'admin_notices', 'wpforo_profile_notice', 10 );
569 + }
570 + }
571 + //Make sure tables structures are correct for current version
572 + $wpforo_version_db = wpforo_get_option( 'version_db', null, false );
573 + if( ! $wpforo_version_db || version_compare( $wpforo_version_db, WPFORO_VERSION, '<' ) || wpforo_setting( 'general', 'debug_mode' ) ) {
574 + if( 'tables' !== wpfval( $_GET, 'view' ) ) {
575 + $db_note = false;
576 + $problems = wpforo_database_check();
577 + if( ! empty( $problems ) ) {
578 + foreach( $problems as $key => $problem ) {
579 + if( wpfval( $problem, 'fields' ) ) $db_note = true;
580 + if( wpfval( $problem, 'exists' ) ) $db_note = true;
581 + if( $key === 'data' ) $db_note = true;
582 + }
583 + if( $db_note ) {
584 + add_action( 'admin_notices', 'wpforo_database_notice', 10 );
585 + }
586 + } else {
587 + wpforo_update_option( 'version_db', WPFORO_VERSION );
588 + }
589 + }
590 + }
591 + //Check cache plugins
592 + $not_excluded_plugins = WPF()->cache->cache_plugins_status();
593 + if( ! empty( $not_excluded_plugins ) ) {
594 + add_action( 'admin_notices', 'wpforo_cache_information', 10 );
595 + }
596 + }
597 +
598 + public function init() {
599 + do_action( 'wpforo_before_init' );
600 + $this->init_classes();
601 + $this->init_current_url();
602 + do_action( 'wpforo_core_inited' );
603 + $this->init_current_object();
604 + do_action( 'wpforo_after_init' );
605 + }
606 +
607 + public function shortcode_atts_to_url( $atts ) {
608 + if( is_null( $this->forum ) ) $this->init_classes();
609 +
610 + $url = wpforo_home_url();
611 +
612 + $args = shortcode_atts(
613 + [
614 + 'boardid' => 0,
615 + 'item' => 'forum',
616 + 'id' => 0,
617 + 'slug' => '',
618 + ],
619 + (array) $atts
620 + );
621 +
622 + WPF()->change_board( $args['boardid'] );
623 +
624 + if( $args['item'] === 'profile' && ! $args['id'] ) $args['id'] = $this->current_userid;
625 +
626 + if( $args['item'] === 'add-topic' ) {
627 + $forum = $this->forum->get_forum( ( $args['slug'] ?: $args['id'] ) );
628 + $forumid = (int) wpfval( $forum, 'is_cat' ) ? 0 : (int) wpfval( $forum, 'forumid' );
629 + $url = wpforo_home_url( wpforo_settings_get_slug( 'add-topic' ) . '/' . $forumid );
630 + } elseif( $args['item'] === 'recent' ) {
631 + $url = wpforo_settings_get_slug( 'recent' ) . '/';
632 + if( trim( (string) $args['slug'] ) ) $url .= '?view=' . wpforo_settings_get_slug( $args['slug'] );
633 + $url = wpforo_home_url( $url );
634 + } elseif( $args['item'] === 'members' ) {
635 + $url = wpforo_members_url();
636 + } elseif( $args['id'] || $args['slug'] ) {
637 + $getid = ( $args['slug'] ?: $args['id'] );
638 + if( $args['item'] === 'topic' ) {
639 + $url = $this->topic->get_url( $getid );
640 + } elseif( $args['item'] === 'profile' ) {
641 + $url = $this->member->get_profile_url( $getid );
642 + } elseif( $args['item'] === 'account' ) {
643 + $url = $this->member->get_profile_url( $getid, 'account' );
644 + } elseif( $args['item'] === 'activity' ) {
645 + $url = $this->member->get_profile_url( $getid, 'activity' );
646 + } elseif( $args['item'] === 'favored' ) {
647 + $url = $this->member->get_profile_url( $getid, 'favored' );
648 + } elseif( $args['item'] === 'subscriptions' ) {
649 + $url = $this->member->get_profile_url( $getid, 'subscriptions' );
650 + } elseif( $args['item'] === 'messages' ) {
651 + $url = $this->member->get_profile_url( $getid, 'messages' );
652 + } else {
653 + $url = $this->forum->get_forum_url( $getid );
654 + }
655 + } elseif( $args['item'] === 'login' ) {
656 + $url = wpforo_login_url();
657 + } elseif( $args['item'] === 'register' ) {
658 + $url = wpforo_register_url();
659 + } elseif( $args['item'] === 'lostpassword' ) {
660 + $url = wpforo_lostpassword_url();
661 + }
662 +
663 + return $url;
664 + }
665 +
666 + public function init_current_url( $atts = [] ) {
667 + if( is_null( $this->post ) ) $this->init_classes();
668 +
669 + if( is_scalar( $atts ) ) {
670 + $url = $atts;
671 + $atts = [];
672 + } else {
673 + $url = wpforo_get_request_uri();
674 + }
675 + if( $atts || is_wpforo_shortcode_page( $url ) ) {
676 + if( $atts || ( $atts = get_wpforo_shortcode_atts( '', $url ) ) ) {
677 + $url = $this->shortcode_atts_to_url( $atts );
678 + } else {
679 + $url = wpforo_home_url();
680 + }
681 + }
682 +
683 + if( is_wpforo_url( $url ) && preg_match( '#/' . preg_quote( wpforo_settings_get_slug( 'postid' ) ) . '/(\d+)/?$#isu', strtok( $url, '?' ), $matches ) ) {
684 + $post_url = $this->post->get_full_url( $matches[1] );
685 + if( $post_url !== wpforo_home_url() ) {
686 + $url = $post_url;
687 + $this->canonical_url = $this->post->get_url( $matches[1] );
688 + }
689 + } elseif( is_wpforo_url( $url ) && preg_match( '#/' . preg_quote( wpforo_settings_get_slug( 'topicid' ) ) . '/(\d+)/?$#isu', strtok( $url, '?' ), $matches ) ) {
690 + $topic_url = $this->topic->get_full_url( $matches[1] );
691 + if( $topic_url !== wpforo_home_url() ) {
692 + $url = $topic_url;
693 + $this->canonical_url = $this->topic->get_url( $matches[1] );
694 + }
695 + }
696 +
697 + if( function_exists( 'pll_default_language' ) ) {
698 + $qvar = wpforo_get_url_query_vars_str( $url );
699 + $qvar = preg_replace( '#^' . preg_quote( pll_default_language() ) . '/#', '', $qvar );
700 + $url = $this->user_trailingslashit( home_url( $qvar ) );
701 + }
702 +
703 + $url = wpforo_fix_url( $url );
704 + $url = preg_replace( '#\#[^/?&]*$#iu', '', $url );
705 + parse_str( (string) parse_url( $url, PHP_URL_QUERY ), $get );
706 + $get = array_merge( (array) $get, $_GET );
707 + $get = wp_unslash( $get );
708 +
709 + if( ! $this->canonical_url ) $this->canonical_url = $this->current_url;
710 +
711 + $this->current_url = apply_filters( 'wpforo_init_current_url', $url );
712 + $this->GET = apply_filters( 'wpforo_init_current_url_GET', $get );
713 +
714 + if( ! $this->canonical_url ) $this->canonical_url = $this->current_url;
715 + if( strpos( $this->canonical_url, '?wpfin=tag' ) === false && strpos( $this->canonical_url, '?view=' ) === false ) {
716 + $this->canonical_url = preg_replace( '#\?.*$#isu', '', $this->canonical_url );
717 + }
718 + $this->canonical_url = apply_filters( 'wpforo_init_canonical_url', $this->canonical_url );
719 +
720 + do_action( 'wpforo_after_init_current_url', $atts );
721 + }
722 +
723 + private function init_defaults() {
724 + $this->default = new stdClass;
725 +
726 + $this->default->current_object = [
727 + 'route' => '',
728 + 'template' => '',
729 + 'qvars' => [],
730 + 'args' => [],
731 + 'layout' => 1,
732 + 'og_text' => '',
733 + 'paged' => 1,
734 + 'items_count' => 0,
735 + 'items_per_page' => 15,
736 + 'is_404' => false,
737 + 'user_is_same_current_user' => false,
738 + 'orderby' => null,
739 + 'members' => [],
740 + 'categories' => [],
741 + 'topics' => [],
742 + 'posts' => [],
743 + 'user' => [],
744 + 'userid' => 0,
745 + 'user_nicename' => '',
746 + 'forum' => [],
747 + 'forumid' => 0,
748 + 'forum_slug' => '',
749 + 'forum_desc' => '',
750 + 'forum_meta_key' => '',
751 + 'forum_meta_desc' => '',
752 + 'topic' => [],
753 + 'topicid' => 0,
754 + 'topic_slug' => '',
755 + 'tags' => [],
756 + 'load_tinymce' => false,
757 + ];
758 +
759 + $this->default->tools_cleanup = [
760 + 'user_reg_days_ago' => 7,
761 + 'auto_cleanup_users' => 0,
762 + 'usergroup' => [ 1 => '0', 5 => '0', 2 => '1', 3 => '0' ],
763 + ];
764 +
765 + $this->default->tools_misc = [
766 + 'admin_note' => '',
767 + 'admin_note_groups' => [ 1, 2, 3, 4, 5 ],
768 + 'admin_note_pages' => [ 'forum' ],
769 + ];
770 +
771 + $this->default->stats = [
772 + 'forums' => 0,
773 + 'topics' => 0,
774 + 'posts' => 0,
775 + 'members' => 0,
776 + 'online_members_count' => 0,
777 + 'last_post_title' => '',
778 + 'last_post_url' => '',
779 + 'newest_member' => [],
780 + 'newest_member_dname' => '',
781 + 'newest_member_profile_url' => '',
782 + ];
783 +
784 + $this->default->dissmissed = [
785 + 'recaptcha_backend_note' => 0,
786 + 'recaptcha_note' => 0,
787 + 'addons_css_update' => 0,
788 + ];
789 + }
790 +
791 + private function reset_current_object() {
792 + $this->current_object = $this->default->current_object;
793 + }
794 +
795 + private function init_options() {
796 + $this->tools_cleanup = wpforo_get_option( 'tools_cleanup', $this->default->tools_cleanup );
797 + $this->tools_misc = wpforo_get_option( 'tools_misc', $this->default->tools_misc );
798 + $this->dissmissed = wpforo_get_option( 'dissmissed', $this->default->dissmissed );
799 + }
800 +
801 + public function can_use_trailing_slashes() {
802 + return '/' === substr( (string) get_option( 'permalink_structure', '' ), - 1, 1 );
803 + }
804 +
805 + public function user_trailingslashit( $url ) {
806 + $rtrimed_url = '';
807 + $url_append_vars = '';
808 + if( preg_match( '#^(.+?)(/?[?&].*)?$#isu', $url, $match ) ) {
809 + if( wpfval( $match, 1 ) ) $rtrimed_url = rtrim( $match[1], '/\\' );
810 + if( wpfval( $match, 2 ) ) $url_append_vars = '?' . trim( $match[2], '?&/\\' );
811 + if( $rtrimed_url ) {
812 + $home_url = rtrim( preg_replace( '#/?\?.*$#isu', '', home_url() ), '/\\' );
813 + if( $rtrimed_url == $home_url ) {
814 + $url = $rtrimed_url . '/';
815 + } else {
816 + $url = $rtrimed_url . ( wpforo_ram_get( [ $this, 'can_use_trailing_slashes' ] ) ? '/' : '' );
817 + }
818 + }
819 + }
820 +
821 + return $url . $url_append_vars;
822 + }
823 +
824 + public function strip_url_paged_var( $url ) {
825 + $patterns = [
826 + '#/' . preg_quote( wpforo_settings_get_slug( 'paged' ) ) . '/?\d*/?#isu',
827 + '#[&?]wpfpaged=\d*#iu',
828 + ];
829 + $url = preg_replace( $patterns, '', (string) $url );
830 +
831 + return $this->user_trailingslashit( $url );
832 + }
833 +
834 + public function statistic_cache_clean() {
835 + $this->db->query( "DELETE FROM `" . $this->db->options . "` WHERE `option_name` REGEXP '^" . wpforo_prefix( 'stat_[0-9]+' ) . "'" );
836 + }
837 +
838 + public function statistic( $mode = 'get', $template = 'all' ) {
839 + $key = 'stat_' . $this->current_user_groupid;
840 + if( $mode === 'get' ) {
841 + if( $cached_stat = wpforo_get_option( $key, [], false ) ) {
842 + $cached_stat['online_members_count'] = $this->member->online_members_count();
843 + if( wpfkey( $cached_stat, 'forums' ) && wpfkey( $cached_stat, 'topics' ) && wpfkey( $cached_stat, 'posts' ) ) {
844 + return wpforo_array_args_cast_and_merge( $cached_stat, $this->default->stats );
845 + }
846 + }
847 + }
848 +
849 + if( $mode === 'get' || $template === 'all' ) {
850 + $stats['forums'] = $this->forum->get_count( [ 'is_cat' => 0 ] );
851 + $stats['topics'] = $this->topic->get_count();
852 + $stats['posts'] = $this->post->get_count();
853 + $member_status = [ 'p.`status`' => $this->member->get_inlist_enabled_statuses() ];
854 + $stats['members'] = $this->member->get_count( $member_status );
855 + $stats['online_members_count'] = $this->member->online_members_count();
856 + $row_count = apply_filters( 'wpforo_get_statistic_row_count', 1 );
857 +
858 + $posts = $this->topic->get_topics( [ 'orderby' => 'modified', 'order' => 'DESC', 'row_count' => $row_count, 'private' => 0, 'status' => 0, 'permgroup' => 4 ] );
859 + $first = key( $posts );
860 + if( !is_null( $first ) && ! empty( $posts[ $first ] ) && $this->perm->forum_can( 'vf', $posts[ $first ]['forumid'] ) ) {
861 + $stats['last_post_title'] = $posts[ $first ]['title'];
862 + $stats['last_post_url'] = $this->post->get_url( $posts[ $first ]['last_post'] );
863 + }
864 +
865 + $newest_member = $this->member->get_newest_member();
866 + if( ! empty( $newest_member ) ) {
867 + $stats['newest_member'] = $newest_member;
868 + $stats['newest_member_dname'] = wpforo_user_dname( $newest_member );
869 + $stats['newest_member_profile_url'] = $newest_member['profile_url'];
870 + }
871 + } else {
872 + $stats = wpforo_get_option( $key, $this->default->stats, false );
873 + switch( $template ) {
874 + case 'forum':
875 + $stats['forums'] = $this->forum->get_count( [ 'is_cat' => 0 ] );
876 + break;
877 + case 'topic':
878 + $stats['topics'] = $this->topic->get_count();
879 + $posts = $this->topic->get_topics( [ 'orderby' => 'modified', 'order' => 'DESC', 'row_count' => 1 ] );
880 + if( isset( $posts[0] ) && ! empty( $posts[0] ) && $this->perm->forum_can( 'vf', $posts[0]['forumid'] ) ) {
881 + $stats['last_post_title'] = $posts[0]['title'];
882 + $stats['last_post_url'] = $this->post->get_url( $posts[0]['last_post'] );
883 + }
884 + break;
885 + case 'post':
886 + $stats['posts'] = $this->post->get_count();
887 + $posts = $this->topic->get_topics( [ 'orderby' => 'modified', 'order' => 'DESC', 'row_count' => 1 ] );
888 + if( isset( $posts[0] ) && ! empty( $posts[0] ) && $this->perm->forum_can( 'vf', $posts[0]['forumid'] ) ) {
889 + $stats['last_post_title'] = $posts[0]['title'];
890 + $stats['last_post_url'] = $this->post->get_url( $posts[0]['last_post'] );
891 + }
892 + break;
893 + case 'user':
894 + //$member_status = [ 'p.`status`' => $this->member->get_inlist_enabled_statuses() ];
895 + //$stats['members'] = $this->member->get_count( $member_status );
896 + $stats['members'] = $this->member->get_count();
897 + $stats['online_members_count'] = $this->member->online_members_count();
898 +
899 + $newest_member = $this->member->get_newest_member( false );
900 + if( ! empty( $newest_member ) ) {
901 + $stats['newest_member'] = $newest_member;
902 + $stats['newest_member_dname'] = wpforo_user_dname( $newest_member );
903 + $stats['newest_member_profile_url'] = $newest_member['profile_url'];
904 + }
905 + break;
906 + }
907 + }
908 +
909 + $stats = apply_filters( 'wpforo_get_statistic_array_filter', $stats );
910 + $stats = wpforo_array_args_cast_and_merge( $stats, $this->default->stats );
911 + wpforo_update_option( $key, $stats );
912 +
913 + return $stats;
914 + }
915 +
916 + public function init_current_object() {
917 + $this->reset_current_object();
918 + $this->current_object['items_per_page'] = $this->post->get_option_items_per_page();
919 + $url = $this->current_url;
920 + $get = $this->GET;
921 +
922 + if( ! is_wpforo_page( $url ) ) return;
923 +
924 + $current_url = wpforo_get_url_query_vars_str( $url );
925 +
926 + $current_object = [];
927 + if( wpfkey( $get, 'wpfs' ) || wpfval( $get, 'foro' ) === 'search' ) $this->current_object['template'] = 'search';
928 + if( wpfval( $get, 'wpforo' ) || wpfval( $get, 'foro' ) ) {
929 + $request = ( wpfval( $get, 'wpforo' ) ) ? wpfval( $get, 'wpforo' ) : wpfval( $get, 'foro' );
930 + if( $request === 'page' ) $this->current_object['template'] = 'page';
931 + }
932 +
933 + $template_key = '';
934 + $wpf_url = preg_replace( '#/?\?.*$#isu', '', $current_url );
935 + $wpf_url_parse = array_values( array_filter( explode( '/', trim( (string) $wpf_url, '/' ) ) ) );
936 + if( array_key_exists( 0, $wpf_url_parse ) && in_array( $wpf_url_parse[0], $this->board->routes ) ) {
937 + $this->current_object['route'] = $wpf_url_parse[0];
938 + unset( $wpf_url_parse[0] );
939 +
940 + if( in_array( $this->current_object['route'], $this->board->base_routes, true ) ) {
941 + $this->current_object['template'] = ( $template_key = wpforo_settings_get_slug_key( $this->current_object['route'] ) ) !== 'member' ? $template_key : '';
942 +
943 + $current_object['qvars'] = $wpf_url_parse;
944 + $current_object['qvars'] = array_values( $current_object['qvars'] );
945 +
946 + if( $this->current_object['template'] === 'register' ) {
947 + $this->form->current['template'] = 'register';
948 + $this->form->current['value'] = array_merge(
949 + (array) wpfval( $this->form->current, 'value' ),
950 + (array) wpfval( $_POST, 'wpfreg' ),
951 + (array) wpfval( $_POST, 'data' )
952 + );
953 + $this->form->current['value']['user_login'] = sanitize_user( (string) wpfval( $_POST, 'wpfreg', 'user_login' ) );
954 + $this->form->current['value']['user_email'] = sanitize_email( (string) wpfval( $_POST, 'wpfreg', 'user_email' ) );
955 + $this->form->current['varname'] = 'wpfreg';
956 + } elseif( $this->current_object['template'] === 'logout' && $this->current_userid ) {
957 + $this->action->logout();
958 + }
959 + }
960 +
961 + if( $this->current_userid && in_array( $this->current_object['template'], [ 'register', 'login', 'lostpassword' ], true ) && ! wpforo_is_admin() ) wpforo_redirect_to();
962 + }
963 + $wpf_url_parse = array_reverse( $wpf_url_parse );
964 +
965 + if( in_array( wpforo_settings_get_slug( 'paged' ), $wpf_url_parse ) ) {
966 + foreach( $wpf_url_parse as $key => $value ) {
967 + if( $value === wpforo_settings_get_slug( 'paged' ) ) {
968 + unset( $wpf_url_parse[ $key ] );
969 + break;
970 + }
971 + if( is_numeric( $value ) ) $paged = intval( $value );
972 +
973 + unset( $wpf_url_parse[ $key ] );
974 + }
975 + }
976 + if( $_paged = intval( wpfval( $get, 'wpfpaged' ) ) ) $paged = $_paged;
977 + $current_object['paged'] = ( isset( $paged ) && $paged > 0 ) ? $paged : 1;
978 + $current_object['orderby'] = wpfval( $get, 'orderby' );
979 +
980 + $wpf_url_parse = array_values( $wpf_url_parse );
981 +
982 + if( ! $this->current_object['template'] ) {
983 + $current_object = apply_filters( 'wpforo_before_init_current_object', $current_object, $wpf_url_parse );
984 + if( wpfkey( $current_object, 'template' ) ) $this->current_object['template'] = (string) wpfval( $current_object, 'template' );
985 + }
986 +
987 + if( ! $this->current_object['template'] ) {
988 + $templates = $template_key === 'member' ? $this->tpl->get_member_templates_list() : $this->tpl->get_templates_list();
989 + if( $templates ) {
990 + if( $template_key === 'member' ) {
991 + if( count( $wpf_url_parse ) > 1 ) {
992 + $nickname = end( $wpf_url_parse );
993 + $profile_route = prev( $wpf_url_parse );
994 + array_pop( $wpf_url_parse );
995 + array_pop( $wpf_url_parse );
996 + array_push( $wpf_url_parse, $nickname, $profile_route );
997 + } else {
998 + if( ! in_array( end( $wpf_url_parse ), array_map( 'wpforo_settings_get_slug', $templates ) ) ) $wpf_url_parse[] = wpforo_settings_get_slug( 'profile' );
999 + }
1000 + }
1001 + $__slug = end( $wpf_url_parse );
1002 + foreach( $templates as $template ) {
1003 + if( $__slug === wpforo_settings_get_slug( $template ) ) {
1004 + $this->current_object['template'] = $template;
1005 + $current_object['qvars'] = $wpf_url_parse;
1006 + array_pop( $current_object['qvars'] );
1007 + $current_object['qvars'] = array_reverse( $current_object['qvars'] );
1008 + break;
1009 + }
1010 + }
1011 +
1012 + if( $template_key === 'member' ) {
1013 + if( ! $this->current_object['template'] && ! $wpf_url_parse ) {
1014 + if( $this->current_userid ) {
1015 + $this->current_object['template'] = 'profile';
1016 + } else {
1017 + wp_safe_redirect( wpforo_login_url() );
1018 + exit();
1019 + }
1020 + } elseif( ! wpforo_is_member_template( $this->current_object['template'] ) ) {
1021 + $this->current_object['template'] = '';
1022 + $current_object['qvars'] = [];
1023 + }
1024 + }
1025 + }
1026 + }
1027 +
1028 + if( ! $this->current_object['template'] ) {
1029 + $this->current_object['template'] = 'forum';
1030 + $this->form->current['varname'] = 'thread';
1031 + if( isset( $wpf_url_parse[0] ) ) {
1032 + if( isset( $wpf_url_parse[1] ) ) {
1033 + $current_object['topic_slug'] = $wpf_url_parse[0];
1034 + $current_object['forum_slug'] = $wpf_url_parse[1];
1035 + $this->current_object['template'] = 'post';
1036 + $this->form->current['varname'] = 'post';
1037 + } else {
1038 + $current_object['forum_slug'] = $wpf_url_parse[0];
1039 + $this->current_object['template'] = 'topic';
1040 + $this->form->current['varname'] = 'thread';
1041 + }
1042 + }
1043 + }
1044 +
1045 + $current_object = apply_filters( 'wpforo_after_init_current_template', $current_object, $wpf_url_parse, $get );
1046 + if( wpfkey( $current_object, 'template' ) ) $this->current_object['template'] = (string) wpfval( $current_object, 'template' );
1047 +
1048 + if( $this->current_object['template'] ) {
1049 + if( wpforo_is_member_template( $this->current_object['template'] ) ) {
1050 + if( ! wpfval( $current_object, 'userid' ) && ! wpfval( $current_object, 'user_nicename' ) ) {
1051 + if( $qvar0 = wpfval( $current_object['qvars'], 0 ) ) {
1052 + if( wpforo_setting( 'profiles', 'url_structure' ) === 'id' ) {
1053 + $current_object['userid'] = $qvar0;
1054 + } else {
1055 + $current_object['user_nicename'] = $qvar0;
1056 + }
1057 + } else {
1058 + if( $this->current_userid ) {
1059 + $current_object['userid'] = $this->current_userid;
1060 + } else {
1061 + wp_safe_redirect( wpforo_login_url() );
1062 + exit();
1063 + }
1064 + }
1065 + }
1066 +
1067 + // redirect old type of member urls to new one
1068 + if( $template_key !== 'member' ) {
1069 + if( count( $current_object['qvars'] ) === 1 ) {
1070 + $redirect = wpforo_url(
1071 + array_shift( $current_object['qvars'] ) . ( $this->current_object['template'] !== 'profile' ? '/' . wpforo_settings_get_slug( $this->current_object['template'] ) : '' ),
1072 + 'member'
1073 + );
1074 + } else {
1075 + $redirect = wpforo_url(
1076 + array_shift( $current_object['qvars'] ) . '/' . wpforo_settings_get_slug( $this->current_object['template'] ) . '/' . implode( '/', $current_object['qvars'] ),
1077 + 'member'
1078 + );
1079 + }
1080 + wp_safe_redirect( $redirect );
1081 + exit();
1082 + }
1083 + // redirection
1084 +
1085 + } elseif( $this->current_object['template'] === 'search' ) {
1086 + $args = [
1087 + 'needle' => sanitize_text_field( wpfval( $get, 'wpfs' ) ),
1088 + 'type' => sanitize_text_field( wpfval( $get, 'wpfin' ) ),
1089 + 'date_period' => intval( wpfval( $get, 'wpfd' ) ),
1090 + 'forumids' => (array) wpfval( $get, 'wpff' ),
1091 + 'offset' => ( $current_object['paged'] - 1 ) * $this->current_object['items_per_page'],
1092 + 'row_count' => $this->current_object['items_per_page'],
1093 + 'orderby' => 'relevancy',
1094 + 'order' => 'desc',
1095 + 'postids' => [],
1096 + ];
1097 + if( ! empty( $get['wpfob'] ) ) {
1098 + $args['orderby'] = wpforo_sanitize_orderby( $get['wpfob'], 'search', 'relevancy' );
1099 + } elseif( in_array( wpfval( $args, 'type' ), [ 'tag', 'user-posts', 'user-topics' ], true ) ) {
1100 + $args['orderby'] = 'date';
1101 + }
1102 + $wpfo = strtolower( (string) wpfval( $get, 'wpfo' ) );
1103 + if( in_array( $wpfo, [ 'asc', 'desc' ], true ) ) $args['order'] = $wpfo;
1104 + $sdata = array_filter( (array) wpfval( $get, 'data' ) );
1105 + $args['postids'] = $this->postmeta->search( $sdata );
1106 + $current_object['args'] = $args;
1107 + if( $sdata && ! $args['postids'] ) {
1108 + $current_object['items_count'] = 0;
1109 + $current_object['posts'] = [];
1110 + } else {
1111 + $current_object['posts'] = $this->post->search( $args, $current_object['items_count'] );
1112 + }
1113 + } elseif( $this->current_object['template'] === 'recent' ) {
1114 + $args = [];
1115 + $view = false;
1116 + $current_object['items_count'] = 0;
1117 + if( ! empty( WPF()->GET['view'] ) ) $view = sanitize_title( WPF()->GET['view'] );
1118 + if( ! empty( WPF()->GET['wpff'] ) ) $args['forumid'] = intval( WPF()->GET['wpff'] );
1119 + if( ! empty( WPF()->GET['prefixid'] ) ) {
1120 + $args['prefixid'] = intval( WPF()->GET['prefixid'] );
1121 + }
1122 +
1123 + $type = ( $view && $view !== 'unapproved' ? 'topics' : wpforo_setting( 'topics', 'recent_posts_type' ) );
1124 + if( $view === 'unapproved' ) $type = 'posts';
1125 + if( $view === 'prefix' ) $type = 'topics';
1126 +
1127 + if( ! WPF()->current_userid || ! WPF()->usergroup->can( 'aum' ) ) {
1128 + $args['private'] = 0;
1129 + $args['status'] = 0;
1130 + }
1131 + $days = apply_filters( 'wpforo_recent_posts_limit', 30 );
1132 +
1133 + $end_date = time() - ( intval( $days ) * 24 * 60 * 60 );
1134 + if( $type === 'topics' ) {
1135 + $current_object['items_per_page'] = wpforo_setting( 'topics', 'topics_per_page' );
1136 +
1137 + if( wpfval( $args, 'prefixid' ) ) $args['prefix'] = (int) wpfval( $args, 'prefixid' );
1138 + $args['where'] = "`modified` > '" . gmdate( 'Y-m-d H:i:s', $end_date ) . "'";
1139 + $args['orderby'] = ( ! empty( WPF()->GET['wpfob'] ) ) ? wpforo_sanitize_orderby( WPF()->GET['wpfob'], 'topics', 'modified' ) : 'modified';
1140 + $args['order'] = 'DESC';
1141 + $args['offset'] = ( $current_object['paged'] - 1 ) * $current_object['items_per_page'];
1142 + $args['row_count'] = $current_object['items_per_page'];
1143 +
1144 + switch( $view ) {
1145 + case 'unread':
1146 + $args['read'] = false;
1147 + break;
1148 + case 'no-replies':
1149 + $args['where'] = null;
1150 + $args['include'] = wpforo_get_not_replied_topicids();
1151 + break;
1152 + case 'solved':
1153 + $args['solved'] = 1;
1154 + break;
1155 + case 'unsolved':
1156 + $args['solved'] = 0;
1157 + break;
1158 + case 'closed':
1159 + $args['closed'] = 1;
1160 + break;
1161 + case 'opened':
1162 + $args['closed'] = 0;
1163 + break;
1164 + case 'sticky':
1165 + $args['type'] = 1;
1166 + break;
1167 + case 'private':
1168 + $args['private'] = 1;
1169 + break;
1170 + case 'unapproved':
1171 + $args['status'] = 1;
1172 + break;
1173 + case 'prefix':
1174 + $args['where'] = null;
1175 + break;
1176 + }
1177 + $topics = $view === 'no-replies' && empty( $args['include'] ) ? [] : WPF()->topic->get_topics( $args, $current_object['items_count'] );
1178 + if( $topics ) {
1179 + $intro_posts = wpforo_setting( 'topics', 'layout_extended_intro_posts_count' );
1180 + if( $intro_posts < 1 ) {
1181 + $intro_posts = null;
1182 + } else {
1183 + $intro_posts = ( $intro_posts > 1 ) ? ( $intro_posts - 1 ) : 0;
1184 + }
1185 + foreach( $topics as $key => $topic ) {
1186 + $topics[ $key ]['replies'] = [];
1187 + $topics[ $key ]['member'] = wpforo_member( $topic );
1188 + $topics[ $key ]['forum'] = wpforo_forum( $topic['forumid'] );
1189 + if( isset( $topic['last_post'] ) && $topic['last_post'] != 0 ) {
1190 + $topics[ $key ]['last_post'] = wpforo_post( $topic['last_post'] );
1191 + $topics[ $key ]['last_poster'] = wpforo_member( $topics[ $key ]['last_post'] );
1192 + }
1193 + if( isset( $topic['first_postid'] ) && $topic['first_postid'] != 0 ) {
1194 + $topics[ $key ]['first_post'] = wpforo_post( $topic['first_postid'] );
1195 +
1196 + $topics[ $key ]['first_poster'] = wpforo_member( $topics[ $key ]['first_post'] );
1197 + if( ! $view && apply_filters( 'wpforo_recent_topics_intro', true, $topic ) ) {
1198 + $topics[ $key ]['replies'] = WPF()->post->get_posts(
1199 + [ 'topicid' => $topic['topicid'], 'orderby' => '`is_first_post` ASC, `created` DESC, `postid` DESC', 'row_count' => $intro_posts ]
1200 + );
1201 + }
1202 + }
1203 + $topics[ $key ]['topic_url'] = wpforo_topic( $topic['topicid'], 'url' );
1204 + $topics[ $key ]['topic_posturl'] = ( $view === 'unread' && wpfval( $topics[ $key ]['last_post'], 'url' ) ) ? $topics[ $key ]['last_post']['url'] : WPF()->topic->get_url(
1205 + $topic['topicid']
1206 + );
1207 + }
1208 + $args['intro_posts'] = $intro_posts;
1209 + }
1210 + $current_object['topics'] = $topics;
1211 + } else {
1212 + $current_object['items_per_page'] = wpforo_setting( 'topics', 'posts_per_page' );
1213 +
1214 + if( $view !== 'unapproved' ) $args['where'] = "`created` > '" . gmdate( 'Y-m-d H:i:s', $end_date ) . "'";
1215 + $args['orderby'] = ( ! empty( WPF()->GET['wpfob'] ) ) ? wpforo_sanitize_orderby( WPF()->GET['wpfob'], 'posts', 'created' ) : 'created';
1216 + $args['order'] = 'DESC';
1217 + $args['offset'] = ( $current_object['paged'] - 1 ) * $current_object['items_per_page'];
1218 + $args['row_count'] = $current_object['items_per_page'];
1219 + if( $view === 'unapproved' ) {
1220 + $args['status'] = 1;
1221 + }
1222 + $current_object['posts'] = WPF()->post->get_posts( $args, $current_object['items_count'] );
1223 + }
1224 + $args['view'] = $view;
1225 + $args['type'] = $type;
1226 + $current_object['args'] = $args;
1227 + } elseif( $this->current_object['template'] === 'recent-activity' ) {
1228 + $current_object['items_per_page'] = 20;
1229 + $current_object['items_count'] = 0;
1230 +
1231 + // Get filter parameters from URL
1232 + $activity_type = ! empty( WPF()->GET['type'] ) ? sanitize_text_field( WPF()->GET['type'] ) : 'all';
1233 + $period = ! empty( WPF()->GET['period'] ) ? sanitize_text_field( WPF()->GET['period'] ) : 'week';
1234 +
1235 + // Calculate date_from based on period
1236 + $date_from = null;
1237 + switch( $period ) {
1238 + case 'day':
1239 + $date_from = time() - ( 24 * 60 * 60 );
1240 + break;
1241 + case 'week':
1242 + $date_from = time() - ( 7 * 24 * 60 * 60 );
1243 + break;
1244 + case 'month':
1245 + $date_from = time() - ( 30 * 24 * 60 * 60 );
1246 + break;
1247 + case 'all':
1248 + default:
1249 + $date_from = null;
1250 + break;
1251 + }
1252 +
1253 + // Get enabled activity types from settings
1254 + $enabled_types = WPF()->settings->activity['enabled_types'] ?? [];
1255 +
1256 + // Build activity query args
1257 + $args = [
1258 + 'types_exclude' => [ 'new_reply' ], // Exclude notification-only types
1259 + 'orderby' => 'date',
1260 + 'order' => 'DESC',
1261 + 'offset' => ( $current_object['paged'] - 1 ) * $current_object['items_per_page'],
1262 + 'row_count' => $current_object['items_per_page'],
1263 + 'date_from' => $date_from,
1264 + ];
1265 +
1266 + // Filter by activity type
1267 + if( $activity_type !== 'all' ) {
1268 + $type_mapping = [
1269 + 'topic' => [ 'wpforo_topic', 'edit_topic' ],
1270 + 'reply' => [ 'wpforo_post', 'edit_post' ],
1271 + 'reaction' => [ 'new_like', 'new_dislike', 'new_up_vote', 'new_down_vote', 'new_reaction' ],
1272 + 'favorite' => [ 'new_favorite' ],
1273 + 'solved' => [ 'topic_solved' ],
1274 + 'closed' => [ 'topic_closed' ],
1275 + 'answer' => [ 'post_answer' ],
1276 + ];
1277 + if( isset( $type_mapping[ $activity_type ] ) ) {
1278 + // Intersect with enabled types to respect settings
1279 + $args['types_include'] = array_intersect( $type_mapping[ $activity_type ], $enabled_types );
1280 + }
1281 + } else {
1282 + // Show all enabled types
1283 + if( ! empty( $enabled_types ) ) {
1284 + $args['types_include'] = $enabled_types;
1285 + }
1286 + }
1287 +
1288 + $current_object['activities'] = WPF()->activity->get_activities( $args, $current_object['items_count'], true, true );
1289 + $current_object['args'] = [
1290 + 'activity_type' => $activity_type,
1291 + 'period' => $period,
1292 + ];
1293 + } elseif( $this->current_object['template'] === 'tags' ) {
1294 + $current_object['items_per_page'] = wpforo_setting( 'tags', 'per_page' );
1295 + // Tag sort: whitelist the URL key, then map to orderby/order. Never pass raw input to get_tags().
1296 + $tag_sort_map = [ 'count' => [ 'count', 'DESC' ], 'az' => [ 'tag', 'ASC' ], 'za' => [ 'tag', 'DESC' ] ];
1297 + $tag_sort_key = sanitize_key( (string) wpfval( $_GET, 'wpf_tag_sort' ) );
1298 + if( ! isset( $tag_sort_map[ $tag_sort_key ] ) ) $tag_sort_key = 'count';
1299 + $current_object['tag_sort'] = $tag_sort_key;
1300 + $args = [
1301 + 'orderby' => $tag_sort_map[ $tag_sort_key ][0],
1302 + 'order' => $tag_sort_map[ $tag_sort_key ][1],
1303 + 'offset' => ( $current_object['paged'] - 1 ) * $current_object['items_per_page'],
1304 + 'row_count' => $current_object['items_per_page'],
1305 + ];
1306 + $current_object['tags'] = $this->topic->get_tags( $args, $current_object['items_count'] );
1307 + } elseif( $this->current_object['template'] === 'members' ) {
1308 + $current_object['items_per_page'] = wpforo_setting( 'members', 'members_per_page' );
1309 +
1310 + $this->form->current['template'] = 'members';
1311 + $this->form->current['value'] = $get;
1312 + $this->form->current['varname'] = '';
1313 +
1314 + if( ! empty( $get['_wpfms'] ) ) {
1315 + $users_include = [];
1316 + $search_fields_names = $this->member->get_search_fields_names();
1317 +
1318 + $wpfms = ( isset( $get['wpfms'] ) ) ? sanitize_text_field( $get['wpfms'] ) : '';
1319 + if( $wpfms ) {
1320 + if( apply_filters( 'wpforo_member_search_provider', false, $wpfms, $search_fields_names, $get ) ) {
1321 + $users_include = apply_filters( 'wpforo_search_by_provider', [], $wpfms, $search_fields_names, $get );
1322 + } else {
1323 + $users_include = $this->member->search( $wpfms, $search_fields_names );
1324 + }
1325 + } else {
1326 + if( $filters = array_filter( $get, function( $v ) { return ! ( is_null( $v ) || $v === false || $v === '' ); } ) ) {
1327 + $filters = array_merge( array_filter( (array) wpfval( $get, 'data' ), function( $v ) { return ! ( is_null( $v ) || $v === false || $v === '' ); } ), $filters );
1328 + unset( $filters['data'] );
1329 + $args = [];
1330 + foreach( $filters as $filter_key => $filter ) {
1331 + if( in_array( $filter_key, $search_fields_names ) ) {
1332 + $args[ $filter_key ] = $filter;
1333 + }
1334 + }
1335 + if( apply_filters( 'wpforo_member_filter_provider', false, $args, $get ) ) {
1336 + $users_include = apply_filters( 'wpforo_filter_by_provider', [], $args, $get );
1337 + } else {
1338 + $users_include = $this->member->filter( $args );
1339 + }
1340 + }
1341 + }
1342 +
1343 + $users_include = apply_filters( 'wpforo_member_search_users_include', $users_include );
1344 + }
1345 + $member_status = $this->member->get_inlist_enabled_statuses();
1346 + $args = [
1347 + 'offset' => ( $current_object['paged'] - 1 ) * $current_object['items_per_page'],
1348 + 'row_count' => $current_object['items_per_page'],
1349 + 'status' => $member_status,
1350 + 'groupids' => $this->usergroup->get_visible_usergroup_ids(),
1351 + ];
1352 +
1353 + $orderby = wpfval( $get, 'wpfob' ) ? sanitize_text_field( $get['wpfob'] ) : wpforo_setting( 'members', 'list_order' );
1354 +
1355 + switch( $orderby ) {
1356 + case 'online_time':
1357 + $args['orderby'] = 'online_time';
1358 + $args['order'] = 'desc';
1359 + break;
1360 + case 'posts__asc':
1361 + $args['orderby'] = 'posts';
1362 + $args['order'] = 'ASC';
1363 + break;
1364 + case 'user_registered__asc':
1365 + $args['orderby'] = 'user_registered';
1366 + $args['order'] = 'ASC';
1367 + break;
1368 + case 'user_registered__desc':
1369 + $args['orderby'] = 'user_registered';
1370 + $args['order'] = 'DESC';
1371 + break;
1372 + case 'display_name__asc':
1373 + $args['orderby'] = 'display_name';
1374 + $args['order'] = 'ASC';
1375 + break;
1376 + case 'display_name__desc':
1377 + $args['orderby'] = 'display_name';
1378 + $args['order'] = 'DESC';
1379 + break;
1380 + default:
1381 + $args['orderby'] = 'posts';
1382 + $args['order'] = 'DESC';
1383 + break;
1384 + }
1385 + if( ! empty( $users_include ) ) $args['include'] = $users_include;
1386 + $args = apply_filters( 'wpforo_current_object_members_args_filter', $args, $get );
1387 + $current_object['members'] = $this->member->get_members( $args, $current_object['items_count'] );
1388 + if( isset( $users_include ) && empty( $users_include ) ) {
1389 + $current_object['members'] = [];
1390 + $current_object['items_count'] = 0;
1391 + }
1392 + } elseif( $this->current_object['template'] === 'add-topic' ) {
1393 + if( $qvar0 = (int) wpfval( $current_object['qvars'], 0 ) ) {
1394 + $forum = (array) $this->forum->get_forum( $qvar0 );
1395 + if( ! $forum || (int) wpfval( $forum, 'is_cat' ) ) {
1396 + wp_safe_redirect( wpforo_home_url( wpforo_settings_get_slug( 'add-topic' ) ), 301 );
1397 + exit();
1398 + }
1399 + }
1400 + }
1401 + }
1402 +
1403 + if( wpfval( $current_object, 'userid' ) || wpfval( $current_object, 'user_nicename' ) ) {
1404 + $args = [];
1405 + if( isset( $current_object['userid'] ) ) $args['userid'] = $current_object['userid'];
1406 + if( isset( $current_object['user_nicename'] ) ) $args['user_nicename'] = $current_object['user_nicename'];
1407 + $selected_user = $this->member->get_member( $args );
1408 + if( isset( $current_object['userid'] ) && empty( $selected_user ) ) $selected_user = $this->member->get_member( [ 'user_nicename' => $current_object['userid'] ] );
1409 + $selected_user = apply_filters( 'wpforo_init_current_selected_user', $selected_user );
1410 + if( $selected_user ) {
1411 + $current_object['user'] = $selected_user;
1412 + $current_object['userid'] = $selected_user['userid'];
1413 + $current_object['user_nicename'] = $selected_user['user_nicename'];
1414 + $current_object['user_is_same_current_user'] = ! empty( $this->current_userid ) && $selected_user['userid'] === $this->current_userid;
1415 +
1416 + if( $this->tpl->can_view_template( $this->current_object['template'], $current_object['user'] ) ) {
1417 + switch( $this->current_object['template'] ) {
1418 + case 'activity':
1419 + $args = [
1420 + 'offset' => ( $current_object['paged'] - 1 ) * $this->current_object['items_per_page'],
1421 + 'row_count' => $this->current_object['items_per_page'],
1422 + 'userid' => $current_object['userid'],
1423 + 'orderby' => '`created` DESC, `postid` DESC',
1424 + 'check_private' => true,
1425 + 'is_first_post' => wpfval( $this->GET, 'filter' ) ? $this->GET['filter'] === 'topics' : null,
1426 + ];
1427 + $current_object['items_count'] = 0;
1428 + $current_object['activities'] = $this->post->get_posts( $args, $current_object['items_count'] );
1429 + break;
1430 + case 'favored':
1431 + $current_object['filter'] = strtolower( (string) wpfval( WPF()->GET, 'filter' ) );
1432 + if( ! in_array( $current_object['filter'], [ 'likes', 'dislikes' ], true ) ) $current_object['filter'] = 'bookmarks';
1433 + if( $current_object['filter'] === 'likes' ) {
1434 + $postids = $this->reaction->get_reactions_col(
1435 + 'postid',
1436 + [
1437 + 'userid' => $current_object['userid'],
1438 + 'type_include' => 'up',
1439 + ]
1440 + );
1441 + } elseif( $current_object['filter'] === 'dislikes' ) {
1442 + $postids = $this->reaction->get_reactions_col(
1443 + 'postid',
1444 + [
1445 + 'userid' => $current_object['userid'],
1446 + 'type_include' => 'down',
1447 + ]
1448 + );
1449 + } else {
1450 + $postids = $this->bookmark->get_bookmarks_col(
1451 + 'postid',
1452 + [
1453 + 'userid' => $current_object['userid'],
1454 + 'boardid' => $this->board->get_current( 'boardid' ),
1455 + 'status' => true,
1456 + ]
1457 + );
1458 + }
1459 +
1460 + if( $postids ) {
1461 + $args = [
1462 + 'offset' => ( $current_object['paged'] - 1 ) * $this->current_object['items_per_page'],
1463 + 'row_count' => $this->current_object['items_per_page'],
1464 + 'orderby' => '`created` DESC, `postid` DESC',
1465 + 'check_private' => true,
1466 + 'include' => $postids,
1467 + ];
1468 + $current_object['items_count'] = 0;
1469 + $current_object['favored_posts'] = $this->post->get_posts( $args, $current_object['items_count'] );
1470 + } else {
1471 + $current_object['items_count'] = 0;
1472 + $current_object['favored_posts'] = [];
1473 + }
1474 + break;
1475 + case 'account':
1476 + $this->form->current['template'] = 'account';
1477 + $this->form->current['varname'] = 'member';
1478 + $this->form->current['value'] = array_merge( $current_object['user'], (array) wpfval( $_POST, 'member' ) );
1479 + break;
1480 + default:
1481 + $this->form->current['template'] = 'profile';
1482 + $this->form->current['value'] = $current_object['user'];
1483 + break;
1484 + }
1485 + } else {
1486 + if( ! $this->current_userid ) {
1487 + wp_safe_redirect( wpforo_login_url() );
1488 + exit();
1489 + }
1490 + $current_object['is_404'] = true;
1491 + }
1492 +
1493 + } else {
1494 + $current_object['is_404'] = true;
1495 + }
1496 + }
1497 +
1498 + if( wpfval( $current_object, 'topic_slug' ) ) {
1499 + $topic = $this->topic->get_topic( [ 'slug' => $current_object['topic_slug'] ], false );
1500 + if( ! empty( $topic ) ) {
1501 + $topic_forumid = intval( wpfval( $topic, 'forumid' ) );
1502 + $is_owner = wpforo_is_owner( $topic['userid'], $topic['email'] );
1503 +
1504 + if( apply_filters( 'wpforo_current_object_topic_protect', true, $topic ) && $topic_forumid && ( ! $this->perm->forum_can(
1505 + 'vf',
1506 + $topic_forumid
1507 + ) || ( ! $is_owner && ! $this->perm->forum_can( 'vt', $topic_forumid ) ) || ( wpfval( $topic, 'private' ) && ! $is_owner && ! $this->perm->forum_can(
1508 + 'vp',
1509 + $topic_forumid
1510 + ) ) || ( wpfval( $topic, 'status' ) && ! $is_owner && ! $this->perm->forum_can( 'au', $topic_forumid ) ) ) ) {
1511 + if( ! $this->current_userid ) {
1512 + wp_safe_redirect( wpforo_login_url() );
1513 + exit();
1514 + }
1515 + $current_object['is_404'] = true;
1516 + } else {
1517 + $current_object['topic'] = $topic;
1518 + $current_object['topicid'] = $topic['topicid'];
1519 + $current_object['og_text'] = (string) wpfval( $topic, 'title' );
1520 + }
1521 + } else {
1522 + $current_object['is_404'] = true;
1523 + }
1524 + }
1525 +
1526 + if( wpfval( $current_object, 'forum_slug' ) ) {
1527 + $args = ( empty( $topic ) ? [ 'slug' => $current_object['forum_slug'] ] : $topic['forumid'] );
1528 + if( $forum = $this->forum->get_forum( $args ) ) {
1529 + if( ! empty( $topic ) && strtolower( (string) $current_object['forum_slug'] ) !== strtolower( (string) $forum['slug'] ) ) {
1530 + wp_safe_redirect( $this->topic->get_url( $topic, $forum ), 301 );
1531 + exit();
1532 + }
1533 + if( $forum['is_cat'] ) $this->current_object['template'] = 'forum';
1534 + $current_object['forum'] = $forum;
1535 + $current_object['forumid'] = $forum['forumid'];
1536 + $current_object['forum_desc'] = $forum['description'];
1537 + $current_object['forum_meta_key'] = $forum['meta_key'];
1538 + $current_object['forum_meta_desc'] = $forum['meta_desc'];
1539 + $current_object['og_text'] = $forum['title'];
1540 + $current_object['layout'] = $this->forum->get_layout( $forum );
1541 +
1542 + if( $this->current_object['template'] === 'topic' ) {
1543 + $current_object['items_per_page'] = wpforo_setting( 'topics', 'topics_per_page' );
1544 + $args = [
1545 + 'offset' => ( $current_object['paged'] - 1 ) * $current_object['items_per_page'],
1546 + 'row_count' => $current_object['items_per_page'],
1547 + 'forumid' => $current_object['forumid'],
1548 + 'orderby' => 'type, modified',
1549 + 'order' => 'DESC',
1550 + ];
1551 + $args = apply_filters( 'wpforo_topic_list_args', $args );
1552 + $current_object['topics'] = $this->topic->get_topics( $args, $current_object['items_count'] );
1553 + }
1554 + } else {
1555 + $current_object['is_404'] = true;
1556 + }
1557 + }
1558 +
1559 + if( in_array( $this->current_object['template'], [ 'forum', 'topic' ] ) ) {
1560 + if( ! empty( $forum ) ) {
1561 + $current_object['categories'] = [ $forum ];
1562 + } else {
1563 + $current_object['categories'] = $this->forum->get_forums( [ "type" => 'category' ] );
1564 + }
1565 + }
1566 +
1567 + if( $this->current_object['template'] === 'post' && ! empty( $forum ) && ! empty( $topic ) ) {
1568 + $current_object['items_per_page'] = $this->post->get_option_items_per_page( $current_object['layout'] );
1569 +
1570 + $args = [
1571 + 'forumid' => $forum['forumid'],
1572 + 'topicid' => $topic['topicid'],
1573 + 'offset' => ( $current_object['paged'] - 1 ) * $current_object['items_per_page'],
1574 + 'row_count' => $current_object['items_per_page'],
1575 + ];
1576 + if( $current_object['layout'] == 4 ) {
1577 + $args['parentid'] = 0;
1578 + } elseif( $current_object['layout'] == 3 ) {
1579 + $args['parentid'] = 0;
1580 + switch( $current_object['orderby'] ) {
1581 + case 'oldest':
1582 + $args['orderby'] = '`is_first_post` DESC, `is_answer` DESC, `created` ASC, `postid` ASC';
1583 + break;
1584 + case 'newest':
1585 + $args['orderby'] = '`is_first_post` DESC, `is_answer` DESC, `modified` DESC, `postid` DESC';
1586 + break;
1587 + default:
1588 + $args['orderby'] = '`is_first_post` DESC, `is_answer` DESC, `votes` DESC, `created` ASC, `postid` ASC';
1589 + break;
1590 + }
1591 + }
1592 + if( $this->post->get_option_union_first_post( $current_object['layout'] ) ) $args['union_first_post'] = true;
1593 + $args = apply_filters( 'wpforo_post_list_args', $args );
1594 + $current_object['posts'] = $this->post->get_posts( $args, $current_object['items_count'] );
1595 + }
1596 +
1597 + $this->current_object = wpforo_parse_args( $current_object, $this->current_object );
1598 +
1599 + $this->current_object = apply_filters( 'wpforo_after_init_current_object', $this->current_object, $wpf_url_parse );
1600 +
1601 + if( $this->current_object['template'] ) {
1602 + /**
1603 + * redirect not logged-in users to login page when that user no access to this page
1604 + */
1605 + if( ! $this->current_userid && $this->current_object['forumid'] && ( ( in_array( $this->current_object['template'], [ 'forum', 'topic' ] ) && ! $this->perm->forum_can(
1606 + 'vf',
1607 + $this->current_object['forumid']
1608 + ) ) || ( $this->current_object['template'] === 'post' && ! $this->perm->forum_can( 'vt', $this->current_object['forumid'] ) ) ) ) {
1609 + wp_safe_redirect( wpforo_login_url() );
1610 + exit();
1611 + }
1612 +
1613 + if( $this->current_object['template'] === 'cantlogin' ) {
1614 + if( $this->current_userid ) {
1615 + if( $this->current_user['status'] !== 'active' ) {
1616 + WPF()->ram_cache->set( 'USER_LOGIN_REFERER', WPF()->current_user_login );
1617 + wp_logout();
1618 + } else {
1619 + wp_safe_redirect( wpforo_home_url() );
1620 + }
1621 + } else {
1622 + wp_safe_redirect( wpforo_login_url() );
1623 + exit();
1624 + }
1625 + }
1626 +
1627 + /**
1628 + * redirect to the first page when paged var is greater items_count
1629 + */
1630 + if( $this->current_object['items_count'] && $this->current_object['paged'] > 1 && ( ( $this->current_object['paged'] - 1 ) * $this->current_object['items_per_page'] ) >= $this->current_object['items_count'] ) {
1631 + wp_safe_redirect( $this->strip_url_paged_var( $this->current_url ), 301 );
1632 + exit();
1633 + }
1634 + } else {
1635 + $this->current_object['is_404'] = true;
1636 + }
1637 + }
1638 +
1639 + public function get_version() {
1640 + return wpforo_get_option( 'version', null, false );
1641 + }
1642 +
1643 + public function need_activation() {
1644 + return WPFORO_VERSION !== $this->get_version();
1645 + }
1646 +
1647 + public function is_installed() {
1648 + return (bool) $this->get_version();
1649 + }
1650 +
1651 + public function can_use_this_slug( $slug ) {
1652 + $return = ! in_array( $slug, $this->settings->slugs, true ) && ! in_array( $slug, array_keys( $this->settings->slugs ), true );
1653 +
1654 + return apply_filters( 'wpforo_can_use_this_slug', $return, $slug );
1655 + }
1656 +}