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

wpforo.php in wpForo Forum 1.8.4, at wpforo.php

1,117 lines 51.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
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
7 * Author URI: https://gvectors.com/
8 * Version: 1.8.4
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.8.4');
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', 'activity', 'forums', 'languages', 'likes', 'phrases', 'postmeta', 'posts', 'post_revisions', 'profiles',
39 'subscribes', 'topics', 'tags', 'usergroups', 'views', 'visits', 'votes' );
40 public $upload_dir_folders = array();
41
42 public $db;
43 public $addons = array();
44 public $current_url;
45 public $GET;
46 public $current_object;
47 public $menu = array();
48 public $data = array();
49 public $default;
50
51 public $wp_current_user = array();
52 public $current_user = array();
53 public $current_usermeta = array();
54 public $current_user_groupid = 4;
55 public $current_user_secondary_groupids = '';
56 public $current_userid = 0;
57 public $current_username = '';
58 public $current_user_email = '';
59 public $current_user_display_name = '';
60 public $current_user_status = '';
61 public $current_user_accesses = array();
62
63 public $use_trailing_slashes;
64 public $use_home_url;
65 public $excld_urls;
66 public $base_permastruct;
67 public $permastruct;
68 public $url;
69 public $pageid;
70
71 public $general_options;
72 public $features;
73 public $tools_antispam;
74 public $tools_cleanup;
75 public $tools_misc;
76 public $tools_legal;
77
78 public $sql_cache;
79 public $action;
80 public $cache;
81 public $phrase;
82 public $forum;
83 public $topic;
84 public $postmeta;
85 public $post;
86 public $usergroup;
87 public $member;
88 public $perm;
89 public $sbscrb;
90 public $tpl;
91 public $notice;
92 public $api;
93 public $log;
94 public $feed;
95 public $form;
96 public $moderation;
97 public $activity;
98 public $revision;
99 public $seo;
100 public $add;
101 public $dissmissed;
102
103 public $member_tpls;
104
105 public static function instance(){
106 if ( is_null(self::$_instance) ) self::$_instance = new self();
107 return self::$_instance;
108 }
109
110 private function __construct(){
111 global $wpdb;
112 $this->db = $wpdb;
113 $this->file = __FILE__;
114 $this->error = NULL;
115 $this->locale = get_locale();
116 $this->basename = plugin_basename($this->file);
117
118 $this->init_db_tables();
119 $this->includes();
120 $this->init_defaults();
121 $this->reset_current_object();
122 $this->init_options();
123 $this->setup();
124 $this->init_hooks();
125
126 $this->sql_cache = new wpForoSqlCache();
127 $this->action = new wpForoAction();
128 $this->cache = new wpForoCache();
129 $this->phrase = new wpForoPhrase();
130 $this->forum = new wpForoForum();
131 $this->topic = new wpForoTopic();
132 $this->postmeta = new wpForoPostMeta();
133 $this->post = new wpForoPost();
134 $this->usergroup = new wpForoUsergroup();
135 $this->member = new wpForoMember();
136 $this->perm = new wpForoPermissions();
137 $this->sbscrb = new wpForoSubscribe();
138 $this->tpl = new wpForoTemplate();
139 $this->notice = new wpForoNotices();
140 $this->api = new wpForoAPI();
141 $this->log = new wpForoLogs();
142 $this->feed = new wpForoFeed();
143 $this->form = new wpForoForm();
144 $this->moderation = new wpForoModeration();
145 $this->activity = new wpForoActivity();
146 $this->revision = new wpForoRevision();
147 $this->seo = new wpForoSEO();
148 $this->add = new stdClass(); // Integrations
149 }
150
151 private function init_hooks(){
152 add_action('plugins_loaded', array($this, 'plugins_loaded'));
153 if( is_admin() ){
154 add_action('admin_init', array($this, 'admin_init'));
155 add_action('admin_init', array($this, 'init'));
156 }else{
157 add_action('wp', array($this, 'init'));
158 }
159 add_action('switch_blog', array($this, 'after_switch_blog'), 10, 2);
160 }
161
162 public function after_switch_blog($new_blog_id, $prev_blog_id){
163 if( intval($new_blog_id) !== intval($prev_blog_id) ){
164 $this->init_db_tables();
165 }
166 }
167
168 private function init_db_tables($blog_id = 0){
169 $this->db->query("SET SESSION group_concat_max_len = 1000000");
170 $blog_id = apply_filters('wpforo_current_blog_id', $blog_id);
171 $this->tables = new stdClass;
172 if(!$blog_id) $blog_id = $this->db->blogid;
173 $this->blog_prefix = $this->db->get_blog_prefix( $blog_id );
174 $this->_tables = apply_filters('wpforo_init_db_tables', $this->_tables);
175 foreach ( $this->_tables as $table )
176 $this->tables->$table = $this->blog_prefix . $this->prefix . $table;
177 }
178
179 private function includes(){
180 require_once( WPFORO_DIR . '/wpf-includes/wpf-hooks.php' );
181 require_once( WPFORO_DIR . '/wpf-includes/functions.php' );
182 require_once( WPFORO_DIR . '/wpf-includes/functions-integration.php' );
183 require_once( WPFORO_DIR . '/wpf-includes/functions-template.php' );
184 if(wpforo_is_admin()) {
185 require_once( WPFORO_DIR . '/wpf-includes/functions-installation.php' );
186 require_once( WPFORO_DIR .'/wpf-admin/admin.php' );
187 }
188
189 require_once( WPFORO_DIR . '/wpf-includes/class-sqlcache.php' );
190 require_once( WPFORO_DIR . '/wpf-includes/class-actions.php' );
191 require_once( WPFORO_DIR . '/wpf-includes/class-cache.php' );
192 require_once( WPFORO_DIR . '/wpf-includes/class-forums.php' );
193 require_once( WPFORO_DIR . '/wpf-includes/class-topics.php' );
194 require_once( WPFORO_DIR . '/wpf-includes/class-postmeta.php' );
195 require_once( WPFORO_DIR . '/wpf-includes/class-posts.php' );
196 require_once( WPFORO_DIR . '/wpf-includes/class-usergroups.php' );
197 require_once( WPFORO_DIR . '/wpf-includes/class-members.php' );
198 require_once( WPFORO_DIR . '/wpf-includes/class-permissions.php' );
199 require_once( WPFORO_DIR . '/wpf-includes/class-phrases.php');
200 require_once( WPFORO_DIR . '/wpf-includes/class-subscribes.php' );
201 require_once( WPFORO_DIR . '/wpf-includes/class-template.php' );
202 require_once( WPFORO_DIR . '/wpf-includes/class-notices.php' );
203 require_once( WPFORO_DIR . '/wpf-includes/class-logs.php' );
204 require_once( WPFORO_DIR . '/wpf-includes/class-api.php' );
205 require_once( WPFORO_DIR . '/wpf-includes/class-feed.php' );
206 require_once( WPFORO_DIR . '/wpf-includes/class-forms.php' );
207 require_once( WPFORO_DIR . '/wpf-includes/class-moderation.php' );
208 require_once( WPFORO_DIR . '/wpf-includes/class-activity.php' );
209 require_once( WPFORO_DIR . '/wpf-includes/class-revisions.php' );
210 require_once( WPFORO_DIR . '/wpf-includes/class-seo.php' );
211 }
212
213 public function plugins_loaded(){
214 if ( wpforo_feature( 'disable_new_user_admin_notification' ) ) {
215 remove_action( 'after_password_reset', 'wp_password_change_notification' );
216
217 remove_action( 'register_new_user', 'wp_send_new_user_notifications' );
218 add_action( 'register_new_user', 'wpforo_send_new_user_notifications');
219
220 remove_action( 'edit_user_created_user', 'wp_send_new_user_notifications' );
221 add_action( 'edit_user_created_user', 'wpforo_send_new_user_notifications', 10, 2);
222
223 remove_action( 'network_site_new_created_user', 'wp_send_new_user_notifications' );
224 add_action( 'network_site_new_created_user', 'wpforo_send_new_user_notifications');
225
226 remove_action( 'network_site_users_created_user', 'wp_send_new_user_notifications' );
227 add_action( 'network_site_new_created_user', 'wpforo_send_new_user_notifications');
228
229 remove_action( 'network_user_new_created_user', 'wp_send_new_user_notifications' );
230 add_action( 'network_user_new_created_user', 'wpforo_send_new_user_notifications');
231 }
232 }
233
234 public function admin_init(){
235 if( wpforo_is_admin() ){
236
237 $this->check_database();
238
239 if( strpos( wpforo_get_request_uri(), 'user-new.php' ) === false ){
240 $sql = "SELECT `groupid` FROM ". $this->tables->profiles ." WHERE `userid` = " . wpforo_bigintval($this->current_userid);
241 if( !$current_groupid = $this->db->get_var($sql) ){
242 $this->member->synchronize_user($this->current_userid);
243 }
244 }
245
246 if( !$this->forum->manage() && wpforo_current_user_is('admin') ){
247 $this->member->set_usergroup($this->current_userid, 1);
248 }
249 }
250 }
251
252 public function check_database(){
253
254 //Make sure all users profiles are created
255 if( !wpforo_feature('user-synch') && get_option('wpforo_version') ){
256 $users = $this->db->get_var("SELECT COUNT(*) FROM `".$this->db->users."`");
257 $profiles = $this->db->get_var("SELECT COUNT(*) FROM `" . $this->tables->profiles."`");
258 $delta = $users - $profiles;
259 if( $users > 100 && $delta > 2 ){ add_action( 'admin_notices', 'wpforo_profile_notice', 10 ); }
260 }
261 //Make sure tables structures are correct for current version
262 $wpforo_version_db = get_option('wpforo_version_db');
263 if( !$wpforo_version_db || version_compare( $wpforo_version_db, WPFORO_VERSION, '<') ){
264 if( 'tables' != wpfval($_GET, 'view') ){
265 $db_note = false;
266 $problems = wpforo_database_check();
267 if( !empty($problems) ) {
268 foreach( $problems as $table_name => $problem ){
269 if( wpfval($problem, 'fields') ) $db_note = true;
270 if( wpfval($problem, 'exists') ) $db_note = true;
271 }
272 if( $db_note ) {
273 add_action( 'admin_notices', 'wpforo_database_notice', 10 );
274 }
275 } else {
276 update_option('wpforo_version_db', WPFORO_VERSION );
277 }
278 }
279 }
280 }
281
282 public function init(){
283 do_action( 'wpforo_before_init' );
284
285 $this->phrase->init();
286
287 $this->perm->init();
288 $this->perm->init_current_user_accesses();
289
290 $this->init_current_url();
291 $this->init_current_object();
292
293 $this->moderation->init();
294 $this->tpl->init();
295 $this->api->hooks();
296
297 do_action( 'wpforo_after_init' );
298 }
299
300 public function shortcode_atts_to_url($atts){
301 $url = wpforo_home_url();
302
303 $args = shortcode_atts( array(
304 'item' => 'forum',
305 'id' => 0,
306 'slug' => '',
307 ), (array) $atts );
308
309 if( $args['item'] === 'profile' && !$args['id'] ) $args['id'] = $this->current_userid;
310
311 if( $args['item'] === 'add-topic' ){
312 $forum = $this->forum->get_forum( ( $args['slug'] ? $args['slug'] : $args['id'] ) );
313 $url = wpforo_home_url( wpforo_get_template_slug('add-topic') . '/' . (int) wpfval($forum, 'forumid') );
314 }elseif( $args['id'] || $args['slug'] ){
315 $getid = ( $args['slug'] ? $args['slug'] : $args['id'] );
316 if( $args['item'] === 'topic' ){
317 $url = $this->topic->get_topic_url($getid);
318 }elseif( $args['item'] === 'profile' ){
319 $url = $this->member->get_profile_url($getid);
320 }else{
321 $url = $this->forum->get_forum_url($getid);
322 }
323 }elseif( $args['item'] === 'signin' ){
324 $url = wpforo_home_url('?foro=signin');
325 }elseif( $args['item'] === 'signup' ){
326 $url = wpforo_home_url('?foro=signup');
327 }elseif( $args['item'] === 'lostpassword' ){
328 $url = wpforo_home_url('?foro=lostpassword');
329 }
330
331 return $url;
332 }
333
334 public function init_current_url($atts = array()){
335 $url = wpforo_get_request_uri();
336 if( $atts || is_wpforo_shortcode_page($url) ){
337 if( $atts || ($atts = get_wpforo_shortcode_atts('', $url)) ){
338 $url = $this->shortcode_atts_to_url($atts);
339 }else{
340 $url = wpforo_home_url();
341 }
342 }elseif( is_wpforo_url($url) && preg_match('#/'.preg_quote(wpforo_get_template_slug('postid')).'/(\d+)/?$#isu', strtok($url, '?'), $matches) ){
343 $post_url = $this->post->get_post_url($matches[1]);
344 if( $post_url !== wpforo_home_url() ) $url = $post_url;
345 }
346
347 $url = wpforo_fix_url($url);
348 $url = preg_replace('#\#[^/?&]*$#isu', '', $url);
349 parse_str( parse_url($url, PHP_URL_QUERY), $get );
350 $get = array_merge( (array) $get, (array) $_GET );
351
352 $this->current_url = apply_filters('wpforo_init_current_url', $url);
353 $this->GET = apply_filters('wpforo_init_current_url_GET', $get);
354 }
355
356 private function init_defaults() {
357 date_default_timezone_set( 'UTC' );
358 ini_set( 'date.timezone', 'UTC' );
359
360 $this->default = new stdClass;
361
362 $this->default->use_home_url = 0;
363 $this->default->excld_urls = '';
364 $this->default->permastruct = 'community';
365
366 $this->default->current_object = array(
367 'template' => '',
368 'qvars' => array(),
369 'args' => array(),
370 'layout' => 1,
371 'og_text' => '',
372 'paged' => 1,
373 'items_count' => 0,
374 'items_per_page' => 15,
375 'is_404' => false,
376 'user_is_same_current_user' => false,
377 'orderby' => null,
378 'members' => array(),
379 'categories' => array(),
380 'topics' => array(),
381 'posts' => array(),
382 'user' => array(),
383 'userid' => 0,
384 'user_nicename' => '',
385 'forum' => array(),
386 'forumid' => 0,
387 'forum_slug' => '',
388 'forum_desc' => '',
389 'forum_meta_key' => '',
390 'forum_meta_desc' => '',
391 'topic' => array(),
392 'topicid' => 0,
393 'topic_slug' => '',
394 'tags' => array(),
395 'load_tinymce' => false
396 );
397
398 $blogname = get_option( 'blogname', '' );
399 $this->default->general_options = array(
400 'title' => $blogname . ' ' . __( 'Forum', 'wpforo' ),
401 'description' => $blogname . ' ' . __( 'Discussion Board', 'wpforo' ),
402 'lang' => 1
403 );
404
405 $this->default->features = array(
406 'user-admin-bar' => 0,
407 'page-title' => 1,
408 'top-bar' => 1,
409 'top-bar-search' => 1,
410 'breadcrumb' => 1,
411 'footer-stat' => 1,
412 'notifications' => 1,
413 'notifications-live' => 0,
414 'notifications-bar' => 1,
415 'mention-nicknames' => 1,
416 'content-do_shortcode' => 0,
417 'view-logging' => 1,
418 'track-logging' => 1,
419 'goto-unread' => 1,
420 'goto-unread-button' => 0,
421 'profile' => 1,
422 'user-register' => 1,
423 'user-register-email-confirm' => 1,
424 'disable_new_user_admin_notification' => 1,
425 'register-url' => 0,
426 'login-url' => 0,
427 'resetpass-url' => 1,
428 //In most cases incompatible with security and antispam plugins
429 'replace-avatar' => 1,
430 'avatars' => 1,
431 'custom-avatars' => 1,
432 'signature' => 1,
433 'rating' => 1,
434 'rating_title' => 1,
435 'member_cashe' => 1,
436 'object_cashe' => 1,
437 'html_cashe' => 0,
438 'memory_cashe' => 1,
439 'seo-title' => 1,
440 'seo-meta' => 1,
441 'seo-profile' => 1,
442 'rss-feed' => 1,
443 'font-awesome' => 1,
444 'bp_activity' => 1,
445 'bp_notification' => 1,
446 'bp_forum_tab' => 1,
447 'um_forum_tab' => 1,
448 'um_notification' => 1,
449 'user-synch' => 0,
450 'role-synch' => 1,
451 'output-buffer' => 1,
452 'wp-date-format' => 0,
453 'subscribe_conf' => 1,
454 'subscribe_checkbox_on_post_editor' => 1,
455 'subscribe_checkbox_default_status' => 0,
456 'attach-media-lib' => 1,
457 'admin-cp' => 1,
458 'debug-mode' => 0,
459 'copyright' => 1
460 );
461
462 $this->default->tools_antispam = array(
463 'spam_filter' => 1,
464 'spam_filter_level_topic' => mt_rand( 30, 60 ),
465 'spam_filter_level_post' => mt_rand( 30, 60 ),
466 'spam_user_ban' => 0,
467 'new_user_max_posts' => 3,
468 'unapprove_post_if_user_is_new' => 0,
469 'spam_user_ban_notification' => 1,
470 'min_number_post_to_attach' => 0,
471 'min_number_post_to_link' => 0,
472 'spam_file_scanner' => 1,
473 'limited_file_ext' => 'pdf|doc|docx|txt|htm|html|rtf|xml|xls|xlsx|zip|rar|tar|gz|bzip|7z',
474 'exclude_file_ext' => 'pdf|doc|docx|txt',
475 'rc_site_key' => '',
476 'rc_secret_key' => '',
477 'rc_theme' => 'light',
478 'rc_login_form' => 0,
479 'rc_reg_form' => 0,
480 'rc_lostpass_form' => 0,
481 'rc_wpf_login_form' => 1,
482 'rc_wpf_reg_form' => 1,
483 'rc_wpf_lostpass_form' => 1,
484 'rc_topic_editor' => 1,
485 'rc_post_editor' => 1,
486 'html' => 'embed(src width height name pluginspage type wmode allowFullScreen allowScriptAccess flashVars),'
487 );
488
489 $this->default->tools_cleanup = array(
490 'user_reg_days_ago' => 7,
491 'auto_cleanup_users' => 0,
492 'usergroup' => array( 1 => '0', 5 => '0', 2 => '1', 3 => '0' )
493 );
494
495 $this->default->tools_misc = array(
496 'dofollow' => '',
497 'noindex' => '',
498 'admin_note' => '',
499 'admin_note_groups' => array( 1, 2, 3, 4, 5 ),
500 'admin_note_pages' => array( 'forum' )
501 );
502
503 $this->default->tools_legal = array(
504 'rules_checkbox' => 0,
505 'rules_text' => null,
506 'page_terms' => '',
507 'page_privacy' => '',
508 'forum_privacy_text' => null,
509 'checkbox_terms_privacy' => 0,
510 'checkbox_email_password' => 1,
511 'checkbox_forum_privacy' => 0,
512 'checkbox_fb_login' => 1,
513 'contact_page_url' => null,
514 'cookies' => 1
515 );
516
517 $this->default->stats = array(
518 'forums' => 0,
519 'topics' => 0,
520 'posts' => 0,
521 'members' => 0,
522 'online_members_count' => 0,
523 'last_post_title' => '',
524 'last_post_url' => '',
525 'newest_member' => array(),
526 'newest_member_dname' => '',
527 'newest_member_profile_url' => ''
528 );
529
530 $this->default->dissmissed = array(
531 'recaptcha_backend_note' => 0,
532 'recaptcha_note' => 0,
533 'addons_css_update' => 0
534 );
535 }
536
537 private function reset_current_object(){
538 $this->current_object = $this->default->current_object;
539 }
540
541 private function init_options(){
542 $permalink_structure = get_option('permalink_structure');
543
544 $this->use_trailing_slashes = ( '/' == substr($permalink_structure, -1, 1) );
545
546 //OPTIONS
547 $this->use_home_url = get_wpf_option('wpforo_use_home_url', $this->default->use_home_url);
548 $this->excld_urls = get_wpf_option('wpforo_excld_urls', $this->default->excld_urls);
549
550 $this->permastruct = trim( get_wpf_option('wpforo_permastruct', $this->default->permastruct), '/' );
551 $this->permastruct = preg_replace('#^/?index\.php/?#isu', '', $this->permastruct);
552 $this->permastruct = trim($this->permastruct, '/');
553
554 $this->base_permastruct = (!$this->use_home_url ? $this->permastruct : '');
555 $this->base_permastruct = rtrim( ( strpos($permalink_structure, 'index.php') !== FALSE ? '/index.php/' . $this->base_permastruct : '/' . $this->base_permastruct ), '/\\' );
556 $this->url = esc_url( home_url( $this->user_trailingslashit($this->base_permastruct) ) );
557 $this->pageid = get_wpf_option( 'wpforo_pageid', 0);
558
559 $this->general_options = get_wpf_option( 'wpforo_general_options', $this->default->general_options);
560 $this->features = get_wpf_option('wpforo_features', $this->default->features);
561 $fp = intval($this->features['profile']);
562 if( ($fp === 3 && !class_exists('BP_Component')) || ($fp === 4 && !function_exists('UM')) ){
563 $this->features['profile'] = 1;
564 update_option('wpforo_features', array_map( 'intval', $this->features));
565 }
566 $this->tools_antispam = get_wpf_option('wpforo_tools_antispam', $this->default->tools_antispam);
567 $this->tools_cleanup = get_wpf_option('wpforo_tools_cleanup', $this->default->tools_cleanup);
568 $this->tools_misc = get_wpf_option('wpforo_tools_misc', $this->default->tools_misc);
569 $this->tools_legal = get_wpf_option('wpforo_tools_legal', $this->default->tools_legal);
570
571 $this->dissmissed = get_wpf_option('wpforo_dissmissed', $this->default->dissmissed);
572
573 //CONSTANTS
574 define('WPFORO_BASE_PERMASTRUCT', $this->base_permastruct );
575 define('WPFORO_BASE_URL', $this->url );
576 }
577
578 private function setup(){
579 if( wpforo_is_admin() ){
580 register_activation_hook($this->basename, 'do_wpforo_activation');
581 register_deactivation_hook($this->basename, 'do_wpforo_deactivation');
582 }
583 }
584
585 public function user_trailingslashit($url) {
586 $rtrimed_url = '';
587 $url_append_vars = '';
588 if( preg_match('#^(.+?)(/?[?&].*)?$#isu', $url, $match) ){
589 if( wpfval($match, 1) ) $rtrimed_url = rtrim($match[1], '/\\');
590 if( wpfval($match, 2) ) $url_append_vars = '?' . trim($match[2], '?&/\\');
591 if( $rtrimed_url ) {
592 $home_url = rtrim( preg_replace('#/?\?.*$#isu', '', home_url()), '/\\' );
593 if( $rtrimed_url == $home_url ){
594 $url = $rtrimed_url . '/';
595 }else{
596 $url = ( $this->use_trailing_slashes ? $rtrimed_url . '/' : $rtrimed_url );
597 }
598 }
599 }
600 return $url . $url_append_vars;
601 }
602
603 public function strip_url_paged_var($url){
604 $patterns = array(
605 '#/'. preg_quote( wpforo_get_template_slug('paged') ) .'/?\d*/?#isu',
606 '#[\&\?]wpfpaged=\d*#isu'
607 );
608 $url = preg_replace($patterns, '', $url);
609 $url = $this->user_trailingslashit($url);
610 return $url;
611 }
612
613 public function statistic( $mode = 'get', $template = 'all' ){
614 if( $mode === 'get' ){
615 if( $cached_stat = get_option('wpforo_stat' ) ){
616 $cached_stat['online_members_count'] = $this->member->online_members_count();
617 if( wpfval($cached_stat, 'forums') && wpfval($cached_stat, 'topics') && wpfval($cached_stat, 'posts') ){
618 $cached_stat = wpforo_array_args_cast_and_merge($cached_stat, $this->default->stats);
619 return $cached_stat;
620 }
621 }
622 }
623
624 if( $mode === 'get' || $template === 'all' ) {
625 $stats['forums'] = $this->forum->get_count( array('is_cat' => 0) );
626 $stats['topics'] = $this->topic->get_count();
627 $stats['posts'] = $this->post->get_count();
628 $member_status = array( 'p.`status`' => apply_filters('wpforo_display_members_status', array('active')));
629 $stats['members'] = $this->member->get_count( $member_status );
630 $stats['online_members_count'] = $this->member->online_members_count();
631 $row_count = apply_filters('wpforo_get_statistic_row_count', 20);
632
633 $posts = $this->topic->get_topics(array('orderby' => 'modified', 'order' => 'DESC', 'row_count' => $row_count, 'private' => 0, 'status' => 0, 'permgroup' => 4 ));
634 $first = key($posts);
635 if ( isset($posts[$first]) && !empty($posts[$first]) && $this->perm->forum_can('vf', $posts[$first]['forumid'], 4) ) {
636 $stats['last_post_title'] = $posts[$first]['title'];
637 $stats['last_post_url'] = $this->post->get_post_url($posts[$first]['last_post']);
638 }
639
640 $members = $this->member->get_members(array('orderby' => 'userid', 'order' => 'DESC', 'row_count' => 1, 'groupids' => $this->usergroup->get_visible_usergroup_ids()));
641 if (isset($members[0]) && !empty($members[0])) {
642 $members[0]['profile_url'] = $this->member->profile_url($members[0]);
643 $stats['newest_member'] = $members[0];
644 $stats['newest_member_dname'] = wpforo_user_dname($members[0]);
645 $stats['newest_member_profile_url'] = $members[0]['profile_url'];
646 }
647 }else{
648 $stats = get_wpf_option('wpforo_stat', $this->default->stats);
649 switch ($template){
650 case 'forum':
651 $stats['forums'] = $this->forum->get_count( array('is_cat' => 0) );
652 break;
653 case 'topic':
654 $stats['topics'] = $this->topic->get_count();
655 $posts = $this->topic->get_topics(array('orderby' => 'modified', 'order' => 'DESC', 'row_count' => 1));
656 if ( isset($posts[0]) && !empty($posts[0]) && $this->perm->forum_can('vf', $posts[0]['forumid']) ) {
657 $stats['last_post_title'] = $posts[0]['title'];
658 $stats['last_post_url'] = $this->post->get_post_url($posts[0]['last_post']);
659 }
660 break;
661 case 'post':
662 $stats['posts'] = $this->post->get_count();
663 $posts = $this->topic->get_topics(array('orderby' => 'modified', 'order' => 'DESC', 'row_count' => 1));
664 if ( isset($posts[0]) && !empty($posts[0]) && $this->perm->forum_can('vf', $posts[0]['forumid']) ) {
665 $stats['last_post_title'] = $posts[0]['title'];
666 $stats['last_post_url'] = $this->post->get_post_url($posts[0]['last_post']);
667 }
668 break;
669 case 'user':
670 $member_status = array( 'p.`status`' => apply_filters('wpforo_display_members_status', array('active')));
671 $stats['members'] = $this->member->get_count( $member_status );
672 $stats['online_members_count'] = $this->member->online_members_count();
673
674 $members = $this->member->get_members(array('orderby' => 'userid', 'order' => 'DESC', 'row_count' => 1, 'groupids' => $this->usergroup->get_visible_usergroup_ids()));
675 if (isset($members[0]) && !empty($members[0])) {
676 $members[0]['profile_url'] = WPF()->member->profile_url($members[0]);
677 $stats['newest_member'] = $members[0];
678 $stats['newest_member_dname'] = wpforo_user_dname($members[0]);
679 $stats['newest_member_profile_url'] = $members[0]['profile_url'];
680 }
681 break;
682 }
683 }
684
685 $stats = apply_filters('wpforo_get_statistic_array_filter', $stats);
686 $stats = wpforo_array_args_cast_and_merge($stats, $this->default->stats);
687 update_option( 'wpforo_stat', $stats );
688 return $stats;
689 }
690
691 public function init_current_object(){
692 $this->current_object['items_per_page'] = $this->post->get_option_items_per_page();
693 $url = $this->current_url;
694 $get = $this->GET;
695
696 if( !is_wpforo_page($url) ) return;
697
698 $current_url = wpforo_get_url_query_vars_str($url);
699
700 if( $this->use_home_url ) $this->permastruct = '';
701
702 $current_object = array();
703 if( wpfkey($get, 'wpfs') || wpfval($get, 'foro') === 'search' ) $current_object['template'] = 'search';
704 if( wpfval($get, 'wpforo') || wpfval($get, 'foro') ){
705 $request = ( wpfval($get, 'wpforo') ) ? wpfval($get, 'wpforo') : wpfval($get, 'foro');
706 switch( $request ){
707 case 'signup':
708 if(!is_user_logged_in()) {
709 $this->data['template'] = $current_object['template'] = 'register';
710 $this->data['value']['user_login'] = sanitize_user((string) wpfval($_POST, 'wpfreg', 'user_login'));
711 $this->data['value']['user_email'] = sanitize_email((string) wpfval($_POST, 'wpfreg', 'user_email'));
712 $this->data['varname'] = 'wpfreg';
713 }
714 break;
715 case 'signin':
716 if(!is_user_logged_in()) $current_object['template'] = 'login';
717 break;
718 case 'lostpassword':
719 if(!is_user_logged_in()) $current_object['template'] = 'lostpassword';
720 break;
721 case 'resetpassword':
722 $current_object['template'] = 'resetpassword';
723 break;
724 case 'page':
725 $current_object['template'] = 'page';
726 break;
727 case 'logout':
728 wp_logout();
729 wp_redirect( wpforo_home_url( preg_replace('#\?.*$#is', '', wpforo_get_request_uri()) ) );
730 exit();
731 break;
732 }
733 }
734
735 $wpf_url = preg_replace( '#^/?'.preg_quote($this->permastruct).'#isu', '' , $current_url, 1 );
736 $wpf_url = preg_replace('#/?\?.*$#isu', '', $wpf_url);
737 $wpf_url_parse = array_filter( explode('/', trim($wpf_url, '/')) );
738 $wpf_url_parse = array_reverse($wpf_url_parse);
739
740 if(in_array(wpforo_get_template_slug('paged'), $wpf_url_parse)){
741 foreach($wpf_url_parse as $key => $value){
742 if( $value === wpforo_get_template_slug('paged')){
743 unset($wpf_url_parse[$key]);
744 break;
745 }
746 if(is_numeric($value)) $paged = intval($value);
747
748 unset($wpf_url_parse[$key]);
749 }
750 }
751 if( $_paged = intval( wpfval($get, 'wpfpaged') ) ) $paged = $_paged;
752 $current_object['paged'] = (isset($paged) && $paged > 0) ? $paged : 1;
753 $current_object['orderby'] = wpfval($get, 'orderby');
754
755 $wpf_url_parse = array_values($wpf_url_parse);
756
757 if( wpfval($current_object, 'template') === 'search' ){
758 $args = array(
759 'needle' => sanitize_text_field( wpfval($get, 'wpfs') ),
760 'type' => sanitize_text_field( wpfval($get, 'wpfin') ),
761 'date_period' => intval( wpfval($get, 'wpfd') ),
762 'forumids' => (array) wpfval($get, 'wpff'),
763 'offset' => ($current_object['paged'] - 1) * $this->current_object['items_per_page'],
764 'row_count' => $this->current_object['items_per_page'],
765 'orderby' => 'relevancy',
766 'order' => 'desc',
767 'postids' => array()
768 );
769 if( !empty($get['wpfob']) ){
770 $args['orderby'] = sanitize_text_field( $get['wpfob'] );
771 }elseif( in_array(wpfval( $args, 'type' ), array('tag','user-posts','user-topics'), true) ) {
772 $args['orderby'] = 'date';
773 }
774 $wpfo = strtolower(wpfval($get, 'wpfo'));
775 if( in_array($wpfo, array('asc','desc'), true) ) $args['order'] = $wpfo;
776 $sdata = array_filter( (array) wpfval($get, 'data') );
777 $args['postids'] = WPF()->postmeta->search($sdata);
778 $current_object['args'] = $args;
779 if( $sdata && !$args['postids'] ){
780 $current_object['items_count'] = 0;
781 $current_object['posts'] = array();
782 }else{
783 $current_object['posts'] = WPF()->post->search($args, $current_object['items_count']);
784 }
785 }
786
787 if( !wpfval($current_object, 'template') ){
788 $current_object = apply_filters('wpforo_before_init_current_object', $current_object, $wpf_url_parse);
789 }
790
791 if( !wpfval($current_object, 'template') ){
792 if( $templates = $this->tpl->get_templates_list() ){
793 $__slug = end($wpf_url_parse);
794 foreach ( $templates as $template ){
795 if( $__slug === wpforo_get_template_slug($template) ){
796 $current_object['template'] = $template;
797 $current_object['qvars'] = $wpf_url_parse;
798 array_pop($current_object['qvars']);
799 $current_object['qvars'] = array_reverse($current_object['qvars']);
800 break;
801 }
802 }
803 }
804 }
805
806 if( wpfval($current_object, 'template') ){
807 if( !wpfval($current_object, 'userid') && !wpfval($current_object, 'user_nicename') && wpforo_is_member_template($current_object['template']) ){
808 if( $qvar0 = wpfval($current_object['qvars'], 0) ){
809 if( $this->member->options['url_structure'] === 'id' ) {
810 $current_object['userid'] = $qvar0;
811 }else {
812 $current_object['user_nicename'] = $qvar0;
813 }
814 }else{
815 if($this->current_userid){
816 $current_object['userid'] = $this->current_userid;
817 }else{
818 wp_redirect( wpforo_login_url() );
819 exit();
820 }
821 }
822 }elseif($current_object['template'] === 'recent'){
823 $current_object['items_per_page'] = $this->post->options['topics_per_page'];
824 }elseif($current_object['template'] === 'tags'){
825 $current_object['items_per_page'] = $this->post->options['tags_per_page'];
826 $args = array(
827 'offset' => ($current_object['paged'] - 1) * $current_object['items_per_page'],
828 'row_count' => $current_object['items_per_page']
829 );
830 $current_object['tags'] = $this->topic->get_tags($args, $current_object['items_count']);
831 }elseif($current_object['template'] === 'members'){
832 $current_object['items_per_page'] = $this->member->options['members_per_page'];
833
834 $this->data['template'] = 'members';
835 $this->data['value'] = $get;
836 $this->data['varname'] = '';
837
838 if( !empty($get['_wpfms']) ){
839 $users_include = array();
840 $search_fields_names = $this->member->get_search_fields_names(false);
841
842 $wpfms = (isset($get['wpfms'])) ? sanitize_text_field($get['wpfms']) : '';
843 if($wpfms){
844 $users_include = $this->member->search($wpfms, $search_fields_names);
845 }else{
846 if( $filters = array_filter($get, function($v){return !( is_null($v) || $v === false || $v === '' );}) ){
847 $filters = array_merge( array_filter((array) wpfval($get, 'data'), function($v){return !( is_null($v) || $v === false || $v === '' );}), $filters );
848 unset($filters['data']);
849 $args = array();
850 foreach ($filters as $filter_key => $filter){
851 if( in_array($filter_key, (array) $search_fields_names) ){
852 $args[$filter_key] = $filter;
853 }
854 }
855 $users_include = $this->member->filter($args);
856 }
857 }
858
859 $users_include = apply_filters('wpforo_member_search_users_include', $users_include);
860 }
861 $member_status = apply_filters('wpforo_display_members_status', array('active'));
862 $args = array(
863 'offset' => ($current_object['paged'] - 1) * $current_object['items_per_page'],
864 'row_count' => $current_object['items_per_page'],
865 'orderby' => 'posts',
866 'order' => 'DESC',
867 'status' => $member_status,
868 'groupids' => $this->usergroup->get_visible_usergroup_ids()
869 );
870 if(!empty($users_include)) $args['include'] = $users_include;
871 $current_object['members'] = $this->member->get_members($args, $current_object['items_count']);
872 if(isset($users_include) && empty($users_include)){ $current_object['members'] = array(); $current_object['items_count'] = 0; }
873 }
874 }else{
875 $current_object['template'] = 'forum';
876 $this->data['varname'] = 'topic';
877 if( isset($wpf_url_parse[0]) ){
878 if( isset($wpf_url_parse[1]) ){
879 $current_object['topic_slug'] = $wpf_url_parse[0];
880 $current_object['forum_slug'] = $wpf_url_parse[1];
881 $current_object['template'] = 'post';
882 $this->data['varname'] = 'post';
883 }else{
884 $current_object['forum_slug'] = $wpf_url_parse[0];
885 $current_object['template'] = 'topic';
886 $this->data['varname'] = 'topic';
887 }
888 }
889 }
890
891 if( wpfval($current_object, 'userid') || wpfval($current_object, 'user_nicename') ){
892 $args = array();
893 if(isset($current_object['userid'])) $args['userid'] = $current_object['userid'];
894 if(isset($current_object['user_nicename'])) $args['user_nicename'] = $current_object['user_nicename'];
895 $selected_user = $this->member->get_member($args);
896 if(isset($current_object['userid']) && empty($selected_user)) $selected_user = $this->member->get_member(array('user_nicename' => $current_object['userid']));
897 if(!empty($selected_user)){
898 $current_object['user'] = $selected_user;
899 $current_object['userid'] = $selected_user['ID'];
900 $current_object['user_nicename'] = $selected_user['user_nicename'];
901 $current_object['user_is_same_current_user'] = !empty($this->current_userid) && $selected_user['ID'] == $this->current_userid;
902
903 if( $this->tpl->can_view_template($current_object['template'], $current_object['user']) ){
904 switch($current_object['template']){
905 case 'activity':
906 $args = array(
907 'offset' => ($current_object['paged'] - 1) * $this->current_object['items_per_page'],
908 'row_count' => $this->current_object['items_per_page'],
909 'userid' => $current_object['userid'],
910 'orderby' => '`created` DESC, `postid` DESC',
911 'check_private' => true
912 );
913 $current_object['items_count'] = 0;
914 $current_object['activities'] = $this->post->get_posts( $args, $current_object['items_count']);
915 break;
916 case 'subscriptions':
917 $args = array(
918 'offset' => ($current_object['paged'] - 1) * $this->current_object['items_per_page'],
919 'row_count' => $this->current_object['items_per_page'],
920 'userid' => $current_object['userid'],
921 'order' => 'DESC'
922 );
923 $current_object['items_count'] = 0;
924 $current_object['subscribes'] = $this->sbscrb->get_subscribes( $args, $current_object['items_count']);
925 break;
926 case 'account':
927 $this->data['template'] = 'account';
928 $this->data['varname'] = 'member';
929 $this->data['value'] = array_merge($current_object['user'], (array) wpfval($_POST, 'member'));
930 break;
931 default:
932 $this->data['template'] = 'profile';
933 $this->data['value'] = $current_object['user'];
934 break;
935 }
936 }else{
937 if( !$this->current_userid ){
938 wp_redirect( wpforo_login_url() );
939 exit();
940 }
941 $current_object['is_404'] = true;
942 }
943
944 }else{
945 $current_object['is_404'] = true;
946 }
947 }
948
949 if( wpfval($current_object, 'topic_slug') ){
950 $topic = $this->topic->get_topic(array('slug' => $current_object['topic_slug']), false);
951 if(!empty($topic)){
952
953 $topic_forumid = intval( wpfval($topic, 'forumid') );
954 $is_owner = wpforo_is_owner($topic['userid'], $topic['email']);
955
956 if( $topic_forumid && (
957 !WPF()->perm->forum_can('vf', $topic_forumid) ||
958 ( !$is_owner && !WPF()->perm->forum_can('vt', $topic_forumid) ) ||
959 ( wpfval($topic, 'private') && !$is_owner && !WPF()->perm->forum_can('vp', $topic_forumid) ) ||
960 ( wpfval($topic, 'status') && !$is_owner && !WPF()->perm->forum_can('au', $topic_forumid) )
961 ) ){
962 if( !$this->current_userid ){
963 wp_redirect( wpforo_login_url() );
964 exit();
965 }
966 $current_object['is_404'] = true;
967 }else{
968 $current_object['topic'] = $topic;
969 $current_object['topicid'] = $topic['topicid'];
970 $current_object['og_text'] = (string) wpfval($topic, 'title');
971 }
972
973 }else{
974 $current_object['is_404'] = true;
975 }
976 }
977
978 if( wpfval($current_object, 'forum_slug') ){
979 $args = ( empty($topic) ? array('slug' => $current_object['forum_slug']) : $topic['forumid'] );
980 if( $forum = $this->forum->get_forum( $args ) ){
981 if( $forum['is_cat'] ) $current_object['template'] = 'forum';
982 $current_object['forum'] = $forum;
983 $current_object['forumid'] = $forum['forumid'];
984 $current_object['forum_desc'] = $forum['description'];
985 $current_object['forum_meta_key'] = $forum['meta_key'];
986 $current_object['forum_meta_desc'] = $forum['meta_desc'];
987 $current_object['og_text'] = $forum['title'];
988 $current_object['layout'] = $this->forum->get_layout( $forum );
989
990 if( $current_object['template'] === 'topic' ){
991 $current_object['items_per_page'] = $this->post->options['topics_per_page'];
992 $args = array(
993 'offset' => ($current_object['paged'] - 1) * $current_object['items_per_page'],
994 'row_count' => $current_object['items_per_page'],
995 'forumid' => $current_object['forumid'],
996 'orderby' => 'type, modified',
997 'order' => 'DESC'
998 );
999 $current_object['topics'] = $this->topic->get_topics( $args, $current_object['items_count'] );
1000 }
1001 }else{
1002 $current_object['is_404'] = true;
1003 }
1004 }
1005
1006 if( in_array($current_object['template'], array('forum', 'topic')) ){
1007 if( !empty($forum) ){
1008 $current_object['categories'] = array( $forum );
1009 }else{
1010 $current_object['categories'] = $this->forum->get_forums( array( "type" => 'category' ) );
1011 }
1012 }
1013
1014 if ( $current_object['template'] === 'post' && ! empty( $forum ) && ! empty( $topic ) ) {
1015 $current_object['items_per_page'] = $this->post->get_option_items_per_page($current_object['layout']);
1016
1017 $args = array(
1018 'forumid' => $forum['forumid'],
1019 'topicid' => $topic['topicid'],
1020 'offset' => ( $current_object['paged'] - 1 ) * $current_object['items_per_page'],
1021 'row_count' => $current_object['items_per_page']
1022 );
1023 if( $current_object['layout'] == 4 ){
1024 $args['parentid'] = 0;
1025 }elseif( $current_object['layout'] == 3 ){
1026 $args['parentid'] = 0;
1027 switch ( $current_object['orderby'] ) {
1028 case 'oldest':
1029 $args['orderby'] = '`is_first_post` DESC, `is_answer` DESC, `created` ASC, `postid` ASC';
1030 break;
1031 case 'newest':
1032 $args['orderby'] = '`is_first_post` DESC, `is_answer` DESC, `modified` DESC, `postid` DESC';
1033 break;
1034 default:
1035 $args['orderby'] = '`is_first_post` DESC, `is_answer` DESC, `votes` DESC, `created` ASC, `postid` ASC';
1036 break;
1037 }
1038 }
1039 if( $this->post->get_option_union_first_post($current_object['layout']) ) $args['union_first_post'] = true;
1040 $current_object['posts'] = $this->post->get_posts( $args, $current_object['items_count']);
1041 }
1042
1043 $this->current_object = wpforo_parse_args($current_object, $this->current_object);
1044
1045 $this->current_object = apply_filters('wpforo_after_init_current_object', $this->current_object, $wpf_url_parse);
1046
1047 if( $this->current_object['template'] ){
1048 /**
1049 * redirect not logged-in users to login page when that user no access to this page
1050 */
1051 if( !$this->current_userid && $this->current_object['forumid'] && (
1052 (in_array($this->current_object['template'], array('forum', 'topic')) && !$this->perm->forum_can('vf', $this->current_object['forumid']))
1053 || ($this->current_object['template'] === 'post' && !$this->perm->forum_can('vt', $this->current_object['forumid']))
1054 )
1055 ){
1056 wp_redirect( wpforo_login_url() );
1057 exit();
1058 }
1059
1060 /**
1061 * redirect to the first page when paged var is greater items_count
1062 */
1063 if( $this->current_object['items_count']
1064 && $this->current_object['paged'] > 1
1065 && (($this->current_object['paged'] - 1) * $this->current_object['items_per_page']) >= $this->current_object['items_count']
1066 ){
1067 wp_redirect( $this->strip_url_paged_var( $this->current_url ) );
1068 exit();
1069 }
1070 }else{
1071 $this->current_object['is_404'] = true;
1072 }
1073 }
1074
1075 public function is_installed(){
1076 return (bool) get_option('wpforo_version');
1077 }
1078
1079 public function can_use_this_slug($slug){
1080 $return = !in_array($slug, $this->tpl->slugs, true) && !in_array($slug, array_keys($this->tpl->slugs), true);
1081 return apply_filters('wpforo_can_use_this_slug', $return, $slug);
1082 }
1083 }
1084
1085 /**
1086 * Main instance of wpForo.
1087 *
1088 * Returns the main instance of WPF to prevent the need to use globals.
1089 *
1090 * @since 1.4.3
1091 * @return wpForo
1092 */
1093 if ( !function_exists('WPF') ){
1094 function WPF() {
1095 return wpForo::instance();
1096 }
1097 }
1098
1099 // Global for backwards compatibility.
1100 $GLOBALS['wpforo'] = WPF();
1101
1102 //ADDONS/////////////////////////////////////////////////////
1103 WPF()->addons = array(
1104 'embeds' => array('version' => '2.0.7', 'requires' => '1.8.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/'),
1105 'polls' => array('version' => '1.0.6', 'requires' => '1.8.0', '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/'),
1106 'tcf' => array('version' => '1.0.0', 'requires' => '1.8.0', 'class' => 'wpForoTcf', 'title' => 'Topic Custom Fields', 'thumb' => WPFORO_URL . '/wpf-assets/addons/tcf/header.png', 'desc' => __('Allows to create topic custom fields and manage topic form layout with a form builder. Adds topic search options by custom fields', 'wpforo'), 'url' => 'https://gvectors.com/product/wpforo-topic-custom-fields/'),
1107 'mycred' => array('version' => '1.1.2', 'requires' => '1.8.0', '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/'),
1108 'ucf' => array('version' => '2.0.2', 'requires' => '1.8.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/'),
1109 'attachments' => array('version' => '2.0.4', 'requires' => '1.8.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/'),
1110 'pm' => array('version' => '1.3.3', 'requires' => '1.8.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/'),
1111 'cross' => array('version' => '2.1.5', 'requires' => '1.8.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/'),
1112 'ad-manager' => array('version' => '1.1.3', 'requires' => '1.8.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/'),
1113 'emoticons' => array('version' => '1.0.5', 'requires' => '1.8.0', 'class' => 'wpForoSmiles', 'title' => 'wpForo Emoticons', 'thumb' => WPFORO_URL . '/wpf-assets/addons/wpforo-emoticons/header.png', 'desc' => __('Adds awesome Sticker and Emoticons packs to editor. Allows to create new custom emoticons packs.', 'wpforo'), 'url' => 'https://gvectors.com/product/wpforo-emoticons/'),
1114 );
1115 $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'));}
1116 /////////////////////////////////////////////////////////////
1117 }