PluginProbe
wpForo Forum / 3.1.1
wpForo Forum v3.1.1
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 / includes / hooks.php

hooks.php in wpForo Forum 3.1.1, at includes/hooks.php

3,722 lines 137.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 // Exit if accessed directly
3 if( ! defined( 'ABSPATH' ) ) {
4 exit;
5 }
6
7 add_filter( 'plugin_action_links_' . WPFORO_BASENAME, function( $links ) {
8 $uninstall_url = wp_nonce_url( admin_url( 'plugins.php?wpfaction=uninstall' ), 'wpforo_uninstall' );
9 $links[] = '<a href="' . esc_url(
10 (string) $uninstall_url
11 ) . '" class="wpforo-uninstall" style="color:#a00;" onclick="return confirm(\'' . __(
12 'IMPORTANT! Uninstall is not a simple deactivation action. This action will permanently remove all forum data (forums, topics, replies, attachments...) from database. Please backup database before this action, you may need this forum data in future. If you are sure that you want to delete all forum data please confirm. If not, just cancel it, then you can deactivate this plugin, that will not remove forum data.',
13 'wpforo'
14 ) . '\')">' . __( 'Uninstall', 'wpforo' ) . '</a>';
15 $settings_link = '<a href="' . esc_url( (string) admin_url( 'admin.php?page=wpforo-boards' ) ) . '">' . __(
16 'Boards',
17 'wpforo'
18 ) . '</a>';
19 array_unshift( $links, $settings_link );
20
21 return $links;
22 } );
23
24 function wpforo_notice_show() {
25 WPF()->notice->show();
26 }
27
28 add_action( 'wp_footer', 'wpforo_notice_show' );
29
30 add_action( 'show_admin_bar', function( $show_admin_bar ) {
31 if( ! is_super_admin() && is_user_logged_in() && WPF()->wp_current_user && ! array_intersect(
32 [ 'editor', 'administrator', 'author', ],
33 (array) WPF()->wp_current_user->roles
34 ) ) {
35 $show_admin_bar = (bool) array_intersect(
36 (array) WPF()->current_user_groupids,
37 (array) wpforo_setting( 'general', 'admin_bar' )
38 );
39 }
40
41 return $show_admin_bar;
42 } );
43
44 add_action( 'admin_notices', function() {
45 if( strpos( wpforo_get_request_uri(), 'nav-menus.php' ) !== false ) {
46 $message = '';
47 foreach(
48 WPF()->tpl->menu as $key => $value
49 ) {
50 $message .= "<tr><td> " . $value['label'] . ": </td><td> /%$key%/ </td></tr>";
51 }
52 $message .= "<tr><td> " . wpforo_phrase( 'register', false ) . ": </td><td> /%wpforo-register%/ </td></tr>
53 <tr><td> " . wpforo_phrase( 'login', false ) . ": </td><td> /%wpforo-login%/ </td></tr>";
54 printf(
55 '<div class="notice notice-warning wpforo-menu-shortcodes">
56 <p class="wpforo-menu-shortcodes-head" style="cursor: pointer;">wpForo Menu Shortcodes hint <span class="dashicons dashicons-arrow-down-alt2"></span></p>
57 <div class="wpforo-menu-shortcodes-body" style="display: none;">
58 <hr/><table>%1$s</table>
59 </div>
60 </div>',
61 $message
62 );
63 ?>
64 <script>
65 jQuery(document).ready(function ($) {
66 $('body').on('click', '.wpforo-menu-shortcodes .wpforo-menu-shortcodes-head', {}, function () {
67 var $this = $(this);
68 var wrap = $this.closest('.wpforo-menu-shortcodes');
69 var body = $('.wpforo-menu-shortcodes-body', wrap);
70 body.toggle();
71 });
72 });
73 </script>
74 <?php
75 }
76 } );
77
78 add_filter( 'comments_open', function( $open ) {
79 if( is_wpforo_page() ) $open = false;
80
81 return $open;
82 } );
83
84 add_filter( 'comments_array', function( $comments ) {
85 if( is_wpforo_page() ) $comments = [];
86
87 return $comments;
88 }, 10, 2 );
89
90 add_action( 'wpforo_actions_end', function() {
91 if( is_wpforo_page() ) {
92 remove_post_type_support( 'post', 'comments' );
93 remove_post_type_support( 'page', 'comments' );
94 }
95 }, 100 );
96
97 add_action( 'wpforo_actions_end', function() {
98 if( ! WPF()->board->get_current( 'is_standalone' ) && ! is_front_page() && ! is_home() && is_wpforo_url() ) {
99 global $wp_query, $post;
100 $pageid = WPF()->board->get_current( 'pageid' );
101 if( is_a( $post, 'WP_Post' ) && $post->ID !== $pageid ) {
102 $args = [
103 'post_count' => 1,
104 'found_posts' => 1,
105 'max_num_pages' => 0,
106 'is_404' => false,
107 'is_page' => true,
108 'is_singular' => true,
109 ];
110
111 $target_post = get_post( $pageid );
112 if( ! is_a( $target_post, 'WP_Post' ) ) {
113 return;
114 }
115
116 $post = $target_post;
117
118 $wp_query->posts = [ $post ];
119 $wp_query->queried_object_id = $post->ID;
120 $wp_query->queried_object = $post;
121
122 foreach( $args as $key => $value ) {
123 $wp_query->$key = $value;
124 }
125
126 setup_postdata( $post );
127 }
128 }
129 } );
130
131 add_filter( 'author_link', function( $link, $author_id ) {
132 if( wpforo_setting( 'profiles', 'profile' ) === 'wpforo' ) return WPF()->member->get_profile_url( $author_id );
133
134 return $link;
135 }, 10, 2 );
136
137 add_filter( 'get_comment_author_url', function( $link, $ID = 0, $object = null ) {
138 if( isset( $object->user_id ) && $object->user_id && wpforo_setting(
139 'profiles',
140 'profile'
141 ) === 'wpforo' ) {
142 return WPF()->member->get_profile_url(
143 $object->user_id
144 );
145 }
146
147 return $link;
148 }, 10, 3 );
149
150 add_filter( 'register_url', function( $register_url ) {
151 if( wpforo_setting( 'authorization', 'use_our_register_url' ) ) $register_url = wpforo_register_url();
152
153 return $register_url;
154 } );
155
156 add_filter( 'login_url', function( $login_url ) {
157 if( wpforo_setting( 'authorization', 'use_our_login_url' ) && strpos(
158 (string) $_SERVER['REQUEST_URI'],
159 '/wp-json/'
160 ) !== 0 && strpos(
161 (string) wp_debug_backtrace_summary(),
162 'wp_auth_check_html, wp_login_url,'
163 ) === false ) {
164 $login_url = wpforo_login_url();
165 }
166
167 return $login_url;
168 } );
169
170 add_filter( 'logout_url', function( $logout_url ) {
171 if( wpforo_setting( 'authorization', 'use_our_login_url' ) ) $logout_url = wpforo_logout_url();
172
173 return $logout_url;
174 } );
175
176 add_filter( 'pre_trash_post', function( $check, $post ) {
177 if( in_array( $post->ID, WPF()->board->get_boards_pageids(), true ) ) {
178 $check = false;
179 WPF()->notice->add( 'DO NOT DELETE WPFORO PAGE!!!', 'error' );
180 }
181
182 return $check;
183 }, 10, 2 );
184
185 add_filter( 'wp_dropdown_pages', function( $output, $r ) {
186 $pageids = WPF()->board->get_boards_pageids();
187 if( $r['name'] === 'page_for_posts' || ( $r['name'] === 'page_on_front' && wpforo_get_shortcode_pageid(
188 $pageids
189 ) ) ) {
190 $pattern = '#[\r\n\t\s]*<option[^<>]*?value=[\'"](' . implode(
191 '|',
192 $pageids
193 ) . ')[\'"][^<>]*?>[^<>]*?</option>#isu';
194 $output = preg_replace( $pattern, '', (string) $output );
195 }
196
197 return $output;
198 }, 10, 2 );
199
200 add_filter( 'pre_update_option', function( $value, $option, $old_value ) {
201 if( $option === 'page_on_front' ) {
202 $pageids = WPF()->board->get_boards_pageids();
203 if( in_array( wpforo_bigintval( $value ), $pageids, true ) ) {
204 if( ! $page_id = wpforo_get_shortcode_pageid( $pageids ) ) {
205 $page_id = wp_insert_post(
206 [
207 'post_date' => current_time( 'mysql', 1 ),
208 'post_date_gmt' => current_time( 'mysql', 1 ),
209 'post_content' => '[wpforo]',
210 'post_title' => 'Forum page_on_front',
211 'post_status' => 'publish',
212 'comment_status' => 'close',
213 'ping_status' => 'close',
214 'post_name' => 'front-community',
215 'post_modified' => current_time( 'mysql', 1 ),
216 'post_modified_gmt' => current_time( 'mysql', 1 ),
217 'post_parent' => 0,
218 'menu_order' => 0,
219 'post_type' => 'page',
220 ]
221 );
222 }
223 $value = ( $page_id && ! is_wp_error( $page_id ) ? $page_id : $old_value );
224 }
225 }
226
227 return $value;
228 }, 10, 3 );
229
230 function wpftpl_url( $filename ) {
231 $tpl_url = '';
232 if( $filename ) {
233 if( $tpl_url = locate_template( 'wpforo/' . $filename ) ) {
234 $tpl_url = get_template_directory_uri() . '/wpforo/' . $filename;
235 }
236 if( ! $tpl_url ) $tpl_url = WPF()->tpl->template_url . '/' . $filename;
237 }
238
239 return apply_filters( 'wpforo_wpftpl_url', $tpl_url, $filename );
240 }
241
242 function wpftpl( $filename ) {
243 $tpl = '';
244 if( $filename ) {
245 $tpl = locate_template( 'wpforo/' . $filename );
246 if( ! $tpl ) $tpl = WPF()->tpl->template_dir . '/' . $filename;
247 }
248
249 return apply_filters( 'wpforo_wpftpl', $tpl, $filename );
250 }
251
252 add_shortcode( 'wpforo', function( $atts ) {
253 wpforo_include_once_theme_functions();
254 if( defined( 'REST_REQUEST' ) && REST_REQUEST ) return '';
255 if( ! is_wpforo_url() ) {
256 if( ! $atts ) $atts = [ 'item' => 'forum' ];
257 WPF()->init_current_url( $atts );
258 WPF()->init_current_object();
259 wpforo_frontend_enqueue_scripts();
260 }
261 if( apply_filters( 'on_wpforo_load_remove_the_content_all_filters', false ) ) {
262 remove_all_filters( 'the_content' );
263 }
264
265 ob_start();
266 if( wpforo_current_user_is( 'admin' ) || ! wpforo_setting( 'board', 'under_construction' ) ) {
267 include( wpftpl( 'index.php' ) );
268 } else {
269 include( wpftpl( 'uc.php' ) );
270 }
271 $output = ob_get_clean();
272 $output = trim( (string) $output );
273 if( ! $output ) $output = wpforo_hook_usage( 'the_content' );
274
275 return $output;
276 } );
277
278 function wpforo_hook_usage( $hook = '' ) {
279 global $wp_filter;
280
281 $output = '<div style="color: #990000; font-size: 16px;">Notice: a plugin conflict has been detected. wpForo forums are affected by other plugin errors.
282 Please deactivate all plugins, delete all caches and test again.
283 Then activate all plugins back one by one and find the conflict maker plugin.</div>
284 <pre style="display: none;">' . ( empty( $hook ) || ! isset( $wp_filter[ $hook ] ) ? 'No hook usage' : print_r(
285 $wp_filter[ $hook ],
286 true
287 ) ) . '</pre>';
288
289 return $output;
290 }
291
292 add_action( 'wpforo_actions_end', 'wpforo_set_header_status' );
293 function wpforo_set_header_status() {
294 if( is_wpforo_page() ) {
295 global $wp_query;
296
297 $status = ( WPF()->current_object['is_404'] ? 404 : 200 );
298 status_header( $status );
299 if( $status === 404 ) nocache_headers();
300 $wp_query->is_404 = false;
301 }
302 }
303
304 add_filter( 'pre_handle_404', function( $bypass ) {
305 if( is_wpforo_page() ) return true;
306
307 return $bypass;
308 } );
309
310 add_action( 'wpforo_actions_end', function() {
311 if( is_wpforo_page() && WPF()->board->get_current( 'is_standalone' ) ) {
312 add_rewrite_rule( '(.*)', 'index.php?page_id=' . WPF()->board->get_current( 'pageid' ), 'top' );
313 add_filter( 'template_include', function( $template ) {
314 if( is_wpforo_page() && ! is_wpforo_shortcode_page() && ( $wpforo_template = wpftpl(
315 'index.php'
316 ) ) ) {
317 return $wpforo_template;
318 }
319
320 return $template;
321 } );
322 }
323 } );
324
325 add_filter( 'rewrite_rules_array', function( $rules ) {
326 $rewrite_prefix = '(?:([a-z]{2,3})/)?';
327 if( function_exists( 'pll_languages_list' ) ) {
328 $rewrite_prefix = '(?:(' . implode(
329 '|',
330 pll_languages_list()
331 ) . ')/)?';
332 }
333
334 if( ! WPF()->board->get_current( 'is_standalone' ) ) {
335 $pageid = 0;
336 $boards = WPF()->board->get_boards( [ 'status' => true ] );
337 foreach( $boards as $board ) {
338 if( $board['boardid'] === 0 ) $pageid = $board['pageid'];
339 $route = urldecode( (string) $board['slug'] );
340 $route = preg_replace( '#^/?index\.php/?#iu', '', $route );
341 $route = trim( (string) $route, '/' );
342 $pattern = $rewrite_prefix . preg_quote( $route ) . '(?:/|$).*$';
343 $to_url = 'index.php?lang=$matches[1]&page_id=' . $board['pageid'];
344 if( ! array_key_exists( $pattern, $rules ) ) $rules = array_merge( [ $pattern => $to_url ], $rules );
345 }
346
347 if( ! $pageid ) $pageid = wpforo_get_option( 'wpforo_pageid', 0 );
348 foreach( WPF()->board->routes as $route ) {
349 // $route = utf8_uri_encode( urldecode( (string) $route ) );
350 $route = urldecode( (string) $route );
351 $route = preg_replace( '#^/?index\.php/?#isu', '', $route );
352 $route = trim( (string) $route, '/' );
353 $pattern = $rewrite_prefix . preg_quote( $route ) . '(?:/|$).*$';
354 $to_url = 'index.php?lang=$matches[1]&page_id=' . $pageid;
355 if( ! array_key_exists( $pattern, $rules ) ) $rules = array_merge( [ $pattern => $to_url ], $rules );
356 }
357 }
358
359 return $rules;
360 } );
361
362 add_action( 'wpforo_actions_end', function() {
363 $pageid = WPF()->board->get_current( 'pageid' );
364 if( is_wpforo_url() && $pageid && WPF()->board->route && get_the_ID() !== $pageid ) {
365 wpforo_repair_main_shortcode_page();
366 }
367 } );
368
369
370 function wpforo_include_once_theme_functions() {
371 $path = wpftpl( 'functions.php' );
372 if( file_exists( $path ) ) include_once( $path );
373
374 $path = wpftpl( 'functions-wp.php' );
375 if( file_exists( $path ) ) include_once( $path );
376 }
377
378 add_action( 'wpforo_after_init', 'wpforo_include_once_theme_functions' );
379
380 function wpforo_meta_title( $title ) {
381 $meta_title = [];
382
383 if( ! wpforo_setting( 'seo', 'seo_title' ) ) return $title;
384
385 if( is_wpforo_page() ) {
386 $template = WPF()->current_object['template'];
387 if( ! WPF()->current_object['is_404'] ) {
388 $paged = ( WPF()->current_object['paged'] > 1 ) ? wpforo_phrase( 'page', false ) . ' ' . WPF()->current_object['paged'] . ' ' : '';
389 if( ! empty( WPF()->current_object['forum'] ) ) {
390 $forum = WPF()->current_object['forum'];
391 }
392 if( ! empty( WPF()->current_object['topic'] ) ) {
393 $topic = WPF()->current_object['topic'];
394 }
395 if( ! empty( WPF()->current_object['user'] ) ) {
396 $user = WPF()->current_object['user'];
397 }
398 if( isset( $topic['title'] ) && isset( $forum['title'] ) && isset(
399 WPF()->board->get_current(
400 'settings'
401 )['title']
402 ) ) {
403 $meta_title = [
404 $topic['title'],
405 $paged,
406 $forum['title'],
407 WPF()->board->get_current( 'settings' )['title'],
408 ];
409 $meta_title = apply_filters( 'wpforo_seo_topic_title', $meta_title );
410 } elseif( ! isset( $topic['title'] ) && isset( $forum['title'] ) && isset(
411 WPF()->board->get_current(
412 'settings'
413 )['title']
414 ) ) {
415 $meta_title = [ $forum['title'], $paged, WPF()->board->get_current( 'settings' )['title'] ];
416 $meta_title = apply_filters( 'wpforo_seo_forum_title', $meta_title );
417 } elseif( ! in_array( $template, [ 'forum', 'topic', 'post' ], true ) ) {
418 if( wpforo_is_member_template( $template ) ) {
419 if( isset( $user['display_name'] ) ) {
420 $meta_title = [
421 $user['display_name'],
422 wpforo_phrase( ucfirst( (string) $template ), false ),
423 WPF()->board->get_current( 'settings' )['title'],
424 $paged,
425 ];
426 } elseif( isset( WPF()->current_object['user_nicename'] ) ) {
427 $meta_title = [
428 WPF()->current_object['user_nicename'],
429 wpforo_phrase( ucfirst( (string) $template ), false ),
430 WPF()->board->get_current( 'settings' )['title'],
431 $paged,
432 ];
433 } else {
434 $meta_title = [
435 wpforo_phrase( 'Member', false ),
436 wpforo_phrase( ucfirst( (string) $template ), false ),
437 WPF()->board->get_current( 'settings' )['title'],
438 $paged,
439 ];
440 }
441 $meta_title = apply_filters( 'wpforo_seo_profile_title', $meta_title );
442 } elseif( $template === 'recent' ) {
443 $wpfpaged = ( isset( $_GET['wpfpaged'] ) && $_GET['wpfpaged'] > 1 ) ? ' - ' . wpforo_phrase(
444 'page',
445 false
446 ) . ' ' . $_GET['wpfpaged'] . ' ' : '';
447 $view = wpfval( $_GET, 'view' );
448 if( $view == 'unread' ) {
449 $main_title = wpforo_phrase( 'Unread Posts', false );
450 } elseif( $view == 'prefix' ) {
451 $main_title = wpforo_phrase( 'Topic Prefix', false );
452 } else {
453 $main_title = wpforo_phrase( 'Recent Posts', false );
454 }
455 $meta_title = [ $main_title . $wpfpaged, WPF()->board->get_current( 'settings' )['title'] ];
456 $meta_title = apply_filters( 'wpforo_seo_recent_posts_title', $meta_title );
457 } elseif( $template === 'tags' ) {
458 $wpfpaged = ( isset( $_GET['wpfpaged'] ) && $_GET['wpfpaged'] > 1 ) ? ' - ' . wpforo_phrase(
459 'page',
460 false
461 ) . ' ' . $_GET['wpfpaged'] . ' ' : '';
462 $meta_title = [
463 wpforo_phrase( 'Tags', false ) . $wpfpaged,
464 WPF()->board->get_current( 'settings' )['title'],
465 ];
466 $meta_title = apply_filters( 'wpforo_seo_tags_title', $meta_title );
467 } elseif( $template === 'search' && wpfval( $_GET, 'wpfin' ) && wpfval(
468 $_GET,
469 'wpfs'
470 ) && $_GET['wpfin'] === 'tag' ) {
471 $wpfpaged = ( isset( $_GET['wpfpaged'] ) && $_GET['wpfpaged'] > 1 ) ? ' - ' . wpforo_phrase(
472 'page',
473 false
474 ) . ' ' . $_GET['wpfpaged'] . ' ' : '';
475 $meta_title = [
476 wpforo_phrase( 'Topic Tag:', false ) . ' ' . esc_html( $_GET['wpfs'] ),
477 $wpfpaged,
478 WPF()->board->get_current( 'settings' )['title'],
479 ];
480 $meta_title = apply_filters( 'wpforo_seo_tag_title', $meta_title );
481 } elseif( $template ) {
482 $wpfpaged = ( isset( $_GET['wpfpaged'] ) && $_GET['wpfpaged'] > 1 ) ? ' - ' . wpforo_phrase(
483 'page',
484 false
485 ) . ' ' . $_GET['wpfpaged'] . ' ' : '';
486 $meta_title = [
487 wpforo_phrase( ucfirst( (string) $template ), false ) . $wpfpaged,
488 WPF()->board->get_current( 'settings' )['title'],
489 ];
490 $meta_title = apply_filters( 'wpforo_seo_template_title', $meta_title );
491 } elseif( $title ) {
492 $meta_title = ( is_array( $title ) ) ? $title : [ $title ];
493 $meta_title = apply_filters( 'wpforo_seo_x_title', $meta_title );
494 } else {
495 $meta_title = [ wpforo_phrase( 'Forum', false ), get_bloginfo( 'name' ) ];
496 $meta_title = apply_filters( 'wpforo_seo_general_title', $meta_title );
497 }
498 } elseif( isset( WPF()->board->get_current( 'settings' )['title'] ) && WPF()->board->get_current(
499 'settings'
500 )['title'] ) {
501 $meta_title = [ WPF()->board->get_current( 'settings' )['title'], get_bloginfo( 'name' ) ];
502 $meta_title = apply_filters( 'wpforo_seo_main_title', $meta_title );
503 } elseif( $title ) {
504 $meta_title = ( is_array( $title ) ) ? $title : [ $title ];
505 $meta_title = apply_filters( 'wpforo_seo_x_title', $meta_title );
506 } else {
507 $meta_title = [ wpforo_phrase( 'Forum', false ), get_bloginfo( 'name' ) ];
508 $meta_title = apply_filters( 'wpforo_seo_general_title', $meta_title );
509 }
510 } else {
511 $meta_title = [
512 wpforo_phrase( '404 - Page not found', false ),
513 WPF()->board->get_current( 'settings' )['title'],
514 ];
515 $meta_title = apply_filters( 'wpforo_seo_404_title', $meta_title );
516 }
517 }
518 if( ! empty( $meta_title ) ) {
519 return $meta_title;
520 } else {
521 return $title;
522 }
523 }
524
525 add_filter( 'document_title_parts', 'wpforo_meta_title', 100 );
526
527 function wpforo_meta_wp_title( $title ) {
528 if( ! wpforo_setting( 'seo', 'seo_title' ) ) return $title;
529 $meta_title = wpforo_meta_title( $title );
530 if( is_array( $meta_title ) && ! empty( $meta_title ) ) {
531 $title = implode( ' &#8211; ', $meta_title );
532 }
533
534 return $title;
535 }
536
537 add_filter( 'wp_title', 'wpforo_meta_wp_title', 100 );
538
539 function wpforo_add_meta_tags() {
540 if( ! wpforo_setting( 'seo', 'seo_meta' ) ) {
541 return;
542 }
543
544 if( is_wpforo_page() && ! is_wpforo_shortcode_page() ) {
545 $title = '';
546 $og_img = '';
547 $tw_img = '';
548 $schema = '';
549 $noindex = '';
550 $template = '';
551 $description = '';
552 $udata = [];
553 if( preg_match( '#\?.*$#is', (string) WPF()->canonical_url, $requests ) ) {
554 if( strpos( (string) $requests[0], 'orderby' ) !== false ) {
555 $canonical = preg_replace( '#\?.*$#is', '', (string) WPF()->canonical_url );
556 } else {
557 $canonical = wpforo_home_url( $requests[0] );
558 }
559 } else {
560 $canonical = WPF()->canonical_url;
561 }
562 $noindex_urls = wpforo_setting( 'seo', 'noindex' );
563 $image = '';
564 foreach( $noindex_urls as $noindex_url ) {
565 $noindex_url = strtok( $noindex_url, "#" );
566 if( strpos( (string) $noindex_url, '*' ) !== false ) {
567 $noindex_url = strtok( $noindex_url, "*" );
568 if( preg_match( '|^' . preg_quote( $noindex_url ) . '|is', (string) $canonical ) ) {
569 $noindex = "<meta name=\"robots\" content=\"noindex\">\r\n";
570 break;
571 }
572 } elseif( $canonical == $noindex_url ) {
573 $noindex = "<meta name=\"robots\" content=\"noindex\">\r\n";
574 break;
575 }
576 }
577 $paged = ( WPF()->current_object['paged'] > 1 ) ? wpforo_phrase( 'page', false ) . ' ' . WPF()->current_object['paged'] . ' | ' : '';
578 if( isset( WPF()->current_object['template'] ) ) {
579 $template = WPF()->current_object['template'];
580 }
581 if( ! empty( WPF()->current_object['forum'] ) ) {
582 $forum = WPF()->current_object['forum'];
583 }
584 if( ! empty( WPF()->current_object['topic'] ) ) {
585 $topic = WPF()->current_object['topic'];
586 }
587 if( ! empty( WPF()->current_object['user'] ) ) {
588 $user = WPF()->current_object['user'];
589 }
590 if( isset( WPF()->current_object ) ) {
591 if( wpfval( WPF()->current_object, 'forumid' ) && ! wpfval( WPF()->current_object, 'topicid' ) ) {
592 if( isset( $forum['title'] ) ) {
593 $title = $forum['title'];
594 }
595 if( isset( WPF()->current_object['forum_meta_desc'] ) && WPF()->current_object['forum_meta_desc'] != '' ) {
596 $description = $paged . WPF()->current_object['forum_meta_desc'];
597 } elseif( isset( WPF()->current_object['forum_desc'] ) && WPF()->current_object['forum_desc'] != '' ) {
598 $description = $paged . WPF()->current_object['forum_desc'];
599 }
600 } elseif( isset( WPF()->current_object['topicid'] ) && isset( $topic['first_postid'] ) ) {
601 $post = WPF()->post->get_post( $topic['first_postid'] );
602 $content = wpforo_content( $post, false );
603 $image = wpforo_find_image_urls( $content, true, 'og:image' );
604 if( isset( $post['title'] ) ) {
605 $title = wpforo_text( $paged . $post['title'], 60, false );
606 }
607 if( isset( $post['body'] ) ) {
608 $description = wpforo_text( $paged . $post['body'], 150, false );
609 }
610 if( isset( $post['body'] ) ) {
611 $schema = wpforo_schema( $forum, $topic, $post );
612 }
613 } elseif( wpforo_is_member_template( $template ) ) {
614 if( isset( WPF()->board->get_current( 'settings' )['title'] ) ) {
615 $title = $paged . WPF()->board->get_current( 'settings' )['title'];
616 }
617 $udata['name'] = ( isset( $user['display_name'] ) && $user['display_name'] ) ? wpforo_phrase(
618 'User',
619 false
620 ) . ': ' . $user['display_name'] : '';
621 $udata['title'] = ( isset( $user['rating']['title'] ) && $user['rating']['title'] ) ? wpforo_phrase(
622 'Title',
623 false
624 ) . ': ' . $user['rating']['title'] : '';
625 $udata['about'] = ( isset( $user['about'] ) && $user['about'] ) ? wpforo_phrase(
626 'About',
627 false
628 ) . ': ' . wpforo_text(
629 $user['about'],
630 150,
631 false
632 ) : '';
633 $description = $title . ' - ' . wpforo_phrase( 'Member Profile', false ) . ' &gt; ' . wpforo_phrase(
634 ucfirst( (string) $template ),
635 false
636 ) . ' ' . wpforo_phrase( 'Page', false ) . '. ' . implode( ', ', $udata );
637 if( ! wpforo_setting( 'seo', 'seo_profile' ) ) {
638 $noindex = "<meta name=\"robots\" content=\"noindex\">\r\n";
639 }
640 } elseif( isset( WPF()->current_object['template'] ) && WPF()->current_object['template'] === 'member' ) {
641 $wpfpaged = ( isset( $_GET['wpfpaged'] ) && $_GET['wpfpaged'] > 1 ) ? wpforo_phrase(
642 'Page',
643 false
644 ) . ' ' . $_GET['wpfpaged'] . ' | ' : '';
645 $description = $wpfpaged . wpforo_phrase( 'Forum Members List', false );
646 } elseif( isset( WPF()->current_object['template'] ) && WPF()->current_object['template'] === 'recent' ) {
647 $wpfpaged = ( isset( $_GET['wpfpaged'] ) && $_GET['wpfpaged'] > 1 ) ? wpforo_phrase(
648 'Page',
649 false
650 ) . ' ' . $_GET['wpfpaged'] . ' | ' : '';
651 $description = $wpfpaged . wpforo_phrase( 'Recent Posts', false );
652 } elseif( isset( WPF()->current_object['template'] ) && WPF()->current_object['template'] === 'tags' ) {
653 $wpfpaged = ( isset( $_GET['wpfpaged'] ) && $_GET['wpfpaged'] > 1 ) ? wpforo_phrase(
654 'Page',
655 false
656 ) . ' ' . $_GET['wpfpaged'] . ' | ' : '';
657 $description = $wpfpaged . wpforo_phrase( 'Tags', false );
658 } else {
659 if( isset( WPF()->board->get_current( 'settings' )['title'] ) ) {
660 $title = $paged . WPF()->board->get_current( 'settings' )['title'];
661 }
662 if( isset( WPF()->board->get_current( 'settings' )['desc'] ) ) {
663 $description = $paged . WPF()->board->get_current( 'settings' )['desc'];
664 }
665 if( isset( WPF()->current_object['template'] ) && ( WPF()->current_object['template'] == 'login' || WPF()->current_object['template'] == 'register' ) ) {
666 $noindex = "<meta name=\"robots\" content=\"noindex\">\r\n";
667 }
668 }
669 $description = strip_tags( str_replace( '>', '> ', $description ) );
670 $description = preg_replace( '#[\t\r\n]+#iu', ' ', $description );
671 if( $image ) {
672 $og_img = '<meta property="og:image" content="' . $image . '" />' . "\r\n";
673 $tw_img = '<meta property="twitter:image" content="' . $image . '" />' . "\r\n";
674 }
675 $meta_tags = "\r\n<!-- wpForo SEO -->\r\n" . $noindex . "<link rel=\"canonical\" href=\"" . $canonical . "\" />\r\n<meta name=\"description\" content=\"" . esc_html(
676 $description
677 ) . "\" />\r\n<meta property=\"og:title\" content=\"" . esc_html(
678 $title
679 ) . "\" />\r\n<meta property=\"og:description\" content=\"" . esc_html(
680 $description
681 ) . "\" />\r\n<meta property=\"og:url\" content=\"" . $canonical . "\" />\r\n<meta property=\"og:locale\" content=\"" . WPF(
682 )->locale . "\" />\r\n" . $og_img . "<meta property=\"og:site_name\" content=\"" . get_bloginfo(
683 'name'
684 ) . "\" />\r\n<meta property=\"og:type\" content=\"website\" />\r\n<meta name=\"twitter:description\" content=\"" . esc_html(
685 $description
686 ) . "\"/>\r\n<meta name=\"twitter:title\" content=\"" . esc_html(
687 $title
688 ) . "\" />\r\n<meta property=\"twitter:card\" content=\"summary_large_image\" />\r\n" . $tw_img . "<!-- wpForo SEO End -->\r\n\r\n";
689 $schema = "<!-- wpForo Schema -->" . $schema . "\r\n<!-- wpForo Schema End -->\r\n\r\n";
690 echo apply_filters( 'wpforo_seo_meta_tags', $meta_tags . $schema );
691 }
692 }
693 }
694
695 add_action( 'wp_head', 'wpforo_add_meta_tags', 1 );
696
697 add_action( 'wp_ajax_wpforo_answer_ajax', 'wpf_answer' );
698 function wpf_answer() {
699 wpforo_verify_nonce( 'wpforo_answer_ajax' );
700 $response = [ 'notice' => WPF()->notice->get_notices() ];
701 if( ! is_user_logged_in() ) {
702 WPF()->notice->add( wpforo_get_login_or_register_notice_text() );
703 $response['notice'] = WPF()->notice->get_notices();
704 wp_send_json_error( $response );
705 }
706 if( ! isset( $_POST['answerstatus'] ) || ! isset( $_POST['postid'] ) || ! $postid = intval( $_POST['postid'] ) ) {
707 WPF()->notice->add( 'action error', 'error' );
708 $response['notice'] = WPF()->notice->get_notices();
709 wp_send_json_error( $response );
710 }
711 if( ! $post = WPF()->post->get_post( $postid ) ) {
712 WPF()->notice->add( 'post not found', 'error' );
713 $response['notice'] = WPF()->notice->get_notices();
714 wp_send_json_error( $response );
715 }
716 if( ! $topic = WPF()->topic->get_topic( $post['topicid'] ) ) {
717 WPF()->notice->add( 'topic not found', 'error' );
718 $response['notice'] = WPF()->notice->get_notices();
719 wp_send_json_error( $response );
720 }
721 if( ! ( WPF()->perm->forum_can( 'at', $post['forumid'] ) || ( WPF()->perm->forum_can(
722 'oat',
723 $post['forumid']
724 ) && WPF()->current_userid == $topic['userid'] ) ) ) {
725 WPF()->notice->add( 'You don\'t have permission to make topic answered', 'error' );
726 $response['notice'] = WPF()->notice->get_notices();
727 wp_send_json_error( $response );
728 }
729 if( intval( $_POST['answerstatus'] ) && WPF()->topic->has_is_answer_post( $topic['topicid'] ) ) {
730 WPF()->notice->add( 'You don\'t have permission to make two best answers for one topic', 'error' );
731 $response['notice'] = WPF()->notice->get_notices();
732 wp_send_json_error( $response );
733 }
734 if( false !== WPF()->db->query(
735 "UPDATE " . WPF()->tables->posts . " SET is_answer = " . intval(
736 $_POST['answerstatus']
737 ) . " WHERE postid = " . intval( $postid )
738 ) ) {
739 wpforo_clean_cache( 'post', $postid, $post );
740 WPF()->db->query(
741 "UPDATE " . WPF()->tables->topics . " SET `solved` = " . intval(
742 $_POST['answerstatus']
743 ) . " WHERE `topicid` = " . intval( $post['topicid'] )
744 );
745 do_action( 'wpforo_answer', intval( $_POST['answerstatus'] ), $post );
746 WPF()->notice->add( 'done', 'success' );
747 $response['notice'] = WPF()->notice->get_notices();
748 wp_send_json_success( $response );
749 }
750 wp_send_json_error( $response );
751 }
752
753 add_action( 'wp_ajax_wpforo_quote_ajax', 'wpf_quote' );
754 add_action( 'wp_ajax_nopriv_wpforo_quote_ajax', 'wpf_quote' );
755 function wpf_quote() {
756 wpforo_verify_nonce( 'wpforo_quote_ajax' );
757 if( ! $current_topicid = wpforo_bigintval( WPF()->current_object['topicid'] ) ) {
758 exit();
759 }
760 $post = WPF()->db->get_row(
761 'SELECT * FROM ' . WPF()->tables->posts . ' WHERE topicid = ' . $current_topicid . ' AND postid =' . wpforo_bigintval(
762 $_POST['postid']
763 ),
764 ARRAY_A
765 );
766 if( ! ( WPF()->perm->forum_can( 'cr', $post['forumid'] ) || ( wpforo_is_owner(
767 wpfval(
768 WPF()->current_object['topic'],
769 'userid'
770 ),
771 wpfval( WPF()->current_object['topic'], 'email' )
772 ) && WPF()->perm->forum_can(
773 'ocr',
774 $post['forumid']
775 ) ) ) ) {
776 return;
777 }
778 $post = apply_filters( 'wpforo_quote_post_ajax', $post );
779 $response = sprintf(
780 '[quote data-userid="%1$d" data-postid="%2$d"]%3$s[/quote]<p></p>',
781 $post['userid'],
782 $post['postid'],
783 wpautop( $post['body'] )
784 );
785 wp_send_json_success( $response );
786 }
787
788 add_action( 'wp_ajax_wpforo_report_ajax', 'wpf_report' );
789 function wpf_report() {
790 wpforo_verify_nonce( 'wpforo_report_ajax' );
791 if( ! is_user_logged_in() ) {
792 WPF()->notice->add( wpforo_get_login_or_register_notice_text() );
793 wp_send_json_error( WPF()->notice->get_notices() );
794 }
795
796 if( ! isset( $_POST['reportmsg'] ) || ! $_POST['reportmsg'] || ! isset( $_POST['postid'] ) || ! $_POST['postid'] ) {
797 WPF()->notice->add( 'Error: please insert some text to report.', 'error' );
798 wp_send_json_error( WPF()->notice->get_notices() );
799 }
800
801 $postid = intval( $_POST['postid'] );
802 $forumid = wpforo_post( $postid, 'forumid' );
803
804 if( ! WPF()->perm->can_report( $forumid ) ) {
805 WPF()->notice->add( 'You are not allowed to report.', 'error' );
806 wp_send_json_error( WPF()->notice->get_notices() );
807 }
808
809 ############### Sending Email ##################
810 $report_text = substr( strip_tags( (string) $_POST['reportmsg'] ), 0, 1000 );
811 $reporter = '<a href="' . WPF()->current_user['profile_url'] . '">' . ( WPF()->current_user['display_name'] ? WPF()->current_user['display_name'] : urldecode(
812 (string) WPF()->current_user['user_nicename']
813 ) ) . '</a>';
814 $reportmsg = wpforo_kses( $report_text, 'email' );
815 $post_url = WPF()->post->get_url( $postid );
816
817 $subject = wpforo_setting( 'email', 'report_email_subject' );
818 $message = wpforo_setting( 'email', 'report_email_message' );
819
820 $from_tags = [ "[reporter]", "[message]", "[post_url]" ];
821 $to_words = [
822 sanitize_text_field( $reporter ),
823 $reportmsg,
824 '<a target="_blank" href="' . esc_url( (string) $post_url ) . '">' . esc_url( (string) $post_url ) . '</a>',
825 ];
826
827 $subject = stripslashes( strip_tags( str_replace( $from_tags, $to_words, (string) $subject ) ) );
828 $message = stripslashes( str_replace( $from_tags, $to_words, (string) $message ) );
829
830 $admin_emails = wpforo_setting( 'email', 'admin_emails' );
831 $admin_email = wpfval( $admin_emails, 0 );
832 $headers = wpforo_admin_mail_headers();
833
834 add_filter( 'wp_mail_content_type', 'wpforo_set_html_content_type', 999 );
835 if( ! @wp_mail( $admin_email, $subject, $message, $headers ) ) {
836 WPF()->notice->add( 'Can\'t send report email', 'error' );
837 wp_send_json_error( WPF()->notice->get_notices() );
838 }
839 remove_filter( 'wp_mail_content_type', 'wpforo_set_html_content_type' );
840
841 ############### Sending Email end ##############
842 do_action( 'wpforo_after_post_report', $postid, $forumid, $_POST['reportmsg'] );
843 WPF()->notice->add( 'Message has been sent', 'success' );
844 wp_send_json_success( WPF()->notice->get_notices() );
845 }
846
847 add_action( 'wp_ajax_wpforo_sticky_ajax', 'wpf_sticky' );
848 add_action( 'wp_ajax_nopriv_wpforo_sticky_ajax', 'wpf_sticky' );
849 function wpf_sticky() {
850 wpforo_verify_nonce( 'wpforo_sticky_ajax' );
851 WPF()->notice->add( 'wrong data', 'error' );
852 $response = [ 'notice' => WPF()->notice->get_notices() ];
853 if( ! $topicid = wpforo_bigintval( wpfval( $_POST, 'topicid' ) ) ) {
854 wp_send_json_error( $response );
855 }
856
857 $sql = "SELECT `forumid` FROM `" . WPF()->tables->topics . "` WHERE `topicid` = $topicid";
858 $forumid = WPF()->db->get_var( $sql );
859 if( ! WPF()->perm->forum_can( 's', $forumid ) ) {
860 WPF()->notice->add( 'You don\'t have permission to do this action from this forum', 'error' );
861 $response['notice'] = WPF()->notice->get_notices();
862 wp_send_json_error( $response );
863 }
864 $status = wpfval( $_POST, 'status' );
865 if( $status === 'sticky' ) {
866 $sql = "UPDATE `" . WPF()->tables->topics . "` SET `type` = 1 WHERE `topicid` = $topicid";
867 if( false !== WPF()->db->query( $sql ) ) {
868 wpforo_clean_cache( 'topic-first-post', $topicid );
869 WPF()->notice->add( 'Done!', 'success' );
870 $response['notice'] = WPF()->notice->get_notices();
871 wp_send_json_success( $response );
872 }
873 } elseif( $status === 'unsticky' ) {
874 $sql = "UPDATE `" . WPF()->tables->topics . "` SET `type` = 0 WHERE `topicid` = $topicid";
875 if( false !== WPF()->db->query( $sql ) ) {
876 wpforo_clean_cache( 'topic-first-post', $topicid );
877 WPF()->notice->add( 'Done!', 'success' );
878 $response['notice'] = WPF()->notice->get_notices();
879 wp_send_json_success( $response );
880 }
881 }
882 wp_send_json_error( $response );
883 }
884
885 add_action( 'wp_ajax_wpforo_private_ajax', 'wpf_private' );
886 function wpf_private() {
887 wpforo_verify_nonce( 'wpforo_private_ajax' );
888 if( ! WPF()->current_userid ) {
889 wp_send_json_error();
890 }
891 if( ! ( $topicid = wpforo_bigintval( wpfval( $_POST, 'topicid' ) ) ) ) {
892 wp_send_json_error();
893 }
894 if( ! ( $topic = WPF()->topic->get_topic( $topicid ) ) ) {
895 wp_send_json_error();
896 }
897 if( ! ( WPF()->perm->forum_can( 'p', $topic['forumid'] ) || ( WPF()->current_userid == $topic['userid'] && WPF()->perm->forum_can( 'op', $topic['forumid'] ) ) ) ) {
898 wp_send_json_error();
899 }
900 $status = wpfval( $_POST, 'status' );
901 if( $status === 'private' ) {
902 WPF()->topic->wprivate( $topicid, 1 );
903 wp_send_json_success();
904 } elseif( $status === 'public' ) {
905 WPF()->topic->wprivate( $topicid, 0 );
906 wp_send_json_success();
907 }
908 wp_send_json_error();
909 }
910
911 add_action( 'wp_ajax_wpforo_solved_ajax', 'wpf_solved' );
912 add_action( 'wp_ajax_nopriv_wpforo_solved_ajax', 'wpf_solved' );
913 function wpf_solved() {
914 wpforo_verify_nonce( 'wpforo_solved_ajax' );
915 if( ! WPF()->current_userid ) {
916 wp_send_json_error();
917 }
918 if( ! $postid = wpforo_bigintval( wpfval( $_POST, 'postid' ) ) ) {
919 wp_send_json_error();
920 }
921 if( $post = WPF()->post->get_post( $postid ) ) {
922 if( WPF()->perm->forum_can( 'sv', $post['forumid'] ) || ( WPF()->current_userid == $post['userid'] && WPF()->perm->forum_can( 'osv', $post['forumid'] ) ) ) {
923 $solved = ( wpfval( $_POST, 'status' ) === 'solved' ? 1 : 0 );
924 $sql = "UPDATE " . WPF()->tables->topics . " SET `solved` = %d WHERE `topicid` = %d";
925 WPF()->db->query( WPF()->db->prepare( $sql, $solved, $post['topicid'] ) );
926 wpforo_clean_cache( 'topic-first-post', $post['topicid'] );
927
928 // Fire action hook for topic solved/unsolved
929 $topic = WPF()->topic->get_topic( $post['topicid'] );
930 if( $topic ) {
931 if( $solved ) {
932 do_action( 'wpforo_topic_solved', $topic, $post );
933 } else {
934 do_action( 'wpforo_topic_unsolved', $topic, $post );
935 }
936 }
937
938 wp_send_json_success();
939 }
940 }
941 wp_send_json_error();
942 }
943
944 add_action( 'wp_ajax_wpforo_approve_ajax', 'wpf_approve' );
945 function wpf_approve() {
946 wpforo_verify_nonce( 'wpforo_approve_ajax' );
947 if( ! WPF()->current_userid ) {
948 WPF()->notice->add( wpforo_get_login_or_register_notice_text() );
949 wp_send_json_error();
950 }
951 if( ! $postid = wpforo_bigintval( wpfval( $_POST, 'postid' ) ) ) {
952 wp_send_json_error();
953 }
954 $post = WPF()->post->get_post( $postid );
955 if( ! $post || ! WPF()->perm->forum_can( 'au', $post['forumid'] ) ) {
956 wp_send_json_error();
957 }
958 $status = wpfval( $_POST, 'status' );
959 if( $status === 'approve' ) {
960 WPF()->moderation->post_approve( $postid );
961 wp_send_json_success();
962 } elseif( $status === 'unapprove' ) {
963 WPF()->moderation->post_unapprove( $postid );
964 wp_send_json_success();
965 }
966 wp_send_json_error();
967 }
968
969 add_action( 'wp_ajax_wpforo_close_ajax', 'wpf_close' );
970 function wpf_close() {
971 wpforo_verify_nonce( 'wpforo_close_ajax' );
972 if( ! WPF()->current_userid ) {
973 wp_send_json_error();
974 }
975
976 if( ! $topicid = wpforo_bigintval( wpfval( $_POST, 'topicid' ) ) ) {
977 wp_send_json_error();
978 }
979 $topic = WPF()->topic->get_topic( $topicid );
980 if( ! $topic || ! WPF()->perm->forum_can( 'cot', $topic['forumid'] ) ) {
981 wp_send_json_error();
982 }
983 $status = wpfval( $_POST, 'status' );
984 $topic = WPF()->topic->get_topic( $topicid );
985
986 if( $status === 'closed' ) {
987 WPF()->topic->open( $topicid );
988 if( $topic ) {
989 do_action( 'wpforo_topic_opened', $topic );
990 }
991 wp_send_json_success();
992 } elseif( $status === 'close' ) {
993 WPF()->topic->close( $topicid );
994 if( $topic ) {
995 do_action( 'wpforo_topic_closed', $topic );
996 }
997 wp_send_json_success();
998 }
999 wp_send_json_error();
1000 }
1001
1002 add_action( 'wp_ajax_wpforo_post_edit', 'wpforo_post_edit' );
1003 add_action( 'wp_ajax_nopriv_wpforo_post_edit', 'wpforo_post_edit' );
1004 function wpforo_post_edit() {
1005 wpforo_verify_nonce( 'wpforo_post_edit' );
1006 $r = [ 'html' => '' ];
1007 if( $postid = wpforo_bigintval( wpfval( $_POST, 'postid' ) ) ) {
1008 if( $post = WPF()->post->get_post( $postid, false ) ) {
1009 if( WPF()->perm->forum_can( 'eor', $post['forumid'] ) || WPF()->perm->forum_can(
1010 'eot',
1011 $post['forumid']
1012 ) ) {
1013 if( $topic = WPF()->topic->get_topic( $post['topicid'] ) ) {
1014 $postmetas = (array) WPF()->postmeta->get_postmeta( $postid, '', true );
1015 $post['body'] = htmlspecialchars( $post['body'], ENT_NOQUOTES );
1016 $values = array_merge( $post, $topic, $postmetas );
1017 $values = apply_filters( 'wpforo_edit_post_ajax', $values, $post, $topic, $postmetas );
1018 ob_start();
1019 if( intval( $post['is_first_post'] ) ) {
1020 WPF()->form->current['varname'] = 'thread';
1021 WPF()->tpl->topic_form( $post['forumid'], $values );
1022 } else {
1023 WPF()->form->current['varname'] = 'post';
1024 if( trim( (string) $post['title'] ) ) {
1025 $values['title'] = $post['title'];
1026 }
1027 WPF()->tpl->reply_form( $topic, $values );
1028 }
1029 $r['html'] = ob_get_clean();
1030 wp_send_json_success( $r );
1031 }
1032 }
1033 }
1034 }
1035 wp_send_json_error( $r );
1036 }
1037
1038 add_action( 'wp_ajax_wpforo_delete_ajax', 'wpf_delete' );
1039 function wpf_delete() {
1040 wpforo_verify_nonce( 'wpforo_delete_ajax' );
1041 $resp = [];
1042 $status = (string) wpfval( $_POST, 'status' );
1043 $postid = (int) wpfval( $_POST, 'postid' );
1044 if( $status === 'topic' ) {
1045 if( WPF()->topic->delete( $postid ) ) {
1046 $forumid = (int) wpfval( $_POST, 'forumid' );
1047 $resp = [
1048 'postid' => $postid,
1049 'location' => $forumid ? WPF()->forum->get_forum_url( $forumid ) : wpforo_home_url(),
1050 ];
1051 $resp['notice'] = WPF()->notice->get_notices();
1052 wp_send_json_success( $resp );
1053 }
1054 } elseif( $status === 'reply' ) {
1055 if( WPF()->post->delete( $postid ) ) {
1056 $root = (int) WPF()->post->get_root( $postid );
1057 $root_replies_count = (int) WPF()->post->get_root_replies_count( $root );
1058 $resp = [
1059 'postid' => $postid,
1060 'root' => $root,
1061 'root_count' => $root_replies_count,
1062 ];
1063 $resp['notice'] = WPF()->notice->get_notices();
1064 wp_send_json_success( $resp );
1065 }
1066 }
1067
1068 $resp['notice'] = WPF()->notice->get_notices();
1069 wp_send_json_error( $resp );
1070 }
1071
1072 add_action( 'wp_ajax_wpforo_layout4_loadmore', 'wpfl4_loadmore' );
1073 add_action( 'wp_ajax_nopriv_wpforo_layout4_loadmore', 'wpfl4_loadmore' );
1074 function wpfl4_loadmore() {
1075 wpforo_verify_nonce( 'wpforo_layout4_loadmore' );
1076 $success = false;
1077 WPF()->notice->add( 'wrong data', 'error' );
1078 $response = [ 'no_more' => 0, 'output_html' => '', 'notice' => WPF()->notice->get_notices() ];
1079 $request = [
1080 'forumid' => 0,
1081 'filter' => 'newest',
1082 'paged' => 1,
1083 ];
1084 $request = array_merge( $request, $_POST );
1085
1086 if( $forumid = intval( $request['forumid'] ) ) {
1087 $items_count = 0;
1088 $childs = WPF()->forum->get_childs( $forumid );
1089 $childs[] = $forumid;
1090 $args = [
1091 'offset' => ( $request['paged'] - 1 ) * wpforo_setting( 'forums', 'layout_threaded_intro_topics_count' ),
1092 'row_count' => wpforo_setting( 'forums', 'layout_threaded_intro_topics_count' ),
1093 'forumids' => $childs,
1094 'orderby' => 'type, modified',
1095 'order' => 'DESC',
1096 ];
1097
1098 switch( $request['filter'] ) {
1099 case 'solved':
1100 $args['solved'] = 1;
1101 $args['type'] = 0;
1102 break;
1103 case 'unsolved':
1104 $args['solved'] = 0;
1105 $args['type'] = 0;
1106 $args['closed'] = 0;
1107 break;
1108 case 'hottest':
1109 $args['orderby'] = 'posts';
1110 break;
1111 }
1112
1113 $topics = WPF()->topic->get_topics( $args, $items_count );
1114 if( $topics ) {
1115 ob_start();
1116 if( function_exists( 'wpforo_thread_forum_template' ) ) {
1117 foreach( $topics as $topic ) {
1118 wpforo_thread_forum_template( $topic['topicid'] );
1119 }
1120 }
1121 $response['output_html'] = ob_get_clean();
1122 $success = true;
1123 $response['notice'] = '';
1124 if( count( $topics ) < wpforo_setting( 'forums', 'layout_threaded_intro_topics_count' ) ) {
1125 $response['no_more'] = 1;
1126 }
1127 } else {
1128 $response['no_more'] = 1;
1129 }
1130
1131 if( $response['no_more'] ) {
1132 WPF()->notice->add( 'all topics has been loaded in this list', 'success' );
1133 $response['notice'] = WPF()->notice->get_notices();
1134 }
1135 }
1136
1137 if( $success ) {
1138 wp_send_json_success( $response );
1139 } else {
1140 wp_send_json_error( $response );
1141 }
1142 }
1143
1144 add_action( 'wp_ajax_wpforo_load_more_activities', 'wpforo_load_more_activities' );
1145 add_action( 'wp_ajax_nopriv_wpforo_load_more_activities', 'wpforo_load_more_activities' );
1146 function wpforo_load_more_activities() {
1147 wpforo_verify_nonce( 'wpforo_load_more_activities' );
1148
1149 $items_per_page = 20;
1150 $page = ! empty( $_POST['page'] ) ? intval( $_POST['page'] ) : 1;
1151 $activity_type = ! empty( $_POST['type'] ) ? sanitize_text_field( $_POST['type'] ) : 'all';
1152 $period = ! empty( $_POST['period'] ) ? sanitize_text_field( $_POST['period'] ) : 'week';
1153
1154 // Calculate date_from based on period
1155 $date_from = null;
1156 switch( $period ) {
1157 case 'day':
1158 $date_from = time() - ( 24 * 60 * 60 );
1159 break;
1160 case 'week':
1161 $date_from = time() - ( 7 * 24 * 60 * 60 );
1162 break;
1163 case 'month':
1164 $date_from = time() - ( 30 * 24 * 60 * 60 );
1165 break;
1166 case 'all':
1167 default:
1168 $date_from = null;
1169 break;
1170 }
1171
1172 // Get enabled activity types from settings
1173 $enabled_types = WPF()->settings->activity['enabled_types'] ?? [];
1174
1175 // Build activity query args
1176 $args = [
1177 'types_exclude' => [ 'new_reply' ], // Exclude notification-only types
1178 'orderby' => 'date',
1179 'order' => 'DESC',
1180 'offset' => ( $page - 1 ) * $items_per_page,
1181 'row_count' => $items_per_page,
1182 'date_from' => $date_from,
1183 ];
1184
1185 // Filter by activity type
1186 if( $activity_type !== 'all' ) {
1187 $type_mapping = [
1188 'topic' => [ 'wpforo_topic', 'edit_topic' ],
1189 'reply' => [ 'wpforo_post', 'edit_post' ],
1190 'reaction' => [ 'new_like', 'new_dislike', 'new_up_vote', 'new_down_vote', 'new_reaction' ],
1191 'favorite' => [ 'new_favorite' ],
1192 'solved' => [ 'topic_solved' ],
1193 'closed' => [ 'topic_closed' ],
1194 'answer' => [ 'post_answer' ],
1195 ];
1196 if( isset( $type_mapping[ $activity_type ] ) ) {
1197 // Intersect with enabled types to respect settings
1198 $args['types_include'] = array_intersect( $type_mapping[ $activity_type ], $enabled_types );
1199 }
1200 } else {
1201 // Show all enabled types
1202 if( ! empty( $enabled_types ) ) {
1203 $args['types_include'] = $enabled_types;
1204 }
1205 }
1206
1207 $items_count = 0;
1208 $activities = WPF()->activity->get_activities( $args, $items_count, true, true );
1209 $has_more = ( $page * $items_per_page ) < $items_count;
1210
1211 // Generate HTML for timeline items
1212 $html = '';
1213 if( ! empty( $activities ) ) {
1214 $index = 0;
1215 foreach( $activities as $activity ) {
1216 // For non-content actions (reactions, favorites, votes, etc.), the actor is in itemid_second
1217 $actor_actions = [ 'new_like', 'new_dislike', 'new_up_vote', 'new_down_vote', 'new_reaction', 'new_mention', 'new_favorite', 'topic_solved', 'topic_closed', 'post_answer' ];
1218 $actor_userid = in_array( $activity['type'], $actor_actions ) && ! empty( $activity['itemid_second'] )
1219 ? $activity['itemid_second']
1220 : $activity['userid'];
1221 $member = wpforo_member( $actor_userid );
1222 $icon = wpforo_activity_icon( $activity['type'] );
1223 $info_html = wpforo_activity_info_html( $activity, $member );
1224 $show_excerpt = in_array( $activity['type'], [ 'wpforo_topic', 'wpforo_post' ] );
1225 $excerpt = '';
1226 if( $show_excerpt && $activity['itemid'] ) {
1227 // For wpforo_topic, itemid is topicid - get first post via topic's first_postid
1228 if( $activity['type'] === 'wpforo_topic' ) {
1229 $topic_data = WPF()->topic->get_topic( $activity['itemid'] );
1230 if( $topic_data && ! empty( $topic_data['first_postid'] ) ) {
1231 $first_post = WPF()->post->get_post( $topic_data['first_postid'] );
1232 if( $first_post && ! empty( $first_post['body'] ) ) {
1233 $excerpt = wp_trim_words( strip_tags( $first_post['body'] ), 20 );
1234 }
1235 }
1236 } else {
1237 $post = WPF()->post->get_post( $activity['itemid'] );
1238 if( $post && ! empty( $post['body'] ) ) {
1239 $excerpt = wp_trim_words( strip_tags( $post['body'] ), 20 );
1240 }
1241 }
1242 }
1243
1244 $html .= '<div class="wpf-timeline-item wpf-timeline-' . esc_attr( $activity['type'] ) . '" data-activity-id="' . esc_attr( $activity['id'] ) . '" style="--delay: ' . ( $index * 0.1 ) . 's">';
1245 $html .= '<div class="wpf-timeline-left">';
1246 if( WPF()->usergroup->can( 'va' ) && wpforo_setting( 'profiles', 'avatars' ) ) {
1247 $html .= '<div class="wpf-timeline-avatar">' . wpforo_user_avatar( $member, 40 ) . '</div>';
1248 }
1249 $html .= '<div class="wpf-timeline-user">';
1250 ob_start();
1251 wpforo_member_link( $member );
1252 $html .= ob_get_clean();
1253 $html .= '</div>';
1254 $html .= '<div class="wpf-timeline-date">';
1255 ob_start();
1256 wpforo_date( $activity['date'], 'ago' );
1257 $html .= ob_get_clean();
1258 $html .= '</div>';
1259 $html .= '</div>';
1260 $html .= '<div class="wpf-timeline-node"><div class="wpf-timeline-icon">' . $icon . '</div></div>';
1261 $html .= '<div class="wpf-timeline-right"><div class="wpf-timeline-card">';
1262 if( WPF()->usergroup->can( 'aum' ) ) {
1263 $html .= '<button type="button" class="wpf-activity-delete" title="' . esc_attr( wpforo_phrase( 'Delete Activity', false ) ) . '"><i class="fas fa-trash-alt"></i></button>';
1264 }
1265 $html .= '<div class="wpf-timeline-activity">' . $info_html . '</div>';
1266 if( $show_excerpt && $excerpt ) {
1267 $html .= '<div class="wpf-timeline-excerpt">' . esc_html( $excerpt ) . '</div>';
1268 }
1269 $html .= '</div></div>';
1270 $html .= '</div>';
1271
1272 $index++;
1273 }
1274 }
1275
1276 wp_send_json_success( [
1277 'html' => $html,
1278 'has_more' => $has_more,
1279 ] );
1280 }
1281
1282 add_action( 'wp_ajax_wpforo_delete_activity', 'wpforo_delete_activity' );
1283 function wpforo_delete_activity() {
1284 wpforo_verify_nonce( 'wpforo_delete_activity' );
1285
1286 // Permission check
1287 if( ! WPF()->usergroup->can( 'aum' ) ) {
1288 wp_send_json_error( [ 'message' => wpforo_phrase( 'Permission denied', false ) ] );
1289 }
1290
1291 $activity_id = ! empty( $_POST['activity_id'] ) ? wpforo_bigintval( $_POST['activity_id'] ) : 0;
1292 if( ! $activity_id ) {
1293 wp_send_json_error( [ 'message' => wpforo_phrase( 'Invalid activity', false ) ] );
1294 }
1295
1296 if( WPF()->activity->delete_activity( $activity_id ) ) {
1297 wp_send_json_success( [ 'message' => wpforo_phrase( 'Activity deleted', false ) ] );
1298 } else {
1299 wp_send_json_error( [ 'message' => wpforo_phrase( 'Failed to delete activity', false ) ] );
1300 }
1301 }
1302
1303 add_action( 'wp_ajax_wpforo_topic_portable_form', 'wpforo_topic_portable_form' );
1304 add_action( 'wp_ajax_nopriv_wpforo_topic_portable_form', 'wpforo_topic_portable_form' );
1305 function wpforo_topic_portable_form() {
1306 wpforo_verify_nonce( 'wpforo_topic_portable_form' );
1307 $html = '';
1308 if( $forumid = wpfval( $_POST, 'forumid' ) ) {
1309 WPF()->form->current['varname'] = 'thread';
1310 ob_start();
1311 WPF()->tpl->topic_form( $forumid );
1312 do_action( 'wpforo_topic_portable_form_extra_html', $forumid );
1313 $html = trim( (string) ob_get_clean() );
1314 }
1315 if( $html ) {
1316 wp_send_json_success( $html );
1317 } else {
1318 wp_send_json_error();
1319 }
1320 }
1321
1322 add_action( 'wp_ajax_wpforo_qa_comment_loadrest', 'wpforo_qa_comment_loadrest' );
1323 add_action( 'wp_ajax_nopriv_wpforo_qa_comment_loadrest', 'wpforo_qa_comment_loadrest' );
1324 function wpforo_qa_comment_loadrest() {
1325 wpforo_verify_nonce( 'wpforo_qa_comment_loadrest' );
1326 WPF()->notice->add( 'wrong data', 'error' );
1327 $response = [ 'output_html' => '', 'notice' => WPF()->notice->get_notices() ];
1328 if( $parentid = wpfval( $_POST, 'parentid' ) ) {
1329 $args = [
1330 'root' => $parentid,
1331 'offset' => wpforo_setting( 'topics', 'layout_qa_comments_limit_count' ),
1332 'row_count' => PHP_INT_MAX,
1333 ];
1334 if( ! wpforo_root_exist() ) {
1335 unset( $args['root'] );
1336 $args['parentid'] = $parentid;
1337 }
1338 if( $comments = WPF()->post->get_posts( $args ) ) {
1339 ob_start();
1340 include_once( wpftpl( 'layouts/3/comment.php' ) );
1341 ob_clean();
1342
1343 foreach( $comments as $comment ) {
1344 wpforo_qa_comment_template( $comment );
1345 }
1346
1347 $response['output_html'] = ob_get_clean();
1348 $response['notice'] = '';
1349 wp_send_json_success( $response );
1350 }
1351 }
1352 wp_send_json_error( $response );
1353 }
1354
1355 add_action( 'wp_ajax_wpforo_post_url_fixer', 'wpforo_post_url_fixer' );
1356 add_action( 'wp_ajax_nopriv_wpforo_post_url_fixer', 'wpforo_post_url_fixer' );
1357 function wpforo_post_url_fixer() {
1358 wpforo_verify_nonce( 'wpforo_post_url_fixer' );
1359 if( ( $postid = wpforo_bigintval( wpfval( $_POST, 'postid' ) ) ) && ( $referer = wpfval( $_POST, 'referer' ) ) ) {
1360 if( is_wpforo_url( $referer ) ) {
1361 $diff = 100;
1362 $referer_hash = md5( $referer . $postid );
1363 $nowtime = time();
1364 if( $lasttime = (int) get_transient( 'wpforo_post_url_fixer' . $referer_hash ) ) {
1365 $diff = $nowtime - $lasttime;
1366 }
1367 if( $diff <= 8 ) {
1368 exit();
1369 }
1370 set_transient( 'wpforo_post_url_fixer' . $referer_hash, $nowtime, 1000 );
1371 if( $post = WPF()->post->get_post( $postid ) ) {
1372 echo WPF()->post->get_url( $post );
1373 }
1374 }
1375 }
1376 exit();
1377 }
1378
1379 add_action( 'wp_ajax_wpforo_update_database', 'wpforo_ajax_update_database' );
1380 function wpforo_ajax_update_database() {
1381 check_admin_referer( 'wpforo_update_database' );
1382 wpforo_set_max_execution_time();
1383 wpforo_update_db();
1384 exit();
1385 }
1386
1387 ############### Sending Email ##################
1388 function wpforo_set_html_content_type() {
1389 return apply_filters( 'wpforo_emails_content_type', 'text/html' );
1390 }
1391
1392 function __wpforo_set_html_content_type() {
1393 return 'text/html';
1394 }
1395
1396 function wpforo_mail_from_name() {
1397 return wpforo_setting( 'email', 'from_name' ) ?: get_option( 'blogname' );
1398 }
1399
1400 function wpforo_mail_from_email() {
1401 return wpforo_setting( 'email', 'from_email' ) ?: get_option( 'admin_email' );
1402 }
1403
1404 function wpforo_mail_headers( $from_name = '', $from_email = '', $cc = [], $bcc = [] ) {
1405 $H = [];
1406 if( ! $from_name ) {
1407 $from_name = wpforo_mail_from_name();
1408 }
1409 if( ! $from_email ) {
1410 $from_email = wpforo_mail_from_email();
1411 }
1412 $H[] = 'From: ' . $from_name . ' <' . $from_email . '>';
1413 if( ! empty( $cc ) ) {
1414 foreach( $cc as $c ) {
1415 $c = sanitize_email( $c );
1416 $H[] = 'CC: ' . $c;
1417 }
1418 }
1419 if( ! empty( $bcc ) ) {
1420 foreach( $bcc as $b ) {
1421 $b = sanitize_email( $b );
1422 $H[] = 'BCC: ' . $b;
1423 }
1424 }
1425
1426 return $H;
1427 }
1428
1429 function wpforo_admin_mail_headers( $from_name = '', $from_email = '', $cc = [], $bcc = [] ) {
1430 $H = [];
1431 if( ! $from_name ) {
1432 $from_name = wpforo_mail_from_name();
1433 }
1434 if( ! $from_email ) {
1435 $from_email = wpforo_mail_from_email();
1436 }
1437 $H[] = 'From: ' . $from_name . ' <' . $from_email . '>';
1438 if( empty( $cc ) ) $cc = wpforo_setting( 'email', 'admin_emails' );
1439 if( ! empty( $cc ) ) {
1440 foreach( $cc as $c ) {
1441 $c = sanitize_email( $c );
1442 $H[] = 'CC: ' . $c;
1443 }
1444 }
1445 if( ! empty( $bcc ) ) {
1446 foreach( $bcc as $b ) {
1447 $b = sanitize_email( $b );
1448 $H[] = 'BCC: ' . $b;
1449 }
1450 }
1451
1452 return $H;
1453 }
1454
1455 function wpforo_get_login_or_register_notice_text() {
1456 $popup_html = '';
1457 if( ! wpforo_is_bot() ) {
1458 $popup_html = sprintf(
1459 wpforo_phrase( 'Please %s or %s', false ),
1460 '<a href="' . wpforo_login_url() . '" rel="noindex,nofollow">' . wpforo_phrase(
1461 'Login',
1462 false
1463 ) . '</a>',
1464 '<a href="' . wpforo_register_url() . '" rel="noindex,nofollow">' . wpforo_phrase(
1465 'Register',
1466 false
1467 ) . '</a>'
1468 );
1469 }
1470
1471 return apply_filters( 'wpforo_login_or_register_popup_message', $popup_html );
1472 }
1473
1474 function wpforo_dynamic_phrases_register() {
1475 if( ! $js = WPF()->phrase->get_wpforo_phrases_inline_js() ) {
1476 return;
1477 }
1478 $md5_js = md5( $js );
1479
1480 $inline = false;
1481 $dynamic_js_file = WPF()->folders['assets']['dir'] . DIRECTORY_SEPARATOR . 'phrases.js';
1482 if( ! file_exists( $dynamic_js_file ) || $md5_js !== md5_file( $dynamic_js_file ) ) {
1483 $result = wpforo_write_file( $dynamic_js_file, $js );
1484 if( wpfval( $result, 'error' ) ) {
1485 $inline = true;
1486 }
1487 }
1488
1489 wp_register_script(
1490 'wpforo-dynamic-phrases',
1491 WPF()->folders['assets']['url'] . '/phrases.js',
1492 false,
1493 WPFORO_VERSION . '.' . $md5_js
1494 );
1495 if( $inline ) {
1496 $js = preg_replace( '|[\r\n\t]+|', '', $js );
1497 wp_add_inline_script( 'wpforo-dynamic-phrases', $js );
1498 }
1499 }
1500
1501 function wpforo_dynamic_style_enqueue() {
1502 if( ! $css = WPF()->tpl->generate_dynamic_css() ) {
1503 return;
1504 }
1505 $md5_css = md5( $css );
1506
1507 $inline = false;
1508 $dynamic_css_file = WPF()->folders['assets']['dir'] . DIRECTORY_SEPARATOR . 'colors.css';
1509 if( ! file_exists( $dynamic_css_file ) || $md5_css !== md5_file( $dynamic_css_file ) ) {
1510 $result = wpforo_write_file( $dynamic_css_file, $css );
1511 if( wpfval( $result, 'error' ) ) {
1512 $inline = true;
1513 }
1514 }
1515
1516 wp_register_style(
1517 'wpforo-dynamic-style',
1518 WPF()->folders['assets']['url'] . '/colors.css',
1519 false,
1520 WPFORO_VERSION . '.' . $md5_css
1521 );
1522 if( $inline ) {
1523 $css = preg_replace( '|[\r\n\t]+|', '', $css );
1524 wp_add_inline_style( 'wpforo-dynamic-style', $css );
1525 }
1526
1527 wp_enqueue_style( 'wpforo-dynamic-style' );
1528 }
1529
1530 add_action( 'wp_enqueue_scripts', 'wpforo_dynamic_style_enqueue', 999 );
1531
1532 function wpforo_frontend_register_scripts() {
1533 wp_register_style(
1534 'wpforo-font-awesome',
1535 WPFORO_URL . '/assets/css/font-awesome/css/fontawesome-all.min.css',
1536 false,
1537 '6.1.1'
1538 );
1539 //wp_register_style( 'wpforo-font-awesome-rtl', WPFORO_URL . '/assets/css/font-awesome/css/font-awesome-rtl.css', [ 'wpforo-font-awesome' ], WPFORO_VERSION );
1540 wpforo_dynamic_phrases_register();
1541 wp_register_script( 'wpforo-frontend-js', WPFORO_URL . '/assets/js/frontend.js', [
1542 'jquery',
1543 'wpforo-dynamic-phrases',
1544 ], WPFORO_VERSION, true );
1545 wp_localize_script( 'wpforo-frontend-js', 'wpforo', [
1546 'ajax_url' => wpforo_get_ajax_url(),
1547 'nonces' => wpforo_generate_ajax_nonces(),
1548 'settings_slugs' => WPF()->settings->slugs,
1549 'editor_settings' => WPF()->tpl->editor_buttons( 'post' ),
1550 'revision_options' => WPF()->settings->posting,
1551 'notice' => [
1552 'login_or_register' => wpforo_get_login_or_register_notice_text(),
1553 'timeouts' => WPF()->notice->get_timeouts(),
1554 ],
1555 ] );
1556 // Register AI features script if AI service is available and any frontend AI feature is enabled
1557 // ai-features.js handles: assistant widget, translation, topic summary, topic suggestions, bot reply
1558 if( isset( WPF()->ai_client ) && WPF()->ai_client->is_service_available() && (
1559 wpforo_setting( 'ai', 'assistant' ) ||
1560 wpforo_setting( 'ai', 'translation' ) ||
1561 wpforo_setting( 'ai', 'topic_summary' ) ||
1562 wpforo_setting( 'ai', 'topic_suggestions' ) ||
1563 wpforo_setting( 'ai', 'bot_reply' )
1564 ) ) {
1565 wp_register_script( 'wpforo-ai-features-js', WPFORO_URL . '/assets/js/ai-features.js', [
1566 'wpforo-frontend-js',
1567 ], WPFORO_VERSION, true );
1568 }
1569 // Register AI Chatbot script separately (can be large, loaded conditionally)
1570 if( isset( WPF()->ai_chatbot ) && WPF()->ai_chatbot->is_enabled() ) {
1571 wp_register_script( 'wpforo-ai-chatbot-js', WPFORO_URL . '/assets/js/ai-chatbot.js', [
1572 'wpforo-frontend-js',
1573 ], WPFORO_VERSION, true );
1574 wp_localize_script( 'wpforo-ai-chatbot-js', 'wpforo_ai_chatbot', [
1575 'ajax_url' => wpforo_get_ajax_url(),
1576 'nonce' => wp_create_nonce( 'wpforo_ai_chatbot' ),
1577 'welcome_message' => wpforo_setting( 'ai', 'chatbot_welcome_message' ),
1578 'use_rag' => (bool) wpforo_setting( 'ai', 'chatbot_use_rag' ),
1579 'use_local_context' => (bool) wpforo_setting( 'ai', 'chatbot_use_local_context' ),
1580 'phrases' => [
1581 'new_conversation' => wpforo_phrase( 'New Conversation', false ),
1582 'send_message' => wpforo_phrase( 'Send a message...', false ),
1583 'delete_confirm' => wpforo_phrase( 'Delete this conversation?', false ),
1584 'error_sending' => wpforo_phrase( 'Error sending message. Please try again.', false ),
1585 'typing' => wpforo_phrase( 'AI is thinking...', false ),
1586 'no_conversations' => wpforo_phrase( 'No conversations yet', false ),
1587 'start_conversation' => wpforo_phrase( 'Start a new conversation to chat with the AI assistant.', false ),
1588 ],
1589 ] );
1590 }
1591 wp_register_script( 'wpforo-ajax', WPFORO_URL . '/assets/js/ajax.js', [
1592 'suggest',
1593 'wpforo-frontend-js',
1594 ], WPFORO_VERSION, true );
1595 wp_register_style( 'wpforo-style', wpftpl_url( 'style.css' ), false, WPFORO_VERSION );
1596 wp_register_style( 'wpforo-style-rtl', wpftpl_url( 'style-rtl.css' ), false, WPFORO_VERSION );
1597 wp_register_style( 'wpforo-widgets', wpftpl_url( 'widgets.css' ), [], WPFORO_VERSION );
1598 wp_register_style( 'wpforo-widgets-rtl', wpftpl_url( 'widgets-rtl.css' ), [], WPFORO_VERSION );
1599 wp_register_script( 'wpforo-widgets-js', WPFORO_URL . '/assets/js/widgets.js', [ 'jquery' ], WPFORO_VERSION, true );
1600 $wpforo_widgets = [
1601 'ajax_url' => wpforo_get_ajax_url(),
1602 'is_live_notifications_on' => 0,
1603 'live_notifications_start' => 30000,
1604 'live_notifications_interval' => 60000,
1605 ];
1606 if( WPF()->current_userid && wpforo_setting( 'notifications', 'notifications' ) && wpforo_setting(
1607 'notifications',
1608 'notifications_live'
1609 ) ) {
1610 $start = apply_filters( 'wpforo_notifications_list', 30000 );
1611 $interval = apply_filters( 'wpforo_notifications_list', 60000 );
1612 if( $interval < 10000 ) {
1613 $interval = 10000;
1614 }
1615 $wpforo_widgets['is_live_notifications_on'] = 1;
1616 $wpforo_widgets['live_notifications_start'] = $start;
1617 $wpforo_widgets['live_notifications_interval'] = $interval;
1618 }
1619 wp_localize_script( 'wpforo-widgets-js', 'wpforo_widgets', $wpforo_widgets );
1620
1621 if( ! WPF()->perm->forum_can( 'va' ) || ! WPF()->usergroup->can( 'caa' ) ) {
1622 wp_add_inline_script(
1623 'wpforo-frontend-js',
1624 "jQuery(document).ready(function($){
1625 $('#wpforo-wrap').on('click', '.attach_cant_view', function(){
1626 wpforo_notice_show(
1627 '<p>" . addslashes(
1628 (string) ( is_user_logged_in() ? wpforo_phrase(
1629 'You are not permitted to view this attachment',
1630 false
1631 ) : wpforo_get_login_or_register_notice_text() )
1632 ) . "</p>'
1633 );
1634 });
1635 })"
1636 );
1637 }
1638
1639 do_action( 'wpforo_frontend_register_scripts' );
1640
1641 wpforo_frontend_enqueue_scripts();
1642 }
1643
1644 add_action( 'wp_enqueue_scripts', 'wpforo_frontend_register_scripts' );
1645
1646 function wpforo_frontend_enqueue_scripts() {
1647 $fontawesome = wpforo_setting( 'general', 'fontawesome' );
1648 if( $fontawesome === 'sitewide' || ( $fontawesome === 'forum' && is_wpforo_page() ) ) {
1649 wp_enqueue_style( 'wpforo-font-awesome' );
1650 //if( is_rtl() ) wp_enqueue_style( 'wpforo-font-awesome-rtl' );
1651 }
1652
1653 if( is_wpforo_page() ) {
1654 wp_enqueue_script( 'wpforo-dynamic-phrases' );
1655 wp_enqueue_script( 'wpforo-frontend-js' );
1656 // Enqueue AI features script if AI service is available and any frontend AI feature is enabled
1657 if( isset( WPF()->ai_client ) && WPF()->ai_client->is_service_available() && (
1658 wpforo_setting( 'ai', 'assistant' ) ||
1659 wpforo_setting( 'ai', 'translation' ) ||
1660 wpforo_setting( 'ai', 'topic_summary' ) ||
1661 wpforo_setting( 'ai', 'topic_suggestions' ) ||
1662 wpforo_setting( 'ai', 'bot_reply' )
1663 ) ) {
1664 wp_enqueue_script( 'wpforo-ai-features-js' );
1665 }
1666 // Enqueue AI Chatbot script if enabled and user can chat
1667 if( isset( WPF()->ai_chatbot ) && WPF()->ai_chatbot->is_enabled() && WPF()->ai_chatbot->user_can_chat() ) {
1668 wp_enqueue_script( 'wpforo-ai-chatbot-js' );
1669 }
1670 wp_enqueue_script( 'wpforo-ajax' );
1671 if( is_rtl() ) {
1672 wp_enqueue_style( 'wpforo-style-rtl' );
1673 } else {
1674 wp_enqueue_style( 'wpforo-style' );
1675 }
1676 }
1677
1678 if( is_rtl() ) {
1679 wp_enqueue_style( 'wpforo-widgets-rtl' );
1680 } else {
1681 wp_enqueue_style( 'wpforo-widgets' );
1682 }
1683
1684 do_action( 'wpforo_frontend_enqueue_scripts' );
1685 }
1686
1687 function wpforo_style_options( $css ) {
1688 $css .= "\r\n#wpforo-wrap .wpforo-forum-title{font-size: " . wpforo_setting(
1689 'styles',
1690 'font_size_forum'
1691 ) . "px!important; line-height: " . ( wpforo_setting( 'styles', 'font_size_forum' ) + 1 ) . "px!important;}";
1692 $css .= "\r\n#wpforo-wrap .wpforo-topic-title a { font-size: " . wpforo_setting(
1693 'styles',
1694 'font_size_topic'
1695 ) . "px!important; }";
1696 $css .= "\r\n#wpforo-wrap .wpforo-post .wpf-right .wpforo-post-content {font-size: " . wpforo_setting(
1697 'styles',
1698 'font_size_post_content'
1699 ) . "px!important;}\r\n#wpforo-wrap .wpforo-post .wpf-right .wpforo-post-content p {font-size: " . wpforo_setting(
1700 'styles',
1701 'font_size_post_content'
1702 ) . "px;}";
1703
1704 if( 'bottom' === wpforo_setting( 'posting', 'topic_editor_toolbar_location' ) ) {
1705 $css .= "\r\n
1706 #wpforo #wpforo-wrap .wpf-topic-create .mce-container-body{display: flex; flex-direction: column;}
1707 #wpforo #wpforo-wrap .wpf-topic-create .mce-top-part{order: 1}
1708 #wpforo #wpforo-wrap .wpf-topic-create .wpf-field-wrap > .wpf-extra-fields,
1709 #wpforo #wpforo-wrap .wpforo-portable-form-wrap .wpf-extra-fields,
1710 #wpforo #wpforo-wrap .wpforo-messages-content .wpfpm-main .wpfpm-form-wrapper .wpf-extra-fields{ margin-top: 10px !important; }";
1711 }
1712 if( 'bottom' === wpforo_setting( 'posting', 'reply_editor_toolbar_location' ) ) {
1713 $css .= "\r\n
1714 #wpforo #wpforo-wrap .wpf-post-create .mce-container-body{display: flex; flex-direction: column;}
1715 #wpforo #wpforo-wrap .wpf-post-create .mce-top-part{order: 1}
1716 #wpforo #wpforo-wrap .wpf-post-create .wpf-field-wrap > .wpf-extra-fields,
1717 #wpforo #wpforo-wrap .wpforo-portable-form-wrap .wpf-extra-fields,
1718 #wpforo #wpforo-wrap .wpforo-messages-content .wpfpm-main .wpfpm-form-wrapper .wpf-extra-fields{ margin-top: 10px !important; }";
1719 }
1720 if( wpforo_setting( 'ai', 'assistant_highlight' ) ) {
1721 $css .= "\r\n
1722 #wpforo #wpforo-wrap .wpf-ai-helper-toggle.wpf-ai-highlight{ background:__WPFCOLOR_12__; color:__WPFCOLOR_1__;}
1723 #wpforo #wpforo-wrap .wpf-ai-helper-toggle.wpf-ai-highlight .wpf-ai-sparkle-icon{ fill:__WPFCOLOR_1__;}
1724 #wpforo #wpforo-wrap .wpf-ai-helper-toggle.wpf-ai-highlight:hover{ background:__WPFCOLOR_12__; color:__WPFCOLOR_1__; opacity: 0.85;}";
1725 }
1726 if( $ccss = wpforo_setting( 'styles', 'custom_css' ) ) $css .= "\r\n" . stripslashes( (string) $ccss );
1727
1728 return $css;
1729 }
1730
1731 add_filter( 'wpforo_dynamic_css_filter', 'wpforo_style_options' );
1732
1733 function wpforo_admin_enqueue() {
1734 wp_register_style(
1735 'wpforo-font-awesome',
1736 WPFORO_URL . '/assets/css/font-awesome/css/fontawesome-all.min.css',
1737 false,
1738 '6.1.1'
1739 );
1740 wp_register_style(
1741 'wpforo-iconpicker-css',
1742 WPFORO_URL . '/admin/assets/third-party/iconpicker/fontawesome-iconpicker.min.css',
1743 [ 'wpforo-font-awesome' ],
1744 '2.0.0'
1745 );
1746 wp_register_script(
1747 'wpforo-iconpicker-js',
1748 WPFORO_URL . '/admin/assets/third-party/iconpicker/fontawesome-iconpicker.js',
1749 [ 'jquery' ],
1750 '2.0.0',
1751 true
1752 );
1753 wp_register_style( 'wpforo-admin', WPFORO_URL . '/admin/assets/css/admin.css', false, WPFORO_VERSION );
1754 wp_localize_script( 'wp-color-picker', 'wpColorPickerL10n', [
1755 'clear' => __( 'Clear' ),
1756 'defaultString' => __( 'Default' ),
1757 'pick' => __( 'Select Color' ),
1758 ] );
1759 wp_register_script(
1760 'wpforo-contenthover-addons',
1761 WPFORO_URL . '/admin/assets/js/contenthover/jquery.contenthover.min.js',
1762 [ 'jquery' ],
1763 WPFORO_VERSION,
1764 false
1765 );
1766 wp_register_script(
1767 'wpforo-backend-widgets-js',
1768 WPFORO_URL . '/admin/assets/js/widgets.js',
1769 [ 'jquery' ],
1770 WPFORO_VERSION,
1771 true
1772 );
1773 wp_register_script(
1774 'wpforo-backend-js',
1775 WPFORO_URL . '/admin/assets/js/backend.js',
1776 [ 'jquery' ],
1777 WPFORO_VERSION,
1778 false
1779 );
1780 wp_localize_script( 'wpforo-backend-js', 'wpforo_admin', [
1781 'phrases' => [
1782 'move' => __( 'Move', 'wpforo' ),
1783 'delete' => __( 'Delete', 'wpforo' ),
1784 ],
1785 ] );
1786 WPF()->settings->init_info();
1787 wp_localize_script(
1788 'wpforo-backend-js',
1789 'wpforo',
1790 [
1791 'ajax_url' => wpforo_get_ajax_url(),
1792 'nonces' => wpforo_generate_ajax_nonces(),
1793 'board' => [ 'has_more_boards' => is_wpforo_multiboard() ],
1794 'settings' => [
1795 'info' => [
1796 'core' => WPF()->settings->info->core,
1797 'addons' => WPF()->settings->info->addons,
1798 ],
1799 ],
1800 ]
1801 );
1802 wp_register_style(
1803 'wpforo-deactivation-css',
1804 WPFORO_URL . '/admin/assets/css/deactivation-dialog.css',
1805 [],
1806 WPFORO_VERSION
1807 );
1808 wp_register_script(
1809 'wpforo-deactivation-js',
1810 WPFORO_URL . '/admin/assets/js/deactivation-dialog.js',
1811 [ 'jquery' ],
1812 WPFORO_VERSION
1813 );
1814 wp_localize_script( 'wpforo-deactivation-js', 'wpforo_deactivation_obj', [
1815 'msgReasonRequired' => __( 'Please choose one reasons before sending a feedback!', 'wpforo' ),
1816 'msgReasonDescRequired' => __( 'Please provide more information', 'wpforo' ),
1817 'msgFeedbackHasEmailNoCheckbox' => __(
1818 'With the email address, please check the "I agree to receive email" checkbox to proceed.',
1819 'wpforo'
1820 ),
1821 'msgFeedbackHasCheckboxNoEmail' => __( 'Please fill your email address for feedback', 'wpforo' ),
1822 'msgFeedbackNotValidEmail' => __( 'Your email address is not valid', 'wpforo' ),
1823 'adminUrl' => get_admin_url(),
1824 ] );
1825 wp_register_script( 'wpforo-iris', admin_url( 'js/iris.min.js' ), [
1826 'jquery-ui-draggable',
1827 'jquery-ui-slider',
1828 'jquery-touch-punch',
1829 ], false, true );
1830
1831 // Register AI Features admin assets
1832 wp_register_style(
1833 'wpforo-ai-features',
1834 WPFORO_URL . '/admin/assets/css/ai-features.css',
1835 false,
1836 WPFORO_VERSION
1837 );
1838 wp_register_script(
1839 'wpforo-ai-features-js',
1840 WPFORO_URL . '/admin/assets/js/ai-features.js',
1841 [ 'jquery' ],
1842 WPFORO_VERSION,
1843 true
1844 );
1845
1846 do_action( 'wpforo_admin_register_scripts' );
1847
1848 if( ! empty( $_GET['page'] ) && strpos( (string) $_GET['page'], 'wpforo' ) === 0 ) {
1849 wp_enqueue_style( 'wpforo-admin' );
1850 wp_enqueue_script( 'wpforo-backend-js' );
1851 wp_enqueue_style( 'wpforo-iconpicker-css' );
1852 wp_enqueue_script( 'wpforo-iconpicker-js' );
1853 wp_enqueue_style( 'wpforo-font-awesome' );
1854 wp_enqueue_script( 'jquery' );
1855 wp_enqueue_script( 'jquery-ui-core' );
1856 wp_enqueue_script( 'jquery-ui-widget' );
1857 wp_enqueue_script( 'jquery-ui-mouse' );
1858 wp_enqueue_script( 'jquery-ui-position' );
1859 wp_enqueue_script( 'jquery-ui-draggable' );
1860 wp_enqueue_script( 'jquery-ui-droppable' );
1861 wp_enqueue_script( 'jquery-ui-menu' );
1862 wp_enqueue_script( 'jquery-ui-sortable' );
1863 wp_enqueue_script( 'jquery-color' );
1864 wp_enqueue_script( 'wp-lists' );
1865 if( preg_match( '#^wpforo-(?:\d+-)?forums$#iu', (string) $_GET['page'] ) ) {
1866 if( ! empty( $_GET['action'] ) ) {
1867 //Just for excluding 'nav-menu' js loading//
1868 wp_enqueue_script( 'postbox' );
1869 wp_enqueue_script( 'link' );
1870 wp_enqueue_style( 'wp-color-picker' );
1871 wp_enqueue_script( 'wp-color-picker' );
1872 wp_enqueue_script( 'wp-color-picker-script-handle' );
1873 } else {
1874 wp_enqueue_script( 'nav-menu' );
1875 }
1876 } elseif( preg_match(
1877 '#^wpforo-(?:\d+-)?settings$#iu',
1878 (string) $_GET['page']
1879 ) && ! empty( $_GET['wpf_tab'] ) && $_GET['wpf_tab'] === 'styles' ) {
1880 wp_enqueue_style( 'wp-color-picker' );
1881 wp_enqueue_script( 'wpforo-iris' );
1882 wp_enqueue_script( 'wp-color-picker' );
1883 } elseif( $_GET['page'] === wpforo_prefix_slug( 'dashboard' ) || $_GET['page'] === 'wpforo-overview' ) {
1884 wp_enqueue_script( 'postbox' );
1885 wp_enqueue_script( 'link' );
1886 } elseif( preg_match( '#^wpforo-(?:\d+-)?addons$#iu', (string) $_GET['page'] ) ) {
1887 wp_enqueue_script( 'wpforo-contenthover-addons' );
1888 } elseif( $_GET['page'] === 'wpforo-ai' ) {
1889 wp_enqueue_style( 'wpforo-ai-features' );
1890 wp_enqueue_script( 'wpforo-ai-features-js' );
1891 } elseif( preg_match(
1892 '#^wpforo-(?:\d+-)?settings$#iu',
1893 (string) $_GET['page']
1894 ) && ! empty( $_GET['wpf_tab'] ) && $_GET['wpf_tab'] === 'ai' ) {
1895 // Load AI features scripts on Settings > AI tab for bot user autocomplete
1896 wp_enqueue_style( 'wpforo-ai-features' );
1897 wp_enqueue_script( 'wpforo-ai-features-js' );
1898 }
1899 }
1900 if( ! wpforo_get_option( 'deactivation_dialog_never_show', false, false ) && ( strpos(
1901 wpforo_get_request_uri(),
1902 '/plugins.php'
1903 ) !== false ) ) {
1904 wp_enqueue_style( 'wpforo-deactivation-css' );
1905 wp_enqueue_script( 'wpforo-deactivation-js' );
1906 }
1907
1908 $screen = get_current_screen();
1909 if( ( 'user-edit' === $screen->id || 'profile' === $screen->id ) ) {
1910 wp_enqueue_style( 'wpforo-font-awesome' );
1911 }
1912
1913 if( $screen->id === 'widgets' ) {
1914 wp_enqueue_script( 'wpforo-backend-widgets-js' );
1915 }
1916
1917 do_action( 'wpforo_admin_enqueue_scripts' );
1918 }
1919
1920 add_action( 'admin_enqueue_scripts', 'wpforo_admin_enqueue' );
1921
1922 function wpforo_admin_permalink_notice() {
1923 $permalink_structure = get_option( 'permalink_structure' );
1924 if( ! $permalink_structure ) {
1925 $class = 'notice notice-warning';
1926 $message = __(
1927 'IMPORTANT: wpForo can\'t work with default permalink, please change permalink structure',
1928 'wpforo'
1929 );
1930 printf( '<div class="%1$s"><p>%2$s</p></div>', $class, $message );
1931 }
1932 }
1933
1934 add_action( 'admin_notices', 'wpforo_admin_permalink_notice' );
1935
1936 function wpforo_userform_to_wpuser_html_form( $wp_user ) {
1937 if( is_super_admin() ) {
1938 $userid = 0;
1939 $groupid = 0;
1940 $timezone = '';
1941 $secondary_groupids = [];
1942 if( is_object( $wp_user ) ) {
1943 $userid = $wp_user->ID;
1944 $user = WPF()->member->get_member( $wp_user->ID );
1945 $groupid = $user['groupid'];
1946 $timezone = sanitize_text_field( $user['timezone'] );
1947 $secondary_groupids = $user['secondary_groupids'];
1948 }
1949 ?>
1950 <style>
1951 #wpf-rating-table {
1952 width: 100%;
1953 font-size: 12px;
1954 }
1955
1956 #wpf-rating-table h4 {
1957 margin: 0;
1958 padding: 0;
1959 font-size: 14px;
1960 font-weight: bold;
1961 white-space: nowrap;
1962 }
1963
1964 #wpf-rating-table .wpf-badge-full {
1965 color: #FFFFFF;
1966 white-space: nowrap;
1967 font-size: 15px;
1968 line-height: 16px;
1969 font-weight: bold;
1970 text-align: center;
1971 display: inline-block;
1972 padding: 2px 8px;
1973 min-width: 30px;
1974 }
1975
1976 #wpf-rating-table .wpf-badge-full.wpf-badge-level-6, #wpf-rating-table .wpf-badge-full.wpf-badge-level-7, #wpf-rating-table .wpf-badge-full.wpf-badge-level-8 {
1977 font-size: 18px !important;
1978 }
1979
1980 #wpf-rating-table .wpf-badge-full.wpf-badge-level-9, #wpf-rating-table .wpf-badge-full.wpf-badge-level-10 {
1981 font-size: 22px !important;
1982 }
1983
1984 #wpf-rating-table th, #wpf-rating-table td {
1985 padding: 5px 10px;
1986 text-align: left;
1987 vertical-align: top;
1988 }
1989
1990 #wpf-rating-table tr:nth-child(odd) {
1991 background: #f5f5f5;
1992 }
1993
1994 #wpf-rating-table tr:nth-child(even) {
1995 background: #FFFFFF;
1996 }
1997
1998 #wpf-rating-table th {
1999 text-transform: uppercase;
2000 font-size: 12px;
2001 padding: 10px;
2002 }
2003
2004 .wpforo-profile-table input[type=checkbox] {
2005 width: auto !important;
2006 }
2007
2008 @media screen and (max-width: 700px) {
2009 #wpf-rating-table th, #wpf-rating-table td {
2010 display: table-cell !important;
2011 }
2012 }
2013 </style>
2014 <h2 style="margin-bottom: 30px; margin-top: 50px;"><?php _e( 'Forum Profile Fields - wpForo' ); ?></h2>
2015 <table class="form-table wpforo-profile-table"
2016 style="box-shadow: 1px 1px 6px #cccccc; background: #f7f7f7; margin-bottom: 30px; width: 97%;">
2017 <tr>
2018 <td colspan="2" style="padding: 5px;"></td>
2019 </tr>
2020 <tr class="form-field">
2021 <th scope="row" style="padding: 10px 20px 10px 20px; width: 30%;">
2022 <label for="wpforo_usergroup">
2023 <?php _e( 'Forum - Usergroup', 'wpforo' ); ?>
2024 </label>
2025 <?php if( wpforo_setting( 'authorization', 'role_synch' ) ): ?>
2026 <p class="description" style="font-weight: normal;">
2027 <?php $wpforo_synch_table = admin_url(
2028 'admin.php?page=' . wpforo_prefix_slug( 'usergroups' )
2029 ) ?>
2030 <?php echo sprintf(
2031 __(
2032 'Forum Usergroups are synched with User Roles based on the %s. When you change this user Role the Usergroup is automatically changed according to that table.',
2033 'wpforo'
2034 ),
2035 '<a href="' . $wpforo_synch_table . '" target="_blank">Role-Usergroup synchronization table</a>'
2036 ); ?>
2037 </p>
2038 <?php endif; ?>
2039 </th>
2040 <td style="padding: 15px 20px 10px 20px; vertical-align: top;">
2041 <?php if( wpforo_setting( 'authorization', 'role_synch' ) ): ?>
2042 <select id="wpforo_usergroup" disabled="disabled">
2043 <option value="0"><?php _e( 'Synced with user role', 'wpforo' ); ?></option>
2044 <?php WPF()->usergroup->show_selectbox( $groupid ); ?>
2045 </select>
2046 <input type="hidden" name="wpforo_usergroup" value="<?php echo $groupid; ?>">
2047 &nbsp; <span
2048 style="color: green"><?php _e(
2049 'Role-Usergroup Synchronization is Turned ON!',
2050 'wpforo'
2051 ); ?></span>
2052 <br/>
2053 <p class="description"
2054 style="font-weight: normal; font-size: 13px; line-height: 18px;"><?php _e(
2055 'This user Usergroup is automatically changed according to current Role. If you want to disable Role-Usergroup synchronization and manage Usergroups and User Roles independently, please navigate to <b>Dashboard > wpForo > Settings > Login & Registration</b> admin page and disable "Role-Usergroup Synchronization" option.',
2056 'wpforo'
2057 ); ?></p>
2058 <?php else: ?>
2059 <select id="wpforo_usergroup"
2060 name="wpforo_usergroup"<?php if( wpforo_is_owner( $userid ) || ! current_user_can(
2061 'administrator'
2062 ) ) {
2063 echo ' disabled="disabled"';
2064 } ?>>
2065 <?php WPF()->usergroup->show_selectbox( $groupid ?: WPF()->usergroup->default_groupid ); ?>
2066 </select>
2067 <?php endif; ?>
2068 </td>
2069 </tr>
2070 <tr class="form-field">
2071 <th scope="row" style="padding: 10px 20px 10px 20px;">
2072 <label for="wpforo_usergroup">
2073 <?php _e( 'Forum - Secondary Usergroups', 'wpforo' ); ?>
2074 </label>
2075 </th>
2076 <td style="padding: 15px 20px 10px 20px; vertical-align: top;">
2077 <?php $usergroups = WPF()->usergroup->get_secondary_groups(); ?>
2078 <?php if( ! empty( $usergroups ) ): ?>
2079 <?php foreach( $usergroups as $usergroup ): ?>
2080 <?php if( $usergroup['groupid'] == 1 || $usergroup['groupid'] == 4 ) {
2081 continue;
2082 } //|| $usergroup['groupid'] == $groupid ?>
2083 <label style="min-width: 20%; display: inline-block; padding-bottom: 5px;">
2084 <input type="checkbox"
2085 name="wpforo_secondary_groupids[]"
2086 value="<?php echo intval( $usergroup['groupid'] ) ?>"
2087 <?php checked(
2088 in_array( (int) $usergroup['groupid'], (array) $secondary_groupids, true )
2089 ); ?>>&nbsp;
2090 <?php echo esc_html( $usergroup['name'] ); ?>
2091 </label>
2092 <?php endforeach; ?>
2093 <?php endif; ?>
2094 <input name="wpforo_secondary_groupids[]" value="0" type="hidden">
2095 </td>
2096 </tr>
2097 <tr class="form-field">
2098 <th scope="row" style="padding: 10px 20px 10px 20px;">
2099 <label for="wpforo_usertimezone"><?php _e( 'Forum - User Timezone', 'wpforo' ); ?></label>
2100 </th>
2101 <td style="padding: 15px 20px 10px 20px; vertical-align: top;">
2102 <select name="wpforo_usertimezone" id="wpforo_usertimezone">
2103 <?php echo wp_timezone_choice( $timezone ); ?>
2104 </select>
2105 </td>
2106 </tr>
2107 <?php if( ! empty( $user ) ) : ?>
2108 <tr class="form-field">
2109 <th scope="row" style="padding: 10px 20px 10px 20px;">
2110 <label><?php _e( 'User Reputation', 'wpforo' ); ?></label>
2111 <p class="description"
2112 style="font-weight: normal;"><?php _e(
2113 'By default all members get rating badges and titles based on number of posts. However, using this option you can grant lower or higher rating to certain user (this user). The default member reputation badges, titles and points can be managed in Forums > Settings > Members Tab.',
2114 'wpforo'
2115 ) ?></p>
2116 </th>
2117 <td style="padding: 15px 20px 10px 20px; vertical-align: top;">
2118 <div style="padding-bottom: 10px; margin-bottom: 10px; border-bottom: 1px dashed #cccccc;">
2119 <label><input type="radio" id="wpf-user-rating-default"
2120 name="wpforo_use_member_custom_points"
2121 value="0" <?php checked( ! $user['custom_points'] ) ?>> <?php _e(
2122 'Default Rating',
2123 'wpforo'
2124 ) ?></label>
2125 &nbsp;&nbsp;
2126 <label><input type="radio" id="wpf-user-rating-custom"
2127 name="wpforo_use_member_custom_points"
2128 value="1" <?php checked( $user['custom_points'] ) ?>> <?php _e(
2129 'Custom Rating',
2130 'wpforo'
2131 ) ?></label>
2132 </div>
2133
2134 <table id="wpf-rating-table" cellspacing="0" cellpadding="0" border="0"
2135 style="display: block; width: 100%; height: 150px; overflow-y: scroll; hidden; border: 1px solid #ccc; border-top: none; border-bottom: none; <?php if( ! $user['custom_points'] ) echo 'opacity:0.5;' ?>">
2136 <tr>
2137 <th style="text-align: center; width: 5%;">#</th>
2138 <th style="width: 30%"><?php _e( 'Rating Level', 'wpforo' ); ?></th>
2139 <th style="width: 35%"><?php _e( 'Rating Title', 'wpforo' ); ?></th>
2140 <th style="width: 30%;text-align:center;"><?php _e( 'Rating Badge', 'wpforo' ); ?></th>
2141 </tr>
2142 <?php $levels = WPF()->member->levels(); ?>
2143 <?php foreach( $levels as $level ): $points = WPF()->member->rating( $level, 'points' );
2144 $bgx = $level === $user['rating']['level'] ? 'background-color: #feff88' : ''; ?>
2145 <tr>
2146 <td style="text-align: center;<?php echo $bgx ?>"><input type="radio"
2147 name="wpforo_member_custom_points"
2148 id="wpf-user-rating-<?php echo intval(
2149 $points
2150 ) ?>"
2151 value="<?php echo intval(
2152 $points
2153 ) ?>" <?php checked(
2154 $level === $user['rating']['level']
2155 ) ?>></td>
2156 <td style="<?php echo $bgx ?>"><h4><label
2157 for="wpf-user-rating-<?php echo intval( $points ) ?>"><?php _e(
2158 'Level',
2159 'wpforo'
2160 ); ?><?php echo esc_html( $level ) ?></label>
2161 </h4></td>
2162 <td style="<?php echo $bgx ?>"><?php echo WPF()->member->rating(
2163 $level,
2164 'title'
2165 ) ?></td>
2166 <td style="text-align:center;<?php echo $bgx ?>">
2167 <div class="wpf-badge-full wpf-badge-level-<?php echo esc_attr( $level ) ?>"
2168 style="color:<?php echo WPF()->member->rating(
2169 $level,
2170 'color'
2171 ) ?>;"><?php echo WPF()->member->rating_badge( $level, 'full' ); ?></div>
2172 </td>
2173 </tr>
2174 <?php endforeach; ?>
2175 </table>
2176 </td>
2177 </tr>
2178 <?php endif; ?>
2179 <tr>
2180 <td colspan="2" style="padding: 5px;"></td>
2181 </tr>
2182 </table>
2183 <script>
2184 jQuery(document).ready(function ($) {
2185 $('#wpf-user-rating-default').change(function () {if (this.checked) {$('#wpf-rating-table').css('opacity', 0.5);}});
2186 $('#wpf-user-rating-custom').change(function () {if (this.checked) { $('#wpf-rating-table').css('opacity', 1);}});
2187 });
2188 </script>
2189 <?php
2190 }
2191 }
2192
2193 add_action( 'user_new_form', 'wpforo_userform_to_wpuser_html_form' );
2194 add_action( 'show_user_profile', 'wpforo_userform_to_wpuser_html_form' );
2195 add_action( 'edit_user_profile', 'wpforo_userform_to_wpuser_html_form' );
2196
2197 add_action( 'register_form', function() {
2198 wp_nonce_field( 'wpforo_user_register', '_wpfnonce' );
2199 }, 21 );
2200
2201 function wpforo_do_hook_user_register( $userid ) {
2202 WPF()->member->synchronize_user( $userid );
2203 if( wpfval( $_POST, 'wpfreg' ) ) {
2204 $data = $_POST;
2205 $data['userid'] = $userid;
2206
2207 // SECURITY: allowlist wpfreg keys + force the trusted userid so an
2208 // attacker cannot pivot the downstream update() onto another user.
2209 $wpfreg = is_array( $data['wpfreg'] ) ? $data['wpfreg'] : [];
2210 $data['wpfreg'] = array_intersect_key( $wpfreg, array_flip( [
2211 'user_login',
2212 'user_email',
2213 'user_pass1',
2214 'user_pass2',
2215 ] ) );
2216 $data['wpfreg']['userid'] = (int) $userid;
2217
2218 // SECURITY: strip reserved wp_users column names from custom-field
2219 // input so they cannot mass-assign via Members::update()'s array_merge().
2220 if( isset( $data['data'] ) && is_array( $data['data'] ) ) {
2221 foreach( [
2222 'user_email',
2223 'user_login',
2224 'user_pass',
2225 'user_pass1',
2226 'user_pass2',
2227 'userid',
2228 'ID',
2229 ] as $reserved ) {
2230 unset( $data['data'][ $reserved ] );
2231 }
2232 }
2233
2234 WPF()->member->update( $data, 'full', false );
2235 }
2236 }
2237
2238 add_action( 'user_register', 'wpforo_do_hook_user_register', 10, 1 );
2239
2240 function wpforo_do_hook_update_profile( $userid ) {
2241 if( $userid ) {
2242 if( current_user_can( 'create_users' ) || current_user_can( 'edit_user' ) ) {
2243 if( wpfval( $_POST, 'wpforo_usergroup' ) || wpfkey( $_POST, 'wpforo_usertimezone' ) ) {
2244 $member = wpforo_member( $userid );
2245 $can_change_own_rating = true;
2246 if( wpfval( $member, 'userid' ) ) {
2247 $groupid = $member['groupid'];
2248 $secondary_groupids = $member['secondary_groupids'];
2249 if( current_user_can( 'administrator' ) ) {
2250 if( wpfval( $_POST, 'wpforo_usergroup' ) ) {
2251 if( $userid != 1 && ! wpforo_is_owner( $userid ) && current_user_can( 'administrator' ) ) {
2252 $groupid = intval( $_POST['wpforo_usergroup'] );
2253 }
2254 }
2255 if( wpfval( $_POST, 'wpforo_secondary_groupids' ) ) {
2256 if( ! empty( $_POST['wpforo_secondary_groupids'] ) ) {
2257 $secondary_groupids = array_filter(
2258 array_map( 'intval', $_POST['wpforo_secondary_groupids'] )
2259 );
2260 }
2261 }
2262 } else {
2263 if( wpforo_is_owner( $userid ) ) {
2264 $can_change_own_rating = false;
2265 }
2266 }
2267
2268 $custom_points = ( $can_change_own_rating && wpfval(
2269 $_POST,
2270 'wpforo_use_member_custom_points'
2271 ) ) ? (int) wpfval( $_POST, 'wpforo_member_custom_points' ) : 0;
2272
2273 $args = [
2274 'groupid' => intval( $groupid ),
2275 'about' => wpforo_kses( $_POST['description'], 'user_description' ),
2276 'timezone' => ( isset( $_POST['wpforo_usertimezone'] ) ? sanitize_text_field(
2277 $_POST['wpforo_usertimezone']
2278 ) : '' ),
2279 'secondary_groupids' => $secondary_groupids,
2280 'custom_points' => $custom_points,
2281 ];
2282 WPF()->member->update_profile_fields( $userid, $args, false );
2283
2284 if( ! wpforo_is_owner( $userid ) ) {
2285 WPF()->member->inactive_to_active( $userid );
2286 }
2287 }
2288 }
2289 }
2290 }
2291 }
2292
2293 add_action( 'personal_options_update', 'wpforo_do_hook_update_profile' );
2294 add_action( 'edit_user_profile_update', 'wpforo_do_hook_update_profile' );
2295
2296 function wpforo_avatar( $avatar, $id_or_email, $size, $default, $alt ) {
2297 if( ! wpforo_setting( 'profiles', 'replace_avatar' ) ) {
2298 return $avatar;
2299 }
2300 $user = false;
2301 if( wpforo_is_id( $id_or_email ) ) {
2302 $id = (int) $id_or_email;
2303 $user = get_user_by( 'id', $id );
2304 } elseif( is_object( $id_or_email ) ) {
2305 if( ! empty( $id_or_email->user_id ) ) {
2306 $id = (int) $id_or_email->user_id;
2307 $user = get_user_by( 'id', $id );
2308 } elseif( ! empty( $id_or_email->ID ) ) {
2309 $id = (int) $id_or_email->ID;
2310 $user = get_user_by( 'id', $id );
2311 }
2312 } else {
2313 $user = get_user_by( 'email', $id_or_email );
2314 }
2315
2316 if( $user && is_object( $user ) ) {
2317 if( $src = WPF()->member->get_avatar_url( $user->data->ID ) ) {
2318 $avatar = "<img alt='" . esc_attr( $alt ) . "' src='" . esc_url(
2319 (string) $src
2320 ) . "' class='avatar avatar-" . esc_attr( $size ) . " photo' height='" . esc_attr(
2321 $size
2322 ) . "' width='" . esc_attr( $size ) . "' />";
2323 }
2324 }
2325
2326 return $avatar;
2327 }
2328
2329 add_filter( 'get_avatar', 'wpforo_avatar', 10, 5 );
2330
2331 function wpforo_pre_get_avatar_data( $args, $id_or_email ) {
2332 if( wpforo_setting( 'profiles', 'replace_avatar' ) ) {
2333 $key = [ 'wpforo_pre_get_avatar_data', $id_or_email ];
2334 if( WPF()->ram_cache->exists( $key ) ) {
2335 $args['url'] = WPF()->ram_cache->get( $key );
2336 } else {
2337 $user = false;
2338 if( is_object( $id_or_email ) && isset( $id_or_email->comment_ID ) ) {
2339 $id_or_email = get_comment( $id_or_email );
2340 }
2341 // Process the user identifier.
2342 if( wpforo_is_id( $id_or_email ) ) {
2343 $user = get_user_by( 'id', absint( $id_or_email ) );
2344 } elseif( is_string( $id_or_email ) ) {
2345 if( ! strpos( (string) $id_or_email, '@md5.gravatar.com' ) ) {
2346 $user = get_user_by( 'email', $id_or_email );
2347 }
2348 } elseif( $id_or_email instanceof WP_User ) {
2349 // User Object
2350 $user = $id_or_email;
2351 } elseif( $id_or_email instanceof WP_Post ) {
2352 // Post Object
2353 $user = get_user_by( 'id', (int) $id_or_email->post_author );
2354 } elseif( function_exists( 'is_avatar_comment_type' ) && $id_or_email instanceof WP_Comment ) {
2355 if( is_avatar_comment_type( get_comment_type( $id_or_email ) ) ) {
2356 if( ! empty( $id_or_email->user_id ) ) {
2357 $user = get_user_by( 'id', (int) $id_or_email->user_id );
2358 }
2359 if( ( ! $user || is_wp_error( $user ) ) && ! empty( $id_or_email->comment_author_email ) ) {
2360 $user = get_user_by( 'email', $id_or_email->comment_author_email );
2361 }
2362 }
2363 }
2364
2365 if( $user && is_object( $user ) ) {
2366 if( $avatar_url = WPF()->member->get_avatar_url( $user->data->ID ) ) {
2367 WPF()->ram_cache->set( $key, $avatar_url );
2368 $args['url'] = $avatar_url;
2369 }
2370 }
2371 }
2372 }
2373
2374 return $args;
2375 }
2376
2377 add_filter( 'pre_get_avatar_data', 'wpforo_pre_get_avatar_data', 10, 2 );
2378
2379 function wpforo_move_uploded_default_attach( $argname, $return = 'html' ) {
2380 if( ! empty( $_FILES[ $argname ] ) && ! empty( $_FILES[ $argname ]['name'] ) ) {
2381 $name = sanitize_file_name( $_FILES[ $argname ]['name'] ); //myimg.png
2382 $type = sanitize_mime_type( $_FILES[ $argname ]['type'] ); //image/png
2383 $tmp_name = sanitize_text_field( $_FILES[ $argname ]['tmp_name'] ); //D:\wamp\tmp\php986B.tmp
2384 $error = intval( $_FILES[ $argname ]['error'] ); //0
2385 $size = intval( $_FILES[ $argname ]['size'] ); //6112
2386
2387 $phpFileUploadErrors = [
2388 0 => 'There is no error, the file uploaded with success',
2389 1 => 'The uploaded file size is too big',
2390 2 => 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form',
2391 3 => 'The uploaded file was only partially uploaded',
2392 4 => 'No file was uploaded',
2393 6 => 'Missing a temporary folder',
2394 7 => 'Failed to write file to disk.',
2395 8 => 'A PHP extension stopped the file upload.',
2396 ];
2397
2398 if( $error ) {
2399 WPF()->notice->add( $phpFileUploadErrors[ $error ], 'error' );
2400
2401 return '';
2402 } elseif( $size > wpforo_setting( 'posting', 'max_upload_size' ) ) {
2403 WPF()->notice->add( 'The uploaded file size is too big', 'error' );
2404
2405 return '';
2406 }
2407
2408 if( function_exists( 'pathinfo' ) ) {
2409 $ext = pathinfo( $name, PATHINFO_EXTENSION );
2410 } else {
2411 $ext = substr( strrchr( (string) $name, '.' ), 1 );
2412 }
2413 $ext = strtolower( (string) $ext );
2414 $mime_types = get_allowed_mime_types();
2415 $mime_types = array_flip( $mime_types );
2416 if( ! empty( $mime_types ) ) {
2417 $allowed_types = implode( '|', $mime_types );
2418 $expld = explode( '|', $allowed_types );
2419 if( ! in_array( $ext, $expld ) ) {
2420 WPF()->notice->add( 'File type is not allowed', 'error' );
2421
2422 return '';
2423 }
2424 if( ! WPF()->perm->can_attach_file_type( $ext ) ) {
2425 WPF()->notice->add( 'You are not allowed to attach this file type', 'error' );
2426
2427 return '';
2428 }
2429 }
2430
2431 $attach_dir = WPF()->folders['default_attachments']['dir'];
2432 $attach_url = WPF()->folders['default_attachments']['url//'];
2433 if( ! is_dir( $attach_dir ) ) wp_mkdir_p( $attach_dir );
2434
2435 $fnm = pathinfo( $name, PATHINFO_FILENAME );
2436 $fnm = str_replace( ' ', '-', $fnm );
2437 while( strpos( (string) $fnm, '--' ) !== false ) {
2438 $fnm = str_replace( '--', '-', $fnm );
2439 }
2440 $fnm = preg_replace( "/[^-a-zA-Z0-9_]/", "", (string) $fnm );
2441 $fnm = trim( (string) $fnm, "-" );
2442 $fnm_empty = ! $fnm;
2443
2444 $file_name = $fnm . "." . $ext;
2445
2446 $attach_fname = time() . ( ! $fnm_empty ? '-' : '' ) . $file_name;
2447 $attach_path = $attach_dir . DIRECTORY_SEPARATOR . $attach_fname;
2448
2449 if( is_dir( $attach_dir ) && move_uploaded_file( $tmp_name, $attach_path ) ) {
2450 $attach_id = wpforo_insert_to_media_library( $attach_path, $fnm );
2451 if( $return === 'html' ) {
2452 return "\r\n" . '<div id="wpfa-' . $attach_id . '" class="wpforo-attached-file"><a class="wpforo-default-attachment" href="' . esc_url(
2453 (string) $attach_url . '/' . $attach_fname
2454 ) . '" target="_blank" title="' . esc_attr(
2455 basename( (string) $name )
2456 ) . '"><i class="fas fa-paperclip"></i>&nbsp;' . esc_html(
2457 basename( (string) $name )
2458 ) . '</a></div>';
2459 } else {
2460 return [
2461 'fileurl' => $attach_url . '/' . $attach_fname,
2462 'filename' => basename( (string) $name ),
2463 'mediaid' => $attach_id,
2464 ];
2465 }
2466 } else {
2467 WPF()->notice->add( 'Can\'t upload file', 'error' );
2468 }
2469 }
2470
2471 return '';
2472 }
2473
2474 function wpforo_add_default_attachment( $args ) {
2475 if( ! empty( $_FILES['attachfile'] ) && ! empty( $_FILES['attachfile']['name'] ) ) {
2476 if( WPF()->perm->can_attach( wpfval( $args, 'forumid' ) ) ) {
2477 if( $default_attach = wpforo_move_uploded_default_attach( 'attachfile' ) ) {
2478 $args['body'] .= $default_attach;
2479 $args['has_attach'] = 1;
2480 }
2481 }
2482 }
2483
2484 return $args;
2485 }
2486
2487 function wpforo_delete_attachment( $attach_post_id ) {
2488 if( ! $attach_post_id ) {
2489 return;
2490 }
2491 $posts = WPF()->db->get_results(
2492 "SELECT `postid`, `body` FROM `" . WPF()->tables->posts . "` WHERE `body` LIKE '%wpfa-" . intval(
2493 $attach_post_id
2494 ) . "%'",
2495 ARRAY_A
2496 );
2497 if( ! empty( $posts ) || is_array( $posts ) ) {
2498 foreach( $posts as $post ) {
2499 $body = preg_replace(
2500 '|<div[^><]*id=[\'\"]+wpfa-' . $attach_post_id . '[\'\"]+[^><]*>.+?</div>|is',
2501 '<div class="wpforo-attached-file wpfa-deleted">' . wpforo_phrase(
2502 'Attachment removed',
2503 false
2504 ) . '</div>',
2505 (string) $post['body']
2506 );
2507 if( $body ) {
2508 WPF()->db->query(
2509 "UPDATE `" . WPF()->tables->posts . "` SET `body` = '" . esc_sql(
2510 $body
2511 ) . "' WHERE `postid` = " . intval( $post['postid'] )
2512 );
2513 }
2514 }
2515 }
2516 }
2517
2518 function wpforo_default_attachments_filter( $text ) {
2519 if( preg_match_all(
2520 '#<a[^<>]*class=[\'"]wpforo-default-attachment[\'"][^<>]*href=[\'"]([^\'"]+)[\'"][^<>]*>[\r\n\t\s\0]*(?:<i[^<>]*>[\r\n\t\s\0]*</i>[\r\n\t\s\0]*)?([^<>]*)</a>#iu',
2521 (string) $text,
2522 $matches,
2523 PREG_SET_ORDER
2524 ) ) {
2525 foreach( $matches as $match ) {
2526 $attach_html = '';
2527 if( file_exists( wpforo_fix_upload_dir( $match[1] ) ) ) {
2528 if( ! WPF()->perm->forum_can( 'va' ) || ! WPF()->usergroup->can( 'caa' ) ) {
2529 $attach_html .= '<br/><div class="wpfa-item wpfa-file"><a class="attach_cant_view" style="cursor: pointer;"><span style="color: #666;">' . wpforo_phrase(
2530 'Attachment',
2531 false
2532 ) . ' : </span> ' . urldecode( basename( $match[2] ) ) . '</a></div>';
2533 }
2534 }
2535 if( $attach_html ) {
2536 $attach_html .= '<br/>';
2537 $text = str_replace( $match[0], $attach_html, $text );
2538 }
2539 }
2540 }
2541
2542 return $text;
2543 }
2544
2545 function wpforo_content_enable_do_shortcode() {
2546 if( wpforo_setting( 'posting', 'content_do_shortcode' ) ) {
2547 add_filter( 'wpforo_content_after', 'do_shortcode', 20 );
2548 }
2549 }
2550
2551 add_action( 'wpforo_after_init', 'wpforo_content_enable_do_shortcode' );
2552
2553 add_filter( 'wpforo_content_after', function( $text ) {
2554 return wpforo_strip_shortcodes( $text, true );
2555 }, 999 );
2556
2557 add_filter( 'wpforo_body_text_filter', function( $text ) {
2558 if( apply_filters( 'wpforo_allow_replace_3asterisk', true ) ) {
2559 $text = preg_replace(
2560 '#\*{3}([^*]+?)\*{3}#',
2561 '<span style="color: red; font-weight: bold;">$1</span>',
2562 (string) $text
2563 );
2564 }
2565
2566 return $text;
2567 } );
2568
2569 add_action( 'wp_footer', function() { WPF()->cache->create(); } );
2570
2571 add_filter( 'retrieve_password_message', function( $message, $key, $user_login, $user_data ) {
2572 $reset_password_url = '';
2573 if( preg_match( wpforo_get_wprp_url_pattern(), (string) $message, $match ) ) {
2574 if( wpforo_setting( 'authorization', 'use_our_lostpassword_url' ) ) {
2575 $reset_password_url = wpforo_resetpassword_url( $key, $user_login );
2576 $message = str_replace( $match[0], $reset_password_url, $message );
2577 } else {
2578 $reset_password_url = $match[0];
2579 }
2580 }
2581
2582 if( wpforo_setting( 'email', 'overwrite_reset_password_email' ) && $reset_password_url ) {
2583 $message = str_replace(
2584 [ '[user_login]', '[reset_password_url]' ],
2585 [ $user_login, $reset_password_url, ],
2586 wpforo_setting( 'email', 'reset_password_email_message' )
2587 );
2588 $message = _wpforo_apply_email_shortcodes( $message, [ 'user' => [ 'userid' => $user_data->ID ] ] );
2589 add_filter( 'wp_mail_content_type', '__wpforo_set_html_content_type', 999 );
2590 }
2591
2592 return $message;
2593 }, 999, 4 );
2594
2595 function wpforo_user_field_shortcode_to_value( $shortcode, $userid = null, $implode = true, $separator = ',' ) {
2596 $value = null;
2597
2598 if( $shortcode && ( $field = preg_replace(
2599 '#^\s*\[?\s*(?:user_|owner_)?(?:fields_)?([^\[\]]+?)\s*]?\s*$#iu',
2600 '$1',
2601 (string) $shortcode
2602 ) ) ) {
2603 if( ! $userid ) $userid = WPF()->current_userid;
2604 if( in_array(
2605 $field,
2606 [ 'login', 'pass', 'nicename', 'email', 'url', 'registered', 'activation_key', 'status' ],
2607 true
2608 ) ) {
2609 $field = 'user_' . $field;
2610 }
2611 $value = wpforo_member( $userid, $field );
2612 if( $implode && wpforo_is_array_of_scalars( $value ) ) $value = implode( $separator, $value );
2613 }
2614
2615 return $value;
2616 }
2617
2618 function wpforo_forum_field_shortcode_to_value( $shortcode, $forumid, $implode = true, $separator = ',' ) {
2619 $value = null;
2620
2621 if( $forumid ) {
2622 if( $shortcode && ( $field = preg_replace(
2623 '#^\s*\[?\s*(?:forum_)?(?:fields_)?([^\[\]]+?)\s*]?\s*$#iu',
2624 '$1',
2625 (string) $shortcode
2626 ) ) ) {
2627 if( $field === 'link' ) {
2628 $value = sprintf(
2629 '<a target="_blank" href="%1$s">%2$s</a>',
2630 esc_url( (string) _wpforo_forum( $forumid, 'url' ) ),
2631 sanitize_text_field( _wpforo_forum( $forumid, 'title' ) )
2632 );
2633 $value = stripslashes( (string) $value );
2634 } else {
2635 $value = _wpforo_forum( $forumid, $field );
2636 if( $implode && wpforo_is_array_of_scalars( $value ) ) $value = implode( $separator, $value );
2637 }
2638 }
2639 }
2640
2641 return $value;
2642 }
2643
2644 function wpforo_topic_field_shortcode_to_value( $shortcode, $topicid, $implode = true, $separator = ',' ) {
2645 $value = null;
2646
2647 if( $topicid ) {
2648 if( $shortcode && ( $field = preg_replace(
2649 '#^\s*\[?\s*(?:topic_)?(?:fields_)?([^\[\]]+?)\s*]?\s*$#iu',
2650 '$1',
2651 (string) $shortcode
2652 ) ) ) {
2653 if( $field === 'link' ) {
2654 $value = sprintf(
2655 '<a target="_blank" href="%1$s">%2$s</a>',
2656 esc_url( (string) _wpforo_topic( $topicid, 'short_url' ) ),
2657 sanitize_text_field( _wpforo_topic( $topicid, 'title' ) )
2658 );
2659 $value = stripslashes( $value );
2660 } else {
2661 $value = _wpforo_topic( $topicid, $field );
2662 if( $implode && wpforo_is_array_of_scalars( $value ) ) $value = implode( $separator, $value );
2663 }
2664 }
2665 }
2666
2667 return $value;
2668 }
2669
2670 function wpforo_post_field_shortcode_to_value( $shortcode, $postid, $implode = true, $separator = ',' ) {
2671 $value = null;
2672
2673 if( $postid ) {
2674 if( $shortcode && ( $field = preg_replace(
2675 '#^\s*\[?\s*(?:post_)?(?:fields_)?([^\[\]]+?)\s*]?\s*$#iu',
2676 '$1',
2677 (string) $shortcode
2678 ) ) ) {
2679 if( $field === 'link' ) {
2680 $value = sprintf(
2681 '<a target="_blank" href="%1$s">%2$s</a>',
2682 esc_url( (string) _wpforo_post( $postid, 'short_url' ) ),
2683 sanitize_text_field( _wpforo_post( $postid, 'title' ) )
2684 );
2685 $value = stripslashes( $value );
2686 } else {
2687 $value = _wpforo_post( $postid, $field );
2688 if( $implode && wpforo_is_array_of_scalars( $value ) ) $value = implode( $separator, $value );
2689 }
2690 }
2691 }
2692
2693 return $value;
2694 }
2695
2696 function wpforo_new_user_notification_email_admin( $wp_new_user_notification_email_admin, $user, $blogname ) {
2697 if( wpforo_setting( 'email', 'overwrite_new_user_notification_admin' ) ) {
2698 $wp_new_user_notification_email_admin['subject'] = str_replace(
2699 '[blogname]',
2700 '[' . $blogname . ']',
2701 wpforo_setting(
2702 'email',
2703 'wp_new_user_notification_email_admin_subject'
2704 )
2705 );
2706 $wp_new_user_notification_email_admin['message'] = str_replace(
2707 '[blogname]',
2708 $blogname,
2709 wpforo_setting(
2710 'email',
2711 'wp_new_user_notification_email_admin_message'
2712 )
2713 );
2714 add_filter( 'wp_mail_content_type', '__wpforo_set_html_content_type', 999 );
2715 }
2716 $userid = $user->ID;
2717 $wp_new_user_notification_email_admin['message'] = preg_replace_callback(
2718 '#\[[^\[\]]+?]#isu',
2719 function( $match ) use ( $userid ) {
2720 $value = wpforo_user_field_shortcode_to_value( $match[0], $userid );
2721 if( ! $value || ! ( is_string( $value ) || is_numeric( $value ) ) ) $value = '';
2722
2723 return $value;
2724 },
2725 (string) $wp_new_user_notification_email_admin['message']
2726 );
2727
2728 return $wp_new_user_notification_email_admin;
2729 }
2730
2731 add_filter( 'wp_new_user_notification_email_admin', 'wpforo_new_user_notification_email_admin', 999, 3 );
2732
2733 function wpforo_new_user_notification_email( $wp_new_user_notification_email, $user, $blogname ) {
2734 $set_password_url = '';
2735 if( preg_match( wpforo_get_wprp_url_pattern(), (string) $wp_new_user_notification_email['message'], $match ) ) {
2736 if( wpforo_setting( 'authorization', 'use_our_lostpassword_url' ) ) {
2737 $set_password_url = wpforo_resetpassword_url( $match['key'], $user->user_login );
2738 $wp_new_user_notification_email['message'] = str_replace(
2739 $match[0],
2740 $set_password_url,
2741 $wp_new_user_notification_email['message']
2742 );
2743 } else {
2744 $set_password_url = $match[0];
2745 }
2746 }
2747
2748 if( wpforo_setting( 'email', 'overwrite_new_user_notification' ) && $set_password_url ) {
2749 $wp_new_user_notification_email['subject'] = str_replace(
2750 '[blogname]',
2751 '[' . $blogname . ']',
2752 wpforo_setting(
2753 'email',
2754 'wp_new_user_notification_email_subject'
2755 )
2756 );
2757 $wp_new_user_notification_email['message'] = str_replace(
2758 [ '[user_login]', '[set_password_url]' ],
2759 [ $user->user_login, $set_password_url ],
2760 wpforo_setting( 'email', 'wp_new_user_notification_email_message' )
2761 );
2762 add_filter( 'wp_mail_content_type', '__wpforo_set_html_content_type', 999 );
2763 }
2764
2765 return $wp_new_user_notification_email;
2766 }
2767
2768 add_filter( 'wp_new_user_notification_email', 'wpforo_new_user_notification_email', 999, 3 );
2769
2770 function wpforo_get_wprp_url_pattern() {
2771 return '#(?:<\s*)?https?://\S+?wp-login\.php(?:[?&]action=rp|[?&]login=[^?&=\s]+)?[?&]key=(?<key>[^?&=\s]+)(?:[?&]action=rp|[?&]login=[^?&=\s]+)?(?:\s*>)?#isu';
2772 }
2773
2774 function wpforo_synch_user_roles( $userid ) {
2775
2776 $user = get_userdata( $userid );
2777
2778 if( ! empty( $user ) && ! empty( $user->roles ) ) {
2779 $role_usergroups = WPF()->usergroup->get_role_usergroup_relation();
2780
2781 if( ! empty( $role_usergroups ) ) {
2782 $append_second_groups = apply_filters( 'wpforo_synch_user_roles_append_secondary_groups', false );
2783 $ug_users_array = WPF()->usergroup->build_users_groupid_array( $role_usergroups, [ $user ] );
2784
2785 if( wpfval( $ug_users_array, 'user_prime_group' ) ) {
2786 $userid_groupids = current( $ug_users_array['user_prime_group'] );
2787 if( ! empty( $userid_groupids ) ) {
2788 $groupid = current( $userid_groupids );
2789 if( $groupid ) WPF()->member->set_groupid( $userid, $groupid );
2790 }
2791 }
2792
2793 if( wpfval( $ug_users_array, 'user_second_groups' ) ) {
2794 foreach( $ug_users_array['user_second_groups'] as $userid => $secondary_usergroups ) {
2795 if( ! empty( $secondary_usergroups ) ) {
2796 if( $append_second_groups ) {
2797 // Merges current secondary groups with new secondary groups
2798 WPF()->member->append_secondary_groupids( $userid, $secondary_usergroups );
2799 } else {
2800 // Removes current secondary groups and sets new secondary groups
2801 WPF()->member->set_secondary_groupids( $userid, $secondary_usergroups );
2802 }
2803 }
2804 }
2805 } elseif( ! $append_second_groups && ! wpfval( $ug_users_array, 'user_second_groups' ) ) {
2806 WPF()->member->set_secondary_groupids( $userid, [] );
2807 }
2808
2809 delete_user_meta( intval( $userid ), '_wpf_member_obj' );
2810 }
2811 }
2812 }
2813
2814
2815 function wpforo_synch_roles() {
2816 if( ! current_user_can( 'manage_options' ) ) {
2817 wp_send_json_error( [ 'message' => 'Permission denied' ] );
2818 }
2819
2820 $status = [
2821 'progress' => 0,
2822 'error' => 0,
2823 'start' => 0,
2824 'step' => 1,
2825 'left' => 0,
2826 'total' => 0,
2827 'id' => 0,
2828 ];
2829
2830 $wpforo_synch_roles_data = isset( $_POST['wpforo_synch_roles_data'] ) ? $_POST['wpforo_synch_roles_data'] : '';
2831
2832 if( $wpforo_synch_roles_data ) {
2833 parse_str( $wpforo_synch_roles_data, $data );
2834 check_ajax_referer( 'wpforo_synch_roles', 'checkthis' );
2835 $limit = apply_filters( 'wpforo_synch_roles_step_limit', 20 );
2836 $append_second_groups = apply_filters( 'wpforo_synch_roles_append_secondary_groups', true );
2837 $success = false;
2838 $group_users = [];
2839 $user_prime_group = [];
2840 $user_second_groups = [];
2841 $options = wpforo_get_option( 'synch_roles' );
2842 $step = isset( $data['wpf-step'] ) ? intval( $data['wpf-step'] ) : 1;
2843 $left = isset( $data['wpf-left-users'] ) ? intval( $data['wpf-left-users'] ) : 0;
2844 $id = isset( $data['wpf-start-id'] ) ? intval( $data['wpf-start-id'] ) : 0;
2845 $start = isset( $data['wpf-start'] ) ? intval( $data['wpf-start'] ) : 0;
2846 $ug_role = isset( $data['wpf_synch_roles'] ) ? $data['wpf_synch_roles'] : [];
2847 if( ! empty( $ug_role ) ) {
2848 /////////////////////////////////////////////////////
2849 /// Update Roles of Usergroups in usergroups table
2850 WPF()->usergroup->set_ug_roles( $ug_role );
2851 /////////////////////////////////////////////////////
2852 if( ! is_array( $options ) || $left > 0 ) {
2853 $args = [ 'orderby' => 'ID', 'order' => 'ASC', 'offset' => $start, 'number' => $limit ];
2854 $users = get_users( $args );
2855 ////////////////////////////////////////////////////////////////////////////////////
2856 /// Builds associative array of Usergroup ID => Users ID array()
2857 $ug_users_array = WPF()->usergroup->build_users_groupid_array( $ug_role, $users, true );
2858 ////////////////////////////////////////////////////////////////////////////////////
2859 if( wpfval( $ug_users_array, 'group_users' ) ) {
2860 $group_users = $ug_users_array['group_users'];
2861 }
2862 if( wpfval( $ug_users_array, 'user_prime_group' ) ) {
2863 $user_prime_group = $ug_users_array['user_prime_group'];
2864 }
2865 if( wpfval( $ug_users_array, 'user_second_groups' ) ) {
2866 foreach( $ug_users_array['user_second_groups'] as $userid => $secondary_usergroups ) {
2867 if( ! empty( $secondary_usergroups ) ) {
2868 if( $append_second_groups ) {
2869 // Merges current secondary groups with new secondary groups
2870 WPF()->member->append_secondary_groupids( $userid, $secondary_usergroups );
2871 } else {
2872 // Removes current secondary groups and sets new secondary groups
2873 WPF()->member->set_secondary_groupids( $userid, $secondary_usergroups );
2874 }
2875 }
2876 }
2877 }
2878 if( ! empty( $group_users ) ) {
2879 /////////////////////////////////////////////////////////////////
2880 /// Updates users Usergroup Ids in profiles table
2881 $return = WPF()->usergroup->set_users_groupid( $group_users );
2882 /////////////////////////////////////////////////////////////////
2883 $success = ( wpfval( $return, 'success' ) ) ? $return['success'] : $success;
2884 $status['error'] = ( wpfval( $return, 'error' ) ) ? $return['error'] : $status['error'];
2885 if( $success ) {
2886 end( $users );
2887 $key = key( $users );
2888 $status['id'] = $users[ $key ]->ID;
2889 $result = count_users();
2890 $status['total'] = ( wpfval( $result, 'total_users' ) ) ? intval(
2891 $result['total_users']
2892 ) : 0;
2893 $status['start'] = $step * $limit;
2894 $status['left'] = ( $status['total'] > $status['start'] ) ? ( $status['total'] - $status['start'] ) : 0;
2895 $status['step'] = $step + 1;
2896 $progress = ( $status['total'] > $status['start'] ) ? ( $status['start'] * 100 ) / $status['total'] : 100;
2897 $status['progress'] = round( $progress );
2898 if( $progress == 100 ) {
2899 wpforo_delete_option( 'synch_roles' );
2900 } else {
2901 wpforo_update_option( 'synch_roles', $status );
2902 }
2903 }
2904 } else {
2905 $status['total'] = 0;
2906 $status['start'] = 0;
2907 $status['left'] = 0;
2908 $status['step'] = 1;
2909 $status['progress'] = 100;
2910 wpforo_delete_option( 'synch_roles' );
2911 }
2912 } else {
2913 $result = count_users();
2914 $status['total'] = ( wpfval( $result, 'total_users' ) ) ? intval( $result['total_users'] ) : 0;
2915 $status['start'] = $step * $limit;
2916 $status['left'] = 0;
2917 $status['step'] = 1;
2918 $status['progress'] = 100;
2919 wpforo_delete_option( 'synch_roles' );
2920 }
2921 }
2922 }
2923
2924 if( intval( wpfval( $status, 'progress' ) ) === 100 ) {
2925 WPF()->notice->add( 'Role-Usergroup synchronization is complete!', 'success' );
2926 }
2927
2928 wp_die( wp_json_encode( $status ) );
2929 }
2930
2931 add_action( 'wp_ajax_wpforo_synch_roles', 'wpforo_synch_roles' );
2932
2933
2934 function wpforo_update_usergroup_on_role_change( $userid, $new_role, $old_roles = [] ) {
2935 if( wpforo_setting( 'authorization', 'role_synch' ) ) {
2936 wpforo_synch_user_roles( $userid );
2937 }
2938 }
2939
2940 add_action( 'add_user_role', 'wpforo_update_usergroup_on_role_change', 99, 2 );
2941 add_action( 'set_user_role', 'wpforo_update_usergroup_on_role_change', 99, 3 );
2942
2943
2944 function wpforo_wp_admin_bar_red_circle_number( $number ) {
2945 $number = intval( $number );
2946 if( $number ) {
2947 return sprintf(
2948 '<div class="wp-core-ui wp-ui-notification wpforo-menu-notification-counter">%1$d</div>',
2949 $number
2950 );
2951 }
2952
2953 return '';
2954 }
2955
2956 function wpforo_get_memb_attention_count(): int {
2957 return WPF()->member->get_count( [ 'p.status' => [ 'banned', 'inactive' ] ] );
2958 }
2959
2960 function wpforo_get_admin_bar_numbers(): array {
2961 $all_count = 0;
2962 $mod_count = WPF()->post->unapproved_count();
2963 $all_count += $mod_count;
2964
2965 return compact( 'all_count', 'mod_count' );
2966 }
2967
2968 function wpforo_admin_bar_menu( $wp_admin_bar ) {
2969 $admin_bar_numbers = wpforo_get_admin_bar_numbers();
2970
2971 if( wpforo_current_user_is( 'admin' ) ) {
2972 $args = [
2973 'id' => 'new-forum',
2974 'title' => '&#43;&nbsp;&nbsp;' . __( 'Add New Forum', 'wpforo' ),
2975 'href' => admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'forums' ) . '&action=add' ),
2976 'parent' => 'new-content',
2977 ];
2978 $wp_admin_bar->add_node( $args );
2979 $args = [
2980 'id' => 'new-ugroup',
2981 'title' => '&#43;&nbsp;&nbsp;' . __( 'Add New User Group', 'wpforo' ),
2982 'href' => admin_url(
2983 'admin.php?page=' . wpforo_prefix_slug( 'usergroups' ) . '&wpfaction=wpforo_usergroup_save_form'
2984 ),
2985 'parent' => 'new-content',
2986 ];
2987 $wp_admin_bar->add_node( $args );
2988 $args = [
2989 'id' => 'new-phrase',
2990 'title' => '&#43;&nbsp;&nbsp;' . __( 'Add New Phrase', 'wpforo' ),
2991 'href' => admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'phrases' ) . '&wpfaction=phrase_add_form' ),
2992 'parent' => 'new-content',
2993 ];
2994 $wp_admin_bar->add_node( $args );
2995 }
2996
2997 $args = [
2998 'id' => 'wpforo-home',
2999 'title' => __( 'Visit Forum', 'wpforo' ),
3000 'href' => wpforo_home_url(),
3001 'parent' => 'wpf-community',
3002 // 'meta' => [ 'target' => '_blank' ]
3003 ];
3004 $wp_admin_bar->add_node( $args );
3005
3006 if( wpforo_current_user_is( 'admin' ) || WPF()->usergroup->can( 'mf' ) || WPF()->usergroup->can( 'ms' ) || WPF()->usergroup->can( 'vm' ) || WPF()->usergroup->can( 'mp' ) || WPF()->usergroup->can(
3007 'aum'
3008 ) || WPF()->usergroup->can( 'vmg' ) || WPF()->usergroup->can( 'mth' ) ) {
3009 $args = [
3010 'id' => 'wpf-community',
3011 'title' => __( 'Forum Dashboard', 'wpforo' ) . wpforo_wp_admin_bar_red_circle_number(
3012 $admin_bar_numbers['all_count']
3013 ),
3014 'href' => admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'dashboard' ) ),
3015 ];
3016 $wp_admin_bar->add_node( $args );
3017 }
3018 if( WPF()->usergroup->can( 'mf' ) || wpforo_current_user_is( 'admin' ) ) {
3019 $args = [
3020 'id' => 'wpf-forums',
3021 'title' => '' . __( 'Forums', 'wpforo' ),
3022 'href' => admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'forums' ) ),
3023 'parent' => 'wpf-community',
3024 ];
3025 $wp_admin_bar->add_node( $args );
3026 $args = [
3027 'id' => 'wpf-new-forum',
3028 'title' => '' . __( 'Add New Forum', 'wpforo' ),
3029 'href' => admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'forums' ) . '&action=add' ),
3030 'parent' => 'wpf-forums',
3031 ];
3032 $wp_admin_bar->add_node( $args );
3033 }
3034 if( WPF()->usergroup->can( 'ms' ) || wpforo_current_user_is( 'admin' ) ) {
3035 $args = [
3036 'id' => 'wpf-settings',
3037 'title' => '' . __( 'Settings', 'wpforo' ),
3038 'href' => admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'settings' ) ),
3039 'parent' => 'wpf-community',
3040 ];
3041 $wp_admin_bar->add_node( $args );
3042 }
3043 if( WPF()->usergroup->can( 'ms' ) || wpforo_current_user_is( 'admin' ) ) {
3044 $args = [
3045 'id' => 'wpf-ai',
3046 'title' => '' . __( 'AI Features', 'wpforo' ),
3047 'href' => admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'ai' ) ),
3048 'parent' => 'wpf-community',
3049 ];
3050 $wp_admin_bar->add_node( $args );
3051 }
3052 if( WPF()->usergroup->can( 'mt' ) || wpforo_current_user_is( 'admin' ) ) {
3053 $args = [
3054 'id' => 'wpf-tools',
3055 'title' => '' . __( 'Tools', 'wpforo' ),
3056 'href' => admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'tools' ) ),
3057 'parent' => 'wpf-community',
3058 ];
3059 $wp_admin_bar->add_node( $args );
3060 }
3061 if( WPF()->usergroup->can( 'aum' ) || wpforo_current_user_is( 'admin' ) ) {
3062 $args = [
3063 'id' => 'wpf-moderation',
3064 'title' => '' . __( 'Moderation', 'wpforo' ) . wpforo_wp_admin_bar_red_circle_number(
3065 $admin_bar_numbers['mod_count']
3066 ),
3067 'href' => admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'moderations' ) ),
3068 'parent' => 'wpf-community',
3069 ];
3070 $wp_admin_bar->add_node( $args );
3071 }
3072 if( WPF()->usergroup->can( 'ms' ) || wpforo_current_user_is( 'admin' ) ) {
3073 $args = [
3074 'id' => 'wpforo-accesses',
3075 'title' => '' . __( 'Accesses', 'wpforo' ),
3076 'href' => admin_url( 'admin.php?page=wpforo-accesses' ),
3077 'parent' => 'wpf-community',
3078 ];
3079 $wp_admin_bar->add_node( $args );
3080 $args = [
3081 'id' => 'wpforo-new-accesses',
3082 'title' => '' . __( 'Add New Forum Access', 'wpforo' ),
3083 'href' => admin_url( 'admin.php?page=wpforo-accesses&wpfaction=wpforo_access_save_form' ),
3084 'parent' => 'wpforo-accesses',
3085 ];
3086 $wp_admin_bar->add_node( $args );
3087 }
3088 if( WPF()->usergroup->can( 'vm' ) || wpforo_current_user_is( 'admin' ) ) {
3089 $args = [
3090 'id' => 'wpf-members',
3091 'title' => '' . __( 'Members', 'wpforo' ) . wpforo_wp_admin_bar_red_circle_number(
3092 wpforo_get_memb_attention_count()
3093 ),
3094 'href' => admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'members' ) ),
3095 'parent' => 'wpf-community',
3096 ];
3097 $wp_admin_bar->add_node( $args );
3098 }
3099 if( WPF()->usergroup->can( 'vmg' ) || wpforo_current_user_is( 'admin' ) ) {
3100 $args = [
3101 'id' => 'wpf-usergroups',
3102 'title' => '' . __( 'Usergroups', 'wpforo' ),
3103 'href' => admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'usergroups' ) ),
3104 'parent' => 'wpf-community',
3105 ];
3106 $wp_admin_bar->add_node( $args );
3107 $args = [
3108 'id' => 'wpf-new-ugroup',
3109 'title' => '' . __( 'Add New Usergroup', 'wpforo' ),
3110 'href' => admin_url(
3111 'admin.php?page=' . wpforo_prefix_slug( 'usergroups' ) . '&wpfaction=wpforo_usergroup_save_form'
3112 ),
3113 'parent' => 'wpf-usergroups',
3114 ];
3115 $wp_admin_bar->add_node( $args );
3116 }
3117 if( WPF()->usergroup->can( 'mp' ) || wpforo_current_user_is( 'admin' ) ) {
3118 $args = [
3119 'id' => 'wpf-phrases',
3120 'title' => '' . __( 'Phrases', 'wpforo' ),
3121 'href' => admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'phrases' ) ),
3122 'parent' => 'wpf-community',
3123 ];
3124 $wp_admin_bar->add_node( $args );
3125 $args = [
3126 'id' => 'wpf-new-phrase',
3127 'title' => '' . __( 'Add New Phrase', 'wpforo' ),
3128 'href' => admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'phrases' ) . '&wpfaction=phrase_add_form' ),
3129 'parent' => 'wpf-phrases',
3130 ];
3131 $wp_admin_bar->add_node( $args );
3132 }
3133 if( WPF()->usergroup->can( 'mth' ) || wpforo_current_user_is( 'admin' ) ) {
3134 $args = [
3135 'id' => 'wpf-themes',
3136 'title' => '' . __( 'Themes', 'wpforo' ),
3137 'href' => admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'themes' ) ),
3138 'parent' => 'wpf-community',
3139 ];
3140 $wp_admin_bar->add_node( $args );
3141 }
3142 if( wpforo_current_user_is( 'admin' ) ) {
3143 $args = [
3144 'id' => 'wpf-addons',
3145 'title' => '' . __( 'Addons', 'wpforo' ),
3146 'href' => admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'addons' ) ),
3147 'parent' => 'wpf-community',
3148 ];
3149 $wp_admin_bar->add_node( $args );
3150 }
3151 }
3152
3153 function wpforo_multiboard_admin_bar_menu( $wp_admin_bar ) {
3154 $bds_bar_numbers = [];
3155 if( wpforo_current_user_is( 'admin' ) ) {
3156 $args = [
3157 'id' => 'wpforo-new-content',
3158 'title' => 'wpForo',
3159 'href' => admin_url( 'admin.php?page=wpforo-overview' ),
3160 'parent' => 'new-content',
3161 ];
3162 $wp_admin_bar->add_node( $args );
3163
3164 if( $boardids = WPF()->board->get_active_boardids() ) {
3165 foreach( $boardids as $boardid ) {
3166 WPF()->change_board( $boardid );
3167 $current = WPF()->board->get_current();
3168 $bds_bar_numbers[ $boardid ] = wpforo_get_admin_bar_numbers();
3169
3170 $menuid = 'wpforo-new-content-' . $current['slug'];
3171 $args = [
3172 'id' => $menuid,
3173 'title' => $current['title'],
3174 'href' => admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'dashboard' ) ),
3175 'parent' => 'wpforo-new-content',
3176 ];
3177 $wp_admin_bar->add_node( $args );
3178 ## ---------------------------------------------------------------------------------- ####
3179 $args = [
3180 'id' => $menuid . 'new-forum',
3181 'title' => '' . __( 'Add New Forum', 'wpforo' ),
3182 'href' => admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'forums' ) . '&action=add' ),
3183 'parent' => $menuid,
3184 ];
3185 $wp_admin_bar->add_node( $args );
3186 $args = [
3187 'id' => $menuid . 'new-ugroup',
3188 'title' => '' . __( 'Add New User Group', 'wpforo' ),
3189 'href' => admin_url(
3190 'admin.php?page=' . wpforo_prefix_slug( 'usergroups' ) . '&wpfaction=wpforo_usergroup_save_form'
3191 ),
3192 'parent' => $menuid,
3193 ];
3194 $wp_admin_bar->add_node( $args );
3195 $args = [
3196 'id' => $menuid . 'new-phrase',
3197 'title' => '' . __( 'Add New Phrase', 'wpforo' ),
3198 'href' => admin_url(
3199 'admin.php?page=' . wpforo_prefix_slug( 'phrases' ) . '&wpfaction=phrase_add_form'
3200 ),
3201 'parent' => $menuid,
3202 ];
3203 $wp_admin_bar->add_node( $args );
3204
3205 }
3206 }
3207 }
3208
3209 if( wpforo_current_user_is( 'admin' ) || WPF()->usergroup->can( 'mf' ) || WPF()->usergroup->can( 'ms' ) || WPF()->usergroup->can( 'vm' ) || WPF()->usergroup->can( 'mp' ) || WPF()->usergroup->can(
3210 'aum'
3211 ) || WPF()->usergroup->can( 'vmg' ) || WPF()->usergroup->can( 'mth' ) ) {
3212 $bds_bar_all = 0;
3213 foreach( $bds_bar_numbers as $x ) $bds_bar_all += $x['all_count'];
3214 $args = [
3215 'id' => 'wpforo',
3216 'title' => 'wpForo' . wpforo_wp_admin_bar_red_circle_number( $bds_bar_all ),
3217 'href' => admin_url( 'admin.php?page=wpforo-overview' ),
3218 ];
3219 $wp_admin_bar->add_node( $args );
3220
3221
3222 if( $boardids = WPF()->board->get_active_boardids() ) {
3223 foreach( $boardids as $boardid ) {
3224 WPF()->change_board( $boardid );
3225 $current = WPF()->board->get_current();
3226
3227 $menuid = 'wpforo-' . $current['slug'];
3228 $args = [
3229 'id' => $menuid,
3230 'title' => '' . $current['title'] . ' (' . strtok(
3231 $current['locale'],
3232 '_'
3233 ) . ')' . wpforo_wp_admin_bar_red_circle_number( $bds_bar_numbers[ $boardid ]['all_count'] ),
3234 'href' => admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'dashboard' ) ),
3235 'parent' => 'wpforo',
3236 ];
3237 $wp_admin_bar->add_node( $args );
3238
3239 ## ---------------------------------------------------------------------------------- ####
3240
3241 $args = [
3242 'id' => $menuid . '-home',
3243 'title' => '' . __( 'Visit Forum', 'wpforo' ),
3244 'href' => wpforo_home_url(),
3245 'parent' => $menuid,
3246 // 'meta' => [ 'target' => '_blank' ]
3247 ];
3248 $wp_admin_bar->add_node( $args );
3249
3250 if( WPF()->usergroup->can( 'mf' ) || wpforo_current_user_is( 'admin' ) ) {
3251 $args = [
3252 'id' => $menuid . '-forums',
3253 'title' => '' . __( 'Forums', 'wpforo' ),
3254 'href' => admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'forums' ) ),
3255 'parent' => $menuid,
3256 ];
3257 $wp_admin_bar->add_node( $args );
3258 $args = [
3259 'id' => $menuid . '-new-forum',
3260 'title' => '' . __( 'Add New Forum', 'wpforo' ),
3261 'href' => admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'forums' ) . '&action=add' ),
3262 'parent' => $menuid . '-forums',
3263 ];
3264 $wp_admin_bar->add_node( $args );
3265 }
3266 if( WPF()->usergroup->can( 'ms' ) || wpforo_current_user_is( 'admin' ) ) {
3267 $args = [
3268 'id' => $menuid . '-settings',
3269 'title' => '' . __( 'Settings', 'wpforo' ),
3270 'href' => admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'settings' ) ),
3271 'parent' => $menuid,
3272 ];
3273 $wp_admin_bar->add_node( $args );
3274 }
3275 if( WPF()->usergroup->can( 'mt' ) || wpforo_current_user_is( 'admin' ) ) {
3276 $args = [
3277 'id' => $menuid . '-tools',
3278 'title' => '' . __( 'Tools', 'wpforo' ),
3279 'href' => admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'tools' ) ),
3280 'parent' => $menuid,
3281 ];
3282 $wp_admin_bar->add_node( $args );
3283 }
3284 if( WPF()->usergroup->can( 'aum' ) || wpforo_current_user_is( 'admin' ) ) {
3285 $args = [
3286 'id' => $menuid . '-moderation',
3287 'title' => '' . __(
3288 'Moderation',
3289 'wpforo'
3290 ) . wpforo_wp_admin_bar_red_circle_number( $bds_bar_numbers[ $boardid ]['mod_count'] ),
3291 'href' => admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'moderations' ) ),
3292 'parent' => $menuid,
3293 ];
3294 $wp_admin_bar->add_node( $args );
3295 }
3296 if( WPF()->usergroup->can( 'mp' ) || wpforo_current_user_is( 'admin' ) ) {
3297 $args = [
3298 'id' => $menuid . '-phrases',
3299 'title' => '' . __( 'Phrases', 'wpforo' ),
3300 'href' => admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'phrases' ) ),
3301 'parent' => $menuid,
3302 ];
3303 $wp_admin_bar->add_node( $args );
3304 $args = [
3305 'id' => $menuid . '-new-phrase',
3306 'title' => '' . __( 'Add New Phrase', 'wpforo' ),
3307 'href' => admin_url(
3308 'admin.php?page=' . wpforo_prefix_slug( 'phrases' ) . '&wpfaction=phrase_add_form'
3309 ),
3310 'parent' => $menuid . '-phrases',
3311 ];
3312 $wp_admin_bar->add_node( $args );
3313 }
3314 }
3315 }
3316
3317 ##### -- ##### ----- $ ----- ###
3318
3319 if( WPF()->usergroup->can( 'ms' ) || wpforo_current_user_is( 'admin' ) ) {
3320 $args = [
3321 'id' => 'wpforo-boards',
3322 'title' => '' . __( 'Boards', 'wpforo' ),
3323 'href' => admin_url( 'admin.php?page=wpforo-boards' ),
3324 'parent' => 'wpforo',
3325 ];
3326 $wp_admin_bar->add_node( $args );
3327 $args = [
3328 'id' => 'wpforo-new-board',
3329 'title' => '' . __( 'Add New Board', 'wpforo' ),
3330 'href' => admin_url( 'admin.php?page=wpforo-boards&wpfaction=wpforo_board_save_form' ),
3331 'parent' => 'wpforo-boards',
3332 ];
3333 $wp_admin_bar->add_node( $args );
3334 }
3335 if( WPF()->usergroup->can( 'ms' ) || wpforo_current_user_is( 'admin' ) ) {
3336 $args = [
3337 'id' => 'wpforo-accesses',
3338 'title' => '' . __( 'Accesses', 'wpforo' ),
3339 'href' => admin_url( 'admin.php?page=wpforo-accesses' ),
3340 'parent' => 'wpforo',
3341 ];
3342 $wp_admin_bar->add_node( $args );
3343 $args = [
3344 'id' => 'wpforo-new-accesses',
3345 'title' => '' . __( 'Add New Forum Access', 'wpforo' ),
3346 'href' => admin_url( 'admin.php?page=wpforo-accesses&wpfaction=wpforo_access_save_form' ),
3347 'parent' => 'wpforo-accesses',
3348 ];
3349 $wp_admin_bar->add_node( $args );
3350 }
3351 if( WPF()->usergroup->can( 'vmg' ) || wpforo_current_user_is( 'admin' ) ) {
3352 $args = [
3353 'id' => 'wpforo-usergroups',
3354 'title' => '' . __( 'Usergroups', 'wpforo' ),
3355 'href' => admin_url( 'admin.php?page=wpforo-usergroups' ),
3356 'parent' => 'wpforo',
3357 ];
3358 $wp_admin_bar->add_node( $args );
3359 $args = [
3360 'id' => 'wpforo-new-ugroup',
3361 'title' => '' . __( 'Add New Usergroup', 'wpforo' ),
3362 'href' => admin_url( 'admin.php?page=wpforo-usergroups&wpfaction=wpforo_usergroup_save_form' ),
3363 'parent' => 'wpforo-usergroups',
3364 ];
3365 $wp_admin_bar->add_node( $args );
3366 }
3367 if( WPF()->usergroup->can( 'vm' ) || wpforo_current_user_is( 'admin' ) ) {
3368 $args = [
3369 'id' => 'wpforo-members',
3370 'title' => '' . __( 'Members', 'wpforo' ) . wpforo_wp_admin_bar_red_circle_number(
3371 wpforo_get_memb_attention_count()
3372 ),
3373 'href' => admin_url( 'admin.php?page=wpforo-members' ),
3374 'parent' => 'wpforo',
3375 ];
3376 $wp_admin_bar->add_node( $args );
3377 }
3378 if( WPF()->usergroup->can( 'ms' ) || wpforo_current_user_is( 'admin' ) ) {
3379 $args = [
3380 'id' => 'wpforo-base-settings',
3381 'title' => '' . __( 'Settings', 'wpforo' ),
3382 'href' => admin_url( 'admin.php?page=wpforo-base-settings' ),
3383 'parent' => 'wpforo',
3384 ];
3385 $wp_admin_bar->add_node( $args );
3386 }
3387 if( WPF()->usergroup->can( 'ms' ) || wpforo_current_user_is( 'admin' ) ) {
3388 $args = [
3389 'id' => 'wpforo-ai',
3390 'title' => '' . __( 'AI Features', 'wpforo' ),
3391 'href' => admin_url( 'admin.php?page=wpforo-ai' ),
3392 'parent' => 'wpforo',
3393 ];
3394 $wp_admin_bar->add_node( $args );
3395 }
3396 if( WPF()->usergroup->can( 'mth' ) || wpforo_current_user_is( 'admin' ) ) {
3397 $args = [
3398 'id' => 'wpforo-themes',
3399 'title' => '' . __( 'Themes', 'wpforo' ),
3400 'href' => admin_url( 'admin.php?page=wpforo-themes' ),
3401 'parent' => 'wpforo',
3402 ];
3403 $wp_admin_bar->add_node( $args );
3404 }
3405 if( wpforo_current_user_is( 'admin' ) ) {
3406 $args = [
3407 'id' => 'wpforo-addons',
3408 'title' => '' . __( 'Addons', 'wpforo' ),
3409 'href' => admin_url( 'admin.php?page=wpforo-addons' ),
3410 'parent' => 'wpforo',
3411 ];
3412 $wp_admin_bar->add_node( $args );
3413 }
3414 }
3415 }
3416
3417 add_action( 'admin_bar_menu', function( $wp_admin_bar ) {
3418 if( is_wpforo_multiboard() ) {
3419 wpforo_multiboard_admin_bar_menu( $wp_admin_bar );
3420 WPF()->change_board();
3421 } else {
3422 wpforo_admin_bar_menu( $wp_admin_bar );
3423 }
3424 echo '<style>
3425 #wpadminbar .wpforo-menu-notification-counter,
3426 #wpadminbar .wpforo-menu-notification-indicator{
3427 background-color: #d63638;
3428 color: #ffffff;
3429 }
3430
3431 #wpadminbar .wpforo-menu-notification-counter{
3432 display: inline-block;
3433 min-width: 18px;
3434 height: 18px;
3435 border-radius: 50%;
3436 margin: 5px 5px 0 5px;
3437 vertical-align: top;
3438 font-size: 11px;
3439 line-height: 1.6;
3440 text-align: center;
3441 }
3442 </style>';
3443 }, 999 );
3444
3445 function wpforo_tag_search() {
3446 $s = wp_unslash( $_GET['q'] );
3447 $tag_separator = ( strpos( $s, '،' ) !== false ) ? '،' : ',';
3448 $tag_separator = apply_filters( 'wpforo_tag_separator', $tag_separator );
3449 if( false !== strpos( (string) $s, $tag_separator ) ) {
3450 $s = str_replace( $tag_separator, ',', $s );
3451 $s = explode( ',', $s );
3452 $s = $s[ count( $s ) - 1 ];
3453 }
3454 $s = trim( (string) $s );
3455 $tag_search_min_chars = apply_filters( 'wpforo_tag_search_min_chars', 2 );
3456 if( wpforo_strlen( $s ) >= $tag_search_min_chars ) {
3457 $limit = wpforo_setting( 'tags', 'suggest_limit' );
3458 $results = WPF()->db->get_col(
3459 "SELECT `tag` FROM `" . WPF()->tables->tags . "` WHERE `tag` LIKE '" . esc_sql( $s ) . "%' LIMIT " . $limit
3460 );
3461 if( ! empty( $results ) ) {
3462 echo implode( "\n", $results );
3463 }
3464 }
3465 wp_die();
3466 }
3467
3468 add_action( 'wp_ajax_wpforo_tag_search', 'wpforo_tag_search' );
3469 add_action( 'wp_ajax_nopriv_wpforo_tag_search', 'wpforo_tag_search' );
3470
3471 function wpforo_add_to_footer() {
3472 if( WPF()->current_object['load_tinymce'] ) {
3473 wp_enqueue_editor();
3474 }
3475 }
3476
3477 add_action( 'wpforo_bottom_hook', 'wpforo_add_to_footer' );
3478
3479 function wpforo_check_notifications() {
3480 $data = [ 'alerts' => 0, 'notifications' => '' ];
3481 if( is_user_logged_in() && wpforo_setting( 'notifications', 'notifications' ) ) {
3482 $data['alerts'] = count( WPF()->activity->notifications );
3483 if( wpfval( $_POST, 'getdata' ) ) {
3484 $data['notifications'] = WPF()->activity->notifications_list( false );
3485 }
3486 wp_send_json_success( $data );
3487 }
3488 wp_send_json_error( $data );
3489 }
3490
3491 add_action( 'wp_ajax_wpforo_notifications', 'wpforo_check_notifications' );
3492
3493 function wpforo_can_display_recaptcha_note() {
3494 $d = wpforo_is_admin() ? 'recaptcha_backend_note' : 'recaptcha_note';
3495
3496 return ! WPF()->dissmissed[ $d ] && current_user_can( 'administrator' ) && ! wp_is_mobile() && wpforo_setting(
3497 'authorization',
3498 'user_register'
3499 ) && ! wpforo_setting( 'authorization', 'register_url' ) && ! wpforo_is_recaptcha_configured();
3500 }
3501
3502 add_action( 'wpforo_header_hook', 'wpforo_recaptcha_note' );
3503 function wpforo_recaptcha_note() {
3504 if( wpforo_can_display_recaptcha_note() ) {
3505 ?>
3506 <div class="wpforo-rcn-wrap">
3507 <div class="wpforo-rcn-body">
3508 <span class="wpforo-rcn-head"><i
3509 class="fas fa-user-secret"></i> <?php wpforo_phrase(
3510 'Protect your forum from spam user registration!'
3511 ); ?></span>
3512 <?php printf(
3513 wpforo_phrase(
3514 'wpForo has not found any protection solution against spam user registration on the forum registration form. Please %1$s and enable the %2$s antibot protection in %3$s or install other alternative %4$s to avoid registration of spam users.',
3515 false,
3516 'native'
3517 ),
3518 '<a class="wpf-rcnl" href="' . admin_url(
3519 'admin.php?page=' . wpforo_prefix_slug(
3520 'base-settings'
3521 ) . '&wpf_tab=recaptcha#wpf-settings-tab'
3522 ) . '" target="_blank">' . wpforo_phrase( 'configure', false, 'lower' ) . '</a>',
3523 '<a class="wpf-rcngl" href="https://developers.google.com/recaptcha" target="_blank">Google reCAPTCHA</a>',
3524 '<a href="' . admin_url(
3525 'admin.php?page=' . wpforo_prefix_slug(
3526 'base-settings'
3527 ) . '&wpf_tab=recaptcha#wpf-settings-tab'
3528 ) . '">' . wpforo_phrase( 'Settings &gt; Spam Protection Tab', false ) . '</a>',
3529 '<a class="wpf-rcnwl" href="https://wordpress.org/plugins/search/spam+users/" target="_blank">' . wpforo_phrase(
3530 'WordPress plugin',
3531 false
3532 ) . '</a>'
3533 )
3534 ?>
3535 </div>
3536 <div class="wpforo-rcn-footer">
3537 <div class="wpforo-rcn-info">
3538 <?php wpforo_phrase(
3539 'This notification is only visible for the website administrators. It will be automatically disabled once some antispam solution is enabled. If you don\'t use wpForo registration form or you\'re sure, that you have an antispam solution just click the [dismiss] button.'
3540 ); ?>
3541 </div>
3542 <div class="wpforo-rcn-dismiss">
3543 <span class="wpforo-rcn-dismiss-button"
3544 wpf-tooltip="<?php wpforo_phrase( 'I got it, please dismiss this message' ) ?>"
3545 wpf-tooltip-size="long"><?php wpforo_phrase( 'Dismiss' ) ?></span>
3546 </div>
3547 </div>
3548 </div>
3549 <?php
3550 }
3551 }
3552
3553 //add_action('admin_notices', 'wpforo_admin_notice_recaptcha');
3554 function wpforo_admin_notice_recaptcha() {
3555 if( wpforo_can_display_recaptcha_note() ) {
3556 wp_enqueue_script( 'wpforo-backend-js' );
3557 $class = 'notice notice-error is-dismissible';
3558 $message = __(
3559 'IMPORTANT! The forum registration form is probably under risk of spam attacks. Please configure wpForo built-in %s antibot for registration form to avoid spam registrations. If you don\'t use the forum registration form or you are sure that your registration forms are secured, just click on (x) button to dismiss this message.',
3560 'wpforo'
3561 );
3562 $message = sprintf(
3563 $message,
3564 '<a href="' . admin_url(
3565 'admin.php?page=' . wpforo_prefix_slug( 'tools' ) . '&tab=antispam#wpf-recaptcha'
3566 ) . '" target="_blank" style="text-decoration:none;">' . __(
3567 'Google reCAPTCHA',
3568 'wpforo'
3569 ) . '</a>'
3570 );
3571 printf( '<div id="wpforo-admin-notice-recaptcha" class="%1$s"><p>%2$s</p></div>', $class, $message );
3572 }
3573 }
3574
3575 function wpforo_is_recaptcha_configured() {
3576 return wpforo_setting( 'recaptcha', 'wpf_reg_form' ) && wpforo_setting( 'recaptcha', 'site_key' ) && wpforo_setting(
3577 'recaptcha',
3578 'secret_key'
3579 );
3580 }
3581
3582
3583 /*add_action( 'plugins_loaded', function() {
3584 if( ! (int) wpfval( WPF()->dissmissed, 'poll_version_is_old' ) && function_exists( 'WPF_POLL' ) ) {
3585 if( version_compare( WPFORO_VERSION, '1.7.7', '>' ) && version_compare( WPFOROPOLL_VERSION, '1.0.5', '<=' ) ) {
3586 remove_action( 'widgets_init', [ WPF_POLL(), 'init_widgets' ] );
3587 remove_action( 'wpforo_before_init', [ WPF_POLL(), 'init' ] );
3588
3589 WPF()->dissmissed['poll_version_is_old'] = 0;
3590 wpforo_update_option( 'dissmissed', WPF()->dissmissed );
3591 } else {
3592 WPF()->dissmissed['poll_version_is_old'] = 1;
3593 wpforo_update_option( 'dissmissed', WPF()->dissmissed );
3594 }
3595 }
3596 } );*/
3597
3598 add_action( 'admin_notices', function() {
3599 if( wpfkey( WPF()->dissmissed, 'poll_version_is_old' ) && ! (int) WPF()->dissmissed['poll_version_is_old'] ) {
3600 $class = 'notice notice-error';
3601 $message = '<div style="font-size: 16px; padding: 10px 0;"><strong>' . __(
3602 'wpForo Polls addon is disabled!',
3603 'wpforo'
3604 ) . '</strong><p style="font-size:15px; margin-bottom:0;">' . __(
3605 ' Your addon version is not compatible with the current version of wpForo. Please update the addon or downgrade wpForo to 1.7.7',
3606 'wpforo'
3607 ) . '</p></div>';
3608 $message .= ' <a href="' . admin_url(
3609 wp_nonce_url(
3610 'admin.php?page=' . wpforo_prefix_slug( 'dashboard' ) . '&wpfaction=dissmiss_poll_version_is_old',
3611 'wpforo-dissmiss-poll-version-is-old'
3612 )
3613 ) . '">[' . __( 'dismiss', 'wpforo' ) . ']</a>';
3614 printf( '<div class="%1$s"><p>%2$s</p></div>', $class, $message );
3615 }
3616 } );
3617
3618 add_action( 'wpforo_update_option', function() {
3619 wpforo_clean_folder(
3620 WPF()->folders['cache']['dir'] . DIRECTORY_SEPARATOR . 'item' . DIRECTORY_SEPARATOR . 'option'
3621 );
3622 } );
3623
3624 add_action( 'wpforo_after_init', function() {
3625 add_action( 'wp_ajax_dismiss_wpforo_addon_note', [ WPF()->notice, 'dismissAddonNote' ] );
3626 add_action( 'admin_notices', [ WPF()->notice, 'addonNote' ] );
3627 } );
3628
3629 add_action( 'wpforo_after_init', function() {
3630 add_action( 'wp_ajax_dismiss_wpforo_cache_conflict_note', [ WPF()->notice, 'dismissCacheConflict' ] );
3631 } );
3632
3633 add_action( 'admin_enqueue_scripts', 'wpforo_cat_cover_js' );
3634
3635 function wpforo_cat_cover_js() {
3636 if( wpfval( $_GET, 'page' ) === wpforo_prefix_slug( 'forums' ) && ! did_action( 'wp_enqueue_media' ) ) {
3637 wp_enqueue_media();
3638 }
3639 }
3640
3641 function wpforo_esc_html( $var ) {
3642 if( is_scalar( $var ) ) {
3643 $var = esc_html( $var );
3644 } else {
3645 $var = wpforo_esc_html( $var );
3646 }
3647
3648 return $var;
3649 }
3650
3651 add_action( 'wpforo_bottom_hook', 'wpforo_debug' );
3652 function wpforo_debug() {
3653 if( wpforo_setting( 'general', 'debug_mode' ) ) : ?>
3654 <div id="wpforo-debug" style="display:none">
3655 <h4>Super Globals</h4>
3656 <textarea style="width:100%; height:300px;">
3657 Requests: <?php //print_r( array_map( 'wpforo_esc_html', $_REQUEST ) ); ?>
3658 Server: <?php //print_r( $_SERVER ); ?>
3659 </textarea>
3660 <h4>Options and Features</h4>
3661 <textarea style="width:100%; height:300px;">
3662 <?php echo @ 'route: ' . WPF()->board->route . "\r\n";
3663 echo @ 'use_home_url: ' . WPF()->board->get_current( 'is_standalone' ) . "\r\n";
3664 echo @ 'url: ' . wpforo_home_url() . "\r\n";
3665 echo @ 'pageid:' . WPF()->board->get_current( 'pageid' ) . "\r\n";
3666 echo @ 'default_groupid: ' . WPF()->usergroup->default_groupid . "\r\n";
3667 @print_r( WPF()->tpl->theme ) . "\r\n";
3668 ?>
3669 </textarea>
3670 </div>
3671 <?php
3672 endif;
3673 }
3674
3675 add_filter( 'wpforo_topic_list_args', function( $args ) {
3676 if( wpforo_setting( 'topics', 'include_subforums_topics' ) ) {
3677 $forumid = (int) $args['forumid'];
3678 $forumids = WPF()->forum->get_forumid_and_childids( $forumid );
3679 unset( $args['forumid'] );
3680 $args['forumids'] = $forumids;
3681 }
3682
3683 return $args;
3684 } );
3685
3686 function wpf_body_wp_encode_emoji( $post ) {
3687 if( wpfkey( $post, 'title' ) ) $post['title'] = wp_encode_emoji( $post['title'] );
3688 if( wpfkey( $post, 'body' ) ) $post['body'] = wp_encode_emoji( $post['body'] );
3689
3690 return $post;
3691 }
3692
3693 add_filter( 'wpforo_add_post_data_filter', 'wpf_body_wp_encode_emoji' );
3694 add_filter( 'wpforo_edit_post_data_filter', 'wpf_body_wp_encode_emoji' );
3695 add_filter( 'wpforo_add_topic_data_filter', 'wpf_body_wp_encode_emoji' );
3696 add_filter( 'wpforo_edit_topic_data_filter', 'wpf_body_wp_encode_emoji' );
3697
3698 // Feature Introduction Modal - AJAX dismiss handler (must be in hooks.php, not admin/index.php, because wpforo_is_admin() excludes AJAX)
3699 add_action( 'wp_ajax_wpforo_dismiss_feature_intro', function() {
3700 \wpforo\classes\FeatureIntro::ajax_dismiss_static();
3701 } );
3702
3703 // Feature Introduction Modal - redirect to wpForo Overview after update/activation
3704 add_action( 'admin_init', function() {
3705 if( wp_doing_ajax() || wp_doing_cron() ) return;
3706 if( is_network_admin() ) return;
3707 if( isset( $_GET['activate-multi'] ) ) return;
3708 if( ! current_user_can( 'manage_options' ) ) return;
3709
3710 $intro_version = \wpforo\classes\FeatureIntro::CURRENT_INTRO;
3711 $version_option = \wpforo\classes\FeatureIntro::VERSION_OPTION;
3712 $last_intro = get_option( $version_option, '' );
3713
3714 if( version_compare( $last_intro, $intro_version, '<' ) ) {
3715 update_option( $version_option, $intro_version );
3716 // Don't redirect if already on a wpForo page
3717 if( isset( $_GET['page'] ) && strpos( sanitize_text_field( $_GET['page'] ), 'wpforo' ) !== false ) return;
3718 wp_safe_redirect( admin_url( 'admin.php?page=wpforo-overview' ) );
3719 exit;
3720 }
3721 }, 1 );
3722