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

Actions.php in wpForo Forum 3.0.2, at classes/Actions.php

3,448 lines 113.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace wpforo\classes;
4
5 // Exit if accessed directly
6 if( ! defined( 'ABSPATH' ) ) exit();
7
8 class Actions {
9 /**
10 * wpForoAction constructor.
11 */
12 public function __construct() {
13 $this->init_hooks();
14 }
15
16 /**
17 * method for initializing all necessary hooks
18 */
19 public function init_hooks() {
20 add_action( 'wpforo_after_init_classes', function() { if( WPF()->need_activation() ) wpforo_activation(); }, 0 );
21
22 add_action( 'wpforo_after_init', [ $this, 'do_actions' ], 999 );
23 add_action( 'wpforo_action_user_delete', [ $this, 'user_delete' ] );
24 add_action( 'deleted_user', [ $this, 'deleted_user' ], 10, 2 );
25
26 add_action( 'wp_ajax_wpforo_profiles_default_cover_upload', [ $this, 'profiles_default_cover_upload' ] );
27 add_action( 'wp_ajax_wpforo_deactivate', [ $this, 'deactivate' ] );
28
29 if( ! wpforo_is_admin() ) {
30 add_action( 'wpforo_actions', function() {
31 if( wpfval( $_REQUEST, 'wpfaction' ) === 'topic_add' ) unregister_post_type( 'topic' );
32 } );
33
34 add_action( 'wpforo_actions', [ $this, 'init_default_attach_hooks' ] );
35 add_action( 'wpforo_actions', [ $this, 'init_wp_emoji_hooks' ] );
36
37 add_action( 'wpforo_actions', [ $this, 'feed_rss2' ] );
38 add_action( 'wpforo_actions', [ $this, 'mark_all_read' ] );
39 add_action( 'wpforo_actions', [ $this, 'mark_notification_read' ] );
40
41 add_action( 'wpforo_action_registration', [ $this, 'registration' ] );
42 add_action( 'wpforo_action_login', [ $this, 'login' ] );
43 add_action( 'wpforo_action_lostpassword', [ $this, 'lostpassword' ] );
44 add_action( 'wpforo_action_resetpassword_form', [ $this, 'resetpassword_form' ] );
45 add_action( 'wpforo_action_resetpassword', [ $this, 'resetpassword' ] );
46 add_action( 'wpforo_action_profile_update', [ $this, 'profile_update' ] );
47 add_action( 'wpforo_action_ucf_file_delete', [ $this, 'ucf_file_delete' ] );
48 add_action( 'wpforo_action_cantlogin_contact', [ $this, 'cantlogin_contact' ] );
49
50 add_action( 'wpforo_action_topic_add', [ $this, 'topic_add' ] );
51 add_action( 'wpforo_action_topic_edit', [ $this, 'topic_edit' ] );
52 add_action( 'wpforo_action_topic_move', [ $this, 'topic_move' ] );
53 add_action( 'wpforo_action_topic_merge', [ $this, 'topic_merge' ] );
54 add_action( 'wpforo_action_topic_split', [ $this, 'topic_split' ] );
55
56 add_action( 'wpforo_action_post_add', [ $this, 'post_add' ] );
57 add_action( 'wpforo_action_post_edit', [ $this, 'post_edit' ] );
58
59 ## ajax actions ##
60 add_action( 'wp_ajax_wpforo_dissmiss_recaptcha_note', [ $this, 'dissmiss_recaptcha_note' ] );
61 add_action( 'wp_ajax_wpforo_acp_toggle', [ $this, 'acp_toggle' ] );
62 add_action( 'wp_ajax_wpforo_clear_all_notifications', [ $this, 'clear_all_notifications' ] );
63 add_action( 'wp_ajax_wpforo_profile_cover_upload', [ $this, 'profile_cover_upload' ] );
64 add_action( 'wp_ajax_wpforo_profile_cover_delete', [ $this, 'profile_cover_delete' ] );
65 add_action( 'wp_ajax_wpforo_get_topic_head_more_info', [ $this, 'get_topic_head_more_info' ] );
66 add_action( 'wp_ajax_nopriv_wpforo_get_topic_head_more_info', [ $this, 'get_topic_head_more_info' ] );
67 add_action( 'wp_ajax_wpforo_get_topic_overview_chunk', [ $this, 'get_topic_overview_chunk' ] );
68 add_action( 'wp_ajax_nopriv_wpforo_get_topic_overview_chunk', [ $this, 'get_topic_overview_chunk' ] );
69 add_action( 'wp_ajax_wpforo_get_overview', [ $this, 'get_overview' ] );
70 add_action( 'wp_ajax_nopriv_wpforo_get_overview', [ $this, 'get_overview' ] );
71 add_action( 'wp_ajax_wpforo_user_ban', [ $this, 'user_ban_ajax' ] );
72 add_action( 'wp_ajax_wpforo_get_member_template', [ $this, 'get_member_template' ] );
73 add_action( 'wp_ajax_nopriv_wpforo_get_member_template', [ $this, 'get_member_template' ] );
74 add_action( 'wp_ajax_wpforo_search_existed_topics', [ $this, 'search_existed_topics' ] );
75 add_action( 'wp_ajax_nopriv_wpforo_search_existed_topics', [ $this, 'search_existed_topics' ] );
76 add_action( 'wp_ajax_wpforo_confirm_current_user_password', [ $this, 'confirm_current_user_password' ] );
77
78 // AI Features admin AJAX handlers
79 add_action( 'wp_ajax_wpforo_ai_store_checkout_mapping', [ $this, 'ai_store_checkout_mapping' ] );
80 add_action( 'wp_ajax_wpforo_ai_get_legal_document', [ $this, 'ai_get_legal_document' ] );
81 } else {
82 add_action( 'wpforo_actions', [ $this, 'check_dashboard_permissions' ], 1 );
83 add_action( 'wpforo_actions', [ $this, 'repair_lost_main_shortcode_page' ] );
84
85 add_action( 'wpforo_action_synch_user_profiles', [ $this, 'synch_user_profiles' ] );
86 add_action( 'wpforo_action_reset_user_cache', [ $this, 'reset_user_cache' ] );
87 add_action( 'wpforo_action_reset_forums_stats', [ $this, 'reset_forums_stats' ] );
88 add_action( 'wpforo_action_reset_topics_stats', [ $this, 'reset_topics_stats' ] );
89 add_action( 'wpforo_action_reset_users_stats', [ $this, 'reset_users_stats' ] );
90 add_action( 'wpforo_action_rebuild_threads', [ $this, 'rebuild_threads' ] );
91 add_action( 'wpforo_action_reset_phrase_cache', [ $this, 'reset_phrase_cache' ] );
92 add_action( 'wpforo_action_recrawl_phrases', [ $this, 'recrawl_phrases' ] );
93 add_action( 'wpforo_action_clean_up', [ $this, 'clean_up' ] );
94 add_action( 'wpforo_action_flush_permalinks', [ $this, 'flush_permalinks' ] );
95
96 add_action( 'wpforo_action_base_slugs_settings_save', [ $this, 'base_slugs_settings_save' ] );
97 add_action( 'wpforo_action_general_settings_save', [ $this, 'general_settings_save' ] );
98
99 add_action( 'wpforo_action_slugs_settings_save', [ $this, 'slugs_settings_save' ] );
100 add_action( 'wpforo_action_board_settings_save', [ $this, 'board_settings_save' ] );
101
102 add_action( 'wpforo_action_akismet_settings_save', [ $this, 'akismet_settings_save' ] );
103 add_action( 'wpforo_action_antispam_settings_save', [ $this, 'antispam_settings_save' ] );
104 add_action( 'wpforo_action_authorization_settings_save', [ $this, 'authorization_settings_save' ] );
105 add_action( 'wpforo_action_buddypress_settings_save', [ $this, 'buddypress_settings_save' ] );
106 add_action( 'wpforo_action_components_settings_save', [ $this, 'components_settings_save' ] );
107 add_action( 'wpforo_action_email_settings_save', [ $this, 'email_settings_save' ] );
108 add_action( 'wpforo_action_forums_settings_save', [ $this, 'forums_settings_save' ] );
109 add_action( 'wpforo_action_logging_settings_save', [ $this, 'logging_settings_save' ] );
110 add_action( 'wpforo_action_activity_settings_save', [ $this, 'activity_settings_save' ] );
111 add_action( 'wpforo_action_members_settings_save', [ $this, 'members_settings_save' ] );
112 add_action( 'wpforo_action_notifications_settings_save', [ $this, 'notifications_settings_save' ] );
113 add_action( 'wpforo_action_posting_settings_save', [ $this, 'posting_settings_save' ] );
114 add_action( 'wpforo_action_profiles_settings_save', [ $this, 'profiles_settings_save' ] );
115 add_action( 'wpforo_action_rating_settings_save', [ $this, 'rating_settings_save' ] );
116 add_action( 'wpforo_action_recaptcha_settings_save', [ $this, 'recaptcha_settings_save' ] );
117 add_action( 'wpforo_action_rss_settings_save', [ $this, 'rss_settings_save' ] );
118 add_action( 'wpforo_action_seo_settings_save', [ $this, 'seo_settings_save' ] );
119 add_action( 'wpforo_action_social_settings_save', [ $this, 'social_settings_save' ] );
120 add_action( 'wpforo_action_styles_settings_save', [ $this, 'styles_settings_save' ] );
121 add_action( 'wpforo_action_tags_settings_save', [ $this, 'tags_settings_save' ] );
122 add_action( 'wpforo_action_topics_settings_save', [ $this, 'topics_settings_save' ] );
123 add_action( 'wpforo_action_um_settings_save', [ $this, 'um_settings_save' ] );
124 add_action( 'wpforo_action_legal_settings_save', [ $this, 'legal_settings_save' ] );
125 add_action( 'wpforo_action_ai_settings_save', [ $this, 'ai_settings_save' ] );
126 add_action( 'wpforo_action_settings_export', [ $this, 'settings_export' ] );
127 add_action( 'wpforo_action_settings_import', [ $this, 'settings_import' ] );
128
129 add_action( 'wpforo_action_board_add', [ $this, 'board_add' ] );
130 add_action( 'wpforo_action_board_edit', [ $this, 'board_edit' ] );
131 add_action( 'wpforo_action_board_repair', [ $this, 'board_repair' ] );
132 add_action( 'wpforo_action_board_delete', [ $this, 'board_delete' ] );
133
134 add_action( 'wpforo_action_add_new_xml_translation', [ $this, 'add_new_xml_translation' ] );
135 add_action( 'wpforo_action_phrases_change_lang', [ $this, 'phrases_change_lang' ] );
136 add_action( 'wpforo_action_dashboard_options_save', [ $this, 'dashboard_options_save' ] );
137 add_action( 'wpforo_action_colors_css_download', [ $this, 'colors_css_download' ] );
138 // add_action( 'wpforo_action_cleanup_options_save', [ $this, 'cleanup_options_save' ] );
139 add_action( 'wpforo_action_misc_options_save', [ $this, 'misc_options_save' ] );
140 add_action( 'wpforo_action_legal_options_save', [ $this, 'legal_options_save' ] );
141 add_action( 'wpforo_action_delete_spam_file', [ $this, 'delete_spam_file' ] );
142 add_action( 'wpforo_action_delete_all_spam_files', [ $this, 'delete_all_spam_files' ] );
143 add_action( 'wpforo_action_database_update', [ $this, 'database_update' ] );
144
145 add_action( 'wpforo_action_forum_copy', [ $this, 'forum_copy' ] );
146 add_action( 'wpforo_action_forum_add', [ $this, 'forum_add' ] );
147 add_action( 'wpforo_action_forum_edit', [ $this, 'forum_edit' ] );
148 add_action( 'wpforo_action_forum_delete', [ $this, 'forum_delete' ] );
149 add_action( 'wpforo_action_forum_hierarchy_save', [ $this, 'forum_hierarchy_save' ] );
150
151 add_action( 'wpforo_action_dashboard_post_unapprove', [ $this, 'dashboard_post_unapprove' ] );
152 add_action( 'wpforo_action_dashboard_post_approve', [ $this, 'dashboard_post_approve' ] );
153 add_action( 'wpforo_action_dashboard_post_delete', [ $this, 'dashboard_post_delete' ] );
154 add_action( 'wpforo_action_bulk_moderation', [ $this, 'bulk_moderation' ] );
155
156 add_action( 'wpforo_action_phrase_add', [ $this, 'phrase_add' ] );
157 add_action( 'wpforo_action_phrase_edit_form', [ $this, 'phrase_edit_form' ] );
158 add_action( 'wpforo_action_phrase_edit', [ $this, 'phrase_edit' ] );
159
160 add_action( 'wpforo_action_user_ban', [ $this, 'user_ban' ] );
161 add_action( 'wpforo_action_user_unban', [ $this, 'user_unban' ] );
162 add_action( 'wpforo_action_user_activate', [ $this, 'user_activate' ] );
163 add_action( 'wpforo_action_user_deactivate', [ $this, 'user_deactivate' ] );
164 add_action( 'wpforo_action_bulk_members', [ $this, 'bulk_members' ] );
165
166 add_action( 'wpforo_action_usergroup_add', [ $this, 'usergroup_add' ] );
167 add_action( 'wpforo_action_usergroup_edit', [ $this, 'usergroup_edit' ] );
168 add_action( 'wpforo_action_usergroup_delete', [ $this, 'usergroup_delete' ] );
169 add_action( 'wpforo_action_default_groupid_change', [ $this, 'default_groupid_change' ] );
170 add_action( 'wpforo_action_usergroup_delete_form', [ $this, 'usergroup_delete_form' ] );
171
172 add_action( 'wpforo_action_access_add', [ $this, 'access_add' ] );
173 add_action( 'wpforo_action_access_edit', [ $this, 'access_edit' ] );
174 add_action( 'wpforo_action_access_delete', [ $this, 'access_delete' ] );
175
176 add_action( 'wpforo_action_theme_activate', [ $this, 'theme_activate' ] );
177 add_action( 'wpforo_action_theme_delete', [ $this, 'theme_delete' ] );
178
179 add_action( 'wpforo_action_update_addons_css', [ $this, 'update_addons_css' ] );
180 add_action( 'wpforo_action_dissmiss_poll_version_is_old', [ $this, 'dissmiss_poll_version_is_old' ] );
181
182 add_action( 'wpforo_action_uninstall', [ $this, 'uninstall' ] );
183 }
184 add_action( 'wpforo_action_reset_all_caches', [ $this, 'reset_all_caches' ] );
185 }
186
187 /**
188 * wpforo main actions doing place
189 */
190 public function do_actions() {
191 do_action( 'wpforo_actions' );
192 $wpforo_actions = array_unique(
193 array_merge( (array) wpfval( $_POST, 'wpfaction' ), (array) wpfval( WPF()->GET, 'wpfaction' ) )
194 );
195 if( ! empty( $wpforo_actions ) ) {
196 foreach( $wpforo_actions as $wpforo_action ) {
197 $wpforo_action = sanitize_title( $wpforo_action );
198 do_action( "wpforo_action_{$wpforo_action}" );
199 }
200 }
201 do_action( 'wpforo_actions_end' );
202 }
203
204 /**
205 * init wpforo default attachments system when wpforo advanced attachments addon has not exists
206 */
207 public function init_default_attach_hooks() {
208 add_action( 'delete_attachment', 'wpforo_delete_attachment', 10 );
209 if( has_action( 'wpforo_topic_form_extra_fields_after', [ WPF()->tpl, 'add_default_attach_input' ] ) ) {
210 add_filter( 'wpforo_add_topic_data_filter', 'wpforo_add_default_attachment' );
211 add_filter( 'wpforo_edit_topic_data_filter', 'wpforo_add_default_attachment' );
212 add_filter( 'wpforo_add_post_data_filter', 'wpforo_add_default_attachment' );
213 add_filter( 'wpforo_edit_post_data_filter', 'wpforo_add_default_attachment' );
214 add_filter( 'wpforo_body_text_filter', 'wpforo_default_attachments_filter' );
215 }
216 }
217
218 /**
219 * init wp emojis when wpforo emoticons addon has not exists
220 */
221 public function init_wp_emoji_hooks() {
222 if( ! class_exists( 'wpForoSmiles' ) ) {
223 add_filter( 'wpforo_body_text_filter', 'wp_encode_emoji', 9 );
224 add_filter( 'wpforo_body_text_filter', 'convert_smilies' );
225 }
226 }
227
228 /**
229 * get request_uri redirect to url with concatenation of &can_do=do
230 * @return bool true if you can do action now | false if you can not do action now
231 */
232 private function can_do() {
233 if( wpfval( $_GET, 'can_do' ) === 'do' ) return true;
234
235 $refresh_url = preg_replace( '#&can_do=?[^=?&\r\n]*#isu', '', wpforo_get_request_uri() );
236 $refresh_url .= '&can_do=do';
237 header( "refresh:0.1;url=" . $refresh_url );
238
239 add_filter( 'wpforo_admin_loading', '__return_true' );
240
241 return false;
242 }
243
244 /**
245 * @return string $u_action return union bulk action
246 */
247 private function get_current_bulk_action() {
248 $u_action = '';
249 if( ! empty( $_GET['action'] ) && $_GET['action'] !== '-1' ) {
250 $u_action = sanitize_textarea_field( $_GET['action'] );
251 } elseif( ! empty( $_GET['action2'] ) && $_GET['action2'] !== '-1' ) {
252 $u_action = sanitize_textarea_field( $_GET['action2'] );
253 }
254
255 return $u_action;
256 }
257
258 /**
259 * catch if rss url show rss feed for given arguments
260 */
261 public function feed_rss2() {
262 if( wpfval( WPF()->GET, 'type' ) === 'rss2' ) {
263 $forum_rss_items = apply_filters( 'wpforo_forum_feed_limit', 10 );
264 $topic_rss_items = apply_filters( 'wpforo_topic_feed_limit', 10 );
265
266 $forumid = intval( wpfval( WPF()->GET, 'forum' ) );
267 if( ! $forumid ) {
268 $forum = [];
269 $forum['forumurl'] = wpforo_home_url();
270 $forum['title'] = '';
271 } elseif( $forum = wpforo_forum( $forumid ) ) {
272 $forum['forumurl'] = $forum['url'];
273 }
274
275 if( wpfval( WPF()->GET, 'topic' ) ) {
276 $topicid = intval( WPF()->GET['topic'] );
277 if( ! $topicid ) {
278 $posts = WPF()->post->get_posts( [
279 'row_count' => $topic_rss_items,
280 'orderby' => '`created` DESC, `postid` DESC',
281 'check_private' => true,
282 'status' => 0,
283 ] );
284 $topic['title'] = '';
285 $topic['topicurl'] = wpforo_home_url();
286 } else {
287 $topic = wpforo_topic( $topicid );
288 if( ! empty( $topic ) && ( intval( wpfval( $topic, 'private' ) ) || intval( wpfval( $topic, 'status' ) ) ) ) {
289 $topic = [];
290 }
291 if( empty( $topic ) ) {
292 WPF()->feed->rss2_topic( $forum, [], [] );
293 }
294 $topic['topicurl'] = ( wpfval( $topic, 'url' ) ) ? $topic['url'] : WPF()->topic->get_url( $topicid );
295 $posts = WPF()->post->get_posts( [
296 'topicid' => $topicid,
297 'row_count' => $topic_rss_items,
298 'orderby' => '`created` DESC, `postid` DESC',
299 'check_private' => true,
300 'status' => 0,
301 ] );
302 }
303 foreach( $posts as $key => $post ) {
304 $member = wpforo_member( $post );
305 $posts[ $key ]['description'] = wpforo_text( trim( strip_tags( (string) $post['body'] ) ), 190, false );
306 $posts[ $key ]['content'] = trim( (string) $post['body'] );
307 $posts[ $key ]['posturl'] = WPF()->post->get_url( $post['postid'] );
308 $posts[ $key ]['author'] = $member['display_name'];
309 }
310 WPF()->feed->rss2_topic( $forum, $topic, $posts );
311 } else {
312 if( ! $forumid ) {
313 $topics = WPF()->topic->get_topics( [
314 'row_count' => $forum_rss_items,
315 'orderby' => 'created',
316 'order' => 'DESC',
317 'private' => 0,
318 'status' => 0,
319 ] );
320 } else {
321 $topics = WPF()->topic->get_topics( [
322 'forumid' => $forumid,
323 'row_count' => $forum_rss_items,
324 'orderby' => 'created',
325 'order' => 'DESC',
326 'private' => 0,
327 'status' => 0,
328 ] );
329 }
330 foreach( $topics as $key => $topic ) {
331 $post = wpforo_post( $topic['first_postid'] );
332 $member = wpforo_member( $topic );
333 $topics[ $key ]['description'] = wpforo_text( trim( strip_tags( (string) $post['body'] ) ), 190, false );
334 $topics[ $key ]['content'] = trim( (string) $post['body'] );
335 $topics[ $key ]['topicurl'] = WPF()->topic->get_url( $topic['topicid'] );
336 $topics[ $key ]['author'] = $member['display_name'];
337 }
338 WPF()->feed->rss2_forum( $forum, $topics );
339 }
340 exit();
341 }
342 }
343
344 /**
345 * ucf_file_delete delete /wp-content/uploads/UCFFILENAME
346 */
347 public function ucf_file_delete() {
348 $userid = 0;
349 if( wpfval( WPF()->GET, 'foro_f' ) && wpfval( WPF()->GET, 'foro_u' ) && wpfval( WPF()->GET, 'foro_n' ) ) {
350 if( wp_verify_nonce( WPF()->GET['foro_n'], 'wpforo_delete_profile_field' ) ) {
351 $userid = intval( WPF()->GET['foro_u'] );
352 $field = sanitize_title( WPF()->GET['foro_f'] );
353 if( $file = WPF()->member->get_custom_field( $userid, $field ) ) {
354 $file = wpforo_fix_upload_dir( $file );
355 $result = WPF()->member->update_custom_field( $userid, $field, '' );
356 if( $result ) {
357 if( file_exists( $file ) ) @unlink( $file );
358 WPF()->phrase->clear_cache();
359 WPF()->notice->add( 'Deleted Successfully!', 'success' );
360 } else {
361 WPF()->notice->clear();
362 WPF()->notice->add( 'Sorry, this file cannot be deleted', 'error' );
363 }
364 }
365 }
366 }
367
368 wp_safe_redirect( $userid ? WPF()->member->get_profile_url( $userid, 'account' ) : wpforo_home_url() );
369 exit();
370 }
371
372 /**
373 * mark all bold forum topics as read
374 */
375 public function mark_all_read() {
376 if( wpfval( WPF()->GET, 'foro' ) === 'allread' ) {
377 if( wpfval( WPF()->GET, 'foro_n' ) && wp_verify_nonce( WPF()->GET['foro_n'], 'wpforo_mark_all_read' ) ) {
378 WPF()->log->mark_all_read();
379 $current_url = wpforo_get_request_uri();
380 $current_url = strtok( $current_url, '?' );
381 wp_safe_redirect( $current_url );
382 exit();
383 }
384 }
385 }
386
387 /**
388 * Open/Close Frontend Admin CPanel
389 */
390 public function acp_toggle() {
391 wpforo_verify_nonce( 'wpforo_acp_toggle' );
392 $toggle_status = wpfval( $_POST, 'toggle_status' );
393 if( in_array( $toggle_status, [ 'open', 'close' ] ) ) {
394 update_user_meta( WPF()->current_userid, 'wpf-acp-toggle', $toggle_status );
395 wp_send_json_success();
396 } else {
397 wp_send_json_error();
398 }
399 }
400
401 /**
402 * set a notification read
403 */
404 public function mark_notification_read() {
405 if( wpfval( WPF()->GET, '_nread' ) && is_user_logged_in() ) {
406 if( wpfval( WPF()->GET, 'foro_n' ) && wp_verify_nonce( WPF()->GET['foro_n'], 'wpforo_mark_notification_read' ) ) {
407 $id = intval( WPF()->GET['_nread'] );
408 WPF()->activity->read_notification( $id );
409 $current_url = wpforo_get_request_uri();
410 $current_url = strtok( $current_url, '?' );
411 wp_safe_redirect( $current_url );
412 exit();
413 }
414 }
415 }
416
417 /**
418 * clear all notifications
419 */
420 public function clear_all_notifications() {
421 if( wpfval( $_POST, 'foro_n' ) && wp_verify_nonce( $_POST['foro_n'], 'wpforo_clear_notifications' ) ) {
422 WPF()->activity->clear_notifications();
423 echo WPF()->activity->get_no_notifications_html();
424 }
425 exit();
426 }
427
428 public function profile_cover_upload() {
429 wpforo_verify_nonce( 'wpforo_profile_cover_upload' );
430 if( WPF()->current_object['user'] && WPF()->usergroup->can( 'upc' ) && WPF()->perm->user_can_edit_account(
431 WPF()->current_object['user']
432 ) && ( $image_blob = wpfval(
433 $_POST,
434 'image_blob'
435 ) ) ) {
436 $data = explode( ',', $image_blob );
437 if( preg_match(
438 '#^data:image/(?:png|jpe?g|gif);base64$#iu',
439 (string) $data[0]
440 ) && ( $file_content = isset( $data[1] ) ? base64_decode( $data[1] ) : '' ) ) {
441 $file_basename = uniqid() . '_' . WPF()->current_object['user']['userid'] . '.jpg';
442 $file_dir = WPF()->folders['covers']['dir'] . DIRECTORY_SEPARATOR . $file_basename;
443 $file_url = WPF()->folders['covers']['url//'] . '/' . $file_basename;
444 if( file_put_contents( $file_dir, $file_content ) ) {
445 WPF()->member->update_profile_field( WPF()->current_object['user']['userid'], 'cover', $file_url );
446 wp_send_json_success();
447 }
448 }
449 }
450 wp_send_json_error();
451 }
452
453 public function profile_cover_delete() {
454 wpforo_verify_nonce( 'wpforo_profile_cover_delete' );
455
456 if( WPF()->current_object['user'] && WPF()->usergroup->can( 'upc' ) && WPF()->perm->user_can_edit_account(
457 WPF()->current_object['user']
458 ) ) {
459 WPF()->member->update_profile_field( WPF()->current_object['user']['userid'], 'cover', '' );
460 wp_send_json_success( [ 'background_url' => wpforo_setting( 'profiles', 'default_cover' ) ] );
461 }
462 wp_send_json_error();
463 }
464
465 public function profiles_default_cover_upload() {
466 wpforo_verify_nonce( 'wpforo_profiles_default_cover_upload' );
467 if( ( wpforo_current_user_is( 'admin' ) || WPF()->usergroup->can( 'ms' ) ) && $image_blob = wpfval(
468 $_POST,
469 'image_blob'
470 ) ) {
471 $data = explode( ',', $image_blob );
472 if( preg_match(
473 '#^data:image/(?:png|jpe?g|gif);base64$#iu',
474 $data[0]
475 ) && ( $file_content = isset( $data[1] ) ? base64_decode( $data[1] ) : '' ) ) {
476 $file_basename = 'profiles_custom_default_cover.jpg';
477 $file_dir = WPF()->folders['covers']['dir'] . DIRECTORY_SEPARATOR . $file_basename;
478 $file_url = WPF()->folders['covers']['url//'] . '/' . $file_basename;
479 if( file_put_contents( $file_dir, $file_content ) ) {
480 WPF()->settings->profiles['default_cover'] = $file_url;
481 wpforo_update_option( 'wpforo_profiles', WPF()->settings->profiles );
482 wp_send_json_success();
483 }
484 }
485 }
486 wp_send_json_error();
487 }
488
489 public function get_topic_head_more_info() {
490 wpforo_verify_nonce( 'wpforo_get_topic_head_more_info' );
491 if( $topicid = wpforo_bigintval( wpfval( $_POST, 'topicid' ) ) ) {
492 if( ( $topic = WPF()->topic->get_topic( $topicid, false ) ) && WPF()->topic->view_access( $topic ) ) {
493 wp_send_json_success(
494 [ 'html' => wpforo_topic_active_participants( $topicid ) . wpforo_topic_overview( $topicid ) ]
495 );
496 }
497 }
498
499 wp_send_json_error();
500 }
501
502 public function get_topic_overview_chunk() {
503 wpforo_verify_nonce( 'wpforo_get_topic_overview_chunk' );
504 if( $topicid = wpforo_bigintval( wpfval( $_POST, 'topicid' ) ) ) {
505 if( ( $topic = WPF()->topic->get_topic( $topicid, false ) ) && WPF()->topic->view_access( $topic ) ) {
506 if( ! ( $chunksize = (int) wpfval( $_POST, 'chunksize' ) ) ) $chunksize = 5;
507 $offset = (int) wpfval( $_POST, 'offset' );
508
509 wp_send_json_success( wpforo_get_topic_overview_chunk( $topicid, $chunksize, $offset ) );
510 }
511 }
512
513 wp_send_json_error();
514 }
515
516 public function get_overview() {
517 wpforo_verify_nonce( 'wpforo_get_overview' );
518 if( $postid = wpforo_bigintval( wpfval( $_POST, 'postid' ) ) ) {
519 if( ( $post = wpforo_post( $postid ) ) && WPF()->post->view_access( $post ) ) {
520 wp_send_json_success(
521 [
522 'title' => '<i class="fas fa-user"></i> &nbsp;' . wpforo_phrase(
523 'Posted by ',
524 false
525 ) . ' ' . wpforo_member_link(
526 wpforo_member( $post ),
527 '',
528 20,
529 '',
530 false
531 ) . '&nbsp;&bullet;&nbsp;' . ' ' . wpforo_date( $post['created'], 'ago', false ),
532 'content' => trim( (string) wpforo_content( $post, false ) ),
533 ]
534 );
535 }
536 }
537
538 wp_send_json_error();
539 }
540
541 /**
542 * registration form submit action
543 */
544 public function registration() {
545 if( ! empty( $_POST['wpfreg'] ) ) {
546 wpforo_verify_form( 'wpforo_user_register' );
547 if( $userid = WPF()->member->create( $_POST ) ) {
548 if( wpforo_setting( 'authorization', 'redirect_url_after_register' ) ) {
549 $redirect_url = wpforo_setting( 'authorization', 'redirect_url_after_register' );
550 } elseif( ( $redirect_to = wpfval( $_GET, 'redirect_to' ) ) && wpforo_is_url_internal(
551 urldecode( (string) $redirect_to )
552 ) ) {
553 $redirect_url = urldecode( (string) $redirect_to );
554 } elseif( is_wpforo_url() ) {
555 $redirect_url = preg_replace( '#\?.*$#is', '', wpforo_get_request_uri() );
556 } else {
557 if( function_exists( 'pll_current_language' ) && $pll_lang = pll_current_language( 'locale' ) ) {
558 $redirect_url = wpforo_get_home_url_for_language( $pll_lang );
559 } else {
560 $redirect_url = ( wpforo_setting( 'authorization', 'user_register_email_confirm' ) ? wpforo_home_url() : WPF()->member->get_profile_url( $userid, 'account' ) );
561 }
562 }
563
564 wp_safe_redirect( $redirect_url );
565 exit();
566 }
567 }
568 }
569
570 /**
571 * login form submit action
572 */
573 public function login() {
574 wpforo_verify_form( 'login' );
575 if( isset( $_POST['wpforologin'] ) && isset( $_POST['log'] ) && isset( $_POST['pwd'] ) ) {
576 if( ! is_wp_error( $user = wp_signon() ) ) {
577 $wpf_login_times = intval( get_user_meta( $user->ID, '_wpf_login_times', true ) );
578 if( isset( $user->ID ) && $wpf_login_times >= 1 ) {
579 $name = ( isset( $user->data->display_name ) ) ? $user->data->display_name : '';
580 WPF()->notice->add( 'Welcome back %s!', 'success', $name );
581 } else {
582 WPF()->notice->add( 'Welcome to our Community!', 'success' );
583 }
584 $wpf_login_times ++;
585 update_user_meta( $user->ID, '_wpf_login_times', $wpf_login_times );
586 if( wpforo_setting( 'authorization', 'redirect_url_after_login' ) ) {
587 $redirect_url = wpforo_setting( 'authorization', 'redirect_url_after_login' );
588 } elseif( ( $redirect_to = wpfval( $_GET, 'redirect_to' ) ) && wpforo_is_url_internal(
589 urldecode( (string) $redirect_to )
590 ) ) {
591 $redirect_url = urldecode( (string) $redirect_to );
592 } elseif( is_wpforo_url() ) {
593 $redirect_url = preg_replace( '#\?.*$#is', '', wpforo_get_request_uri() );
594 } else {
595 if( function_exists( 'pll_current_language' ) && $pll_lang = pll_current_language( 'locale' ) ) {
596 $redirect_url = wpforo_get_home_url_for_language( $pll_lang );
597 } else {
598 $redirect_url = wpforo_home_url();
599 }
600 }
601 wp_safe_redirect( $redirect_url );
602 } else {
603 $args = [];
604 foreach( $user->errors as $u_err ) $args[] = $u_err[0];
605 WPF()->notice->add( $args, 'error' );
606 wp_safe_redirect( wpforo_get_request_uri() );
607 }
608 exit();
609 }
610 }
611
612 public function lostpassword() {
613 wpforo_verify_form( 'lostpassword' );
614 $redirect_url = wp_get_raw_referer();
615 if( wpfval( $_POST, 'user_login' ) ) {
616 $errors = retrieve_password();
617 if( is_wp_error( $errors ) ) {
618 $redirect_url = wpforo_lostpassword_url();
619 WPF()->notice->add( implode( ',', $errors->get_error_messages() ), 'error' );
620 } else {
621 $redirect_url = wpforo_login_url();
622 WPF()->notice->add( 'Email has been sent', 'success' );
623 }
624 }
625
626 wp_safe_redirect( $redirect_url );
627 exit();
628 }
629
630 public function resetpassword_form() {
631 $rp_key = sanitize_text_field( wp_unslash( $_REQUEST['rp_key'] ) );
632 $rp_login = sanitize_user( wp_unslash( $_REQUEST['rp_login'] ) );
633 $user = check_password_reset_key( $rp_key, $rp_login );
634 if( ! $user || is_wp_error( $user ) ) {
635 if( $user && $user->get_error_code() === 'expired_key' ) {
636 WPF()->notice->add( 'The key is expired', 'error' );
637 } else {
638 WPF()->notice->add( 'The key is invalid', 'error' );
639 }
640 wp_safe_redirect( wpforo_login_url() );
641 exit();
642 }
643 }
644
645 public function resetpassword() {
646 $this->resetpassword_form();
647
648 $pass1 = wpfval( $_POST, 'pass1' );
649 $pass2 = wpfval( $_POST, 'pass2' );
650
651 if( ! $pass1 ) {
652 WPF()->notice->add( 'The password reset empty', 'error' );
653 wp_safe_redirect( wp_get_raw_referer() );
654 exit();
655 }
656
657 if( strlen( (string) $pass1 ) < WPF()->member->pass_min_length || strlen( (string) $pass1 ) > WPF()->member->pass_max_length ) {
658 WPF()->notice->add( 'Password length must be between %d characters and %d characters.', 'error', [
659 WPF()->member->pass_min_length,
660 WPF()->member->pass_max_length,
661 ] );
662 wp_safe_redirect( wp_get_raw_referer() );
663 exit();
664 }
665
666 if( $pass1 !== $pass2 ) {
667 WPF()->notice->add( 'The password reset mismatch', 'error' );
668 wp_safe_redirect( wp_get_raw_referer() );
669 exit();
670 }
671
672 $rp_login = sanitize_user( wp_unslash( $_REQUEST['rp_login'] ) );
673 reset_password( get_user_by( 'login', $rp_login ), $pass1 );
674 wp_signon( [ 'user_login' => $rp_login, 'user_password' => $pass1 ] );
675
676 WPF()->notice->add( 'The password has been changed', 'success' );
677 wp_safe_redirect( wpforo_home_url() );
678 exit();
679 }
680
681 public function logout() {
682 wpforo_verify_nonce( 'wpforo_logout', 'full' );
683 wp_logout();
684 $redirect_url = wpforo_home_url();
685 if( ( $redirect_to = wpfval( $_GET, 'redirect_to' ) ) && wpforo_is_url_internal( urldecode( (string) $redirect_to ) ) ) {
686 $redirect_url = urldecode( (string) $redirect_to );
687 if( strpos( $redirect_url, 'lostpassword' ) !== false ) $redirect_url = wpforo_login_url();
688 }
689 wp_safe_redirect( $redirect_url );
690 exit();
691 }
692
693 /**
694 * profile_update form submit action
695 */
696 public function profile_update() {
697 if( wpfval( $_POST, 'member', 'userid' ) ) {
698 wpforo_verify_form();
699 $uid = intval( $_POST['member']['userid'] );
700 if( ! ( $uid === WPF()->current_userid || ( WPF()->usergroup->can( 'em' ) && WPF()->perm->user_can_manage_user(
701 WPF()->current_userid,
702 $uid
703 ) ) ) ) {
704 WPF()->notice->clear();
705 WPF()->notice->add( 'Permission denied', 'error' );
706 wp_safe_redirect( wpforo_get_request_uri() );
707 exit();
708 }
709 if( WPF()->member->update( $_POST ) ) {
710 if( $profile_url = WPF()->member->get_profile_url( $uid, 'account', false ) ) {
711 wp_safe_redirect( $profile_url );
712 exit();
713 }
714 }
715 }
716
717 wp_safe_redirect( wpforo_get_request_uri() );
718 exit();
719 }
720
721 public function cantlogin_contact() {
722 if( wpforo_setting( 'authorization', 'manually_approval_contact_form' ) && ( $msg = wpfval( $_POST, 'msg' ) ) ) {
723 $admin_emails = wpforo_setting( 'email', 'admin_emails' );
724 $admin_email = wpfval( $admin_emails, 0 );
725 $sbj = wpforo_phrase( 'Request for account approval', false ) . ' ( ' . wpfval(
726 $_POST,
727 'user_login'
728 ) . ' )';
729
730 add_filter( 'wp_mail_content_type', 'wpforo_set_html_content_type', 999 );
731 if( @wpforo_send_email( $admin_email, $sbj, $msg, wpforo_admin_mail_headers() ) ) {
732 WPF()->notice->add( 'Message has been sent', 'success' );
733 } else {
734 WPF()->notice->add( 'Can\'t send report email', 'error' );
735 }
736 remove_filter( 'wp_mail_content_type', 'wpforo_set_html_content_type' );
737 }
738
739 wp_safe_redirect( wpforo_home_url() );
740 exit();
741 }
742
743 /**
744 * topic_add form submit action
745 */
746 public function topic_add() {
747 wpforo_verify_form();
748 $args = $_REQUEST['thread'];
749 $args['postmetas'] = (array) wpfval( $_REQUEST, 'data' );
750 if( $topicid = WPF()->topic->add( $args ) ) {
751 wp_safe_redirect( WPF()->topic->get_url( $topicid ) );
752 exit();
753 }
754 wp_safe_redirect( wpforo_get_request_uri() );
755 exit();
756 }
757
758 /**
759 * topic_edit form submit action
760 */
761 public function topic_edit() {
762 wpforo_verify_form();
763 $args = $_REQUEST['thread'];
764 $args['postmetas'] = (array) wpfval( $_REQUEST, 'data' );
765 if( $topicid = WPF()->topic->edit( $args ) ) {
766 wp_safe_redirect( WPF()->topic->get_url( $topicid ) );
767 exit();
768 }
769 wp_safe_redirect( wpforo_get_request_uri() );
770 exit();
771 }
772
773 /**
774 * post_add form submit action
775 */
776 public function post_add() {
777 wpforo_verify_form();
778 $args = $_REQUEST['post'];
779 $args['postmetas'] = (array) wpfval( $_REQUEST, 'data' );
780 if( $postid = WPF()->post->add( $args ) ) {
781 wp_safe_redirect( WPF()->post->get_url( $postid ) );
782 exit();
783 }
784 wp_safe_redirect( wpforo_get_request_uri() );
785 exit();
786 }
787
788 /**
789 * post_edit form submit action
790 */
791 public function post_edit() {
792 wpforo_verify_form();
793 $args = $_REQUEST['post'];
794 $args['postmetas'] = (array) wpfval( $_REQUEST, 'data' );
795 if( $postid = WPF()->post->edit( $args ) ) {
796 wp_safe_redirect( WPF()->post->get_url( $postid ) );
797 exit();
798 }
799 wp_safe_redirect( wpforo_get_request_uri() );
800 exit();
801 }
802
803 /**
804 * topic_move form submit action
805 */
806 public function topic_move() {
807 if( ! empty( $_POST['topic_move'] ) ) {
808 wpforo_verify_form();
809 $topicid = intval( wpfval( $_POST['topic_move'], 'topicid' ) );
810 $forumid = intval( wpfval( $_POST['topic_move'], 'forumid' ) );
811 if( $topicid && $forumid ) {
812 $topic = WPF()->topic->get_topic( $topicid );
813 if( ! $topic || ! WPF()->perm->forum_can( 'mt', $topic['forumid'] ) ) {
814 wp_safe_redirect( wpforo_get_request_uri() );
815 exit();
816 }
817 WPF()->topic->move( $topicid, $forumid );
818 $url = WPF()->topic->get_url( $topicid, [], false );
819 wpforo_clean_cache();
820 wp_safe_redirect( $url );
821 exit();
822 }
823 }
824
825 wp_safe_redirect( wpforo_get_request_uri() );
826 exit();
827 }
828
829 /**
830 * topic_merge form submit action
831 */
832 public function topic_merge() {
833 wpforo_verify_form();
834 $redirect_to = wpforo_get_request_uri();
835 if( ! WPF()->current_object['topic'] || ! WPF()->perm->forum_can( 'mt', WPF()->current_object['topic']['forumid'] ) ) {
836 wp_safe_redirect( $redirect_to );
837 exit();
838 }
839 if( WPF()->current_object['topic'] && ! empty( $_POST['wpforo'] ) && ! empty( $_POST['wpforo']['target_topic_url'] ) ) {
840 $target_slug = wpforo_get_topic_slug_from_url( esc_url( (string) $_POST['wpforo']['target_topic_url'] ) );
841 if( ! is_null( $target_slug ) && $target = WPF()->topic->get_topic( $target_slug ) ) {
842 $append = ( empty( $_POST['wpforo']['update_date_and_append'] ) ? 0 : 1 );
843 $to_target_title = ( empty( $_POST['wpforo']['to_target_title'] ) ? 0 : 1 );
844
845 if( WPF()->topic->merge( $target, WPF()->current_object['topic'], [], $to_target_title, $append ) ) {
846 $redirect_to = WPF()->topic->get_url( $target, [], false );
847 wpforo_clean_cache();
848 }
849 } else {
850 WPF()->notice->add( 'Target Topic not found', 'error' );
851 }
852 }
853 wp_safe_redirect( $redirect_to );
854 exit();
855 }
856
857 /**
858 * topic_split form submit action
859 */
860 public function topic_split() {
861 wpforo_verify_form();
862 $redirect_to = wpforo_get_request_uri();
863 if( ! WPF()->current_object['topic'] || ! WPF()->perm->forum_can( 'mt', WPF()->current_object['topic']['forumid'] ) ) {
864 wp_safe_redirect( $redirect_to );
865 exit();
866 }
867 if( WPF()->current_object['topic'] && ! empty( $_POST['wpforo'] ) ) {
868 if( ! empty( $_POST['wpforo']['create_new'] ) ) {
869 $args = [
870 'title' => sanitize_text_field( $_POST['wpforo']['new_topic_title'] ),
871 'forumid' => intval( $_POST['wpforo']['new_topic_forumid'] ),
872 'postids' => array_map( 'intval', $_POST['wpforo']['posts'] ),
873 ];
874 $to_target_title = ( empty( $_POST['wpforo']['to_target_title'] ) ? 0 : 1 );
875 if( $topicid = WPF()->topic->split( $args, $to_target_title ) ) {
876 $redirect_to = WPF()->topic->get_url( $topicid );
877 }
878 } else {
879 if( ! empty( $_POST['wpforo']['target_topic_url'] ) && ! empty( $_POST['wpforo']['posts'] ) ) {
880 $target_slug = wpforo_get_topic_slug_from_url( esc_url( (string) $_POST['wpforo']['target_topic_url'] ) );
881 if( ! is_null( $target_slug ) && $target = WPF()->topic->get_topic( $target_slug ) ) {
882 $append = ( empty( $_POST['wpforo']['update_date_and_append'] ) ? 0 : 1 );
883 $to_target_title = ( empty( $_POST['wpforo']['to_target_title'] ) ? 0 : 1 );
884 $postids = array_map( 'intval', $_POST['wpforo']['posts'] );
885 if( WPF()->topic->merge(
886 $target,
887 WPF()->current_object['topic'],
888 $postids,
889 $to_target_title,
890 $append
891 ) ) {
892 $redirect_to = WPF()->topic->get_url( $target );
893 }
894 } else {
895 WPF()->notice->add( 'Target Topic not found', 'error' );
896 }
897 }
898 }
899 }
900 wp_safe_redirect( $redirect_to );
901 exit();
902 }
903
904 /**
905 * board add action
906 */
907 public function board_add() {
908 check_admin_referer( 'wpforo-board-add' );
909 if( $board = wp_unslash( (array) wpfval( $_POST, 'board' ) ) ) {
910 if( ! ( $board['locale'] = trim( (string) $board['locale'] ) ) ) $board['locale'] = 'en_US';
911 $status = wpfkey( $board, 'status' ) ? (int) wpfval( $board, 'status' ) : 1;
912 if( $boardid = WPF()->board->add( $board ) ) {
913 // Handle translation installation.
914 if( $status && $board['locale'] && current_user_can( 'install_languages' ) ) {
915 require_once ABSPATH . 'wp-admin/includes/file.php';
916 require_once ABSPATH . 'wp-admin/includes/translation-install.php';
917 if( wp_can_install_language_pack() ) wp_download_language_pack( $board['locale'] );
918 }
919
920 if( ( $board = WPF()->board->_get_board( $boardid ) ) && $status ) {
921 wp_safe_redirect( admin_url( 'admin.php?page=wpforo-' . $boardid . '-settings' ) );
922 exit();
923 }
924 }
925 }
926
927 wp_safe_redirect( admin_url( 'admin.php?page=wpforo-boards' ) );
928 exit();
929 }
930
931 /**
932 * board edit action
933 */
934 public function board_edit() {
935 check_admin_referer( 'wpforo-board-edit' );
936 if( $board = wp_unslash( (array) wpfval( $_POST, 'board' ) ) ) {
937 $boardid = (int) wpfval( $board, 'boardid' );
938 $status = wpfkey( $board, 'status' ) ? (int) wpfval( $board, 'status' ) : 1;
939 if( ! ( $board['locale'] = trim( (string) $board['locale'] ) ) ) $board['locale'] = 'en_US';
940 if( WPF()->board->edit( $board, $boardid ) ) {
941 if( $status && ! is_wpforo_multiboard() ) {
942 wp_update_post(
943 [
944 'ID' => $board['pageid'],
945 'post_name' => $board['slug'],
946 ]
947 );
948 }
949 // Handle translation installation.
950 if( $status && $board['locale'] && current_user_can( 'install_languages' ) ) {
951 require_once ABSPATH . 'wp-admin/includes/file.php';
952 require_once ABSPATH . 'wp-admin/includes/translation-install.php';
953 if( wp_can_install_language_pack() ) wp_download_language_pack( $board['locale'] );
954 }
955 }
956 }
957
958 wp_safe_redirect( admin_url( 'admin.php?page=wpforo-boards' ) );
959 exit();
960 }
961
962 /**
963 * board delete action
964 */
965 public function board_repair() {
966 $boardid = (int) wpfval( $_GET, 'boardid' );
967 if( $boardid === WPF()->board->get_current( 'boardid' ) ) {
968 check_admin_referer( 'wpforo-board-repair-' . $boardid );
969 wpforo_board_repair( $boardid );
970 }
971
972 wp_safe_redirect( wp_get_raw_referer() );
973 exit();
974 }
975
976 /**
977 * board delete action
978 */
979 public function board_delete() {
980 if( ( $boardid = (int) wpfval( $_GET, 'boardid' ) ) && $boardid === WPF()->board->get_current( 'boardid' ) ) {
981 check_admin_referer( 'wpforo-board-delete-' . $boardid );
982 wpforo_board_uninstall( $boardid );
983 }
984
985 wp_safe_redirect( admin_url( 'admin.php?page=wpforo-boards' ) );
986 exit();
987 }
988
989 /**
990 * action to synchronize wp_users to wp_wpforo_profiles
991 */
992 public function synch_user_profiles() {
993 check_admin_referer( 'wpforo_synch_user_profiles' );
994
995 if( $this->can_do() ) {
996 wpforo_set_max_execution_time();
997 wp_raise_memory_limit();
998
999 if( WPF()->member->synchronize_users( apply_filters( 'wpforo_rebuild_per_request', 200 ) ) ) {
1000 WPF()->member->clear_db_cache();
1001 wpforo_clean_cache();
1002 WPF()->notice->add( 'Synched Successfully!', 'success' );
1003 wp_safe_redirect( admin_url( 'admin.php?page=wpforo-overview' ) );
1004 } else {
1005 wp_safe_redirect(
1006 htmlspecialchars_decode(
1007 wp_nonce_url(
1008 admin_url( 'admin.php?page=wpforo-overview&wpfaction=synch_user_profiles' ),
1009 'wpforo_synch_user_profiles'
1010 )
1011 )
1012 );
1013 }
1014 exit();
1015 }
1016 }
1017
1018 /**
1019 * reset user caches
1020 */
1021 public function reset_user_cache() {
1022 check_admin_referer( 'wpforo_reset_user_cache' );
1023
1024 if( ! current_user_can( 'administrator' ) ) {
1025 WPF()->notice->add( 'Permission denied', 'error' );
1026 wp_safe_redirect( admin_url() );
1027 exit();
1028 }
1029
1030 wpforo_set_max_execution_time();
1031 wp_raise_memory_limit();
1032
1033 WPF()->member->clear_db_cache();
1034 WPF()->notice->add( 'Deleted Successfully!', 'success' );
1035
1036 wp_safe_redirect( admin_url( 'admin.php?page=wpforo-overview' ) );
1037 exit();
1038 }
1039
1040 /**
1041 * rebuild forums statistics first|last posts etc.
1042 */
1043 public function reset_forums_stats() {
1044 check_admin_referer( 'wpforo_reset_forums_stat' );
1045
1046 if( ! current_user_can( 'administrator' ) ) {
1047 WPF()->notice->add( 'Permission denied', 'error' );
1048 wp_safe_redirect( admin_url() );
1049 exit();
1050 }
1051
1052 wpforo_set_max_execution_time();
1053 wp_raise_memory_limit();
1054
1055 $forumids = WPF()->db->get_col(
1056 "SELECT `forumid` FROM " . WPF()->tables->forums . " WHERE `is_cat` = 0 ORDER BY `forumid` ASC"
1057 );
1058 if( ! empty( $forumids ) ) {
1059 foreach( $forumids as $forumid ) {
1060 WPF()->forum->rebuild_stats( $forumid );
1061 WPF()->forum->rebuild_last_infos( $forumid, false );
1062 }
1063 WPF()->statistic_cache_clean();
1064 WPF()->forum->delete_tree_cache();
1065 wpforo_clean_cache();
1066 WPF()->notice->add( 'Updated Successfully!', 'success' );
1067 }
1068
1069 wp_safe_redirect( admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'dashboard' ) ) );
1070 exit();
1071 }
1072
1073 /**
1074 * rebuild topics statistics first|last posts etc.
1075 */
1076 public function reset_topics_stats() {
1077 check_admin_referer( 'wpforo_reset_topics_stat' );
1078
1079 if( ! current_user_can( 'administrator' ) ) {
1080 WPF()->notice->add( 'Permission denied', 'error' );
1081 wp_safe_redirect( admin_url() );
1082 exit();
1083 }
1084
1085 if( $this->can_do() ) {
1086 wpforo_set_max_execution_time();
1087 wp_raise_memory_limit();
1088
1089 $lastid = (int) wpfval( $_GET, 'topic_lastid' );
1090 $sql = "SELECT `topicid` FROM " . WPF()->tables->topics . " WHERE `topicid` > %d ORDER BY `topicid` ASC LIMIT %d";
1091 $topicids = WPF()->db->get_col(
1092 WPF()->db->prepare( $sql, $lastid, apply_filters( 'wpforo_rebuild_per_request', 200 ) )
1093 );
1094 if( $topicids ) {
1095 foreach( $topicids as $topicid ) {
1096 $topic = WPF()->topic->get_topic( $topicid );
1097 WPF()->topic->rebuild_first_last( $topic );
1098 WPF()->topic->rebuild_stats( $topic );
1099 }
1100 wp_safe_redirect(
1101 htmlspecialchars_decode(
1102 wp_nonce_url(
1103 admin_url(
1104 'admin.php?page=' . wpforo_prefix_slug(
1105 'dashboard'
1106 ) . '&wpfaction=reset_topics_stats&topic_lastid=' . end( $topicids )
1107 ),
1108 'wpforo_reset_topics_stat'
1109 )
1110 )
1111 );
1112 } else {
1113 @WPF()->db->query(
1114 "UPDATE `" . WPF()->tables->topics . "` t
1115 INNER JOIN `" . WPF()->tables->posts . "` p ON p.`topicid` = t.`topicid` AND p.`is_answer` = 1
1116 SET t.`solved` = 1
1117 WHERE t.`solved` = 0"
1118 );
1119 WPF()->statistic_cache_clean();
1120 WPF()->notice->add( 'Updated Successfully!', 'success' );
1121 wp_safe_redirect( admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'dashboard' ) ) );
1122 }
1123 exit();
1124 }
1125 }
1126
1127 /**
1128 * rebuild users statistics etc.
1129 */
1130 public function reset_users_stats() {
1131 check_admin_referer( 'wpforo_reset_users_stat' );
1132
1133 if( ! current_user_can( 'administrator' ) ) {
1134 WPF()->notice->add( 'Permission denied', 'error' );
1135 wp_safe_redirect( admin_url() );
1136 exit();
1137 }
1138
1139 if( $this->can_do() ) {
1140 wpforo_set_max_execution_time();
1141 wp_raise_memory_limit();
1142
1143 $lastid = (int) wpfval( $_GET, 'user_lastid' );
1144 $sql = "SELECT `userid` FROM " . WPF()->tables->profiles . " WHERE `userid` > %d ORDER BY `userid` ASC LIMIT %d";
1145 $userids = WPF()->db->get_col(
1146 WPF()->db->prepare( $sql, $lastid, apply_filters( 'wpforo_rebuild_per_request', 200 ) )
1147 );
1148 if( $userids ) {
1149 foreach( $userids as $userid ) {
1150 WPF()->member->rebuild_stats( $userid );
1151 }
1152
1153 wp_safe_redirect(
1154 htmlspecialchars_decode(
1155 wp_nonce_url(
1156 admin_url(
1157 'admin.php?page=wpforo-overview&wpfaction=reset_users_stats&user_lastid=' . end( $userids )
1158 ),
1159 'wpforo_reset_users_stat'
1160 )
1161 )
1162 );
1163 } else {
1164 WPF()->notice->add( 'Updated Successfully!', 'success' );
1165 wp_safe_redirect( admin_url( 'admin.php?page=wpforo-overview' ) );
1166 }
1167 exit();
1168 }
1169 }
1170
1171 /**
1172 * rebuild 4 layout forum topics threads root
1173 */
1174 public function rebuild_threads() {
1175 check_admin_referer( 'wpforo_rebuild_threads' );
1176
1177 if( ! current_user_can( 'administrator' ) ) {
1178 WPF()->notice->add( 'Permission denied', 'error' );
1179 wp_safe_redirect( admin_url() );
1180 exit();
1181 }
1182
1183 wpforo_set_max_execution_time( 3600 );
1184 wp_raise_memory_limit();
1185
1186 WPF()->topic->rebuild_forum_threads();
1187 wpforo_clean_cache();
1188 WPF()->notice->add( 'Threads rebuilt successfully', 'success' );
1189
1190 wp_safe_redirect( admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'dashboard' ) ) );
1191 exit();
1192 }
1193
1194 /**
1195 * reset phrases cache from db
1196 */
1197 public function reset_phrase_cache() {
1198 check_admin_referer( 'wpforo_reset_phrase_cache' );
1199
1200 if( ! current_user_can( 'administrator' ) ) {
1201 WPF()->notice->add( 'Permission denied', 'error' );
1202 wp_safe_redirect( admin_url() );
1203 exit();
1204 }
1205
1206 wpforo_set_max_execution_time();
1207 wp_raise_memory_limit();
1208
1209 WPF()->phrase->clear_cache();
1210 WPF()->notice->add( 'Deleted Successfully!', 'success' );
1211
1212 wp_safe_redirect( admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'dashboard' ) ) );
1213 exit();
1214 }
1215
1216 /**
1217 * recrawling phrases from all wpforo, wpforo-addons code files
1218 */
1219 public function recrawl_phrases() {
1220 check_admin_referer( 'wpforo_recrawl_phrases' );
1221
1222 if( ! current_user_can( 'administrator' ) ) {
1223 WPF()->notice->add( 'Permission denied', 'error' );
1224 wp_safe_redirect( admin_url() );
1225 exit();
1226 }
1227
1228 wpforo_set_max_execution_time();
1229 wp_raise_memory_limit();
1230
1231 WPF()->phrase->crawl_phrases();
1232 WPF()->phrase->clear_cache();
1233 WPF()->notice->clear();
1234 WPF()->notice->add( 'Rebuilt Successfully!', 'success' );
1235
1236 wp_safe_redirect( admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'dashboard' ) ) );
1237 exit();
1238 }
1239
1240 /**
1241 * reset wpforo all caches (phrase, user, forum, post, stats, AI) etc.
1242 */
1243 public function reset_all_caches() {
1244 check_admin_referer( 'wpforo_reset_cache' );
1245
1246 if( ! current_user_can( 'administrator' ) ) {
1247 WPF()->notice->add( 'Permission denied', 'error' );
1248 wp_safe_redirect( admin_url() );
1249 exit();
1250 }
1251
1252 wpforo_set_max_execution_time();
1253 wp_raise_memory_limit();
1254
1255 WPF()->member->clear_db_cache();
1256 wpforo_clean_cache();
1257
1258 // Clear AI Cache (translations, summaries, embeddings cache)
1259 $this->clear_ai_cache();
1260
1261 // Flush WordPress Cache
1262 wp_cache_flush();
1263
1264 WPF()->notice->add( 'Deleted Successfully!', 'success' );
1265
1266 $redirect = ( is_admin() ) ? admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'dashboard' ) ) : wpforo_home_url();
1267 wp_safe_redirect( $redirect );
1268 exit();
1269 }
1270
1271 /**
1272 * Clear AI-related caches (translations, summaries, embeddings cache)
1273 *
1274 * Clears:
1275 * - ai_cache table (translations, topic summaries)
1276 * - ai_embeddings_cache table (similarity search cache)
1277 *
1278 * Does NOT clear:
1279 * - ai_embeddings (indexed content - expensive to regenerate)
1280 * - ai_chat_* tables (user conversation history)
1281 * - ai_logs (audit logs)
1282 * - ai_moderation (moderation history)
1283 */
1284 private function clear_ai_cache() {
1285 global $wpdb;
1286
1287 // Clear AI cache table (translations, summaries)
1288 if ( ! empty( WPF()->tables->ai_cache ) ) {
1289 $wpdb->query( "TRUNCATE TABLE `" . WPF()->tables->ai_cache . "`" );
1290 }
1291
1292 // Clear AI embeddings cache table (similarity search results cache)
1293 if ( ! empty( WPF()->tables->ai_embeddings_cache ) ) {
1294 $wpdb->query( "TRUNCATE TABLE `" . WPF()->tables->ai_embeddings_cache . "`" );
1295 }
1296 }
1297
1298 /**
1299 * Clean Up damaged content in database
1300 */
1301 public function clean_up() {
1302 check_admin_referer( 'wpforo_clean_up' );
1303
1304 if( ! current_user_can( 'administrator' ) ) {
1305 WPF()->notice->add( 'Permission denied', 'error' );
1306 wp_safe_redirect( admin_url() );
1307 exit();
1308 }
1309
1310 wpforo_set_max_execution_time();
1311 wp_raise_memory_limit();
1312
1313 wpforo_clean_up();
1314 WPF()->notice->add( 'Cleaned Up!', 'success' );
1315
1316 wp_safe_redirect( admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'dashboard' ) ) );
1317 exit();
1318 }
1319
1320 /**
1321 * Flush Permalinks
1322 */
1323 public function flush_permalinks() {
1324 check_admin_referer( 'wpforo_flush_permalinks' );
1325
1326 if( ! current_user_can( 'administrator' ) ) {
1327 WPF()->notice->add( 'Permission denied', 'error' );
1328 wp_safe_redirect( admin_url() );
1329 exit();
1330 }
1331
1332 wpforo_set_max_execution_time();
1333 wp_raise_memory_limit();
1334
1335 if( 'hard' === wpfval( WPF()->GET, 'flush_type' ) ) {
1336 $bk_time = time();
1337 $current = get_option( 'rewrite_rules' );
1338 update_option( 'rewrite_rules_bk_' . $bk_time, $current );
1339 copy( ABSPATH . '/.htaccess', ABSPATH . '/.htaccess-bk-' . $bk_time );
1340 flush_rewrite_rules( true );
1341 delete_option( 'rewrite_rules' );
1342 } else {
1343 flush_rewrite_rules( false );
1344 }
1345
1346 WPF()->phrase->clear_cache();
1347 WPF()->notice->clear();
1348 WPF()->notice->add( 'Flushed Successfully!', 'success' );
1349
1350 wp_safe_redirect( admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'dashboard' ) ) );
1351 exit();
1352 }
1353
1354 /**
1355 * dashboard_options_save form submit action
1356 */
1357 public function dashboard_options_save() {
1358 if( ! current_user_can( 'administrator' ) ) {
1359 WPF()->notice->add( 'Permission denied', 'error' );
1360 wp_safe_redirect( admin_url() );
1361 exit();
1362 }
1363 if( $dashboard_count_per_page = (int) wpfval( $_POST, 'wpforo_dashboard_count_per_page' ) ) {
1364 wpforo_update_option( 'count_per_page', $dashboard_count_per_page );
1365 }
1366 wp_safe_redirect( wpforo_get_request_uri() );
1367 exit();
1368 }
1369
1370 /**
1371 * checking accesses to forum admin menu pages settings etc...
1372 */
1373 public function check_dashboard_permissions() {
1374 $page = wpfval( WPF()->GET, 'page' );
1375 if( $page === wpforo_prefix_slug( 'settings' ) ) {
1376 if( ! WPF()->usergroup->can( 'ms' ) ) {
1377 WPF()->notice->add( 'Permission denied', 'error' );
1378 wp_safe_redirect( admin_url() );
1379 exit();
1380 }
1381 }
1382 }
1383
1384 /**
1385 * check if [wpforo] page has been deleted, restore or create new [wpforo] page
1386 */
1387 public function repair_lost_main_shortcode_page() {
1388 if( wpfval( WPF()->GET, 'page' ) === wpforo_prefix_slug( 'settings' ) ) wpforo_repair_main_shortcode_page();
1389 }
1390
1391 /**
1392 * add_new_xml_translation form submit action
1393 */
1394 public function add_new_xml_translation() {
1395 check_admin_referer( 'wpforo-settings-language' );
1396
1397 if( ! WPF()->usergroup->can( 'ms' ) ) {
1398 WPF()->notice->add( 'Permission denied', 'error' );
1399 wp_safe_redirect( admin_url() );
1400 exit();
1401 }
1402
1403 if( ! empty( $_FILES['add_lang'] ) ) {
1404 WPF()->phrase->add_lang();
1405 wpforo_clean_cache();
1406 }
1407 wp_safe_redirect( admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'settings' ) . '&tab=general' ) );
1408 exit();
1409 }
1410
1411 /**
1412 * add_new_xml_translation form submit action
1413 */
1414 public function phrases_change_lang() {
1415 check_admin_referer( 'wpforo-phrases-change-language' );
1416
1417 if( $langid = (int) wpfval( $_POST, 'langid' ) ) {
1418 if( WPF()->phrase->set_language_status( $langid ) ) {
1419 WPF()->notice->add( 'Successfully updated', 'success' );
1420 } else {
1421 WPF()->notice->add( 'Invalid request!', 'error' );
1422 }
1423 }
1424
1425 wp_safe_redirect( wp_get_raw_referer() );
1426 exit();
1427 }
1428
1429 /**
1430 * colors.css download action
1431 */
1432 public function colors_css_download() {
1433 check_admin_referer( 'dynamic_css_download' );
1434
1435 if( ! WPF()->usergroup->can( 'ms' ) ) {
1436 WPF()->notice->add( 'Permission denied', 'error' );
1437 wp_safe_redirect( admin_url() );
1438 exit();
1439 }
1440
1441 $dynamic_css = WPF()->tpl->generate_dynamic_css();
1442 header( 'Content-Type: application/download' );
1443 header( 'Content-Disposition: attachment; filename="colors.css"' );
1444 header( 'Content-Transfer-Encoding: binary' );
1445 header( "Content-Length: " . strlen( $dynamic_css ) );
1446 echo $dynamic_css;
1447 exit();
1448 }
1449
1450
1451 /**
1452 * cleanup_options_save form submit action
1453 */
1454 public function cleanup_options_save() {
1455 check_admin_referer( 'wpforo-tools-cleanup' );
1456
1457 if( ! WPF()->usergroup->can( 'mt' ) ) {
1458 WPF()->notice->add( 'Permission denied', 'error' );
1459 wp_safe_redirect( admin_url() );
1460 exit();
1461 }
1462
1463 if( ! wpfkey( $_POST, 'reset' ) ) {
1464 if( $options = wpfval( $_POST, 'wpforo_tools_cleanup' ) ) {
1465 if( wpforo_update_option( 'tools_cleanup', $options ) ) {
1466 WPF()->notice->add( 'Settings successfully updated', 'success' );
1467 }
1468 }
1469 } else {
1470 wpforo_delete_option( 'tools_cleanup' );
1471 WPF()->notice->add( 'Cleanup options reset successfully', 'success' );
1472 }
1473
1474 wp_safe_redirect( admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'tools' ) . '&tab=cleanup' ) );
1475 exit();
1476 }
1477
1478 /**
1479 * misc_options_save form submit action
1480 */
1481 public function misc_options_save() {
1482 check_admin_referer( 'wpforo-tools-misc' );
1483
1484 if( ! WPF()->usergroup->can( 'mt' ) ) {
1485 WPF()->notice->add( 'Permission denied', 'error' );
1486 wp_safe_redirect( admin_url() );
1487 exit();
1488 }
1489
1490 if( ! wpfkey( $_POST, 'reset' ) ) {
1491 if( $options = wpfval( $_POST, 'wpforo_tools_misc' ) ) {
1492 $options['admin_note'] = wpforo_kses( $options['admin_note'] );
1493 $options['admin_note_groups'] = ( wpfval( $_POST, 'wpforo_tools_misc', 'admin_note_groups' ) ) ? array_map(
1494 'intval',
1495 $options['admin_note_groups']
1496 ) : [];
1497 $options['admin_note_pages'] = ( wpfval( $_POST, 'wpforo_tools_misc', 'admin_note_pages' ) ) ? array_map(
1498 'sanitize_textarea_field',
1499 $options['admin_note_pages']
1500 ) : [];
1501 if( wpforo_update_option( 'tools_misc', $options ) ) {
1502 wpforo_clean_cache( 'forum-soft' );
1503 WPF()->notice->add( 'Settings successfully updated', 'success' );
1504 }
1505 }
1506 } else {
1507 wpforo_delete_option( 'tools_misc' );
1508 WPF()->notice->add( 'Misc options reset successfully', 'success' );
1509 }
1510
1511 wp_safe_redirect( admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'tools' ) . '&tab=misc' ) );
1512 exit();
1513 }
1514
1515 /**
1516 * legal_options_save form submit action
1517 */
1518 public function legal_options_save() {
1519 check_admin_referer( 'wpforo-tools-legal' );
1520
1521 if( ! WPF()->usergroup->can( 'mt' ) ) {
1522 WPF()->notice->add( 'Permission denied', 'error' );
1523 wp_safe_redirect( admin_url() );
1524 exit();
1525 }
1526
1527 if( ! wpfkey( $_POST, 'reset' ) ) {
1528 if( $options = wpfval( $_POST, 'wpforo_tools_legal' ) ) {
1529 $options['contact_page_url'] = esc_url( (string) $options['contact_page_url'] );
1530 $options['checkbox_terms_privacy'] = intval( $options['checkbox_terms_privacy'] );
1531 $options['checkbox_email_password'] = intval( $options['checkbox_email_password'] );
1532 $options['page_terms'] = esc_url( (string) $options['page_terms'] );
1533 $options['page_privacy'] = esc_url( (string) $options['page_privacy'] );
1534 $options['checkbox_forum_privacy'] = intval( $options['checkbox_forum_privacy'] );
1535 $options['forum_privacy_text'] = wpforo_kses( $options['forum_privacy_text'], 'post' );
1536 $options['cookies'] = intval( $options['cookies'] );
1537 $options['rules_checkbox'] = intval( $options['rules_checkbox'] );
1538 $options['rules_text'] = wpforo_kses( $options['rules_text'], 'post' );
1539 if( wpforo_update_option( 'tools_legal', $options ) ) {
1540 WPF()->notice->add( 'Settings successfully updated', 'success' );
1541 }
1542 }
1543 } else {
1544 wpforo_delete_option( 'tools_legal' );
1545 WPF()->notice->add( 'Settings reset successfully', 'success' );
1546 }
1547
1548 wp_safe_redirect( admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'tools' ) . '&tab=legal' ) );
1549 exit();
1550 }
1551
1552 /**
1553 * delete detected spam file
1554 */
1555 public function delete_spam_file() {
1556 check_admin_referer( 'wpforo_tools_antispam_files' );
1557
1558 if( ! WPF()->usergroup->can( 'mt' ) ) {
1559 WPF()->notice->add( 'Permission denied', 'error' );
1560 wp_safe_redirect( admin_url() );
1561 exit();
1562 }
1563
1564 if( $filename = trim( (string) wpfval( $_GET, 'sfname' ) ) ) {
1565 $filename = str_replace( [ '../', './', '/' ], '', sanitize_file_name( $filename ) );
1566 $filename = urldecode( (string) $filename );
1567 if( $filename ) {
1568 $attachmentid = WPF()->post->get_attachment_id( '/' . $filename );
1569 if( ! wp_delete_attachment( $attachmentid ) ) {
1570 @unlink( WPF()->folders['default_attachments']['dir'] . DIRECTORY_SEPARATOR . $filename );
1571 }
1572 WPF()->notice->add( 'Deleted', 'success' );
1573 }
1574 }
1575
1576 wp_safe_redirect( admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'tools' ) . '&tab=antispam' ) );
1577 exit();
1578 }
1579
1580 /**
1581 * delete_all_spam_files all detected spam file using level attribute
1582 */
1583 public function delete_all_spam_files() {
1584 check_admin_referer( 'wpforo_tools_antispam_files' );
1585
1586 if( ! WPF()->usergroup->can( 'mt' ) ) {
1587 WPF()->notice->add( 'Permission denied', 'error' );
1588 wp_safe_redirect( admin_url() );
1589 exit();
1590 }
1591
1592 if( $delete_level = (int) wpfval( $_GET, 'level' ) ) {
1593 $default_attachments_dir = WPF()->folders['default_attachments']['dir'];
1594 if( is_dir( $default_attachments_dir ) ) {
1595 if( $handle = opendir( $default_attachments_dir ) ) {
1596 while( false !== ( $filename = readdir( $handle ) ) ) {
1597 if( $filename === '.' || $filename === '..' ) continue;
1598 if( ! $level = WPF()->moderation->spam_file( $filename ) ) continue;
1599 if( $delete_level === $level ) {
1600 $attachmentid = WPF()->post->get_attachment_id( '/' . $filename );
1601 if( ! wp_delete_attachment( $attachmentid ) ) {
1602 @unlink( $default_attachments_dir . DIRECTORY_SEPARATOR . $filename );
1603 }
1604 }
1605 }
1606 closedir( $handle );
1607 WPF()->notice->add( 'Deleted', 'success' );
1608 }
1609 }
1610 }
1611
1612 wp_safe_redirect( admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'tools' ) . '&tab=antispam' ) );
1613 exit();
1614 }
1615
1616 /**
1617 * do database alter fixing using install.sql db-strukture
1618 */
1619 public function database_update() {
1620 check_admin_referer( 'wpforo_update_database' );
1621
1622 if( ! WPF()->usergroup->can( 'mt' ) ) {
1623 WPF()->notice->add( 'Permission denied', 'error' );
1624 wp_safe_redirect( admin_url() );
1625 exit();
1626 }
1627
1628 wpforo_set_max_execution_time( 3600 );
1629
1630 wpforo_update_db();
1631
1632 wp_safe_redirect( admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'tools' ) . '&tab=debug&view=tables' ) );
1633 exit();
1634 }
1635
1636 public function forum_copy() {
1637 wpforo_verify_nonce( 'forum_copy', 'full' );
1638
1639 if( ! WPF()->usergroup->can_manage_forum() ) {
1640 WPF()->notice->add( 'Permission denied', 'error' );
1641 wp_safe_redirect( admin_url() );
1642 exit();
1643 }
1644
1645 $forumid = (int) wpfval( $_GET, 'forumid' );
1646
1647 if( $forumid ) {
1648 WPF()->forum->copy( $forumid );
1649 }
1650
1651 wp_safe_redirect( admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'forums' ) ) );
1652 exit();
1653 }
1654
1655 /**
1656 * forum_add form submit action
1657 */
1658 public function forum_add() {
1659 check_admin_referer( 'wpforo-forum-add' );
1660
1661 if( ! WPF()->usergroup->can_manage_forum() ) {
1662 WPF()->notice->add( 'Permission denied', 'error' );
1663 wp_safe_redirect( admin_url() );
1664 exit();
1665 }
1666
1667 if( ! empty( $_REQUEST['forum'] ) ) {
1668 WPF()->forum->add();
1669 }
1670
1671 wp_safe_redirect( admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'forums' ) ) );
1672 exit();
1673 }
1674
1675 /**
1676 * forum_edit form submit action
1677 */
1678 public function forum_edit() {
1679 check_admin_referer( 'wpforo-forum-edit' );
1680
1681 if( ! WPF()->usergroup->can_manage_forum() ) {
1682 WPF()->notice->add( 'Permission denied', 'error' );
1683 wp_safe_redirect( admin_url() );
1684 exit();
1685 }
1686
1687 if( ! empty( $_REQUEST['forum'] ) ) {
1688 WPF()->forum->edit();
1689 }
1690
1691 wp_safe_redirect( wpforo_get_request_uri() );
1692 exit();
1693 }
1694
1695 /**
1696 * forum_delete form submit action
1697 */
1698 public function forum_delete() {
1699 check_admin_referer( 'wpforo-forum-delete' );
1700
1701 if( ! WPF()->usergroup->can_manage_forum() ) {
1702 WPF()->notice->add( 'Permission denied', 'error' );
1703 wp_safe_redirect( admin_url() );
1704 exit();
1705 }
1706
1707 $delete = (int) wpfval( $_REQUEST, 'forum', 'delete' );
1708 if( $delete === 1 ) {
1709 WPF()->forum->delete( 0, false );
1710 } elseif( $delete === 0 ) {
1711 WPF()->forum->merge();
1712 }
1713
1714 wp_safe_redirect( admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'forums' ) ) );
1715 exit();
1716 }
1717
1718 /**
1719 * forum_hierarchy_save form submit action
1720 */
1721 public function forum_hierarchy_save() {
1722 check_admin_referer( 'wpforo-forums-hierarchy' );
1723
1724 if( ! WPF()->usergroup->can_manage_forum() ) {
1725 WPF()->notice->add( 'Permission denied', 'error' );
1726 wp_safe_redirect( admin_url() );
1727 exit();
1728 }
1729
1730 if( ! empty( $_REQUEST['forum'] ) ) {
1731 WPF()->forum->update_hierarchy();
1732 wpforo_clean_cache( 'forum' );
1733 }
1734
1735 wp_safe_redirect( admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'forums' ) ) );
1736 exit();
1737 }
1738
1739 /**
1740 * dashboard_post_unapprove action
1741 */
1742 public function dashboard_post_unapprove() {
1743 $postid = wpfval( $_GET, 'postid' );
1744 check_admin_referer( "wpforo-unapprove-post-{$postid}" );
1745
1746 if( ! WPF()->usergroup->can( 'aum' ) ) {
1747 WPF()->notice->add( 'Permission denied', 'error' );
1748 wp_safe_redirect( admin_url() );
1749 exit();
1750 }
1751
1752 WPF()->moderation->post_unapprove( $postid );
1753 wpforo_clean_cache( 'post', $postid );
1754
1755 wp_safe_redirect( wp_get_referer() );
1756 exit();
1757 }
1758
1759 /**
1760 * dashboard_post_approve action
1761 */
1762 public function dashboard_post_approve() {
1763 $postid = wpfval( $_GET, 'postid' );
1764 check_admin_referer( "wpforo-approve-post-{$postid}" );
1765
1766 if( ! WPF()->usergroup->can( 'aum' ) ) {
1767 WPF()->notice->add( 'Permission denied', 'error' );
1768 wp_safe_redirect( admin_url() );
1769 exit();
1770 }
1771
1772 WPF()->moderation->post_approve( $postid );
1773 wpforo_clean_cache( 'post', $postid );
1774
1775 wp_safe_redirect( wp_get_referer() );
1776 exit();
1777 }
1778
1779 /**
1780 * dashboard_post_delete action
1781 */
1782 public function dashboard_post_delete() {
1783 $postid = wpfval( $_GET, 'postid' );
1784 check_admin_referer( "wpforo-delete-post-{$postid}" );
1785
1786 if( ! WPF()->usergroup->can( 'aum' ) ) {
1787 WPF()->notice->add( 'Permission denied', 'error' );
1788 wp_safe_redirect( admin_url() );
1789 exit();
1790 }
1791
1792 WPF()->post->delete( $postid );
1793
1794 wp_safe_redirect( wp_get_referer() );
1795 exit();
1796 }
1797
1798 /**
1799 * doing bulk moderation actions ( approve, unapprove, delete )
1800 */
1801 public function bulk_moderation() {
1802 check_admin_referer( 'bulk-moderations' );
1803
1804 if( ! WPF()->usergroup->can( 'aum' ) ) {
1805 WPF()->notice->add( 'Permission denied', 'error' );
1806 wp_safe_redirect( admin_url() );
1807 exit();
1808 }
1809
1810 $u_action = $this->get_current_bulk_action();
1811 $postids = (array) wpfval( $_GET, 'postids' );
1812 if( $u_action && ! empty( $postids ) ) {
1813 if( $u_action === 'delete' ) {
1814 foreach( $postids as $postid ) WPF()->post->delete( $postid );
1815 } elseif( $u_action === 'approve' ) {
1816 foreach( $postids as $postid ) WPF()->moderation->post_approve( $postid );
1817 } elseif( $u_action === 'unapprove' ) {
1818 foreach( $postids as $postid ) WPF()->moderation->post_unapprove( $postid );
1819 }
1820 }
1821
1822 wp_safe_redirect( wp_get_referer() );
1823 exit();
1824 }
1825
1826 /**
1827 * phrase_add form submit action
1828 */
1829 public function phrase_add() {
1830 check_admin_referer( 'wpforo-phrase-add' );
1831
1832 if( ! WPF()->usergroup->can( 'mp' ) ) {
1833 WPF()->notice->add( 'Permission denied', 'error' );
1834 wp_safe_redirect( admin_url() );
1835 exit();
1836 }
1837
1838 if( ! empty( $_POST['phrase'] ) ) {
1839 WPF()->phrase->add();
1840 }
1841
1842 wp_safe_redirect( admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'phrases' ) ) );
1843 exit();
1844 }
1845
1846 /**
1847 * phrase_edit_form action redirect to phrase list page when phraseid(s) not chosen
1848 */
1849 public function phrase_edit_form() {
1850 $phraseids = array_filter(
1851 array_map( 'intval', array_merge( (array) wpfval( $_GET, 'phraseid' ), (array) wpfval( $_GET, 'phraseids' ) ) )
1852 );
1853 if( ! $phraseids ) {
1854 wp_safe_redirect( admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'phrases' ) ) );
1855 exit();
1856 }
1857 }
1858
1859 /**
1860 * phrase_edit form submit action
1861 */
1862 public function phrase_edit() {
1863 check_admin_referer( 'wpforo-phrases-edit' );
1864
1865 if( ! WPF()->usergroup->can( 'mp' ) ) {
1866 WPF()->notice->add( 'Permission denied', 'error' );
1867 wp_safe_redirect( admin_url() );
1868 exit();
1869 }
1870
1871 if( ! empty( $_POST['phrases'] ) ) {
1872 WPF()->phrase->edit();
1873 }
1874
1875 wp_safe_redirect( admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'phrases' ) ) );
1876 exit();
1877 }
1878
1879 /**
1880 * user_ban action
1881 */
1882 public function user_ban() {
1883 $userid = intval( wpfval( $_GET, 'userid' ) );
1884 check_admin_referer( 'wpforo-user-ban-' . $userid );
1885
1886 if( ! WPF()->usergroup->can( 'vm' ) || ! WPF()->usergroup->can( 'bm' ) || $userid === WPF()->current_userid ) {
1887 WPF()->notice->add( 'Permission denied', 'error' );
1888 wp_safe_redirect( admin_url() );
1889 exit();
1890 }
1891
1892 WPF()->member->ban( $userid );
1893 wpforo_clean_cache( 'user' );
1894
1895 wp_safe_redirect( wp_get_referer() );
1896 exit();
1897 }
1898
1899 /**
1900 * user_unban action
1901 */
1902 public function user_unban() {
1903 $userid = intval( wpfval( $_GET, 'userid' ) );
1904 check_admin_referer( 'wpforo-user-unban-' . $userid );
1905
1906 if( ! WPF()->usergroup->can( 'vm' ) || ! WPF()->usergroup->can( 'bm' ) || $userid === WPF()->current_userid ) {
1907 WPF()->notice->add( 'Permission denied', 'error' );
1908 wp_safe_redirect( admin_url() );
1909 exit();
1910 }
1911
1912 WPF()->member->unban( $userid );
1913 wpforo_clean_cache( 'user' );
1914
1915 wp_safe_redirect( wp_get_referer() );
1916 exit();
1917 }
1918
1919 /**
1920 * user_activate action
1921 */
1922 public function user_activate() {
1923 $userid = intval( wpfval( $_GET, 'userid' ) );
1924 check_admin_referer( 'wpforo-user-activate-' . $userid );
1925
1926 if( ! WPF()->usergroup->can( 'vm' ) || ! WPF()->usergroup->can( 'bm' ) || $userid === WPF()->current_userid ) {
1927 WPF()->notice->add( 'Permission denied', 'error' );
1928 wp_safe_redirect( admin_url() );
1929 exit();
1930 }
1931
1932 WPF()->member->activate( $userid );
1933
1934 wp_safe_redirect( wp_get_referer() );
1935 exit();
1936 }
1937
1938 /**
1939 * user_deactivate action
1940 */
1941 public function user_deactivate() {
1942 $userid = intval( wpfval( $_GET, 'userid' ) );
1943 check_admin_referer( 'wpforo-user-deactivate-' . $userid );
1944
1945 if( ! WPF()->usergroup->can( 'vm' ) || ! WPF()->usergroup->can( 'bm' ) || $userid === WPF()->current_userid ) {
1946 WPF()->notice->add( 'Permission denied', 'error' );
1947 wp_safe_redirect( admin_url() );
1948 exit();
1949 }
1950
1951 WPF()->member->deactivate( $userid );
1952
1953 wp_safe_redirect( wp_get_referer() );
1954 exit();
1955 }
1956
1957 public function user_ban_ajax() {
1958 wpforo_verify_nonce( 'wpforo_user_ban' );
1959 $userid = WPF()->current_object['user']['userid'];
1960 $currentstate = (int) wpfval( $_POST, 'currentstate' );
1961 if( $currentstate ) {
1962 $r = WPF()->member->unban( $userid );
1963 } else {
1964 $r = WPF()->member->ban( $userid );
1965 }
1966
1967 if( $r ) {
1968 wp_send_json_success( [
1969 'currentstate' => (int) ! $currentstate,
1970 'notice' => WPF()->notice->get_notices(),
1971 ] );
1972 } else {
1973 wp_send_json_error( [ 'notice' => WPF()->notice->get_notices() ] );
1974 }
1975 }
1976
1977 public function get_member_template() {
1978 wpforo_verify_nonce( 'wpforo_get_member_template' );
1979 $href = wpfval( $_POST, 'href' );
1980 WPF()->init_current_url( $href );
1981 WPF()->init_current_object();
1982 if( wpforo_is_member_template() ) {
1983 if( ( $template = WPF()->tpl->get_template(
1984 WPF()->current_object['template']
1985 ) ) && $template['type'] === 'callback' && is_callable( $template['callback_for_page'] ) ) {
1986 ob_start();
1987 echo call_user_func( $template['callback_for_page'], $template );
1988 wp_send_json_success( [ 'html' => ob_get_clean() ] );
1989 }
1990 }
1991 wp_send_json_error();
1992 }
1993
1994 public function search_existed_topics() {
1995 if( ! apply_filters( 'wpforo_topic_suggestion', true ) ) {
1996 wp_send_json_error();
1997 }
1998 wpforo_verify_nonce( 'wpforo_search_existed_topics' );
1999 $title = trim( (string) wpfval( $_POST, 'title' ) );
2000 $topicids = WPF()->topic->search( $title, 'title' );
2001 if( $topicids ) {
2002 $topics = WPF()->topic->get_topics(
2003 [
2004 'include' => $topicids,
2005 'row_count' => apply_filters( 'wpforo_suggested_topics_limit', 5 ),
2006 'orderby' => 'created',
2007 ]
2008 );
2009 if( $topics ) {
2010 $topics = array_map( function( $topic ) {
2011 $topic['url'] = WPF()->topic->get_url( $topic );
2012
2013 return $topic;
2014 }, $topics );
2015
2016 wp_send_json_success( $topics );
2017 }
2018 }
2019
2020 wp_send_json_error();
2021 }
2022
2023 public function confirm_current_user_password() {
2024 wpforo_verify_nonce( 'wpforo_confirm_current_user_password' );
2025 $pwd = wpfval( $_POST, 'pwd' );
2026 if( wp_check_password( $pwd, WPF()->current_user['user_pass'], WPF()->current_user['userid'] ) ) {
2027 wp_send_json_success();
2028 } else {
2029 wp_send_json_error();
2030 }
2031 }
2032
2033 /**
2034 * Handle frontend user delete action
2035 *
2036 * Fires two hooks:
2037 * - wpforo_before_front_delete_user: before the user is deleted, passes the current user array
2038 * - wpforo_after_front_delete_user: after the user is deleted, passes the (previous) user array
2039 */
2040 public function user_delete() {
2041 wpforo_verify_nonce( 'user_delete', 'full' );
2042 if( WPF()->current_object['user'] && ( $action = WPF()->member->get_action(
2043 WPF()->current_object['user'],
2044 'delete'
2045 ) ) && is_callable( $action['callback_for_can'] ) && call_user_func(
2046 $action['callback_for_can']
2047 ) ) {
2048
2049 if( $pwd = wpfval( $_GET, 'pwd' ) ) {
2050 if( wp_check_password( $pwd, WPF()->current_user['user_pass'], WPF()->current_user['userid'] ) ) {
2051 // Fire an action before the frontend user deletion happens so integrators can capture user data
2052 do_action( 'wpforo_before_front_delete_user', WPF()->current_object['user'] );
2053 if( ! function_exists( 'wp_delete_user' ) ) require_once ABSPATH . "wp-admin/includes/user.php";
2054 if( wp_delete_user( WPF()->current_object['user']['userid'] ) ) {
2055
2056 do_action( 'wpforo_after_front_delete_user', WPF()->current_object['user'] );
2057
2058 WPF()->notice->add( 'User successfully deleted', 'success' );
2059 } else {
2060 WPF()->notice->add( 'User delete error', 'error' );
2061 }
2062 } else {
2063 WPF()->notice->add( 'User deletion error: The password you entered is incorrect.', 'error' );
2064 }
2065 } else {
2066 WPF()->notice->add( 'User delete error: missing argument.', 'error' );
2067 }
2068 } else {
2069 WPF()->notice->add( 'Permission denied for this action', 'error' );
2070 }
2071
2072 wp_safe_redirect( wpforo_url( '', 'members' ) );
2073 exit();
2074 }
2075
2076 /**
2077 * action after WordPress native deleted_user hook
2078 *
2079 * @param int $userid already deleted user ID
2080 */
2081 public function deleted_user( $userid, $reassign = null ) {
2082 if( wpfval( $_REQUEST, 'wpforo_user_delete_option' ) === 'reassign' ) {
2083 WPF()->member->delete( $userid, wpforo_bigintval( wpfval( $_REQUEST, 'wpforo_reassign_userid' ) ) );
2084 } elseif( wpfval( $_REQUEST, 'wpforo_user_delete_option' ) === 'delete' ) {
2085 WPF()->member->delete( $userid );
2086 } elseif( $reassign ) {
2087 WPF()->member->delete( $userid, $reassign );
2088 } else {
2089 WPF()->member->delete( $userid, ( wpforo_setting( 'authorization', 'user_delete_method' ) === 'soft' ? 0 : null ) );
2090 }
2091 WPF()->notice->clear();
2092 }
2093
2094 /**
2095 * doing bulk member actions ( ban, unban, delete )
2096 */
2097 public function bulk_members() {
2098 check_admin_referer( 'bulk-members' );
2099
2100 if( ! WPF()->usergroup->can( 'vm' ) ) {
2101 WPF()->notice->add( 'Permission denied', 'error' );
2102 wp_safe_redirect( admin_url() );
2103 exit();
2104 }
2105
2106 $new_groupid = - 1;
2107 if( ! empty( $_GET['new_groupid'] ) && $_GET['new_groupid'] !== '-1' ) {
2108 $new_groupid = intval( $_GET['new_groupid'] );
2109 } elseif( ! empty( $_GET['new_groupid2'] ) && $_GET['new_groupid2'] !== '-1' ) {
2110 $new_groupid = intval( $_GET['new_groupid2'] );
2111 }
2112
2113 $u_action = $this->get_current_bulk_action();
2114 if( in_array( $u_action, [ 'ban', 'unban', 'activate', 'deactivate' ] ) && ! WPF()->usergroup->can( 'bm' ) ) {
2115 WPF()->notice->add( 'Permission denied', 'error' );
2116 wp_safe_redirect( admin_url() );
2117 exit();
2118 } elseif( $u_action === 'delete' && ! WPF()->usergroup->can( 'dm' ) ) {
2119 WPF()->notice->add( 'Permission denied', 'error' );
2120 wp_safe_redirect( admin_url() );
2121 exit();
2122 }
2123
2124 $userids = (array) wpfval( $_GET, 'userids' );
2125 $userids = array_filter( array_map( 'wpforo_bigintval', $userids ) );
2126 $userids = array_diff( $userids, (array) WPF()->current_userid );
2127 if( $u_action && ! empty( $userids ) ) {
2128 if( $u_action === 'delete' ) {
2129 $url = self_admin_url( 'users.php?action=delete&users[]=' . implode( '&users[]=', $userids ) );
2130 $url = str_replace( '&amp;', '&', wp_nonce_url( $url, 'bulk-users' ) );
2131 wp_safe_redirect( $url );
2132 exit();
2133 } elseif( $u_action === 'ban' ) {
2134 foreach( $userids as $userid ) {
2135 WPF()->member->ban( $userid );
2136 }
2137 } elseif( $u_action === 'unban' ) {
2138 foreach( $userids as $userid ) {
2139 WPF()->member->unban( $userid );
2140 }
2141 } elseif( $u_action === 'activate' ) {
2142 foreach( $userids as $userid ) {
2143 WPF()->member->activate( $userid );
2144 }
2145 } elseif( $u_action === 'deactivate' ) {
2146 foreach( $userids as $userid ) {
2147 WPF()->member->deactivate( $userid );
2148 }
2149 }
2150 } elseif( ! $u_action && wpfkey( $_GET, 'change_group' ) ) {
2151 if( ! empty( $userids ) && $new_groupid !== - 1 ) {
2152 $status = WPF()->usergroup->set_users_groupid( [ $new_groupid => $userids ] );
2153 if( $status['success'] ) WPF()->notice->add( 'Usergroup is successfully changed for selected users', 'success' );
2154 } else {
2155 WPF()->notice->add( 'Please select users and usergroup', 'error' );
2156 }
2157 }
2158 wpforo_clean_cache( 'user' );
2159
2160 wp_safe_redirect( wp_get_referer() );
2161 exit();
2162 }
2163
2164 /**
2165 * usergroup_add form submit action
2166 */
2167 public function usergroup_add() {
2168 check_admin_referer( 'wpforo-usergroup-add' );
2169
2170 if( ! WPF()->usergroup->can( 'vmg' ) ) {
2171 WPF()->notice->add( 'Permission denied', 'error' );
2172 wp_safe_redirect( admin_url() );
2173 exit();
2174 }
2175
2176 if( ! empty( $_POST['usergroup'] ) ) {
2177 $group = WPF()->usergroup->fix_group( $_POST['usergroup'] );
2178 $color = wpfval( $group, 'wpfugc' ) ? '' : sanitize_text_field( $group['color'] );
2179 $groupid = WPF()->usergroup->add(
2180 $group['name'],
2181 $group['cans'],
2182 $group['description'],
2183 $group['role'],
2184 $group['access'],
2185 $color,
2186 $group['visible'],
2187 $group['secondary']
2188 );
2189 if( $groupid ) wpforo_clean_cache( 'loop', $groupid );
2190 }
2191
2192 wp_safe_redirect( admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'usergroups' ) ) );
2193 exit();
2194 }
2195
2196 /**
2197 * usergroup_edit form submit action
2198 */
2199 public function usergroup_edit() {
2200 check_admin_referer( 'wpforo-usergroup-edit' );
2201
2202 if( ! WPF()->usergroup->can( 'vmg' ) ) {
2203 WPF()->notice->add( 'Permission denied', 'error' );
2204 wp_safe_redirect( admin_url() );
2205 exit();
2206 }
2207
2208 if( ! empty( $_POST['usergroup'] ) ) {
2209 $group = WPF()->usergroup->fix_group( $_POST['usergroup'] );
2210 $color = wpfval( $group, 'wpfugc' ) ? '' : sanitize_text_field( $group['color'] );
2211 WPF()->usergroup->edit(
2212 $group['groupid'],
2213 $group['name'],
2214 $group['cans'],
2215 $group['description'],
2216 $group['role'],
2217 null,
2218 $color,
2219 $group['visible'],
2220 $group['secondary']
2221 );
2222 wpforo_clean_cache( 'loop', $group['groupid'] );
2223 }
2224
2225 wp_safe_redirect( admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'usergroups' ) ) );
2226 exit();
2227 }
2228
2229 /**
2230 * usergroup_delete form submit action
2231 */
2232 public function usergroup_delete() {
2233 check_admin_referer( 'wpforo-usergroup-delete' );
2234
2235 if( ! WPF()->usergroup->can( 'vmg' ) ) {
2236 WPF()->notice->add( 'Permission denied', 'error' );
2237 wp_safe_redirect( admin_url() );
2238 exit();
2239 }
2240
2241 if( wpfval( $_POST, 'usergroup', 'delete' ) ) {
2242 $args = [ 'groupid' => wpfval( $_POST, 'usergroup', 'groupid' ) ];
2243 if( $userids = WPF()->member->get_userids( $args ) ) {
2244 $redirect_to = self_admin_url( 'users.php?action=delete&users[]=' . implode( '&users[]=', $userids ) );
2245 $redirect_to = str_replace( '&amp;', '&', wp_nonce_url( $redirect_to, 'bulk-users' ) );
2246 wp_safe_redirect( $redirect_to );
2247 exit();
2248 }
2249 }
2250
2251 if( ! empty( $_POST['usergroup'] ) ) {
2252 WPF()->usergroup->delete( wpfval( $_POST['usergroup'], 'groupid' ), wpfval( $_POST['usergroup'], 'mergeid' ) );
2253 wpforo_clean_cache( 'user' );
2254 }
2255
2256 wp_safe_redirect( admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'usergroups' ) ) );
2257 exit();
2258 }
2259
2260 /**
2261 * default_groupid_change action
2262 */
2263 public function default_groupid_change() {
2264 $default_groupid = intval( wpfval( $_GET, 'default_groupid' ) );
2265 check_admin_referer( 'wpforo-default-groupid-change-' . $default_groupid );
2266
2267 if( ! WPF()->usergroup->can( 'vmg' ) ) {
2268 WPF()->notice->add( 'Permission denied', 'error' );
2269 wp_safe_redirect( admin_url() );
2270 exit();
2271 }
2272
2273 if( $default_groupid ) WPF()->usergroup->set_default( $default_groupid );
2274
2275 wp_safe_redirect( wp_get_raw_referer() );
2276 exit();
2277 }
2278
2279 /**
2280 * prevent to show usergroup delete form when !$groupid || $groupid <= 5
2281 */
2282 public function usergroup_delete_form() {
2283 if( intval( wpfval( $_GET, 'groupid' ) ) <= 5 ) {
2284 wp_safe_redirect( admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'usergroups' ) ) );
2285 exit();
2286 }
2287 }
2288
2289 /**
2290 * access_add form submit action
2291 */
2292 public function access_add() {
2293 check_admin_referer( 'wpforo-access-add' );
2294
2295 if( ! WPF()->usergroup->can( 'ms' ) ) {
2296 WPF()->notice->add( 'Permission denied', 'error' );
2297 wp_safe_redirect( admin_url() );
2298 exit();
2299 }
2300
2301 if( ! empty( $_POST['access'] ) ) {
2302 WPF()->perm->add( WPF()->perm->fix_access( $_POST['access'] ) );
2303 }
2304
2305 wp_safe_redirect( admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'accesses' ) ) );
2306 exit();
2307 }
2308
2309 /**
2310 * access_edit form submit action
2311 */
2312 public function access_edit() {
2313 check_admin_referer( 'wpforo-access-edit' );
2314
2315 if( ! WPF()->usergroup->can( 'ms' ) ) {
2316 WPF()->notice->add( 'Permission denied', 'error' );
2317 wp_safe_redirect( admin_url() );
2318 exit();
2319 }
2320
2321 if( ! empty( $_POST['access'] ) ) {
2322 WPF()->perm->edit( WPF()->perm->fix_access( $_POST['access'] ) );
2323 wpforo_clean_cache( 'loop' );
2324 }
2325
2326 wp_safe_redirect( wp_get_raw_referer() );
2327 exit();
2328 }
2329
2330 /**
2331 * access_delete form submit action
2332 */
2333 public function access_delete() {
2334 $accessid = intval( wpfval( $_GET, 'accessid' ) );
2335 check_admin_referer( 'wpforo-access-delete-' . $accessid );
2336
2337 if( ! WPF()->usergroup->can( 'ms' ) ) {
2338 WPF()->notice->add( 'Permission denied', 'error' );
2339 wp_safe_redirect( admin_url() );
2340 exit();
2341 }
2342
2343 WPF()->perm->delete( $accessid );
2344 wpforo_clean_cache( 'loop' );
2345
2346 wp_safe_redirect( admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'accesses' ) ) );
2347 exit();
2348 }
2349
2350 public function theme_activate() {
2351 check_admin_referer( 'wpforo-theme-activate' );
2352
2353 if( ! WPF()->usergroup->can( 'mth' ) ) {
2354 WPF()->notice->add( 'Permission denied', 'error' );
2355 wp_safe_redirect( admin_url() );
2356 exit();
2357 }
2358
2359 $notice = __( 'Theme file not readable', 'wpforo' );
2360 $notice_type = 'error';
2361 if( ( $theme = trim( sanitize_text_field( (string) wpfval( $_GET, 'theme' ) ) ) ) && WPF()->tpl->theme_exists(
2362 $theme
2363 ) ) {
2364 $general = WPF()->settings->general;
2365 $general['current_theme'] = $theme;
2366 wpforo_update_option( 'wpforo_general', $general );
2367 $notice = __( 'Theme Successfully Activated', 'wpforo' );
2368 $notice_type = 'success';
2369 }
2370
2371 WPF()->notice->add( $notice, $notice_type );
2372 wp_safe_redirect( wp_get_raw_referer() );
2373 exit();
2374 }
2375
2376 /**
2377 * theme_delete action
2378 */
2379 public function theme_delete() {
2380 check_admin_referer( 'wpforo-theme-delete' );
2381
2382 if( ! WPF()->usergroup->can( 'mth' ) ) {
2383 WPF()->notice->add( 'Permission denied', 'error' );
2384 wp_safe_redirect( admin_url() );
2385 exit();
2386 }
2387
2388 $notice = __( 'Theme delete error', 'wpforo' );
2389 $notice_type = 'error';
2390 if( $theme = trim( sanitize_text_field( (string) wpfval( $_GET, 'theme' ) ) ) ) {
2391 if( WPF()->tpl->theme !== $theme ) {
2392 $remove_dir = WPFORO_THEME_DIR . '/' . $theme;
2393 if( is_dir( $remove_dir ) ) {
2394 wpforo_remove_directory( $remove_dir );
2395 $notice = __( 'Theme delete success', 'wpforo' );
2396 $notice_type = 'success';
2397 }
2398 }
2399 }
2400
2401 WPF()->notice->add( $notice, $notice_type );
2402 wp_safe_redirect( admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'themes' ) ) );
2403 exit();
2404 }
2405
2406 /**
2407 * update wpForo addons CSS styles to make compatible with the current version of wpForo
2408 */
2409 function update_addons_css() {
2410 check_admin_referer( 'wpforo-update-addons-css' );
2411 wpforo_wrap_in_all_addons_css();
2412 wp_safe_redirect( admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'settings' ) ) );
2413 exit();
2414 }
2415
2416 /**
2417 * dissmiss the poll version is old notification for admins
2418 */
2419 public function dissmiss_poll_version_is_old() {
2420 check_admin_referer( 'wpforo-dissmiss-poll-version-is-old' );
2421 WPF()->dissmissed['poll_version_is_old'] = 1;
2422 wpforo_update_option( 'dissmissed', WPF()->dissmissed );
2423 wp_safe_redirect( admin_url( 'admin.php?page=' . wpforo_prefix_slug( 'dashboard' ) ) );
2424 exit();
2425 }
2426
2427 /**
2428 * dissmiss the recaptcha not configured notification for admins
2429 */
2430 public function dissmiss_recaptcha_note() {
2431 if( wpfval( $_POST, 'backend' ) ) {
2432 WPF()->dissmissed['recaptcha_backend_note'] = 1;
2433 } else {
2434 WPF()->dissmissed['recaptcha_note'] = 1;
2435 }
2436 $response = wpforo_update_option( 'dissmissed', WPF()->dissmissed );
2437 if( $response ) {
2438 wp_send_json_success();
2439 } else {
2440 wp_send_json_error();
2441 }
2442 }
2443
2444 /**
2445 * wpforo before deactivate action
2446 */
2447 public function deactivate() {
2448 $response = [ 'code' => 0 ];
2449 $json = filter_input( INPUT_POST, 'deactivateData' );
2450 if( $json ) {
2451 parse_str( $json, $data );
2452
2453 $blogTitle = get_option( 'blogname' );
2454 $to = 'feedback@wpforo.com';
2455 $subject = '[wpForo Feedback - ' . WPFORO_VERSION . ']';
2456 $headers = [];
2457 $contentType = 'text/html';
2458 $fromName = apply_filters( 'wp_mail_from_name', $blogTitle );
2459 $fromName = html_entity_decode( $fromName, ENT_QUOTES );
2460 $siteUrl = get_site_url();
2461 $parsedUrl = parse_url( $siteUrl );
2462 $domain = isset( $parsedUrl['host'] ) ? $parsedUrl['host'] : '';
2463 $fromEmail = 'no-reply@' . $domain;
2464 $headers[] = "Content-Type: $contentType; charset=UTF-8";
2465 $headers[] = "From: " . $fromName . " <" . $fromEmail . "> \r\n";
2466 $message = "Dismiss and never show again";
2467
2468 if( isset( $data['never_show'] ) && ( $v = intval( $data['never_show'] ) ) ) {
2469 wpforo_update_option( 'deactivation_dialog_never_show', $v );
2470 $response['code'] = 'dismiss_and_deactivate';
2471 } elseif( isset( $data['deactivation_reason'] ) && ( $reason = trim( (string) $data['deactivation_reason'] ) ) ) {
2472 $subject .= ' - ' . $reason;
2473 $message = "<strong>Deactivation reason:</strong> " . $reason . "\r\n" . "<br/>";
2474 if( isset( $data['deactivation_reason_desc'] ) && ( $reasonDesc = trim(
2475 (string) $data['deactivation_reason_desc']
2476 ) ) ) {
2477 $message .= "<strong>Deactivation reason description:</strong> " . $reasonDesc . "\r\n" . "<br/>";
2478 }
2479 if( isset( $data['deactivation_feedback_email'] ) && ( $feedback_email = trim(
2480 (string) $data['deactivation_feedback_email']
2481 ) ) ) {
2482 $to = 'support@wpforo.com';
2483 $message .= "<strong>Feedback Email:</strong> " . $feedback_email . "\r\n" . "<br/>";
2484 }
2485 $subject = html_entity_decode( $subject, ENT_QUOTES );
2486 $message = html_entity_decode( $message, ENT_QUOTES );
2487 $response['code'] = 'send_and_deactivate';
2488 }
2489
2490 wp_mail( $to, $subject, $message, $headers );
2491 }
2492 wp_die( wp_json_encode( $response ) );
2493 }
2494
2495 /**
2496 * base_slugs_settings_save from submit action
2497 *
2498 * @return void
2499 */
2500 public function base_slugs_settings_save() {
2501 check_admin_referer( 'wpforo_settings_save_general' );
2502
2503 if( wpfkey( $_POST, 'reset' ) ) {
2504 wpforo_delete_option( 'wpforo_base_slugs' );
2505 WPF()->notice->add( 'Successfully Done', 'success' );
2506 } else {
2507 $slugs = wpforo_array_args_cast_and_merge(
2508 array_filter( array_map( 'sanitize_title', wp_unslash( $_POST['slugs'] ) ) ),
2509 WPF()->settings->_slugs
2510 );
2511 $slugs = array_intersect_key( $slugs, WPF()->settings->_slugs );
2512 $slugs = array_diff_key( $slugs, WPF()->tpl->templates );
2513 if( $slugs == array_unique( $slugs ) ) {
2514 wpforo_update_option( 'wpforo_base_slugs', $slugs );
2515 WPF()->notice->add( 'Successfully Done', 'success' );
2516 } else {
2517 WPF()->notice->add( 'Please save "Forum template slugs" uniqueness', 'error' );
2518 }
2519 }
2520
2521 /*wp_safe_redirect( wp_get_raw_referer() );
2522 exit();*/
2523 }
2524
2525 /**
2526 * general_settings_save from submit action
2527 *
2528 * @return void
2529 */
2530 public function general_settings_save() {
2531 check_admin_referer( 'wpforo_settings_save_general' );
2532
2533 if( wpfkey( $_POST, 'reset' ) ) {
2534 wpforo_delete_option( 'wpforo_general' );
2535 } else {
2536 $general = wpforo_array_args_cast_and_merge(
2537 wp_unslash( $_POST['general'] ),
2538 WPF()->settings->_general
2539 );
2540 $general['admin_bar'] = array_map( 'intval', (array) wpfval( $_POST['general'], 'admin_bar' ) );
2541 $general['current_theme'] = WPF()->tpl->theme;
2542 wpforo_update_option( 'wpforo_general', $general );
2543 }
2544
2545 WPF()->notice->add( 'Successfully Done', 'success' );
2546 wp_safe_redirect( wp_get_raw_referer() );
2547 exit();
2548 }
2549
2550 /**
2551 * base_slugs_settings_save from submit action
2552 *
2553 * @return void
2554 */
2555 public function slugs_settings_save() {
2556 check_admin_referer( 'wpforo_settings_save_board' );
2557
2558 if( wpfkey( $_POST, 'reset' ) ) {
2559 wpforo_delete_option( 'slugs' );
2560 WPF()->notice->add( 'Successfully Done', 'success' );
2561 } else {
2562 $slugs = wpforo_array_args_cast_and_merge(
2563 array_filter( array_map( 'sanitize_title', wp_unslash( $_POST['slugs'] ) ) ),
2564 WPF()->settings->_slugs
2565 );
2566 $slugs = array_intersect_key( $slugs, WPF()->tpl->templates );
2567 if( $slugs == array_unique( $slugs ) ) {
2568 foreach( $this->generate_option_names( 'slugs' ) as $option_name ) {
2569 wpforo_update_option( $option_name, $slugs );
2570 }
2571 WPF()->notice->add( 'Successfully Done', 'success' );
2572 } else {
2573 WPF()->notice->add( 'Please save "Forum template slugs" uniqueness', 'error' );
2574 }
2575 }
2576
2577 /*wp_safe_redirect( wp_get_raw_referer() );
2578 exit();*/
2579 }
2580
2581 /**
2582 * general_settings_save from submit action
2583 *
2584 * @return void
2585 */
2586 public function board_settings_save() {
2587 check_admin_referer( 'wpforo_settings_save_board' );
2588
2589 if( wpfkey( $_POST, 'reset' ) ) {
2590 wpforo_delete_option( 'board' );
2591 } else {
2592 $board = wpforo_array_args_cast_and_merge( wp_unslash( $_POST['board'] ), WPF()->settings->_board );
2593 foreach( $this->generate_option_names( 'board' ) as $option_name ) {
2594 wpforo_update_option( $option_name, $board );
2595 }
2596 }
2597
2598 wpforo_clean_cache();
2599
2600 WPF()->notice->add( 'Successfully Done', 'success' );
2601 wp_safe_redirect( wp_get_raw_referer() );
2602 exit();
2603 }
2604
2605 /**
2606 * akismet_settings_save from submit action
2607 *
2608 * @return void
2609 */
2610 public function akismet_settings_save() {
2611 check_admin_referer( 'wpforo_settings_save_akismet' );
2612
2613 if( wpfkey( $_POST, 'reset' ) ) {
2614 wpforo_delete_option( 'akismet' );
2615 } else {
2616 $akismet = wpforo_array_args_cast_and_merge( wp_unslash( $_POST['akismet'] ), WPF()->settings->_akismet );
2617 foreach( $this->generate_option_names( 'akismet' ) as $option_name ) {
2618 wpforo_update_option( $option_name, $akismet );
2619 }
2620 }
2621
2622 WPF()->notice->add( 'Successfully Done', 'success' );
2623 wp_safe_redirect( wp_get_raw_referer() );
2624 exit();
2625 }
2626
2627 /**
2628 * antispam_settings_save from submit action
2629 *
2630 * @return void
2631 */
2632 public function antispam_settings_save() {
2633 check_admin_referer( 'wpforo_settings_save_antispam' );
2634
2635 if( wpfkey( $_POST, 'reset' ) ) {
2636 wpforo_delete_option( 'antispam' );
2637 } else {
2638 $antispam = wp_unslash( $_POST['antispam'] );
2639 $antispam['limited_file_ext'] = array_unique(
2640 array_filter(
2641 preg_split(
2642 '#\s*\|\s*|\s*,\s*|\s+#',
2643 trim( sanitize_textarea_field( (string) wpfval( $antispam, 'limited_file_ext' ) ) )
2644 )
2645 )
2646 );
2647 $antispam['exclude_file_ext'] = array_unique(
2648 array_filter(
2649 preg_split(
2650 '#\s*\|\s*|\s*,\s*|\s+#',
2651 trim( sanitize_textarea_field( (string) wpfval( $antispam, 'exclude_file_ext' ) ) )
2652 )
2653 )
2654 );
2655 $_antispam = WPF()->settings->_antispam;
2656 $_antispam['limited_file_ext'] = $_antispam['exclude_file_ext'] = [];
2657 $antispam = wpforo_array_args_cast_and_merge( $antispam, $_antispam );
2658 foreach( $this->generate_option_names( 'antispam' ) as $option_name ) {
2659 wpforo_update_option( $option_name, $antispam );
2660 }
2661 }
2662
2663 WPF()->notice->add( 'Successfully Done', 'success' );
2664 wp_safe_redirect( wp_get_raw_referer() );
2665 exit();
2666 }
2667
2668 /**
2669 * authorization_settings_save after submit action
2670 *
2671 * @return void
2672 */
2673 public function authorization_settings_save() {
2674 check_admin_referer( 'wpforo_settings_save_authorization' );
2675
2676 if( wpfkey( $_POST, 'reset' ) ) {
2677 wpforo_delete_option( 'wpforo_authorization' );
2678 } else {
2679 $authorization = wpforo_array_args_cast_and_merge(
2680 wp_unslash( $_POST['authorization'] ),
2681 WPF()->settings->_authorization
2682 );
2683
2684 if( preg_match( '#^https?://\S+$#iu', (string) $authorization['login_url'] ) ) $authorization['login_url'] = '';
2685 if( preg_match( '#^https?://\S+$#iu', (string) $authorization['register_url'] ) ) $authorization['register_url'] = '';
2686 if( preg_match(
2687 '#^https?://\S+$#iu',
2688 (string) $authorization['lost_password_url']
2689 ) ) {
2690 $authorization['lost_password_url'] = '';
2691 }
2692
2693 if( ! preg_match(
2694 '#^https?://\S+$#iu',
2695 (string) $authorization['redirect_url_after_login']
2696 ) ) {
2697 $authorization['redirect_url_after_login'] = '';
2698 }
2699 if( ! preg_match(
2700 '#^https?://\S+$#iu',
2701 (string) $authorization['redirect_url_after_register']
2702 ) ) {
2703 $authorization['redirect_url_after_register'] = '';
2704 }
2705 if( ! preg_match(
2706 '#^https?://\S+$#iu',
2707 (string) $authorization['redirect_url_after_confirm_sbscrb']
2708 ) ) {
2709 $authorization['redirect_url_after_confirm_sbscrb'] = '';
2710 }
2711
2712 $authorization['login_url'] = esc_url_raw( (string) $authorization['login_url'] );
2713 $authorization['register_url'] = esc_url_raw( (string) $authorization['register_url'] );
2714 $authorization['lost_password_url'] = esc_url_raw( (string) $authorization['lost_password_url'] );
2715 $authorization['redirect_url_after_login'] = esc_url_raw(
2716 (string) $authorization['redirect_url_after_login']
2717 );
2718 $authorization['redirect_url_after_register'] = esc_url_raw(
2719 (string) $authorization['redirect_url_after_register']
2720 );
2721 $authorization['redirect_url_after_confirm_sbscrb'] = esc_url_raw(
2722 (string) $authorization['redirect_url_after_confirm_sbscrb']
2723 );
2724
2725 wpforo_update_option( 'wpforo_authorization', $authorization );
2726 }
2727
2728 WPF()->notice->add( 'Successfully Done', 'success' );
2729 wp_safe_redirect( wp_get_raw_referer() );
2730 exit();
2731 }
2732
2733 /**
2734 * buddypress_settings_save from submit action
2735 *
2736 * @return void
2737 */
2738 public function buddypress_settings_save() {
2739 check_admin_referer( 'wpforo_settings_save_buddypress' );
2740
2741 if( wpfkey( $_POST, 'reset' ) ) {
2742 wpforo_delete_option( 'wpforo_buddypress' );
2743 } else {
2744 $buddypress = wpforo_array_args_cast_and_merge( wp_unslash( $_POST['buddypress'] ), WPF()->settings->_buddypress );
2745 wpforo_update_option( 'wpforo_buddypress', $buddypress );
2746 }
2747
2748 WPF()->notice->add( 'Successfully Done', 'success' );
2749 wp_safe_redirect( wp_get_raw_referer() );
2750 exit();
2751 }
2752
2753 /**
2754 * components_settings_save from submit action
2755 *
2756 * @return void
2757 */
2758 public function components_settings_save() {
2759 check_admin_referer( 'wpforo_settings_save_components' );
2760
2761 if( wpfkey( $_POST, 'reset' ) ) {
2762 wpforo_delete_option( 'components' );
2763 } else {
2764 $components = wpforo_array_args_cast_and_merge( wp_unslash( $_POST['components'] ), WPF()->settings->_components );
2765 foreach( $this->generate_option_names( 'components' ) as $option_name ) {
2766 wpforo_update_option( $option_name, $components );
2767 }
2768 }
2769
2770 WPF()->notice->add( 'Successfully Done', 'success' );
2771 wp_safe_redirect( wp_get_raw_referer() );
2772 exit();
2773 }
2774
2775 /**
2776 * email_settings_save from submit action
2777 *
2778 * @return void
2779 */
2780 public function email_settings_save() {
2781 check_admin_referer( 'wpforo_settings_save_email' );
2782
2783 if( wpfkey( $_POST, 'reset' ) ) {
2784 wpforo_delete_option( 'wpforo_email' );
2785 } else {
2786 $email = wp_unslash( $_POST['email'] );
2787 $email['admin_emails'] = sanitize_text_field( (string) $email['admin_emails'] );
2788 $email['admin_emails'] = array_map( 'sanitize_email', preg_split( '#\s*,\s*#u', trim( $email['admin_emails'] ) ) );
2789 $email['admin_emails'] = array_filter( $email['admin_emails'] );
2790 if( ! $email['admin_emails'] ) $email['admin_emails'] = (array) get_option( 'admin_email' );
2791 $email = wpforo_array_args_cast_and_merge( $email, WPF()->settings->_email );
2792
2793 $email['from_name'] = sanitize_text_field( $email['from_name'] );
2794 $email['from_email'] = sanitize_text_field( $email['from_email'] );
2795 $email['report_email_subject'] = sanitize_text_field( $email['report_email_subject'] );
2796 $email['report_email_message'] = wpforo_kses( $email['report_email_message'], 'email' );
2797 $email['wp_new_user_notification_email_admin_subject'] = sanitize_text_field(
2798 $email['wp_new_user_notification_email_admin_subject']
2799 );
2800 $email['wp_new_user_notification_email_admin_message'] = wpforo_kses(
2801 $email['wp_new_user_notification_email_admin_message'],
2802 'email'
2803 );
2804 $email['wp_new_user_notification_email_subject'] = sanitize_text_field(
2805 $email['wp_new_user_notification_email_subject']
2806 );
2807 $email['wp_new_user_notification_email_message'] = wpforo_kses(
2808 $email['wp_new_user_notification_email_message'],
2809 'email'
2810 );
2811 $email['reset_password_email_message'] = wpforo_kses(
2812 $email['reset_password_email_message'],
2813 'email'
2814 );
2815 $email['after_user_approve_email_subject'] = sanitize_text_field(
2816 $email['after_user_approve_email_subject']
2817 );
2818 $email['after_user_approve_email_message'] = wpforo_kses(
2819 $email['after_user_approve_email_message'],
2820 'email'
2821 );
2822
2823 wpforo_update_option( 'wpforo_email', $email );
2824 }
2825
2826 WPF()->notice->add( 'Successfully Done', 'success' );
2827 wp_safe_redirect( wp_get_raw_referer() );
2828 exit();
2829 }
2830
2831 /**
2832 * forums_settings_save from submit action
2833 *
2834 * @return void
2835 */
2836 public function forums_settings_save() {
2837 check_admin_referer( 'wpforo_settings_save_forums' );
2838
2839 if( wpfkey( $_POST, 'reset' ) ) {
2840 wpforo_delete_option( 'forums' );
2841 } else {
2842 $forums = wpforo_array_args_cast_and_merge( wp_unslash( $_POST['forums'] ), WPF()->settings->_forums );
2843 foreach( $this->generate_option_names( 'forums' ) as $option_name ) {
2844 wpforo_update_option( $option_name, $forums );
2845 }
2846 }
2847
2848 WPF()->notice->add( 'Successfully Done', 'success' );
2849 wp_safe_redirect( wp_get_raw_referer() );
2850 exit();
2851 }
2852
2853 /**
2854 * logging_settings_save from submit action
2855 *
2856 * @return void
2857 */
2858 public function logging_settings_save() {
2859 check_admin_referer( 'wpforo_settings_save_logging' );
2860
2861 if( wpfkey( $_POST, 'reset' ) ) {
2862 wpforo_delete_option( 'logging' );
2863 } else {
2864 $logging = wpforo_array_args_cast_and_merge( wp_unslash( $_POST['logging'] ), WPF()->settings->_logging );
2865 foreach( $this->generate_option_names( 'logging' ) as $option_name ) {
2866 wpforo_update_option( $option_name, $logging );
2867 }
2868 }
2869
2870 WPF()->notice->add( 'Successfully Done', 'success' );
2871 wp_safe_redirect( wp_get_raw_referer() );
2872 exit();
2873 }
2874
2875 /**
2876 * activity_settings_save from submit action
2877 *
2878 * @return void
2879 */
2880 public function activity_settings_save() {
2881 check_admin_referer( 'wpforo_settings_save_activity' );
2882
2883 if( wpfkey( $_POST, 'reset' ) ) {
2884 wpforo_delete_option( 'activity' );
2885 // Unschedule cleanup cron when settings are reset
2886 WPF()->activity->unschedule_cleanup();
2887 } else {
2888 $activity = wpforo_array_args_cast_and_merge( wp_unslash( $_POST['activity'] ), WPF()->settings->_activity );
2889 $activity['enabled_types'] = array_map( 'sanitize_text_field', (array) wpfval( $_POST['activity'], 'enabled_types' ) );
2890 foreach( $this->generate_option_names( 'activity' ) as $option_name ) {
2891 wpforo_update_option( $option_name, $activity );
2892 }
2893
2894 // Handle activity cleanup cron based on retention_days setting
2895 $retention_days = isset( $activity['retention_days'] ) ? (int) $activity['retention_days'] : 365;
2896 if( $retention_days > 0 ) {
2897 WPF()->activity->schedule_cleanup();
2898 } else {
2899 WPF()->activity->unschedule_cleanup();
2900 }
2901 }
2902
2903 WPF()->notice->add( 'Successfully Done', 'success' );
2904 wp_safe_redirect( wp_get_raw_referer() );
2905 exit();
2906 }
2907
2908 /**
2909 * members_settings_save from submit action
2910 *
2911 * @return void
2912 */
2913 public function members_settings_save() {
2914 check_admin_referer( 'wpforo_settings_save_members' );
2915
2916 if( wpfkey( $_POST, 'reset' ) ) {
2917 wpforo_delete_option( 'wpforo_members' );
2918 } else {
2919 $members = wpforo_array_args_cast_and_merge( wp_unslash( $_POST['members'] ), WPF()->settings->_members );
2920 wpforo_update_option( 'wpforo_members', $members );
2921 }
2922
2923 WPF()->notice->add( 'Successfully Done', 'success' );
2924 wp_safe_redirect( wp_get_raw_referer() );
2925 exit();
2926 }
2927
2928 /**
2929 * notifications_settings_save from submit action
2930 *
2931 * @return void
2932 */
2933 public function notifications_settings_save() {
2934 check_admin_referer( 'wpforo_settings_save_notifications' );
2935
2936 if( wpfkey( $_POST, 'reset' ) ) {
2937 wpforo_delete_option( 'notifications' );
2938 } else {
2939 $notifications = wpforo_array_args_cast_and_merge(
2940 wp_unslash( $_POST['notifications'] ),
2941 WPF()->settings->_notifications
2942 );
2943 foreach( $this->generate_option_names( 'notifications' ) as $option_name ) {
2944 wpforo_update_option( $option_name, $notifications );
2945 }
2946 }
2947
2948 WPF()->notice->add( 'Successfully Done', 'success' );
2949 wp_safe_redirect( wp_get_raw_referer() );
2950 exit();
2951 }
2952
2953 /**
2954 * posting_settings_save from submit action
2955 *
2956 * @return void
2957 */
2958 public function posting_settings_save() {
2959 check_admin_referer( 'wpforo_settings_save_posting' );
2960
2961 if( wpfkey( $_POST, 'reset' ) ) {
2962 wpforo_delete_option( 'posting' );
2963 } else {
2964 $posting = wpforo_array_args_cast_and_merge(
2965 wp_unslash( $_POST['posting'] ),
2966 WPF()->settings->_posting
2967 );
2968 $posting['max_upload_size'] = $posting['max_upload_size'] * 1024 * 1024;
2969 $posting['edit_own_topic_durr'] = $posting['edit_own_topic_durr'] * 60;
2970 $posting['delete_own_topic_durr'] = $posting['delete_own_topic_durr'] * 60;
2971 $posting['edit_own_post_durr'] = $posting['edit_own_post_durr'] * 60;
2972 $posting['delete_own_post_durr'] = $posting['delete_own_post_durr'] * 60;
2973 $posting['extra_html_tags'] = sanitize_textarea_field( $posting['extra_html_tags'] );
2974 foreach( $this->generate_option_names( 'posting' ) as $option_name ) {
2975 wpforo_update_option( $option_name, $posting );
2976 }
2977 }
2978
2979 WPF()->notice->add( 'Successfully Done', 'success' );
2980 wp_safe_redirect( wp_get_raw_referer() );
2981 exit();
2982 }
2983
2984 /**
2985 * profiles_settings_save from submit action
2986 *
2987 * @return void
2988 */
2989 public function profiles_settings_save() {
2990 check_admin_referer( 'wpforo_settings_save_profiles' );
2991
2992 if( wpfkey( $_POST, 'reset' ) ) {
2993 wpforo_delete_option( 'wpforo_profiles' );
2994 } else {
2995 $profiles = wpforo_array_args_cast_and_merge(
2996 wp_unslash( $_POST['profiles'] ),
2997 WPF()->settings->_profiles
2998 );
2999 $profiles['default_cover'] = WPF()->settings->profiles['default_cover'];
3000 $profiles['default_title'] = sanitize_text_field( $profiles['default_title'] );
3001 $profiles['online_status_timeout'] = $profiles['online_status_timeout'] * 60;
3002 $profiles['title_groupids'] = array_map( 'intval', (array) wpfval( $_POST['profiles'], 'title_groupids' ) );
3003 $profiles['title_secondary_groupids'] = array_map(
3004 'intval',
3005 (array) wpfval( $_POST['profiles'], 'title_secondary_groupids' )
3006 );
3007 wpforo_update_option( 'wpforo_profiles', $profiles );
3008 }
3009
3010 WPF()->notice->add( 'Successfully Done', 'success' );
3011 wp_safe_redirect( wp_get_raw_referer() );
3012 exit();
3013 }
3014
3015 /**
3016 * rating_settings_save from submit action
3017 *
3018 * @return void
3019 */
3020 public function rating_settings_save() {
3021 check_admin_referer( 'wpforo_settings_save_rating' );
3022
3023 if( wpfkey( $_POST, 'reset' ) ) {
3024 wpforo_delete_option( 'wpforo_rating' );
3025 } else {
3026 $rating = wpforo_array_args_cast_and_merge(
3027 wp_unslash( $_POST['rating'] ),
3028 WPF()->settings->_rating
3029 );
3030 $rating['rating_title_ug'] = array_map( 'intval', (array) wpfval( $_POST['rating'], 'rating_title_ug' ) );
3031 $rating['rating_badge_ug'] = array_map( 'intval', (array) wpfval( $_POST['rating'], 'rating_badge_ug' ) );
3032 wpforo_update_option( 'wpforo_rating', $rating );
3033 }
3034
3035 WPF()->notice->add( 'Successfully Done', 'success' );
3036 wp_safe_redirect( wp_get_raw_referer() );
3037 exit();
3038 }
3039
3040 /**
3041 * recaptcha_settings_save from submit action
3042 *
3043 * @return void
3044 */
3045 public function recaptcha_settings_save() {
3046 check_admin_referer( 'wpforo_settings_save_recaptcha' );
3047
3048 if( wpfkey( $_POST, 'reset' ) ) {
3049 wpforo_delete_option( 'wpforo_recaptcha' );
3050 } else {
3051 $recaptcha = wpforo_array_args_cast_and_merge(
3052 wp_unslash( $_POST['recaptcha'] ),
3053 WPF()->settings->_recaptcha
3054 );
3055 $recaptcha['site_key'] = sanitize_text_field( $recaptcha['site_key'] );
3056 $recaptcha['secret_key'] = sanitize_text_field( $recaptcha['secret_key'] );
3057 wpforo_update_option( 'wpforo_recaptcha', $recaptcha );
3058 }
3059
3060 WPF()->notice->add( 'Successfully Done', 'success' );
3061 wp_safe_redirect( wp_get_raw_referer() );
3062 exit();
3063 }
3064
3065 /**
3066 * rss_settings_save from submit action
3067 *
3068 * @return void
3069 */
3070 public function rss_settings_save() {
3071 check_admin_referer( 'wpforo_settings_save_rss' );
3072
3073 if( wpfkey( $_POST, 'reset' ) ) {
3074 wpforo_delete_option( 'rss' );
3075 } else {
3076 $rss = wpforo_array_args_cast_and_merge( wp_unslash( $_POST['rss'] ), WPF()->settings->_rss );
3077 foreach( $this->generate_option_names( 'rss' ) as $option_name ) {
3078 wpforo_update_option( $option_name, $rss );
3079 }
3080 }
3081
3082 WPF()->notice->add( 'Successfully Done', 'success' );
3083 wp_safe_redirect( wp_get_raw_referer() );
3084 exit();
3085 }
3086
3087 /**
3088 * seo_settings_save from submit action
3089 *
3090 * @return void
3091 */
3092 public function seo_settings_save() {
3093 check_admin_referer( 'wpforo_settings_save_seo' );
3094
3095 if( wpfkey( $_POST, 'reset' ) ) {
3096 wpforo_delete_option( 'seo' );
3097 } else {
3098 $seo = wp_unslash( $_POST['seo'] );
3099 $seo['dofollow'] = array_filter(
3100 preg_split( '#\s+#', sanitize_textarea_field( (string) wpfval( $seo, 'dofollow' ) ) )
3101 );
3102 $seo['noindex'] = array_filter(
3103 preg_split( '#\s+#', sanitize_textarea_field( (string) wpfval( $seo, 'noindex' ) ) )
3104 );
3105 $seo['noindex'] = array_map( 'esc_url_raw', $seo['noindex'] );
3106 $seo = wpforo_array_args_cast_and_merge( $seo, WPF()->settings->_seo );
3107 foreach( $this->generate_option_names( 'seo' ) as $option_name ) {
3108 wpforo_update_option( $option_name, $seo );
3109 }
3110 wpforo_clean_cache( 'forum-soft' );
3111 }
3112
3113 WPF()->notice->add( 'Successfully Done', 'success' );
3114 wp_safe_redirect( wp_get_raw_referer() );
3115 exit();
3116 }
3117
3118 /**
3119 * social_settings_save from submit action
3120 *
3121 * @return void
3122 */
3123 public function social_settings_save() {
3124 check_admin_referer( 'wpforo_settings_save_social' );
3125
3126 if( wpfkey( $_POST, 'reset' ) ) {
3127 wpforo_delete_option( 'social' );
3128 } else {
3129 $social = wpforo_array_args_cast_and_merge( wp_unslash( $_POST['social'] ), WPF()->settings->_social );
3130 $social['sb'] = wpforo_array_args_cast_and_merge(
3131 (array) wpfval( $_POST['social'], 'sb' ),
3132 array_map( '__return_false', WPF()->settings->_social['sb'] )
3133 );
3134 $social['sb_location'] = wpforo_array_args_cast_and_merge(
3135 (array) wpfval( $_POST['social'], 'sb_location' ),
3136 array_map(
3137 '__return_false',
3138 WPF()->settings->_social['sb_location']
3139 )
3140 );
3141 foreach( $this->generate_option_names( 'social' ) as $option_name ) {
3142 wpforo_update_option( $option_name, $social );
3143 }
3144 }
3145
3146 WPF()->notice->add( 'Successfully Done', 'success' );
3147 wp_safe_redirect( wp_get_raw_referer() );
3148 exit();
3149 }
3150
3151 /**
3152 * styles_settings_save from submit action
3153 *
3154 * @return void
3155 */
3156 public function styles_settings_save() {
3157 check_admin_referer( 'wpforo_settings_save_styles' );
3158
3159 if( wpfkey( $_POST, 'reset' ) ) {
3160 wpforo_delete_option( 'styles_' . WPF()->tpl->theme );
3161 } else {
3162 $styles = wpforo_array_args_cast_and_merge( wp_unslash( $_POST['styles'] ), WPF()->settings->_styles );
3163 $styles['custom_css'] = sanitize_textarea_field( $styles['custom_css'] );
3164 foreach( $this->generate_option_names( 'styles_' . WPF()->tpl->theme ) as $option_name ) {
3165 wpforo_update_option( $option_name, $styles );
3166 }
3167 }
3168
3169 WPF()->notice->add( 'Successfully Done', 'success' );
3170 wp_safe_redirect( wp_get_raw_referer() );
3171 exit();
3172 }
3173
3174 /**
3175 * tags_settings_save from submit action
3176 *
3177 * @return void
3178 */
3179 public function tags_settings_save() {
3180 check_admin_referer( 'wpforo_settings_save_tags' );
3181
3182 if( wpfkey( $_POST, 'reset' ) ) {
3183 wpforo_delete_option( 'tags' );
3184 } else {
3185 $tags = wpforo_array_args_cast_and_merge( wp_unslash( $_POST['tags'] ), WPF()->settings->_tags );
3186 foreach( $this->generate_option_names( 'tags' ) as $option_name ) {
3187 wpforo_update_option( $option_name, $tags );
3188 }
3189 }
3190
3191 WPF()->notice->add( 'Successfully Done', 'success' );
3192 wp_safe_redirect( wp_get_raw_referer() );
3193 exit();
3194 }
3195
3196 /**
3197 * topics_settings_save from submit action
3198 *
3199 * @return void
3200 */
3201 public function topics_settings_save() {
3202 check_admin_referer( 'wpforo_settings_save_topics' );
3203
3204 if( wpfkey( $_POST, 'reset' ) ) {
3205 wpforo_delete_option( 'topics' );
3206 } else {
3207 $topics = wpforo_array_args_cast_and_merge( wp_unslash( $_POST['topics'] ), WPF()->settings->_topics );
3208 foreach( $this->generate_option_names( 'topics' ) as $option_name ) {
3209 wpforo_update_option( $option_name, $topics );
3210 }
3211 }
3212
3213 WPF()->notice->add( 'Successfully Done', 'success' );
3214 wp_safe_redirect( wp_get_raw_referer() );
3215 exit();
3216 }
3217
3218 /**
3219 * um_settings_save from submit action
3220 *
3221 * @return void
3222 */
3223 public function um_settings_save() {
3224 check_admin_referer( 'wpforo_settings_save_um' );
3225
3226 if( wpfkey( $_POST, 'reset' ) ) {
3227 wpforo_delete_option( 'wpforo_um' );
3228 } else {
3229 $um = wpforo_array_args_cast_and_merge( wp_unslash( $_POST['um'] ), WPF()->settings->_um );
3230 wpforo_update_option( 'wpforo_um', $um );
3231 }
3232
3233 WPF()->notice->add( 'Successfully Done', 'success' );
3234 wp_safe_redirect( wp_get_raw_referer() );
3235 exit();
3236 }
3237
3238 /**
3239 * um_settings_save from submit action
3240 *
3241 * @return void
3242 */
3243 public function legal_settings_save() {
3244 check_admin_referer( 'wpforo_settings_save_legal' );
3245
3246 if( wpfkey( $_POST, 'reset' ) ) {
3247 wpforo_delete_option( 'wpforo_legal' );
3248 } else {
3249 $legal = wpforo_array_args_cast_and_merge( wp_unslash( $_POST['legal'] ), WPF()->settings->_legal );
3250 wpforo_update_option( 'wpforo_legal', $legal );
3251 }
3252
3253 WPF()->notice->add( 'Successfully Done', 'success' );
3254 wp_safe_redirect( wp_get_raw_referer() );
3255 exit();
3256 }
3257
3258 /**
3259 * ai_settings_save from submit action
3260 *
3261 * @return void
3262 */
3263 public function ai_settings_save() {
3264 check_admin_referer( 'wpforo_settings_save_ai' );
3265
3266 if( wpfkey( $_POST, 'reset' ) ) {
3267 wpforo_delete_option( 'ai' );
3268 } else {
3269 $post_ai = wp_unslash( $_POST['ai'] );
3270 $ai = wpforo_array_args_cast_and_merge( $post_ai, WPF()->settings->_ai );
3271 // Ensure max_results is within bounds
3272 $ai['search_max_results'] = max( 1, min( 10, intval( $ai['search_max_results'] ) ) );
3273 // Fix checkbox array fields: wpforo_array_args_cast_and_merge re-adds default
3274 // values for missing numeric keys, so we must override with the actual POST data.
3275 // When all checkboxes are unchecked the key is absent from POST, meaning empty array.
3276 $ai['chatbot_allowed_groups'] = array_map( 'intval', (array) wpfval( $post_ai, 'chatbot_allowed_groups' ) );
3277 $ai['bot_reply_includes'] = array_map( 'sanitize_text_field', (array) wpfval( $post_ai, 'bot_reply_includes' ) );
3278 // Filter out Guest usergroup (groupid 4) - guests cannot use chatbot (login required)
3279 $ai['chatbot_allowed_groups'] = array_values( array_filter( $ai['chatbot_allowed_groups'], function( $gid ) {
3280 return $gid !== 4;
3281 } ) );
3282 foreach( $this->generate_option_names( 'ai' ) as $option_name ) {
3283 wpforo_update_option( $option_name, $ai );
3284 }
3285 }
3286
3287 WPF()->notice->add( 'Successfully Done', 'success' );
3288 wp_safe_redirect( wp_get_raw_referer() );
3289 exit();
3290 }
3291
3292 public function settings_export() {
3293 check_admin_referer( 'wpforo_settings_export' );
3294
3295 if( $groups = (array) wpfval( $_POST, 'groups' ) ) {
3296 WPF()->settings->export( $groups );
3297 } else {
3298 WPF()->notice->add( 'Invalid groups: One or more checkboxes must be selected.', 'error' );
3299 }
3300
3301 wp_safe_redirect( wp_get_raw_referer() );
3302 exit();
3303 }
3304
3305 public function settings_import() {
3306 check_admin_referer( 'wpforo_settings_import' );
3307
3308 if( wpfval( $_FILES, 'wpfsimpjson', 'tmp_name' ) && wpfval( $_FILES, 'wpfsimpjson', 'type' ) === 'application/json' ) {
3309 $json = file_get_contents( $_FILES['wpfsimpjson']['tmp_name'] );
3310 if( $json ) {
3311 json_decode( $json );
3312 if( json_last_error() == JSON_ERROR_NONE ) {
3313 if( ( $groups = (array) wpfval( $_POST, 'groups' ) ) ) {
3314 WPF()->settings->import( $json, $groups );
3315 WPF()->notice->add( 'Successfully Done', 'success' );
3316 wp_safe_redirect( wp_get_raw_referer() );
3317 exit();
3318 } else {
3319 WPF()->notice->add( 'Invalid groups: One or more checkboxes must be selected.', 'error' );
3320 wp_safe_redirect( wp_get_raw_referer() );
3321 exit();
3322 }
3323 }
3324 }
3325 }
3326
3327 WPF()->notice->add( 'You should choose the right JSON file.', 'error' );
3328 wp_safe_redirect( wp_get_raw_referer() );
3329 exit();
3330 }
3331
3332 /**
3333 * @return array with all boardids where need to save options
3334 */
3335 private function get_boardids_to_be_saved() {
3336 $boardids = (array) WPF()->board->get_current( 'boardid' );
3337 if( wpfkey( $_POST, 'save_for_all' ) ) {
3338 $boardids = array_unique( array_merge( $boardids, WPF()->board->get_active_boardids() ) );
3339 }
3340
3341 return $boardids;
3342 }
3343
3344 /**
3345 * @param string $basename
3346 *
3347 * @return string[]
3348 */
3349 public function generate_option_names( $basename ) {
3350 return array_map(
3351 function( $boardid ) use ( $basename ) {
3352 return 'wpforo_' . ( $boardid ? $boardid . '_' : '' ) . $basename;
3353 },
3354 $this->get_boardids_to_be_saved()
3355 );
3356 }
3357
3358 /**
3359 * uninstall all wpforo
3360 */
3361 public function uninstall() {
3362 check_admin_referer( 'wpforo_uninstall' );
3363 if( current_user_can( 'administrator' ) && current_user_can( 'activate_plugins' ) ) {
3364 wpforo_uninstall();
3365 }
3366 wp_safe_redirect( wp_get_referer() );
3367 exit();
3368 }
3369
3370 /**
3371 * Store checkout mapping for Freemius webhook lookup
3372 *
3373 * This is primarily a validation step before opening checkout.
3374 * The actual tenant lookup in the webhook will be done by matching
3375 * the WordPress site URL from the Freemius install object.
3376 */
3377 public function ai_store_checkout_mapping() {
3378 // Verify nonce
3379 check_ajax_referer( 'wpforo_ai_features_nonce', 'nonce' );
3380
3381 // Check permissions
3382 if ( ! wpforo_current_user_is( 'admin' ) && ! WPF()->usergroup->can( 'ms' ) ) {
3383 wp_send_json_error( [ 'message' => 'Insufficient permissions' ], 403 );
3384 }
3385
3386 // Get parameters
3387 $email = isset( $_POST['email'] ) ? sanitize_email( $_POST['email'] ) : '';
3388 $tenant_id = isset( $_POST['tenant_id'] ) ? sanitize_text_field( $_POST['tenant_id'] ) : '';
3389
3390 if ( empty( $email ) || empty( $tenant_id ) ) {
3391 wp_send_json_error( [ 'message' => 'Email and tenant_id are required' ], 400 );
3392 }
3393
3394 // The webhook will look up tenant_id by matching the WordPress site URL
3395 // No need to store mapping here - just validate and proceed
3396 wp_send_json_success( [
3397 'message' => 'Checkout ready',
3398 'email' => $email,
3399 'tenant_id' => $tenant_id,
3400 'site_url' => home_url()
3401 ] );
3402 }
3403
3404 /**
3405 * AJAX handler for loading legal documents (Terms of Service, Privacy Policy)
3406 * Used by the AI Features settings page modal
3407 */
3408 public function ai_get_legal_document() {
3409 // Verify nonce
3410 check_ajax_referer( 'wpforo_ai_features_nonce', 'nonce' );
3411
3412 // Check permissions - admin only
3413 if ( ! wpforo_current_user_is( 'admin' ) && ! WPF()->usergroup->can( 'ms' ) ) {
3414 wp_send_json_error( [ 'message' => 'Insufficient permissions' ], 403 );
3415 }
3416
3417 // Get document type
3418 $document = isset( $_POST['document'] ) ? sanitize_text_field( $_POST['document'] ) : '';
3419
3420 // Map document type to file
3421 $document_files = [
3422 'terms' => 'terms-of-service.php',
3423 'privacy' => 'privacy-policy.php',
3424 ];
3425
3426 if ( empty( $document ) || ! isset( $document_files[ $document ] ) ) {
3427 wp_send_json_error( [ 'message' => 'Invalid document type' ], 400 );
3428 }
3429
3430 // Build file path
3431 $file_path = WPFORO_DIR . '/admin/pages/legal/' . $document_files[ $document ];
3432
3433 if ( ! file_exists( $file_path ) ) {
3434 wp_send_json_error( [ 'message' => 'Document not found' ], 404 );
3435 }
3436
3437 // Capture the output of the PHP file
3438 ob_start();
3439 include $file_path;
3440 $content = ob_get_clean();
3441
3442 wp_send_json_success( [
3443 'content' => $content,
3444 'title' => $document === 'terms' ? __( 'Terms of Service', 'wpforo' ) : __( 'Privacy Policy', 'wpforo' ),
3445 ] );
3446 }
3447 }
3448