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

Members.php in wpForo Forum 2.4.6, at classes/Members.php

4,266 lines 137.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace wpforo\classes;
4
5 use stdClass;
6 use WP_Error;
7 use wpforo\admin\listtables\Members as MembersListTable;
8 use wpforo\modules\reactions\Reactions;
9
10 // Exit if accessed directly
11 if( ! defined( 'ABSPATH' ) ) exit;
12
13
14 class Members {
15 private $default;
16 private $fields;
17 private $countries;
18 private $timezones;
19 public $login_min_length;
20 public $login_max_length;
21 public $pass_min_length;
22 public $pass_max_length;
23 public $list_table;
24 private $touched_userids = [];
25
26 function __construct() {
27 $this->init_defaults();
28 $this->init_hooks();
29 }
30
31 private function init_defaults() {
32 $this->login_min_length = 3;
33 $this->login_max_length = 30;
34 $this->pass_min_length = 6;
35 $this->pass_max_length = 20;
36 $this->default = new stdClass();
37 $this->default->member = [
38 'user_login' => '',
39 'user_nicename' => '',
40 'user_email' => '',
41 'user_url' => '',
42 'user_registered' => '0000-00-00 00:00:00',
43 'user_activation_key' => '',
44 'display_name' => '',
45
46 'first_name' => '',
47 'last_name' => '',
48
49 'userid' => 0,
50 'title' => '',
51 'groupid' => 0,
52 'secondary_groupids' => [],
53 'groupids' => [],
54 'avatar' => '',
55 'cover' => '',
56
57 'posts' => 0,
58 'topics' => 0,
59 'questions' => 0,
60 'answers' => 0,
61 'comments' => 0,
62 'reactions_in' => [],
63 'reactions_out' => [],
64 'points' => 0,
65 'custom_points' => 0,
66
67 'online_time' => 0,
68 'timezone' => '',
69 'location' => '',
70 'signature' => '',
71 'occupation' => '',
72 'about' => '',
73 'status' => 'inactive',
74 'is_email_confirmed' => 0,
75 'is_mention_muted' => 0,
76
77 'fields' => [],
78
79 'group_name' => '',
80 'group_color' => '',
81
82 'profile_url' => '',
83 'dname' => '',
84 'rating' => [
85 'level' => 0,
86 'percent' => 0,
87 'color' => $this->rating( 0, 'color' ),
88 'title' => $this->rating( 0, 'title' ),
89 'badge' => $this->rating( 0, 'icon' ),
90 ],
91 ];
92 $this->default->action = [
93 'label' => 'Action Button',
94 'ico' => '<svg height="12" width="12" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M224 256A128 128 0 1 0 224 0a128 128 0 1 0 0 256zm-45.7 48C79.8 304 0 383.8 0 482.3C0 498.7 13.3 512 29.7 512H418.3c16.4 0 29.7-13.3 29.7-29.7C448 383.8 368.2 304 269.7 304H178.3z"/></svg>',
95 'callback_for_can' => '',
96 'callback_for_get_url' => '',
97 'data' => [],
98 'confirm_msg' => '',
99 ];
100
101 $this->login_min_length = apply_filters( 'wpforo_login_min_length', $this->login_min_length );
102 $this->login_max_length = apply_filters( 'wpforo_login_max_length', $this->login_max_length );
103 $this->pass_min_length = apply_filters( 'wpforo_pass_min_length', $this->pass_min_length );
104 $this->pass_max_length = apply_filters( 'wpforo_pass_max_length', $this->pass_max_length );
105 }
106
107 private function init_hooks() {
108 if( is_admin() ) add_action( 'wpforo_after_init', [ $this, 'init_list_table' ] );
109 add_action( 'delete_user_form', [ $this, 'show_delete_form' ], 10, 2 );
110 add_action( 'register_new_user', [ $this, 'after_register_new_user' ] );
111 add_action( 'after_password_reset', [ $this, 'after_password_reset' ] );
112 add_action( 'wp_login', [ $this, 'wp_login' ], 10, 2 );
113 add_action( 'set_current_user', [ $this, 'init_current_user' ] );
114 add_action( 'clean_user_cache', function( $userid ) { $this->reset( $userid ); } );
115 add_action( 'init', function() { if( ! WPF()->current_userid ) $this->init_current_user(); } );
116 add_action( 'set_logged_in_cookie', function( $logged_in_cookie ) {
117 $cookie = explode( '|', $logged_in_cookie );
118 WPF()->session_token = (string) wpfval( $cookie, 2 );
119 } );
120
121 add_action( 'wpforo_after_add_topic', [ $this, 'after_add_topic' ] );
122 add_action( 'wpforo_after_delete_topic', [ $this, 'after_delete_topic' ] );
123 add_action( 'wpforo_topic_status_update', [ $this, 'after_topic_status_update' ] );
124 add_action( 'wpforo_before_merge_topic', [ $this, 'before_merge_topic' ], 10, 3 );
125 add_action( 'wpforo_after_merge_topic', [ $this, 'after_merge_topic' ] );
126 add_action( 'wpforo_after_move_topic', [ $this, 'after_move_topic' ] );
127
128 add_action( 'wpforo_after_add_post', [ $this, 'after_add_post' ] );
129 add_action( 'wpforo_after_delete_post', [ $this, 'after_delete_post' ] );
130 add_action( 'wpforo_post_status_update', [ $this, 'after_post_status_update' ] );
131
132 add_action( 'wpforo_after_add_reaction', [ $this, 'after_add_reaction' ] );
133 add_action( 'wpforo_after_edit_reaction', [ $this, 'after_edit_reaction' ], 10, 2 );
134 add_action( 'wpforo_before_delete_reaction', [ $this, 'before_delete_reaction' ], 10, 2 );
135 add_action( 'wpforo_after_delete_reaction', [ $this, 'after_delete_reaction' ] );
136
137 add_action( 'wpforo_after_delete_user', [ $this, 'after_delete_user' ], 11, 2 );
138
139 add_action( 'wpforo_after_activate_user', [ $this, 'after_activate_user' ] );
140
141 add_action( 'wpforo_after_front_delete_user', [ $this, 'after_front_delete_user' ] );
142 }
143
144 public function init_list_table() {
145 if( wpfval( $_GET, 'page' ) === wpforo_prefix_slug( 'members' ) ) {
146 $this->list_table = new MembersListTable();
147 $this->list_table->prepare_items();
148 }
149 }
150
151 /**
152 * @param array $member
153 *
154 * @return array
155 */
156 public function decode( $member ) {
157 $reaction_types = array_map( '__return_zero', array_flip( Reactions::get_type_list() ) );
158 $member = array_merge( $this->default->member, (array) $member );
159 $member['userid'] = wpforo_bigintval( $member['userid'] );
160 $member['first_name'] = trim( strip_tags( (string) $member['first_name'] ) );
161 $member['last_name'] = trim( strip_tags( (string) $member['last_name'] ) );
162 $member['groupid'] = intval( $member['groupid'] );
163 $member['secondary_groupids'] = array_map(
164 'intval',
165 (array) ( is_scalar( $member['secondary_groupids'] ) ? explode(
166 ',',
167 $member['secondary_groupids']
168 ) : $member['secondary_groupids'] )
169 );
170 $member['secondary_groupids'] = array_diff( $member['secondary_groupids'], (array) $member['groupid'] );
171 $member['groupids'] = array_unique(
172 array_filter( array_merge( (array) $member['groupid'], $member['secondary_groupids'] ) )
173 );
174 $member['avatar'] = preg_replace( '#^https?://#iu', '//', esc_url( (string) $member['avatar'] ) );
175 $member['cover'] = preg_replace( '#^https?://#iu', '//', esc_url( (string) $member['cover'] ) );
176 $member['topics'] = intval( $member['topics'] );
177 $member['posts'] = intval( $member['posts'] );
178 $member['questions'] = intval( $member['questions'] );
179 $member['answers'] = intval( $member['answers'] );
180 $member['comments'] = intval( $member['comments'] );
181
182 sort( $member['secondary_groupids'], SORT_NUMERIC );
183 sort( $member['groupids'], SORT_NUMERIC );
184
185 $member['reactions_in'] = array_map(
186 'intval',
187 (array) ( wpforo_is_json( $member['reactions_in'] ) ? json_decode(
188 $member['reactions_in'],
189 true
190 ) : $member['reactions_in'] )
191 );
192 $member['reactions_in']['__ALL__'] = 0;
193 foreach( $member['reactions_in'] as $r ) $member['reactions_in']['__ALL__'] += $r;
194 $member['reactions_in'] = array_merge( $reaction_types, $member['reactions_in'] );
195
196 $member['reactions_out'] = array_map(
197 'intval',
198 (array) ( wpforo_is_json( $member['reactions_out'] ) ? json_decode(
199 $member['reactions_out'],
200 true
201 ) : $member['reactions_out'] )
202 );
203 $member['reactions_out']['__ALL__'] = 0;
204 foreach( $member['reactions_out'] as $r ) $member['reactions_out']['__ALL__'] += $r;
205 $member['reactions_out'] = array_merge( $reaction_types, $member['reactions_out'] );
206
207 $member['custom_points'] = floatval( $member['custom_points'] );
208 $member['points'] = $member['custom_points'] ?: $this->calc_points( $member );
209 $member['rating'] = $this->calc_rating( $member['points'] );
210
211 $member['online_time'] = (int) ( $member['online_time'] && ! is_numeric(
212 $member['online_time']
213 ) ? strtotime(
214 (string) $member['online_time'] . ' GMT'
215 ) : $member['online_time'] );
216 $member['is_email_confirmed'] = (bool) (int) $member['is_email_confirmed'];
217 $member['is_mention_muted'] = (bool) (int) $member['is_mention_muted'];
218
219 $member['title'] = trim( strip_tags( (string) $member['title'] ) );
220 $member['profile_url'] = $this->get_profile_url( $member );
221 $member['dname'] = wpforo_user_dname( $member );
222
223 $member['fields'] = (array) ( wpforo_is_json( $member['fields'] ) ? json_decode(
224 $member['fields'],
225 true
226 ) : $member['fields'] );
227 // $member = wpforo_array_ordered_intersect_key( $member, $this->default->member );
228
229 if( ! $member['userid'] ) $member['timezone'] = '';
230
231 return array_merge( $member['fields'], $member );
232 }
233
234 /** @TODO use this function for member all insert|update queries
235 * @param $member
236 *
237 * @return array
238 */
239 private function encode( $member ) {
240 $member = $this->decode( $member );
241 $member['secondary_groupids'] = implode( ',', $member['secondary_groupids'] );
242 $member['groupids'] = implode( ',', $member['groupids'] );
243 unset( $member['reactions_in']['__ALL__'], $member['reactions_out']['__ALL__'] );
244 $member['reactions_in'] = json_encode( $member['reactions_in'] );
245 $member['reactions_out'] = json_encode( $member['reactions_out'] );
246 $member['is_email_confirmed'] = intval( $member['is_email_confirmed'] );
247 $member['is_mention_muted'] = intval( $member['is_mention_muted'] );
248 $member['fields'] = json_encode( $member['fields'] );
249
250 return $member;
251 }
252
253 private function fix_action( $action ) {
254 return array_merge( $this->default->action, $action );
255 }
256
257 private function _get_actions( $user ) {
258 $userid = wpforo_bigintval( $user['userid'] );
259 $actions = [
260 'edit' => [
261 'label' => wpforo_phrase( 'Edit Account Information', false ),
262 'ico' => '<svg height="12" width="12" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path fill="currentColor" d="M224 0a128 128 0 1 1 0 256A128 128 0 1 1 224 0zM178.3 304h91.4c11.8 0 23.4 1.2 34.5 3.3c-2.1 18.5 7.4 35.6 21.8 44.8c-16.6 10.6-26.7 31.6-20 53.3c4 12.9 9.4 25.5 16.4 37.6s15.2 23.1 24.4 33c15.7 16.9 39.6 18.4 57.2 8.7v.9c0 9.2 2.7 18.5 7.9 26.3H29.7C13.3 512 0 498.7 0 482.3C0 383.8 79.8 304 178.3 304zM436 218.2c0-7 4.5-13.3 11.3-14.8c10.5-2.4 21.5-3.7 32.7-3.7s22.2 1.3 32.7 3.7c6.8 1.5 11.3 7.8 11.3 14.8v17.7c0 7.8 4.8 14.8 11.6 18.7c6.8 3.9 15.1 4.5 21.8 .6l13.8-7.9c6.1-3.5 13.7-2.7 18.5 2.4c7.6 8.1 14.3 17.2 20.1 27.2s10.3 20.4 13.5 31c2.1 6.7-1.1 13.7-7.2 17.2l-14.4 8.3c-6.5 3.7-10 10.9-10 18.4s3.5 14.7 10 18.4l14.4 8.3c6.1 3.5 9.2 10.5 7.2 17.2c-3.3 10.6-7.8 21-13.5 31s-12.5 19.1-20.1 27.2c-4.8 5.1-12.5 5.9-18.5 2.4l-13.8-7.9c-6.7-3.9-15.1-3.3-21.8 .6c-6.8 3.9-11.6 10.9-11.6 18.7v17.7c0 7-4.5 13.3-11.3 14.8c-10.5 2.4-21.5 3.7-32.7 3.7s-22.2-1.3-32.7-3.7c-6.8-1.5-11.3-7.8-11.3-14.8V467.8c0-7.9-4.9-14.9-11.7-18.9c-6.8-3.9-15.2-4.5-22-.6l-13.5 7.8c-6.1 3.5-13.7 2.7-18.5-2.4c-7.6-8.1-14.3-17.2-20.1-27.2s-10.3-20.4-13.5-31c-2.1-6.7 1.1-13.7 7.2-17.2l14-8.1c6.5-3.8 10.1-11.1 10.1-18.6s-3.5-14.8-10.1-18.6l-14-8.1c-6.1-3.5-9.2-10.5-7.2-17.2c3.3-10.6 7.7-21 13.5-31s12.5-19.1 20.1-27.2c4.8-5.1 12.4-5.9 18.5-2.4l13.6 7.8c6.8 3.9 15.2 3.3 22-.6c6.9-3.9 11.7-11 11.7-18.9V218.2zm92.1 133.5a48.1 48.1 0 1 0 -96.1 0 48.1 48.1 0 1 0 96.1 0z"/></svg>',
263 'callback_for_can' => function() {
264 return WPF()->perm->user_can_edit_account();
265 },
266 'callback_for_get_url' => function() use ( $user ) {
267 return WPF()->member->get_profile_url( $user, 'account' );
268 },
269 ],
270 'edit_dash' => [
271 'label' => wpforo_phrase( 'Edit User in Dashboard', false ),
272 'ico' => '<svg height="12" width="12" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path fill="currentColor" d="M224 256A128 128 0 1 0 224 0a128 128 0 1 0 0 256zm-45.7 48C79.8 304 0 383.8 0 482.3C0 498.7 13.3 512 29.7 512H322.8c-3.1-8.8-3.7-18.4-1.4-27.8l15-60.1c2.8-11.3 8.6-21.5 16.8-29.7l40.3-40.3c-32.1-31-75.7-50.1-123.9-50.1H178.3zm435.5-68.3c-15.6-15.6-40.9-15.6-56.6 0l-29.4 29.4 71 71 29.4-29.4c15.6-15.6 15.6-40.9 0-56.6l-14.4-14.4zM375.9 417c-4.1 4.1-7 9.2-8.4 14.9l-15 60.1c-1.4 5.5 .2 11.2 4.2 15.2s9.7 5.6 15.2 4.2l60.1-15c5.6-1.4 10.8-4.3 14.9-8.4L576.1 358.7l-71-71L375.9 417z"/></svg>',
273 'callback_for_can' => function() {
274 return current_user_can( 'administrator' );
275 },
276 'callback_for_get_url' => function() use ( $userid ) {
277 return admin_url( "user-edit.php?user_id=" . $userid );
278 },
279 ],
280 'ban' => [
281 'label' => ( $user['status'] === 'banned' ? wpforo_phrase(
282 'Unban User',
283 false
284 ) : wpforo_phrase(
285 'Ban User',
286 false
287 ) ),
288 'ico' => '<svg height="12" width="12" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path fill="currentColor" d="M224 256A128 128 0 1 0 224 0a128 128 0 1 0 0 256zm-45.7 48C79.8 304 0 383.8 0 482.3C0 498.7 13.3 512 29.7 512H392.6c-5.4-9.4-8.6-20.3-8.6-32V352c0-2.1 .1-4.2 .3-6.3c-31-26-71-41.7-114.6-41.7H178.3zM528 240c17.7 0 32 14.3 32 32v48H496V272c0-17.7 14.3-32 32-32zm-80 32v48c-17.7 0-32 14.3-32 32V480c0 17.7 14.3 32 32 32H608c17.7 0 32-14.3 32-32V352c0-17.7-14.3-32-32-32V272c0-44.2-35.8-80-80-80s-80 35.8-80 80z"/></svg>',
289 'callback_for_can' => function() use ( $userid ) {
290 return $userid !== WPF()->current_userid && ( WPF()->usergroup->can(
291 'bm'
292 ) || wpforo_current_user_is( 'admin' ) );
293 },
294 'callback_for_get_url' => function() use ( $userid ) {
295 return '';
296 },
297 'data' => [
298 'currentstate' => (int) ( $user['status'] === 'banned' ),
299 'active_label' => wpforo_phrase( 'Unban User', false ),
300 'inactive_label' => wpforo_phrase( 'Ban User', false ),
301 ],
302 'confirm_msg' => wpforo_phrase( 'Please confirm you want to do this action?', false ),
303 ],
304 'delete' => [
305 'label' => wpforo_phrase( 'Delete Account', false ),
306 'ico' => '<svg height="12" width="12" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path fill="currentColor" d="M96 128a128 128 0 1 1 256 0A128 128 0 1 1 96 128zM0 482.3C0 383.8 79.8 304 178.3 304h91.4C368.2 304 448 383.8 448 482.3c0 16.4-13.3 29.7-29.7 29.7H29.7C13.3 512 0 498.7 0 482.3zM471 143c9.4-9.4 24.6-9.4 33.9 0l47 47 47-47c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9l-47 47 47 47c9.4 9.4 9.4 24.6 0 33.9s-24.6 9.4-33.9 0l-47-47-47 47c-9.4 9.4-24.6 9.4-33.9 0s-9.4-24.6 0-33.9l47-47-47-47c-9.4-9.4-9.4-24.6 0-33.9z"/></svg>',
307 'callback_for_can' => function() use ( $userid ) {
308 $self = $userid === WPF()->current_userid && ! is_super_admin( $userid ) && apply_filters(
309 'wpforo_can_user_self_delete',
310 true
311 );
312 $not_self = $userid !== WPF()->current_userid && ( current_user_can( 'administrator' ) || WPF(
313 )->usergroup->can( 'dm' ) ) && WPF()->perm->user_can_manage_user(
314 WPF()->current_userid,
315 $userid
316 );
317
318 return $self || $not_self;
319 },
320 'callback_for_get_url' => function() use ( $userid ) {
321 return wp_nonce_url(
322 trim( WPF()->member->get_profile_url( $userid ), '/' ) . '/?wpfaction=user_delete',
323 'user_delete',
324 '_wpfnonce'
325 );
326 },
327 'confirm_msg' => wpforo_phrase( 'Please confirm you want to do this action?', false ),
328 ],
329 'delete_dash' => [
330 'label' => wpforo_phrase( 'Delete User in Dashboard', false ),
331 'ico' => '<svg height="12" width="12" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path fill="currentColor" d="M38.8 5.1C28.4-3.1 13.3-1.2 5.1 9.2S-1.2 34.7 9.2 42.9l592 464c10.4 8.2 25.5 6.3 33.7-4.1s6.3-25.5-4.1-33.7L381.9 274c48.5-23.2 82.1-72.7 82.1-130C464 64.5 399.5 0 320 0C250.4 0 192.4 49.3 178.9 114.9L38.8 5.1zM545.5 512H528L284.3 320h-59C136.2 320 64 392.2 64 481.3c0 17 13.8 30.7 30.7 30.7H545.3l.3 0z"/></svg>',
332 'callback_for_can' => function() use ( $userid ) {
333 return ( current_user_can( 'administrator' ) && WPF()->perm->user_can_manage_user(
334 WPF()->current_userid,
335 $userid
336 ) && $userid !== WPF()->current_userid );
337 },
338 'callback_for_get_url' => function() use ( $userid ) {
339 return admin_url( wp_nonce_url( "users.php?action=delete&user=" . $userid, 'bulk-users' ) );
340 },
341 ],
342 ];
343
344 return array_map( [ $this, 'fix_action' ], apply_filters( 'wpforo_member_get_actions', $actions, $user ) );
345 }
346
347 public function get_action( $user, $key ) {
348 $actions = $this->_get_actions( $user );
349
350 return wpfval( $actions, $key );
351 }
352
353 public function get_actions( $user ) {
354 $actions = $this->_get_actions( $user );
355
356 return array_filter( $actions, function( $action ) use ( $user ) {
357 if( is_callable( $action['callback_for_can'] ) ) return call_user_func( $action['callback_for_can'] );
358
359 return true;
360 } );
361 }
362
363 private function add_profile( $args ) {
364 if( ! $userid = wpforo_bigintval( wpfval( $args, 'userid' ) ) ) return false;
365 $sql = "INSERT IGNORE INTO `" . WPF(
366 )->tables->profiles . "` (`userid`, `title`, `groupid`, `timezone`, `about`) VALUES ( %d, %s, %d, %s, %s )";
367 $sql = WPF()->db->prepare(
368 $sql,
369 $userid,
370 sanitize_text_field( wpfval( $args, 'title' ) ) ?: wpforo_setting( 'profiles', 'default_title' ),
371 (int) wpfval( $args, 'groupid' ) ?: WPF()->usergroup->default_groupid,
372 sanitize_text_field( wpfval( $args, 'timezone' ) ) ?: '',
373 stripslashes( wpforo_kses( trim( (string) wpfval( $args, 'about' ) ), 'user_description' ) ) ?: ''
374 );
375
376 $r = WPF()->db->query( $sql );
377 $this->reset( $userid );
378
379 return $r;
380 }
381
382 function create( $data ) {
383 if( ! wpforo_setting( 'authorization', 'user_register' ) ) {
384 WPF()->notice->add( 'User registration is disabled.', 'error' );
385
386 return false;
387 }
388
389 $user_fields = [];
390 if( ! empty( $data ) ) {
391 if( wpfval( $data, 'wpfreg' ) ) {
392 $user_fields = $data['wpfreg'];
393 } else {
394 $user_fields = $data;
395 }
396 }
397
398 //-- START -- copied from update code
399 //Define $user
400 $user = $user_fields;
401
402 //Define $userid
403 $userid = intval( wpfval( $user, 'userid' ) );
404
405 //Check custom fields and merge to $user array
406 if( wpfval( $data, 'data' ) && is_array( $data['data'] ) && ! empty( $data['data'] ) ) {
407 $custom_fields = $data['data'];
408 $user = array_merge( $custom_fields, $user );
409 }
410
411 //Check file uploading custom fields and merge to $user array
412 $file_data = isset( $_FILES['data']['name'] ) && $_FILES['data']['name'] && is_array(
413 $_FILES['data']['name']
414 ) ? array_filter( $_FILES['data']['name'] ) : [];
415 $file_fields = WPF()->form->prepare_file_args( $file_data, $userid );
416 if( wpfval( $file_fields, 'fields' ) ) {
417 $user = array_merge( $file_fields['fields'], $user );
418 }
419
420 //Validate fields
421 $form_fields = $this->get_register_fields();
422 $result = WPF()->form->validate( $user, $form_fields );
423 if( wpfval( $result, 'error' ) ) {
424 if( wpforo_is_admin() && wpfval( $result['error'], 0 ) ) {
425 wp_die( $result['error'][0] );
426 } else {
427 WPF()->notice->add( $result['error'], 'error' );
428
429 return false;
430 }
431 }
432 //-- END -- copied from update code
433
434 $user_fields = apply_filters( 'wpforo_create_profile', $user_fields );
435
436 if( ! $user_fields ) {
437 WPF()->notice->add( 'Empty fields', 'error' );
438
439 return false;
440 } elseif( wpfval( $user_fields, 'error' ) ) {
441 WPF()->notice->add( sanitize_text_field( $user_fields['error'] ), 'error' );
442
443 return false;
444 }
445
446 if( ! wpforo_setting( 'authorization', 'user_register_email_confirm' ) && ! empty( $user_fields ) && is_array(
447 $user_fields
448 ) && ! empty( $user_fields['user_pass1'] ) ) {
449
450 remove_action( 'register_new_user', 'wp_send_new_user_notifications' );
451 remove_action( 'register_new_user', 'wpforo_send_new_user_notifications' );
452 add_action( 'register_new_user', function( $user_id ) {
453 wpforo_send_new_user_notifications( $user_id, 'admin' );
454 } );
455
456 do_action( 'wpforo_create_profile_before', $user_fields );
457
458 $errors = new WP_Error();
459
460 extract( $user_fields, EXTR_OVERWRITE );
461 $sanitized_user_login = sanitize_user( $user_login );
462 $user_email = apply_filters( 'user_registration_email', $user_email );
463 $user_pass1 = trim( substr( (string) $user_pass1, 0, 100 ) );
464 $user_pass2 = trim( substr( (string) $user_pass2, 0, 100 ) );
465 $illegal_user_logins = array_map( 'strtolower', (array) apply_filters( 'illegal_user_logins', [] ) );
466
467 if( $sanitized_user_login == '' ) {
468 $errors->add( 'empty_username', __( '<strong>ERROR</strong>: Please enter a username.' ) );
469 WPF()->notice->add( 'Username is missed.', 'error' );
470
471 return false;
472 } elseif( ! validate_username( $user_login ) ) {
473 $errors->add(
474 'invalid_username',
475 __(
476 '<strong>ERROR</strong>: This username is invalid because it uses illegal characters. Please enter a valid username.'
477 )
478 );
479 WPF()->notice->add( 'Illegal character in username.', 'error' );
480
481 return false;
482 } elseif( strlen( (string) $user_login ) < $this->login_min_length || strlen(
483 (string) $user_login
484 ) > $this->login_max_length ) {
485 WPF()->notice->add(
486 'Username length must be between %d characters and %d characters.',
487 'error',
488 [ $this->login_min_length, $this->login_max_length ]
489 );
490
491 return false;
492 } elseif( username_exists( $sanitized_user_login ) ) {
493 $errors->add(
494 'username_exists',
495 __(
496 '<strong>ERROR</strong>: This username is already registered. Please choose another one.'
497 )
498 );
499 WPF()->notice->add( 'Username exists. Please insert another.', 'error' );
500
501 return false;
502 } elseif( in_array( strtolower( $sanitized_user_login ), $illegal_user_logins ) ) {
503 $errors->add(
504 'invalid_username',
505 __( '<strong>ERROR</strong>: Sorry, that username is not allowed.' )
506 );
507 WPF()->notice->add(
508 'ERROR: invalid_username. Sorry, that username is not allowed. Please insert another.',
509 'error'
510 );
511
512 return false;
513 } elseif( $user_email == '' ) {
514 $errors->add( 'empty_email', __( '<strong>ERROR</strong>: Please type your email address.' ) );
515 WPF()->notice->add( 'Insert your Email address.', 'error' );
516
517 return false;
518 } elseif( ! is_email( $user_email ) ) {
519 $errors->add( 'invalid_email', __( '<strong>ERROR</strong>: The email address isn&#8217;t correct.' ) );
520 WPF()->notice->add( 'Invalid Email address', 'error' );
521
522 return false;
523 } elseif( email_exists( $user_email ) ) {
524 $errors->add(
525 'email_exists',
526 __(
527 '<strong>ERROR</strong>: This email is already registered, please choose another one.'
528 )
529 );
530 WPF()->notice->add( 'Email address exists. Please insert another.', 'error' );
531
532 return false;
533 } elseif( strlen( $user_pass1 ) < $this->pass_min_length || strlen(
534 $user_pass1
535 ) > $this->pass_max_length ) {
536 WPF()->notice->add(
537 'Password length must be between %d characters and %d characters.',
538 'error',
539 [ $this->pass_min_length, $this->pass_max_length ]
540 );
541
542 return false;
543 } elseif( $user_pass1 != $user_pass2 ) {
544 WPF()->notice->add( 'Password mismatch.', 'error' );
545
546 return false;
547 } else {
548 do_action( 'register_post', $sanitized_user_login, $user_email, $errors );
549 $errors = apply_filters( 'registration_errors', $errors, $sanitized_user_login, $user_email );
550 if( $errors->get_error_code() ) {
551 $user_fields = [];
552 foreach( $errors->errors as $u_err ) $user_fields[] = $u_err[0];
553 WPF()->notice->add( $user_fields, 'error' );
554
555 return false;
556 }
557 $user_id = wp_create_user( $sanitized_user_login, $user_pass1, $user_email );
558 if( ! is_wp_error( $user_id ) && $user_id ) {
559 do_action( 'register_new_user', $user_id );
560 do_action( 'wpforo_create_user_after', $data );
561 wp_signon( [ 'user_login' => $sanitized_user_login, 'user_password' => $user_pass1 ] );
562 WPF()->notice->clear();
563 WPF()->notice->add( 'Success!', 'success' );
564
565 return $user_id;
566 }
567 }
568 } elseif( wpforo_setting(
569 'authorization',
570 'user_register_email_confirm'
571 ) && ! empty( $user_fields['user_login'] ) && ! empty( $user_fields['user_email'] ) ) {
572 if( strlen( (string) $user_fields['user_login'] ) < $this->login_min_length || strlen(
573 (string) $user_fields['user_login']
574 ) > $this->login_max_length ) {
575 WPF()->notice->add(
576 'Username length must be between %d characters and %d characters.',
577 'error',
578 [ $this->login_min_length, $this->login_max_length ]
579 );
580
581 return false;
582 }
583 if( is_multisite() && apply_filters( 'wpforo_mu_signup', false ) ) {
584 wpmu_signup_user( $user_fields['user_login'], $user_fields['user_email'] );
585 WPF()->notice->clear();
586 WPF()->notice->add( 'Success! Please check your mail for confirmation.', 'success' );
587
588 return true;
589 } else {
590 $user_id = register_new_user( $user_fields['user_login'], $user_fields['user_email'] );
591 }
592 if( ! is_wp_error( $user_id ) && $user_id ) {
593 do_action( 'wpforo_create_user_after', $data );
594 WPF()->notice->clear();
595 WPF()->notice->add( 'Success! Please check your mail for confirmation.', 'success' );
596
597 return $user_id;
598 }
599 }
600
601 if( ! empty( $user_id->errors ) ) {
602 $user_fields = [];
603 foreach( $user_id->errors as $u_err ) $user_fields[] = $u_err[0];
604 WPF()->notice->add( $user_fields, 'error' );
605
606 return false;
607 }
608
609 WPF()->notice->add( 'Registration Error', 'error' );
610
611 return false;
612 }
613
614 /**
615 * Updates user data
616 *
617 * @param array $data - User data as a simple array( field => value ) OR
618 * $data['member'] = array( field => value ) user and profile fields - Account form
619 * $data['wpfreg'] = array( field => value ) user and profile fields - Registration form
620 * $data['data'] = array( field => value ) user custom fields
621 *
622 * $data['member']['userid'] or $data['userid'] is required
623 *
624 * @param string|array $type User data update types (comma separated)
625 * $type = 'full' user fields, profile fields, custom fields
626 * $type = 'user' only user fields (wp_users table)
627 * $type = 'profile' only profile fields (wp_wpforo_profiles table)
628 * $type = 'custom_fields' only custom fields (wp_wpforo_profiles table > fields column)
629 * $type = 'profile, custom_fields'
630 *
631 * @param boolean $check_permissions Whether check the current editor permissions or not
632 *
633 * @return false|array wpForo User array
634 * @since 1.5.0
635 *
636 */
637 public function update( $data, $type = 'full', $check_permissions = true ) {
638 $type = (array) $type;
639
640 switch( WPF()->current_object['template'] ) {
641 case 'register':
642 $form = 'wpfreg';
643 $form_fields = $this->get_register_fields();
644 break;
645 default:
646 $form = 'member';
647 $form_fields = $this->get_account_fields();
648 break;
649 }
650 if( ! $form_fields ) {
651 WPF()->notice->add( 'Form template not found', 'error' );
652
653 return false;
654 }
655
656 if( ! wpfkey( $data, $form ) ) {
657 if( in_array( 'custom_fields', $type ) && count( $type ) === 1 ) {
658 if( ! wpfval( $data, 'data' ) ) {
659 $data['data'] = $data;
660 if( wpfkey( $data, 'data', 'userid' ) ) unset( $data['data']['userid'] );
661 }
662 } else {
663 $data[ $form ] = $data;
664 }
665 }
666 if( wpfval( $data, 'userid' ) && ! wpfval(
667 $data,
668 $form,
669 'userid'
670 ) ) {
671 $data[ $form ]['userid'] = $data['userid'];
672 }
673
674 if( wpfval( $data, $form, 'userid' ) ) {
675 $result_user = true;
676 $result_fields = true;
677 $result_profile = true;
678 $custom_fields = [];
679
680 //Define $user
681 $user = $data[ $form ];
682
683 //Define $userid
684 $userid = intval( $data[ $form ]['userid'] );
685
686 //Check profile editor permissions
687 if( $check_permissions ) WPF()->perm->can_edit_user( $userid );
688
689 //Check custom fields and merge to $user array
690 if( wpfkey( $data, 'data' ) && is_array( $data['data'] ) && ! empty( $data['data'] ) ) {
691 $custom_fields = $data['data'];
692 $user = array_merge( $custom_fields, $user );
693 }
694
695 //Check file uploading custom fields and merge to $user array
696 $file_data = isset( $_FILES['data']['name'] ) && $_FILES['data']['name'] && is_array(
697 $_FILES['data']['name']
698 ) ? array_filter( $_FILES['data']['name'], function( $key ) {
699 if( trim( (string) $key ) && ( $field = $this->get_field( $key ) ) ) {
700 if( wpfval( $field, 'type' ) === 'file' ) {
701 $mime_type = wpfval( $_FILES, 'data', 'type', $key );
702 $mime_types = wp_get_mime_types();
703 $allowed_mime_types = get_allowed_mime_types();
704 $name = wpfval( $_FILES, 'data', 'name', $key );
705 $ext = pathinfo( $name, PATHINFO_EXTENSION );
706 $size = intval( $field['fileSize'] );
707 $fileExtensions = array_filter(
708 (array) ( is_scalar( $field['fileExtensions'] ) ? explode(
709 ',',
710 trim( (string) $field['fileExtensions'] )
711 ) : $field['fileExtensions'] )
712 );
713 if( $fileExtensions ) {
714 if( in_array( $ext, $fileExtensions ) ) {
715 $extensions = explode( '|', array_search( $mime_type, $mime_types ) );
716 $e = in_array( $ext, $extensions );
717 } else {
718 $e = false;
719 }
720 } else {
721 $extensions = explode( '|', array_search( $mime_type, $allowed_mime_types ) );
722 $e = in_array( $ext, $extensions );
723 }
724
725 return ! empty( $e ) && wpfval( $_FILES, 'data', 'size', $key ) <= ( $size * 1024 * 1024 );
726 }
727 }
728
729 return false;
730 }, ARRAY_FILTER_USE_KEY ) : [];
731 $file_fields = WPF()->form->prepare_file_args( $file_data, $userid );
732 if( wpfval( $file_fields, 'fields' ) ) {
733 $user = array_merge( $file_fields['fields'], $user );
734 $custom_fields = ( ! empty( $custom_fields ) ) ? array_merge(
735 $custom_fields,
736 $file_fields['fields']
737 ) : $file_fields['fields'];
738 }
739
740 //Hooks
741 $user = apply_filters( 'wpforo_update_profile', $user );
742 do_action( 'wpforo_update_profile_before', $user );
743 if( wpfval( $user, 'error' ) || empty( $user ) ) {
744 $error_message = ( wpfval( $user, 'error_message' ) ) ? sanitize_text_field(
745 $user['error_message']
746 ) : 'Unknown error in profile editing hook. Please disable all plugins and check it again.';
747 WPF()->notice->add( $error_message, 'error' );
748
749 return false;
750 }
751
752 //Validate avatar_url
753 if( wpfval( $user, 'avatar_type' ) === 'remote' && wpfval( $user, 'avatar_url' ) ) {
754 if( ! is_avatar_url( $user['avatar_url'] ) ) {
755 WPF()->notice->add( 'The avatar URL is not an image file.', 'error' );
756
757 return false;
758 }
759 }
760
761 //Validate fields
762 $result = WPF()->form->validate( $user, $form_fields );
763 if( wpfval( $result, 'error' ) ) {
764 if( is_admin() && wpfval( $result['error'], 0 ) ) {
765 wp_die( $result['error'][0] );
766 } else {
767 WPF()->notice->add( $result['error'], 'error' );
768
769 return false;
770 }
771 }
772
773 if( $gid = (int) wpfval( $user, 'groupid' ) ) {
774 $err = '';
775 if( WPF()->current_object['template'] !== 'register' ) {
776 if( WPF()->form->owner() || ! wpforo_current_user_is( 'admin' ) ) {
777 $err = 'You have no permission to edit Usergroup field';
778 }
779 } else {
780 if( in_array( $gid, [ 1, 2, 4 ], true ) ) {
781 $err = 'Admin and Moderator Usergroups are not permitted';
782 } else {
783 $f = $this->get_field( 'groupid' );
784 if( wpfval( $f, 'allowedGroupIds' ) ) {
785 $allowedGroupIds = wpforo_parse_args( $f['allowedGroupIds'] );
786 if( ! in_array( $gid, $allowedGroupIds, true ) ) {
787 $err = 'The selected Usergroup cannot be set';
788 }
789 } else {
790 $err = 'The selected Usergroup is not found in allowed list';
791 }
792 }
793 }
794
795 if( $err ) {
796 unset( $user['groupid'] );
797 }
798 }
799
800 if( $sgids = array_filter( array_map( 'intval', (array) wpfval( $user, 'secondary_groupids' ) ) ) ) {
801 $participant_fields_list = $this->get_participant_fields_list( $form_fields, true );
802 $f = $this->get_field( 'secondary_groupids' );
803 if(
804 in_array( 'secondary_groupids', $participant_fields_list )
805 && ( WPF()->current_object['template'] === 'register'
806 || ( WPF()->form->owner() && $f['isEditable'] )
807 || ( ! WPF()->form->owner() && in_array( WPF()->current_user_groupid, (array) $f['canEdit'] ) )
808 || wpforo_current_user_is( 'admin' )
809 )
810 ) {
811 if( ! empty( $sgids ) ) {
812 $secondary_groupids = WPF()->usergroup->get_secondary_groupids();
813 foreach( $sgids as $sgid ) {
814 if( in_array( $sgid, [ 1, 2, 4 ], true ) ) {
815 $user['secondary_groupids'] = array_diff( $user['secondary_groupids'], [ $sgid ] );
816 }
817 if( ! in_array( $sgid, $secondary_groupids ) ) {
818 $user['secondary_groupids'] = array_diff( $user['secondary_groupids'], [ $sgid ] );
819 }
820 }
821 }
822 } else {
823 unset( $user['secondary_groupids'] );
824 }
825 }
826
827 //Sanitize fields
828 $user = WPF()->form->sanitize( $user, $form_fields );
829
830 //Update User Fields
831 if( ! empty( $user ) && ( in_array( 'full', $type ) || in_array( 'user', $type ) ) ) {
832 $result_user = $this->update_user_fields( $userid, $user, false );
833 }
834
835 //Update Profile Fields
836 if( ! empty( $user ) && ( in_array( 'full', $type ) || in_array( 'profile', $type ) ) ) {
837 $result_profile = $this->update_profile_fields( $userid, $user, false );
838 }
839
840 //Password field validation and update
841 $result_password = WPF()->form->validate_password( $user );
842 if( $result_password === false ) {
843 $result_password = true;
844 }
845 if( wpfval( $result_password, 'error' ) ) {
846 WPF()->notice->add( $result_password['error'], 'error' );
847 $result_password = false;
848 }
849 if( $result_password && wpfval( $user, 'old_pass' ) && wpfval( $user, 'user_pass1' ) ) {
850 $result_password = $this->change_password( $user['old_pass'], $user['user_pass1'], $userid );
851 }
852
853 //Upload avatar
854 if( wpfval( $user, 'avatar_type' ) === 'custom' ) {
855 $this->upload_avatar( $userid );
856 }
857
858 //Update Custom Fields
859 if( ! empty( $custom_fields ) && ( in_array( 'full', $type ) || in_array( 'custom_fields', $type ) ) ) {
860 $result_fields = $this->update_custom_fields( $userid, $custom_fields, false );
861 }
862
863 //Upload Files from Custom Fields
864 if( wpfval( $file_fields, 'files' ) ) {
865 $this->upload_files( $file_fields['files'] );
866 }
867
868 //Reset this user cache
869 $this->reset( $userid );
870
871 if( $result_user === false || $result_profile === false || $result_fields === false || $result_password === false ) {
872 return false;
873 } else {
874 WPF()->notice->add( 'Profile updated successfully', 'success' );
875 do_action( 'wpforo_update_profile_after', $user );
876
877 return $user;
878 }
879 }
880
881 return false;
882 }
883
884 public function update_user_fields( $userid, $data, $check_permissions = true ) {
885 $result_user = true;
886 if( $check_permissions ) WPF()->perm->can_edit_user( $userid );
887
888 //User Fields
889 if( wpfkey( $data, 'display_name' ) ) {
890 $user_fields['display_name'] = $data['display_name'];
891 $user_fields_types[] = '%s';
892 }
893 if( wpfkey( $data, 'user_email' ) ) {
894 $user_fields['user_email'] = $data['user_email'];
895 $user_fields_types[] = '%s';
896 }
897 if( wpfkey( $data, 'user_nicename' ) ) {
898 if( ! wpfval( $data, 'user_nicename' ) ) {
899 $user_info = get_userdata( $userid );
900 $data['user_nicename'] = sanitize_title( sanitize_user( $user_info->user_nicename, true ) );
901 }
902 $user_fields['user_nicename'] = $data['user_nicename'];
903 $user_fields_types[] = '%s';
904 update_user_meta( $userid, 'nickname', $data['user_nicename'] );
905 }
906 if( wpfkey( $data, 'first_name' ) ) {
907 update_user_meta( $userid, 'first_name', $data['first_name'] );
908 }
909 if( wpfkey( $data, 'last_name' ) ) {
910 update_user_meta( $userid, 'last_name', $data['last_name'] );
911 }
912 if( wpfkey( $data, 'user_url' ) ) {
913 $user_fields['user_url'] = $data['user_url'];
914 $user_fields_types[] = '%s';
915 }
916
917 if( ! empty( $user_fields ) && ! empty( $user_fields_types ) ) {
918 $result_user = WPF()->db->update(
919 WPF()->db->users,
920 $user_fields,
921 [ 'ID' => $userid ],
922 $user_fields_types,
923 [ '%d' ]
924 );
925 if( false === $result_user ) {
926 WPF()->notice->add( 'User data update failed', 'error' );
927 if( WPF()->db->last_error ) {
928 WPF()->notice->add( sanitize_text_field( WPF()->db->last_error ), 'error' );
929 }
930 } else {
931 clean_user_cache( $userid );
932 }
933 }
934
935 if( $result_user ) $this->reset( $userid );
936
937 return $result_user;
938 }
939
940 public function update_profile_field( $userid, $key, $value ) {
941 $r = false;
942 if( $key && ! is_null( $value ) ) {
943 $member = $this->encode( [ $key => $value ] );
944 if( wpfkey( $member, $key ) ) {
945 $r = WPF()->db->update(
946 WPF()->tables->profiles,
947 [ $key => $value ],
948 [ 'userid' => $userid ],
949 [ wpforo_db_data_format( $member[ $key ] ) ], [ '%d' ]
950 );
951
952 if( $r ) $this->reset( $userid );
953 }
954 }
955
956 return $r;
957 }
958
959 public function update_profile_fields( $userid, $data, $check_permissions = true ) {
960 $result_profile = true;
961
962 if( $check_permissions ) {
963 WPF()->perm->can_edit_user( $userid );
964 }
965
966 $member = $this->encode( $data );
967
968 $profile_fields = [];
969 $profile_fields_types = [];
970
971 //Profile Fields
972 if( wpfkey( $data, 'groupid' ) ) {
973 $profile_fields['groupid'] = $member['groupid'];
974 $profile_fields_types[] = '%d';
975 }
976 if( wpfkey( $data, 'title' ) ) {
977 $profile_fields['title'] = $member['title'];
978 $profile_fields_types[] = '%s';
979 }
980 if( wpfkey( $data, 'signature' ) ) {
981 $profile_fields['signature'] = $member['signature'];
982 $profile_fields_types[] = '%s';
983 }
984 if( wpfkey( $data, 'about' ) ) {
985 $profile_fields['about'] = $member['about'];
986 $profile_fields_types[] = '%s';
987 update_user_meta( $userid, 'description', $member['about'] );
988 }
989 if( wpfkey( $data, 'occupation' ) ) {
990 $profile_fields['occupation'] = $member['occupation'];
991 $profile_fields_types[] = '%s';
992 }
993 if( wpfkey( $data, 'location' ) ) {
994 $profile_fields['location'] = $member['location'];
995 $profile_fields_types[] = '%s';
996 }
997 if( wpfkey( $data, 'timezone' ) ) {
998 $profile_fields['timezone'] = $member['timezone'];
999 $profile_fields_types[] = '%s';
1000 }
1001 if( wpfkey( $data, 'avatar_type' ) && $data['avatar_type'] !== 'gravatar' && wpfval( $data, 'avatar_url' ) ) {
1002 $profile_fields['avatar'] = esc_url( trim( (string) $data['avatar_url'] ) );
1003 $profile_fields_types[] = '%s';
1004 }
1005 if( wpfkey( $data, 'avatar_type' ) && $data['avatar_type'] === 'gravatar' ) {
1006 $profile_fields['avatar'] = '';
1007 $profile_fields_types[] = '%s';
1008 }
1009 if( wpfkey( $data, 'cover' ) ) {
1010 $profile_fields['cover'] = $member['cover'];
1011 $profile_fields_types[] = '%s';
1012 }
1013 if( wpfkey( $data, 'secondary_groupids' ) ) {
1014 $profile_fields['secondary_groupids'] = $member['secondary_groupids'];
1015 $profile_fields_types[] = '%s';
1016 }
1017 if( wpfkey( $data, 'custom_points' ) ) {
1018 $profile_fields['custom_points'] = $member['custom_points'];
1019 $profile_fields_types[] = '%d';
1020 }
1021 if( wpfkey( $data, 'online_time' ) ) {
1022 $profile_fields['online_time'] = $member['online_time'];
1023 $profile_fields_types[] = '%d';
1024 }
1025 if( wpfkey( $data, 'status' ) ) {
1026 $profile_fields['status'] = $member['status'];
1027 $profile_fields_types[] = '%s';
1028 }
1029 if( wpfkey( $data, 'is_email_confirmed' ) ) {
1030 $profile_fields['is_email_confirmed'] = $member['is_email_confirmed'];
1031 $profile_fields_types[] = '%d';
1032 }
1033 if( wpfkey( $data, 'is_mention_muted' ) ) {
1034 $profile_fields['is_mention_muted'] = $member['is_mention_muted'];
1035 $profile_fields_types[] = '%d';
1036 }
1037
1038 $profile_fields = apply_filters(
1039 'wpforo_before_update_profile_fields',
1040 $profile_fields,
1041 $userid,
1042 $data,
1043 $check_permissions
1044 );
1045
1046 if( ! empty( $profile_fields ) ) {
1047 $result_profile = WPF()->db->update(
1048 WPF()->tables->profiles,
1049 $profile_fields,
1050 [ 'userid' => intval( $userid ) ],
1051 $profile_fields_types,
1052 [ '%d' ]
1053 );
1054 if( false === $result_profile ) {
1055 WPF()->notice->add( 'User profile update failed', 'error' );
1056 if( WPF()->db->last_error ) {
1057 WPF()->notice->add( sanitize_text_field( WPF()->db->last_error ), 'error' );
1058 }
1059 }
1060 }
1061 do_action( 'wpforo_update_profile_fields', $userid, $data, $result_profile );
1062
1063 if( $result_profile ) $this->reset( $userid );
1064
1065 return $result_profile;
1066 }
1067
1068 public function update_custom_field( $userid, $field_name, $field_value = null ) {
1069 $result = false;
1070 $fields = $this->get_custom_fields( $userid );
1071 if( ! empty( $fields ) && $field_name && ! is_null( $field_value ) ) {
1072 foreach( $fields as $name => $value ) {
1073 if( $name == $field_name ) {
1074 $fields[ $name ] = $field_value;
1075 }
1076 }
1077 $custom_fields = array_filter( $fields );
1078 $custom_fields = wpforo_unslashe( $custom_fields );
1079 $custom_fields = wpforo_decode( $custom_fields );
1080 $custom_fields = wpforo_encode( $custom_fields );
1081 $fields_json = json_encode( $custom_fields, JSON_UNESCAPED_UNICODE );
1082 $sql = "UPDATE `" . WPF()->tables->profiles . "` SET `fields` = %s WHERE `userid` = %d;";
1083 $sql = WPF()->db->prepare( $sql, $fields_json, $userid );
1084 $result = WPF()->db->query( $sql );
1085 }
1086
1087 if( $result ) $this->reset( $userid );
1088
1089 return $result;
1090 }
1091
1092 public function update_custom_fields( $userid, $custom_fields, $check_permissions = true ) {
1093
1094 $result_fields = true;
1095
1096 if( ! empty( $custom_fields ) ) {
1097 if( $check_permissions ) {
1098 WPF()->perm->can_edit_user( $userid );
1099 }
1100 $custom_fields = wpforo_unslashe( $custom_fields );
1101 $custom_fields = wpforo_decode( $custom_fields );
1102 $custom_fields = wpforo_encode( $custom_fields );
1103 $data_old = $this->get_custom_fields( $userid );
1104 if( $data_old && is_array( $data_old ) ) {
1105 $custom_fields = wp_parse_args( $custom_fields, $data_old );
1106 }
1107 $fields_json = json_encode( $custom_fields, JSON_UNESCAPED_UNICODE );
1108 $sql = "UPDATE `" . WPF()->tables->profiles . "` SET `fields` = %s WHERE `userid` = %d;";
1109 $sql = WPF()->db->prepare( $sql, $fields_json, $userid );
1110 $result_fields = WPF()->db->query( $sql );
1111 if( false === $result_fields ) {
1112 WPF()->notice->add( 'User custom field update failed', 'error' );
1113 if( WPF()->db->last_error ) {
1114 WPF()->notice->add( sanitize_text_field( WPF()->db->last_error ), 'error' );
1115 }
1116 }
1117 }
1118
1119 if( $result_fields ) $this->reset( $userid );
1120
1121 return $result_fields;
1122 }
1123
1124 public function upload_avatar( $userid = 0 ) {
1125 $userid = intval( $userid );
1126
1127 $_FILES['avatar'] = wpforo_check_for_svg( $_FILES['avatar'] );
1128
1129 if( wpfval( WPF()->current_object, 'template' ) ) {
1130 $template = WPF()->current_object['template'];
1131 if( $template === 'account' ) {
1132 if( ! WPF()->usergroup->can( 'upa' ) ) return false;
1133 }
1134 }
1135
1136 if( ! $user = $this->get_member( $userid ) ) return false;
1137 $user_nicename = urldecode( (string) $user['user_nicename'] );
1138 if( isset( $_FILES['avatar'] ) && ! empty( $_FILES['avatar'] ) && isset( $_FILES['avatar']['name'] ) && $_FILES['avatar']['name'] ) {
1139 $name = sanitize_file_name( $_FILES['avatar']['name'] ); //myimg.png
1140 $tmp_name = sanitize_text_field( $_FILES['avatar']['tmp_name'] ); //D:\wamp\tmp\php986B.tmp
1141 $error = sanitize_text_field( $_FILES['avatar']['error'] ); //0
1142 $size = intval( $_FILES['avatar']['size'] ); //6112
1143
1144 $upload_max_filesize = apply_filters( 'wpforo_avatar_upload_max_filesize', 2 * 1048576 );
1145 if( $size > $upload_max_filesize ) {
1146 WPF()->notice->clear();
1147 WPF()->notice->add(
1148 'Avatar image is too big maximum allowed size is %s',
1149 'error',
1150 wpforo_print_size( $upload_max_filesize )
1151 );
1152
1153 return false;
1154 }
1155
1156 if( $error ) {
1157 $error = wpforo_file_upload_error( $error );
1158 WPF()->notice->clear();
1159 WPF()->notice->add( $error, 'error' );
1160
1161 return false;
1162 }
1163
1164 $avatar_dir = WPF()->folders['avatars']['dir'];
1165 if( ! is_dir( $avatar_dir ) ) wp_mkdir_p( $avatar_dir );
1166
1167 $ext = pathinfo( $name, PATHINFO_EXTENSION );
1168 if( ! wpforo_is_image( $ext ) ) {
1169 WPF()->notice->clear();
1170 WPF()->notice->add( 'Incorrect file format. Allowed formats: jpeg, jpg, png, gif.', 'error' );
1171
1172 return false;
1173 }
1174
1175 $fnm = pathinfo( $user_nicename, PATHINFO_FILENAME );
1176 $fnm = str_replace( ' ', '-', $fnm );
1177 while( strpos( (string) $fnm, '--' ) !== false ) $fnm = str_replace( '--', '-', $fnm );
1178 $fnm = preg_replace( "/[^-a-zA-Z0-9]/", "", (string) $fnm );
1179 $fnm = trim( (string) $fnm, "-" );
1180
1181 $avatar_fname = $fnm . ( $fnm ? '_' : '' ) . $userid . "." . strtolower( (string) $ext );
1182 $avatar_fname_orig = $fnm . ( $fnm ? '_' : '' ) . $userid . "." . $ext;
1183 $avatar_path = $avatar_dir . DIRECTORY_SEPARATOR . $avatar_fname;
1184 $avatar_path_orig = $avatar_dir . DIRECTORY_SEPARATOR . $avatar_fname_orig;
1185
1186 if( is_dir( $avatar_dir ) ) {
1187 if( move_uploaded_file( $tmp_name, $avatar_path ) ) {
1188 $image = wp_get_image_editor( $avatar_path );
1189 if( ! is_wp_error( $image ) ) {
1190 $image->resize( 150, 150, true );
1191 $saved = $image->save( $avatar_path );
1192 if( ! is_wp_error( $saved ) && $avatar_fname != $avatar_fname_orig ) {
1193 if( defined( PHP_OS ) && strtoupper( substr( PHP_OS, 0, 3 ) ) !== 'WIN' ) {
1194 unlink(
1195 $avatar_path_orig
1196 );
1197 }
1198 }
1199 }
1200 WPF()->db->update(
1201 WPF()->tables->profiles,
1202 [ 'avatar' => WPF()->folders['avatars']['url//'] . "/" . $avatar_fname ],
1203 [ 'userid' => intval( $userid ) ],
1204 [ '%s' ],
1205 [ '%d' ]
1206 );
1207 $this->reset( $userid );
1208
1209 return true;
1210 }
1211 }
1212 }
1213
1214 return false;
1215 }
1216
1217 public function upload_files( $file_fields ) {
1218 if( ! empty( $file_fields ) ) {
1219 foreach( $file_fields as $field_name => $file_path ) {
1220 if( wpfval( $_FILES, 'data', 'tmp_name', $field_name ) && ! move_uploaded_file(
1221 $_FILES['data']['tmp_name'][ $field_name ],
1222 $file_path
1223 ) ) {
1224 WPF()->notice->add( 'Sorry, there was an error uploading attached file', 'error' );
1225 }
1226 }
1227 }
1228 }
1229
1230 public function get_custom_field( $userid, $field_name ) {
1231 $field_value = '';
1232 if( $userid ) {
1233 $sql = WPF()->db->prepare(
1234 "SELECT `fields` FROM `" . WPF()->tables->profiles . "` WHERE userid = %d",
1235 $userid
1236 );
1237 $fields = WPF()->db->get_var( $sql );
1238 if( $fields ) {
1239 $data = (array) json_decode( $fields, true );
1240 if( ! empty( $data ) ) {
1241 $data = wpforo_unslashe( $data );
1242 if( wpfkey( $data, $field_name ) ) {
1243 $field_value = $data[ $field_name ];
1244 }
1245 }
1246 }
1247 }
1248
1249 return $field_value;
1250 }
1251
1252 public function get_custom_fields( $userid ) {
1253 $data = [];
1254 if( $userid ) {
1255 $sql = WPF()->db->prepare(
1256 "SELECT `fields` FROM `" . WPF()->tables->profiles . "` WHERE userid = %d",
1257 $userid
1258 );
1259 $fields = WPF()->db->get_var( $sql );
1260 if( $fields ) {
1261 $data = (array) json_decode( $fields, true );
1262 }
1263 $data = wpforo_unslashe( $data );
1264 }
1265
1266 return $data;
1267 }
1268
1269 public function change_password( $old_passw, $new_passw, $userid ) {
1270 if( ! ( $userid = wpforo_bigintval( $userid ) ) || ! ( $user = $this->get_member( $userid ) ) ) {
1271 WPF()->notice->clear();
1272 WPF()->notice->add( 'Userid is wrong', 'error' );
1273
1274 return false;
1275 }
1276
1277 $user['user_pass'] = ( $userdata = get_userdata( $userid ) ) ? $userdata->user_pass : '';
1278
1279 if( ! apply_filters( 'wpforo_change_password_validate', true, $old_passw, $new_passw, $user ) ) return false;
1280
1281 if( wp_check_password( $old_passw, $user['user_pass'], $userid ) ) {
1282 wp_set_password( $new_passw, $userid );
1283 if( ! wpforo_is_owner( $userid ) ) $this->inactive_to_active( $userid );
1284
1285 /**
1286 * Login user after change password with new pass
1287 */
1288 if( wpforo_is_owner( $userid ) ) {
1289 wp_signon( [ 'user_login' => sanitize_user( $user['user_login'] ), 'user_password' => $new_passw ] );
1290 }
1291
1292 WPF()->notice->add( 'Password successfully changed', 'success' );
1293
1294 return true;
1295 }
1296
1297 WPF()->notice->clear();
1298 WPF()->notice->add( 'Old password is wrong', 'error' );
1299
1300 return false;
1301 }
1302
1303 public function get_status( $userid ) {
1304 return WPF()->db->get_var(
1305 WPF()->db->prepare(
1306 "SELECT `status`
1307 FROM " . WPF()->tables->profiles . "
1308 WHERE `userid` = %d",
1309 $userid
1310 )
1311 );
1312 }
1313
1314 public function inactive_to_active( $userid, $user_login = '', $raw = false ) {
1315 if( $this->get_status( $userid ) === 'inactive' ) {
1316 if( $raw || ! wpforo_setting( 'authorization', 'manually_approval' ) ) {
1317 $this->update_profile_fields( $userid, [ 'status' => 'active' ], false );
1318 } else {
1319 wp_safe_redirect( wpforo_url( '', 'cantlogin' ) );
1320 exit();
1321 }
1322 }
1323 }
1324
1325 public function synchronize_user( $userid, $roles_usergroups = [] ) {
1326 $groupid = false;
1327 if( ! $userid || ! ( $user = get_userdata( $userid ) ) ) return false;
1328 $user->roles = (array) $user->roles;
1329
1330 //Don't synchronize User Roles with Usergroups if the option is disabled
1331 if( wpforo_setting( 'authorization', 'role_synch' ) ) {
1332 if( ! $roles_usergroups ) $roles_usergroups = WPF()->usergroup->get_role_usergroup_relation();
1333 if( ! empty( $roles_usergroups ) && ! empty( $user->roles ) ) {
1334 foreach( $user->roles as $role ) {
1335 if( isset( $roles_usergroups[ $role ] ) ) {
1336 $groupid = $roles_usergroups[ $role ];
1337 break;
1338 }
1339 }
1340 }
1341 }
1342
1343 if( ! $groupid ) {
1344 if( is_super_admin( $userid ) || in_array( 'administrator', $user->roles ) ) {
1345 $groupid = 1;
1346 } elseif( in_array( 'editor', $user->roles ) ) {
1347 $groupid = 2;
1348 } elseif( in_array( 'customer', $user->roles ) ) {
1349 $groupid = 5;
1350 } else {
1351 $groupid = WPF()->usergroup->default_groupid;
1352 }
1353 }
1354 $insert_groupid = ( isset( $_POST['wpforo_usergroup'] ) && ! wpforo_setting(
1355 'authorization',
1356 'role_synch'
1357 ) ) ? intval( $_POST['wpforo_usergroup'] ) : $groupid;
1358 $insert_timezone = ( isset( $_POST['wpforo_usertimezone'] ) ) ? sanitize_text_field(
1359 $_POST['wpforo_usertimezone']
1360 ) : '';
1361 $about = get_user_meta( $userid, 'description', true );
1362 $return = $this->add_profile( [
1363 'userid' => wpforo_bigintval( $userid ),
1364 'groupid' => intval( $insert_groupid ),
1365 'timezone' => sanitize_text_field( $insert_timezone ),
1366 'about' => stripslashes(
1367 wpforo_kses( trim( (string) $about ), 'user_description' )
1368 ),
1369 ] );
1370
1371 if( $return !== false && ( $secondary_groupids = wpfval( $_POST, 'wpforo_secondary_groupids' ) ) ) {
1372 $this->set_secondary_groupids( $userid, $secondary_groupids );
1373 }
1374
1375 return $return;
1376 }
1377
1378 public function synchronize_users( $limit = null ) {
1379
1380 if( is_multisite() ) {
1381 $sql = "SELECT `user_id` FROM `" . WPF()->db->usermeta . "` WHERE `meta_key` LIKE '" . WPF(
1382 )->blog_prefix . "capabilities' AND `user_id` NOT IN( SELECT `userid` FROM `" . WPF(
1383 )->tables->profiles . "` ) ORDER BY `user_id` ASC";
1384 } else {
1385 $sql = "SELECT `ID` as user_id FROM `" . WPF()->db->users . "` WHERE `ID` NOT IN( SELECT `userid` FROM `" . WPF(
1386 )->tables->profiles . "` ) ORDER BY `ID` ASC";
1387 }
1388 if( ! is_null( $limit ) ) {
1389 $sql .= " LIMIT " . intval( $limit );
1390 }
1391
1392 $userids = WPF()->db->get_col( $sql );
1393 if( ! empty( $userids ) ) {
1394 $roles_usergroups = WPF()->usergroup->get_role_usergroup_relation();
1395 foreach( $userids as $userid ) {
1396 $this->synchronize_user( $userid, $roles_usergroups );
1397 }
1398
1399 return false;
1400 }
1401
1402 ## -- START -- delete profiles where not participant on multisite blog
1403 if( is_multisite() ) {
1404 $sql = "DELETE FROM `" . WPF()->tables->profiles . "` WHERE `userid` NOT IN( SELECT `user_id` FROM `" . WPF(
1405 )->db->usermeta . "` WHERE `meta_key` LIKE '" . WPF()->blog_prefix . "capabilities' )";
1406 WPF()->db->query( $sql );
1407 }
1408
1409 ## -- END -- delete profiles where not participant on multisite blog
1410
1411 return true;
1412 }
1413
1414 public function _get_member( $args ) {
1415 if( ! $args ) return $this->get_guest();
1416
1417 $default = [
1418 'userid' => null, // $userid
1419 'user_nicename' => '', // $user_nicename
1420 ];
1421
1422 if( wpforo_is_id( $args ) ) {
1423 $args = [ 'userid' => $args ];
1424 } elseif( ! is_array( $args ) ) {
1425 $args = [ 'user_nicename' => $args ];
1426 }
1427
1428 $args = wpforo_parse_args( $args, $default );
1429
1430 extract( $args );
1431
1432 $userid = wpforo_bigintval( $userid );
1433
1434 $user_meta_obj = true;
1435 if( $user_nicename ) {
1436 $user_obj = get_user_by( 'user_nicename', $user_nicename );
1437 if( ! empty( $user_obj ) ) $userid = $user_obj->ID;
1438 }
1439 $member = get_user_meta( $userid, '_wpf_member_obj', true );
1440
1441 if( empty( $member ) ) {
1442 $user_meta_obj = false;
1443 $sql = "SELECT *,
1444 ug.`name` AS group_name,
1445 ug.`color` AS group_color,
1446 fn.`meta_value` AS first_name,
1447 ln.`meta_value` AS last_name
1448 FROM `" . WPF()->db->users . "` u
1449 INNER JOIN `" . WPF()->tables->profiles . "` p ON p.`userid` = u.`ID`
1450 LEFT JOIN `" . WPF()->tables->usergroups . "` ug ON ug.`groupid` = p.`groupid`
1451 LEFT JOIN `" . WPF()->db->usermeta . "` fn ON fn.`user_id` = u.`ID` AND fn.`meta_key` LIKE 'first_name'
1452 LEFT JOIN `" . WPF()->db->usermeta . "` ln ON ln.`user_id` = u.`ID` AND ln.`meta_key` LIKE 'last_name'";
1453 $wheres = [];
1454 if( $userid ) $wheres[] = "`ID` = $userid";
1455 if( $user_nicename ) $wheres[] = "`user_nicename` = '" . esc_sql( $user_nicename ) . "'";
1456 if( ! empty( $wheres ) ) $sql .= " WHERE " . implode( " AND ", $wheres );
1457 $member = WPF()->db->get_row( $sql, ARRAY_A );
1458 }
1459
1460 if( ! empty( $member ) && ! $user_meta_obj ) update_user_meta( $userid, '_wpf_member_obj', $member );
1461
1462 if( $member ) $member = $this->decode( $member );
1463
1464 return $member;
1465 }
1466
1467 public function get_member( $args ) {
1468 return wpforo_ram_get( [ $this, '_get_member' ], $args );
1469 }
1470
1471 public function get_members( $args = [], &$items_count = 0 ) {
1472 $default = [
1473 'include' => [], // array( 2, 10, 25 )
1474 'exclude' => [], // array( 2, 10, 25 )
1475 'status' => [ 'active', 'inactive', 'banned' ], // 'active', 'blocked', 'trashed', 'spamer'
1476 'groupid' => null, // groupid
1477 'online_time' => null, // groupid
1478 'orderby' => 'userid', //
1479 'order' => 'ASC', // ASC DESC
1480 'offset' => 0, // OFFSET
1481 'row_count' => null, // ROW COUNT
1482 'groupids' => [], // array( 1, 2 )
1483 ];
1484
1485 $args = wpforo_parse_args( $args, $default );
1486 extract( $args, EXTR_OVERWRITE );
1487
1488 $include = wpforo_parse_args( $include );
1489 $exclude = wpforo_parse_args( $exclude );
1490
1491 $sql = "SELECT *,
1492 ug.`name` AS group_name,
1493 ug.`color` AS group_color,
1494 fn.`meta_value` AS first_name,
1495 ln.`meta_value` AS last_name
1496 FROM `" . WPF()->db->users . "` u
1497 INNER JOIN `" . WPF()->tables->profiles . "` p ON p.`userid` = u.`ID`
1498 LEFT JOIN `" . WPF()->tables->usergroups . "` ug ON ug.`groupid` = p.`groupid`
1499 LEFT JOIN `" . WPF()->db->usermeta . "` fn ON fn.`user_id` = u.`ID` AND fn.`meta_key` LIKE 'first_name'
1500 LEFT JOIN `" . WPF()->db->usermeta . "` ln ON ln.`user_id` = u.`ID` AND fn.`meta_key` LIKE 'last_name'";
1501
1502 $sql_count = "SELECT count(*)
1503 FROM `" . WPF()->db->users . "` u
1504 INNER JOIN `" . WPF()->tables->profiles . "` p ON p.`userid` = u.`ID`
1505 LEFT JOIN `" . WPF()->tables->usergroups . "` ug ON ug.`groupid` = p.`groupid`";
1506
1507
1508 $wheres = [];
1509 if( ! empty( $include ) ) $wheres[] = " u.`ID` IN(" . implode( ', ', array_map( 'intval', $include ) ) . ")";
1510 if( ! empty( $exclude ) ) {
1511 $wheres[] = " u.`ID` NOT IN(" . implode(
1512 ', ',
1513 array_map( 'intval', $exclude )
1514 ) . ")";
1515 }
1516 if( ! empty( $status ) ) {
1517 $wheres[] = " p.`status` IN('" . implode(
1518 "','",
1519 array_map(
1520 'esc_sql',
1521 array_map(
1522 'sanitize_text_field',
1523 $status
1524 )
1525 )
1526 ) . "')";
1527 }
1528 if( ! empty( $groupids ) ) {
1529 $wheres[] = " (p.`groupid` IN(" . implode(
1530 ', ',
1531 array_map( 'intval', $groupids )
1532 ) . ") OR CONCAT(',', p.`secondary_groupids`, ',') REGEXP ',(" . implode(
1533 '|',
1534 array_map(
1535 'intval',
1536 $groupids
1537 )
1538 ) . "),' )";
1539 }
1540 if( ! is_null( $groupid ) ) {
1541 $wheres[] = " (p.`groupid` = " . intval( $groupid ) . " OR FIND_IN_SET(" . intval(
1542 $groupid
1543 ) . ", p.`secondary_groupids`) ) ";
1544 }
1545 if( ! is_null( $online_time ) ) $wheres[] = " p.`online_time` > " . intval( $online_time );
1546
1547 if( ! empty( $wheres ) ) {
1548 $sql .= " WHERE " . implode( " AND ", $wheres );
1549 $sql_count .= " WHERE " . implode( " AND ", $wheres );
1550 }
1551
1552 $item_count_sql = preg_replace( '#ORDER.+$#is', '', $sql_count );
1553 if( $item_count_sql ) $items_count = WPF()->db->get_var( $item_count_sql );
1554
1555 if( $orderby === 'groupid' ) $orderby = 'p.`groupid`';
1556 $sql .= esc_sql( " ORDER BY $orderby " . $order );
1557 if( $row_count ) $sql .= esc_sql( " LIMIT $offset,$row_count" );
1558
1559 return array_map( [ $this, 'decode' ], WPF()->db->get_results( $sql, ARRAY_A ) );
1560 }
1561
1562 public function search( $needle, $fields = [], $limit = null, $orderby = null ) {
1563 if( $needle ) {
1564 $needle = sanitize_text_field( $needle );
1565 if( empty( $fields ) ) {
1566 $fields = [
1567 'title',
1568 'user_nicename',
1569 'user_email',
1570 'signature',
1571 ];
1572 }
1573
1574 $sql = "SELECT `ID` FROM `" . WPF()->db->users . "` u
1575 INNER JOIN `" . WPF()->tables->profiles . "` p ON p.`userid` = u.`ID`";
1576 $wheres = [];
1577
1578 foreach( $fields as $field ) {
1579 $f = $this->get_field( $field );
1580 $field = sanitize_text_field( $field );
1581 if( $f['isDefault'] ) {
1582 if( $f['fieldKey'] === 'title' ) {
1583 $wheres[] = "`" . esc_sql( $field ) . "` LIKE '" . esc_sql( $needle ) . "'";
1584 } else {
1585 $wheres[] = "`" . esc_sql( $field ) . "` LIKE '%" . esc_sql( $needle ) . "%'";
1586 }
1587 } else {
1588 $needle = preg_quote( preg_quote( $needle ) );
1589 if( in_array( $f['type'], [ 'text', 'search', 'textarea' ], true ) ) {
1590 $wheres[] = "`fields` REGEXP '[{,]\"" . $field . "\":(\\\[[^\\\[]*)?\"[^\"]*" . esc_sql(
1591 $needle
1592 ) . "[^\"]*\"'";
1593 } else {
1594 $wheres[] = "`fields` REGEXP '[{,]\"" . $field . "\":(\\\[[^\\\[]*)?\"" . esc_sql(
1595 $needle
1596 ) . "\"'";
1597 }
1598 }
1599 }
1600
1601 if( ! empty( $wheres ) ) {
1602 $sql .= " WHERE " . implode( " OR ", $wheres );
1603 if( ! is_null( $orderby ) ) {
1604 $sql .= " ORDER BY " . implode( ', ', (array) $orderby );
1605 }
1606 if( $limit ) $sql .= " LIMIT " . intval( $limit );
1607
1608 return WPF()->db->get_col( $sql );
1609 } else {
1610 return [];
1611 }
1612 } else {
1613 return [];
1614 }
1615
1616 }
1617
1618 public function filter( $args, $limit = null, $orderby = null ) {
1619 if( $args && is_array( $args ) ) {
1620 $sql = "SELECT `ID` FROM `" . WPF()->db->users . "` u
1621 INNER JOIN `" . WPF()->tables->profiles . "` p ON p.`userid` = u.`ID`";
1622 $wheres = [];
1623
1624 foreach( $args as $field => $needle ) {
1625 $f = $this->get_field( $field );
1626 $field = sanitize_text_field( $field );
1627 if( $f['isDefault'] ) {
1628 if( is_scalar( $needle ) ) {
1629 $needle = sanitize_text_field( $needle );
1630 $wheres[] = "`" . esc_sql( $field ) . "` LIKE '%" . esc_sql( $needle ) . "%'";
1631 } elseif( is_array( $needle ) ) {
1632 foreach( $needle as $n ) {
1633 $n = sanitize_text_field( $n );
1634 $wheres[] = "`" . esc_sql( $field ) . "` LIKE '%" . esc_sql( $n ) . "%'";
1635 }
1636 }
1637 } else {
1638 if( in_array( $f['type'], [ 'text', 'search', 'textarea' ], true ) ) {
1639 if( is_scalar( $needle ) ) {
1640 $needle = preg_quote( preg_quote( wpforo_encode( $needle ) ) );
1641 $wheres[] = "`fields` REGEXP '[{,]\"" . $field . "\":(\\\[[^\\\[]*)?\"[^\"]*" . esc_sql(
1642 $needle
1643 ) . "[^\"]*\"'";
1644 } elseif( is_array( $needle ) ) {
1645 foreach( $needle as $n ) {
1646 $n = preg_quote( preg_quote( wpforo_encode( $n ) ) );
1647 $wheres[] = "`fields` REGEXP '[{,]\"" . $field . "\":(\\\[[^\\\[]*)?\"[^\"]*" . esc_sql(
1648 $n
1649 ) . "[^\"]*\"'";
1650 }
1651 }
1652 } else {
1653 if( is_scalar( $needle ) ) {
1654 $needle = preg_quote( preg_quote( wpforo_encode( $needle ) ) );
1655 $wheres[] = "`fields` REGEXP '[{,]\"" . $field . "\":(\\\[[^\\\[]*)?\"" . esc_sql(
1656 $needle
1657 ) . "\"'";
1658 } elseif( is_array( $needle ) ) {
1659 foreach( $needle as $n ) {
1660 $n = preg_quote( preg_quote( wpforo_encode( $n ) ) );
1661 $wheres[] = "`fields` REGEXP '[{,]\"" . $field . "\":(\\\[[^\\\[]*)?\"" . esc_sql(
1662 $n
1663 ) . "\"'";
1664 }
1665 }
1666 }
1667 }
1668 }
1669
1670 if( $wheres ) {
1671 $sql .= " WHERE " . implode( " AND ", $wheres );
1672 if( ! is_null( $orderby ) ) {
1673 $sql .= " ORDER BY " . implode( ', ', (array) $orderby );
1674 }
1675 if( $limit ) $sql .= " LIMIT " . intval( $limit );
1676
1677 return WPF()->db->get_col( $sql );
1678 }
1679 }
1680
1681 return [];
1682 }
1683
1684 public function ban( $userid ) {
1685 if( $userid == WPF()->current_userid ) {
1686 WPF()->notice->add( 'You can\'t make yourself banned user', 'error' );
1687
1688 return false;
1689 }
1690 if( ! WPF()->usergroup->can( 'bm' ) || ! WPF()->perm->user_can_manage_user(
1691 WPF()->current_userid,
1692 intval( $userid )
1693 ) ) {
1694 WPF()->notice->add( 'Permission denied for this action', 'error' );
1695
1696 return false;
1697 }
1698 if( false !== WPF()->db->update(
1699 WPF()->tables->profiles,
1700 [ 'status' => 'banned' ],
1701 [ 'userid' => intval( $userid ) ],
1702 [ '%s' ],
1703 [ '%d' ]
1704 ) ) {
1705 do_action( 'wpforo_after_ban_user', $userid );
1706 $this->reset( $userid );
1707 WPF()->notice->add( 'User successfully banned from wpforo', 'success' );
1708
1709 return true;
1710 }
1711
1712 WPF()->notice->add( 'User ban action error', 'error' );
1713
1714 return false;
1715 }
1716
1717 public function unban( $userid ) {
1718 if( ! WPF()->usergroup->can( 'bm' ) || ! WPF()->perm->user_can_manage_user(
1719 WPF()->current_userid,
1720 intval( $userid )
1721 ) ) {
1722 WPF()->notice->add( 'Permission denied for this action', 'error' );
1723
1724 return false;
1725 }
1726 if( false !== WPF()->db->update(
1727 WPF()->tables->profiles,
1728 [ 'status' => 'active' ],
1729 [ 'userid' => intval( $userid ) ],
1730 [ '%s' ],
1731 [ '%d' ]
1732 ) ) {
1733 do_action( 'wpforo_after_unban_user', $userid );
1734 $this->reset( $userid );
1735 WPF()->notice->add( 'User successfully unbanned from wpforo', 'success' );
1736
1737 return true;
1738 }
1739
1740 WPF()->notice->add( 'User unban action error', 'error' );
1741
1742 return false;
1743 }
1744
1745 public function activate( $userid ) {
1746 if( false !== WPF()->db->update(
1747 WPF()->tables->profiles,
1748 [ 'status' => 'active' ],
1749 [ 'userid' => intval( $userid ) ],
1750 [ '%s' ],
1751 [ '%d' ]
1752 ) ) {
1753 do_action( 'wpforo_after_activate_user', $userid );
1754 $this->reset( $userid );
1755 WPF()->notice->add( 'User successfully activated from wpforo', 'success' );
1756
1757 return true;
1758 }
1759
1760 WPF()->notice->add( 'User activate action error', 'error' );
1761
1762 return false;
1763 }
1764
1765 public function deactivate( $userid ) {
1766 if( false !== WPF()->db->update(
1767 WPF()->tables->profiles,
1768 [ 'status' => 'inactive' ],
1769 [ 'userid' => intval( $userid ) ],
1770 [ '%s' ],
1771 [ '%d' ]
1772 ) ) {
1773 do_action( 'wpforo_after_deactivate_user', $userid );
1774 $this->reset( $userid );
1775 WPF()->notice->add( 'User successfully deactivated from wpforo', 'success' );
1776
1777 return true;
1778 }
1779
1780 WPF()->notice->add( 'User deactivate action error', 'error' );
1781
1782 return false;
1783 }
1784
1785 /**
1786 *
1787 * @param int $userid
1788 * @param int $reassign
1789 *
1790 * @return bool true | false if user successfully deleted
1791 */
1792 public function delete( $userid, $reassign = null ) {
1793 if( ! ( $userid = wpforo_bigintval( $userid ) ) ) return false;
1794 do_action( 'wpforo_before_delete_user', $userid, $reassign );
1795
1796 if( false !== WPF()->db->delete( WPF()->tables->profiles, [ 'userid' => $userid ], [ '%d' ] ) ) {
1797 do_action( 'wpforo_after_delete_user', $userid, $reassign );
1798
1799 WPF()->notice->add( 'User successfully deleted', 'success' );
1800
1801 return true;
1802 }
1803
1804 WPF()->notice->add( 'User delete error', 'error' );
1805
1806 return false;
1807 }
1808
1809 /**
1810 * @deprecated since 2.1.6 version instead of this use $this->_get_avatar() method
1811 */
1812 public function _avatar( $user, $attr = '', $size = 96 ) {
1813 return $this->_get_avatar( $user, $size, $attr );
1814 }
1815
1816 /**
1817 * @deprecated since 2.1.6 version instead of this use $this->get_avatar() method
1818 */
1819 public function avatar( $user, $attr = '', $size = 96 ) {
1820 return wpforo_ram_get( [ $this, '_avatar' ], $user, $attr, $size );
1821 }
1822
1823 public function _get_avatar( $user, $size = 96, $attr = '' ) {
1824 return $this->get_avatar_html( $this->get_avatar_url( $user ), $user, $size, $attr );
1825 }
1826
1827 public function get_avatar( $user, $size = 96, $attr = '' ) {
1828 return wpforo_ram_get( [ $this, '_get_avatar' ], $user, $size, $attr );
1829 }
1830
1831 public function _get_avatar_url( $user ) {
1832 $cache = WPF()->cache->on( 'avatar' );
1833
1834 if( is_scalar( $user ) ) {
1835 $userid = wpforo_bigintval( $user );
1836 $cache_avatar = apply_filters( 'wpforo_avatar_cache', true, $userid );
1837 if( $cache && $cache_avatar && $avatar_url = WPF()->cache->get_item( $userid, 'avatar' ) ) {
1838 return str_replace( '#', '', (string) $avatar_url );
1839 }
1840 $avatar_url = (string) WPF()->db->get_var(
1841 WPF()->db->prepare(
1842 "SELECT `avatar` FROM `" . WPF()->tables->profiles . "` WHERE `userid` = %d",
1843 wpforo_bigintval( $userid )
1844 )
1845 );
1846 } else {
1847 $avatar_url = (string) wpfval( $user, 'avatar' );
1848 $userid = wpforo_bigintval( wpfval( $user, 'userid' ) );
1849 }
1850
1851 if( $cache && $userid ) {
1852 WPF()->cache->create( 'item', [ $userid => $avatar_url ?: '#' ], 'avatar' );
1853 }
1854
1855 return apply_filters( 'wpforo_avatar_url', $avatar_url, $userid );
1856 }
1857
1858 public function get_avatar_url( $user ) {
1859 return wpforo_ram_get( [ $this, '_get_avatar_url' ], $user );
1860 }
1861
1862 public function get_avatar_html( $url, $user = [], $size = 96, $attr = '' ) {
1863 $size = intval( $size );
1864 if( $url && wpforo_setting( 'profiles', 'custom_avatars' ) ) {
1865 $url = apply_filters( 'wpforo_avatar_url', $url, $user );
1866 $dname = ! is_scalar( $user ) ? wpforo_user_dname( $user ) : $this->get_member( $user )['dname'];
1867 if( strpos( (string) $attr, 'alt=' ) === false ) $attr .= ' ' . sprintf( 'alt="%1$s"', esc_attr( $dname ) );
1868 if( strpos( (string) $attr, 'title=' ) === false ) {
1869 $attr .= ' ' . sprintf(
1870 'title="%1$s"',
1871 esc_attr( $dname )
1872 );
1873 }
1874 if( strpos( (string) $attr, 'height=' ) === false ) $attr .= ' ' . sprintf( 'height="%1$d"', $size );
1875 if( strpos( (string) $attr, 'width=' ) === false ) $attr .= ' ' . sprintf( 'width="%1$d"', $size );
1876 $img = '<img class="avatar" src="' . esc_url( (string) $url ) . '" ' . $attr . ' >';
1877 } else {
1878 $userid = is_scalar( $user ) ? wpforo_bigintval( $user ) : ( wpforo_bigintval(
1879 wpfval( $user, 'userid' )
1880 ) ?: (string) wpfval( $user, 'user_email' ) );
1881 $img = get_avatar( $userid, $size );
1882 if( $attr ) $img = str_replace( '<img', '<img ' . $attr, $img );
1883 }
1884
1885 return $img;
1886 }
1887
1888 /**
1889 * @param array|int|string $arg
1890 * @param string $template
1891 *
1892 * @return string
1893 */
1894 public function get_profile_url( $arg, $template = 'profile', $ram_cache = true ) {
1895 $user = is_scalar( $arg ) ? ( $ram_cache ? $this->get_member(
1896 intval( basename( (string) $arg ) )
1897 ) : $this->_get_member(
1898 intval( basename( (string) $arg ) )
1899 ) ) ?: [ 'user_nicename' => basename( (string) $arg ) ] : $arg;
1900 if( wpfkey( $user, 'userid' ) && wpfkey( $user, 'user_nicename' ) ) {
1901 $user_slug = ( wpforo_setting(
1902 'profiles',
1903 'url_structure'
1904 ) === 'id' ? $user['userid'] : $user['user_nicename'] );
1905 if( $template === 'profile' ) {
1906 $profile_url = wpforo_url( $user_slug, 'member' );
1907 } else {
1908 $template_slug = wpforo_settings_get_slug( $template );
1909 $profile_url = wpforo_url( "$user_slug/$template_slug", 'member' );
1910 }
1911 } else {
1912 $profile_url = wpforo_home_url();
1913 }
1914
1915 return apply_filters( 'wpforo_member_profile_url', $profile_url, $user, $template );
1916 }
1917
1918 /**
1919 * @param float $points
1920 *
1921 * @return array
1922 */
1923 public function calc_rating( float $points ): array {
1924 $rating = $this->default->member['rating'];
1925
1926 $rating['level'] = $this->rating_level( floatval( $points ), false );
1927 $rating['percent'] = $rating['level'] * 10;
1928 $rating['title'] = $this->rating( $rating['level'], 'title' );
1929 $rating['color'] = $this->rating( $rating['level'], 'color' );
1930 $rating['badge'] = $this->rating( $rating['level'], 'icon' );
1931
1932 return $rating;
1933 }
1934
1935 /**
1936 * @param $member
1937 *
1938 * @return float
1939 */
1940 private function calc_points( $member ): float {
1941 $topic_points = intval( $member['topics'] ) * wpforo_setting( 'rating', 'topic_points' );
1942 $post_points = intval( $member['posts'] ) * wpforo_setting( 'rating', 'post_points' );
1943 $like_points = intval( wpfval( $member, 'reactions_in', 'up' ) ) * wpforo_setting( 'rating', 'like_points' );
1944 $dislike_points = intval( wpfval( $member, 'reactions_in', 'down' ) ) * wpforo_setting(
1945 'rating',
1946 'dislike_points'
1947 );
1948
1949 $topic_points = (float) apply_filters( 'wpforo_member_get_points_topic_points', $topic_points, $member );
1950 $post_points = (float) apply_filters( 'wpforo_member_get_points_post_points', $post_points, $member );
1951 $like_points = (float) apply_filters( 'wpforo_member_get_points_like_points', $like_points, $member );
1952 $dislike_points = (float) apply_filters( 'wpforo_member_get_points_dislike_points', $dislike_points, $member );
1953 $other_points = (float) apply_filters( 'wpforo_member_get_points_other_points', 0, $member );
1954
1955 return $topic_points + $post_points + $like_points + $dislike_points + $other_points;
1956 }
1957
1958 public function get_count( $args = [] ): int {
1959 $sql = "SELECT SQL_NO_CACHE COUNT(*) FROM `" . WPF()->tables->profiles . "` p
1960 INNER JOIN `" . WPF()->db->users . "` u ON u.`ID` = p.`userid` WHERE p.`status` NOT LIKE 'trashed'";
1961 if( $args ) {
1962 $wheres = [];
1963 foreach( $args as $key => $value ) {
1964 if( is_array( $value ) ) {
1965 $wheres[] = "$key IN('" . implode( "','", array_map( 'esc_sql', $value ) ) . "')";
1966 } else {
1967 $wheres[] = "$key = '" . esc_sql( $value ) . "'";
1968 }
1969 }
1970 if( $wheres ) $sql .= " AND " . implode( ' AND ', $wheres );
1971 }
1972
1973 return (int) WPF()->db->get_var( $sql );
1974 }
1975
1976 public function _is_online( $userid, $duration = null ) {
1977 if( ! $duration ) $duration = wpforo_setting( 'profiles', 'online_status_timeout' );
1978 $sql = "SELECT `online_time` FROM `" . WPF()->tables->profiles . "` WHERE `userid` = %d";
1979 $sql = WPF()->db->prepare( $sql, $userid );
1980 $online_time = intval( WPF()->db->get_var( $sql ) );
1981 $current_time = time();
1982
1983 return ( $current_time - $online_time ) < $duration;
1984 }
1985
1986 public function is_online( $userid, $duration = null ) {
1987 return wpforo_ram_get( [ $this, '_is_online' ], $userid, $duration );
1988 }
1989
1990 public function show_online_indicator( $userid, $ico = true ) {
1991 if( $this->is_online( $userid ) ) : ?>
1992
1993 <?php if( $ico ) : ?>
1994 <i class="fas fa-circle wpfsx wpfcl-8" title="<?php wpforo_phrase( 'Online' ) ?>"></i>
1995 <?php else : wpforo_phrase( 'Online' ); endif ?>
1996
1997 <?php else : ?>
1998
1999 <?php if( $ico ) : ?>
2000 <i class="fas fa-circle wpfsx wpfcl-0" title="<?php wpforo_phrase( 'Offline' ) ?>"></i>
2001 <?php else : wpforo_phrase( 'Offline' ); endif ?>
2002
2003 <?php endif;
2004 }
2005
2006 public function online_members_count( $duration = null ) {
2007 if( ! ( $duration = intval( $duration ) ) ) {
2008 $duration = (int) wpforo_setting(
2009 'profiles',
2010 'online_status_timeout'
2011 );
2012 }
2013 $online_timeframe = time() - $duration;
2014 $key = [ 'member', 'online_members_count', $online_timeframe ];
2015 if( WPF()->ram_cache->exists( $key ) ) return WPF()->ram_cache->get( $key );
2016 $sql = "SELECT COUNT(DISTINCT `userid`, `ip`) AS total FROM `" . WPF()->tables->visits . "` WHERE `time` > %d";
2017 $var = (int) WPF()->db->get_var( WPF()->db->prepare( $sql, $online_timeframe ) );
2018 if( ! $var ) {
2019 $sql = "SELECT COUNT(*) FROM `" . WPF()->tables->profiles . "` WHERE `online_time` > %d";
2020 $var = (int) WPF()->db->get_var( WPF()->db->prepare( $sql, $online_timeframe ) );
2021 }
2022 WPF()->ram_cache->set( $key, $var );
2023
2024 return $var;
2025 }
2026
2027 public function get_online_members( $count = 1, $groupids = [], $duration = null ) {
2028 if( ! $duration ) $duration = wpforo_setting( 'profiles', 'online_status_timeout' );
2029 $current_time = time();
2030 $online_timeframe = $current_time - $duration;
2031 $groupids = array_filter( wpforo_parse_args( $groupids ) );
2032 $args = [
2033 'groupids' => $groupids,
2034 'online_time' => $online_timeframe, // $current_time - $duration
2035 'orderby' => 'userid', // forumid, order, parentid
2036 'row_count' => $count,
2037 'order' => 'ASC', // ASC DESC
2038 ];
2039
2040 return $this->get_members( $args );
2041 }
2042
2043 public function levels() {
2044 $max_rating_levels = (int) apply_filters( 'wpforo_max_rating_levels', 10 );
2045
2046 return range( 0, $max_rating_levels );
2047 }
2048
2049 public function rating( $level = null, $var = '' ) {
2050 if( is_null( $level ) ) return wpforo_setting( 'rating', 'levels' );
2051 $_levels = wpforo_setting( 'rating', 'levels' );
2052 if( ! wpfkey( $_levels, $level ) ) $level = 0;
2053 if( ! $var ) return wpforo_setting( 'rating', 'levels', $level );
2054
2055 return wpforo_setting( 'rating', 'levels', $level, $var );
2056 }
2057
2058 /**
2059 * @param int $points
2060 * @param bool $percent
2061 *
2062 * @return int
2063 */
2064 public function rating_level( $points, $percent = true ) {
2065 $points = intval( $points );
2066 $max_rating_levels = (int) apply_filters( 'wpforo_max_rating_levels', 10 );
2067 $increment = 100 / $max_rating_levels;
2068 for( $level = 1; $level <= $max_rating_levels; $level ++ ) {
2069 if( $points < $this->rating( $level, 'points' ) ) {
2070 $bar = ( $level - 1 ) * $increment;
2071 break;
2072 }
2073 }
2074 // If the points are greater than or equal to the highest level's points, set $bar to 100
2075 if( ! isset( $bar ) ) $bar = 100;
2076
2077 return $percent ? $bar : (int) floor( $bar / ( 100 / $max_rating_levels ) );
2078 }
2079
2080
2081 public function rating_badge( $level = 0, $view = 'short' ) {
2082
2083 $max_rating_levels = (int) apply_filters( 'wpforo_max_rating_levels', 10 );
2084 $level = ( $level > $max_rating_levels ) ? floor( $level / $max_rating_levels ) : $level;
2085
2086 if( $level === 0 ) {
2087 return '<i class="' . $this->rating( $level, 'icon' ) . '"></i>';
2088 } elseif( $level > 0 && $level < 6 ) {
2089 if( $view == 'full' ) {
2090 return str_repeat( ' <i class="' . $this->rating( $level, 'icon' ) . '"></i> ', $level );
2091 } else {
2092 return '<span>' . esc_html( $level ) . '</span> <i class="' . $this->rating(
2093 $level,
2094 'icon'
2095 ) . '"></i>';
2096 }
2097 } elseif( $level > 5 && $level < 9 ) {
2098 if( $view == 'full' ) {
2099 return str_repeat( ' <i class="' . $this->rating( $level, 'icon' ) . '"></i> ', ( $level - 5 ) );
2100 } else {
2101 return '<span>' . esc_html( $level - 5 ) . '</span> <i class="' . $this->rating(
2102 $level,
2103 'icon'
2104 ) . '"></i>';
2105 }
2106 }
2107
2108 if( $max_rating_levels > 10 ) {
2109 if( $level < 12 ) {
2110 if( $view == 'full' ) {
2111 return str_repeat( ' <i class="' . $this->rating( $level, 'icon' ) . '"></i> ', ( $level - 8 ) );
2112 } else {
2113 return '<span>' . esc_html( $level - 8 ) . '</span> <i class="' . $this->rating(
2114 $level,
2115 'icon'
2116 ) . '"></i>';
2117 }
2118 } elseif( $level < 15 ) {
2119 if( $view == 'full' ) {
2120 return str_repeat( ' <i class="' . $this->rating( $level, 'icon' ) . '"></i> ', ( $level - 11 ) );
2121 } else {
2122 return '<span>' . esc_html( $level - 11 ) . '</span> <i class="' . $this->rating(
2123 $level,
2124 'icon'
2125 ) . '"></i>';
2126 }
2127 }
2128 } else {
2129 if( $level > 8 ) {
2130 return '<i class="' . $this->rating( $level, 'icon' ) . '"></i>';
2131 }
2132 }
2133
2134 return '';
2135 }
2136
2137 public function reset( $userid ) {
2138 if( ! $userid ) return;
2139 wpforo_clean_cache( 'avatar', $userid );
2140 delete_user_meta( intval( $userid ), '_wpf_member_obj' );
2141 if( wpforo_setting( 'seo', 'seo_profile' ) ) WPF()->seo->clear_cache();
2142 }
2143
2144 public function clear_db_cache() {
2145 WPF()->db->query( "DELETE FROM `" . WPF()->db->usermeta . "` WHERE `meta_key` = '_wpf_member_obj'" );
2146 }
2147
2148 private function update_online_time( $userid = null ) {
2149 if( ! $userid ) $userid = WPF()->current_userid;
2150 if( ! $userid ) return false;
2151 $current_timestamp = time();
2152 $sql = "UPDATE `" . WPF()->tables->profiles . "` SET `online_time` = %d WHERE `userid` = %d";
2153 $sql = WPF()->db->prepare( $sql, $current_timestamp, wpforo_bigintval( $userid ) );
2154 if( false !== WPF()->db->query( $sql ) ) return $current_timestamp;
2155
2156 return false;
2157 }
2158
2159 public function init_current_user() {
2160 WPF()->wp_current_user = $current_user = wp_get_current_user();
2161 if( $current_user->exists() ) {
2162 WPF()->current_userid = $current_user->ID;
2163 WPF()->current_user_login = $current_user->user_login;
2164 WPF()->current_user_email = $current_user->user_email;
2165 WPF()->current_user_display_name = $current_user->display_name;
2166
2167 $user = $this->get_member( $current_user->ID );
2168 if( ! wpfkey( $user, 'groupid' ) ) {
2169 $this->synchronize_user( $current_user->ID );
2170 $user = $this->get_member( $current_user->ID );
2171 }
2172 $user_meta = get_user_meta( $current_user->ID );
2173 WPF()->current_user = $user;
2174 WPF()->current_usermeta = $user_meta;
2175 WPF()->current_user_groupid = WPF()->current_user['groupid'];
2176 WPF()->current_user_secondary_groupids = WPF()->current_user['secondary_groupids'];
2177 WPF()->current_user_groupids = WPF()->current_user['groupids'];
2178 WPF()->current_user_status = (string) wpfval( $user, 'status' );
2179 $this->update_online_time();
2180 } elseif( $guest = $this->get_guest_cookies() ) {
2181 WPF()->current_userid = 0;
2182 WPF()->current_user_login = '';
2183 WPF()->current_user_email = $guest['email'];
2184 WPF()->current_user_display_name = $guest['name'];
2185 WPF()->current_user = $this->get_guest( $guest );
2186 WPF()->current_usermeta = [];
2187 WPF()->current_user_groupid = 4;
2188 WPF()->current_user_groupids = [ 4 ];
2189 WPF()->current_user_secondary_groupids = [];
2190 WPF()->current_user_status = '';
2191 WPF()->current_user_accesses = [];
2192 }
2193
2194 WPF()->usergroup->init_current();
2195
2196 if( function_exists( 'wp_get_session_token' ) && function_exists( 'wp_parse_auth_cookie' ) ) {
2197 WPF()->session_token = wp_get_session_token();
2198 }
2199 if( ! WPF()->session_token ) {
2200 $secret_key = defined( 'SECRET_KEY' ) && SECRET_KEY ? SECRET_KEY : 'wpforo';
2201 WPF()->session_token = hash_hmac(
2202 'sha256',
2203 md5( (string) wpfval( $_SERVER, 'HTTP_USER_AGENT' ) ) . md5(
2204 (string) wpfval( $_SERVER, 'REMOTE_ADDR' )
2205 ) . md5(
2206 (string) wpfval( $_SERVER, 'SERVER_ADDR' )
2207 ),
2208 $secret_key
2209 );
2210 }
2211
2212 do_action(
2213 'wpforo_after_init_current_user',
2214 WPF()->current_user,
2215 WPF()->current_usermeta,
2216 WPF()->current_user_groupid,
2217 WPF()->current_user_secondary_groupids,
2218 WPF()->current_user_groupids
2219 );
2220 }
2221
2222 public function blog_posts( $userid ) {
2223 if( isset( $userid ) && $userid ) return count_user_posts( $userid );
2224
2225 return 0;
2226 }
2227
2228 public function blog_comments( $userid, $user_email ) {
2229 global $wpdb;
2230 if( ! $userid || ! $user_email ) return 0;
2231
2232 return (int) $wpdb->get_var(
2233 "SELECT COUNT(*) FROM " . $wpdb->comments . " WHERE `user_id` = " . intval(
2234 $userid
2235 ) . " OR `comment_author_email` = '" . esc_sql( $user_email ) . "'"
2236 );
2237 }
2238
2239 public function show_delete_form( $current_user, $userids ) {
2240 if( empty( $current_user ) || empty( $userids ) ) return;
2241
2242 $userids = array_diff( $userids, [ $current_user->ID ] );
2243 $users_have_content = false;
2244 if( WPF()->db->get_var(
2245 "SELECT `postid` FROM `" . WPF()->tables->posts . "` WHERE `userid` IN( " . implode(
2246 ',',
2247 array_map( 'intval', $userids )
2248 ) . " ) LIMIT 1"
2249 ) ) {
2250 $users_have_content = true;
2251 }
2252 ?>
2253 <hr/><strong>#wpForo</strong>
2254 <?php if( ! $users_have_content ) : ?>
2255 <input type="hidden" name="wpforo_user_delete_option" value="delete"/>
2256 <?php else: ?>
2257 <?php if( 1 == count( $userids ) ) : ?>
2258 <fieldset>
2259 <legend><?php _e( 'What should be done with wpForo content owned by this user?', 'wpforo' ); ?></legend>
2260 <?php else : ?>
2261 <fieldset>
2262 <legend><?php _e(
2263 'What should be done with wpForo content owned by these users?',
2264 'wpforo'
2265 ); ?></legend>
2266 <?php endif; ?>
2267 <ul style="list-style:none;">
2268 <li><label><input type="radio" id="wpforo_delete_option0" name="wpforo_user_delete_option"
2269 value="delete">
2270 <?php _e( 'Delete all wpForo content.', 'wpforo' ); ?></label></li>
2271 <li><input type="radio" id="wpforo_delete_option1" name="wpforo_user_delete_option" value="reassign">
2272 <label for="wpforo_delete_option1"><?php _e( 'Attribute all content to:' ) ?></label>
2273 <?php
2274 wp_dropdown_users( [
2275 'name' => 'wpforo_reassign_userid',
2276 'exclude' => $userids,
2277 'show' => 'display_name_with_login',
2278 ] );
2279 ?>
2280 </li>
2281 </ul></fieldset>
2282 <script type="text/javascript">
2283 jQuery(document).ready(function ($) {
2284 $('#wpforo_reassign_userid').on('focus', function () {
2285 $('#wpforo_delete_option1').prop('checked', true).trigger('change');
2286 });
2287 });
2288 </script>
2289 <?php endif;
2290 }
2291
2292 public function autoban( $userid ) {
2293 if( ! WPF()->usergroup->can( 'em' ) ) {
2294 WPF()->db->update(
2295 WPF()->tables->profiles,
2296 [ 'status' => 'banned' ],
2297 [ 'userid' => intval( $userid ) ],
2298 [ '%s' ],
2299 [ '%d' ]
2300 );
2301 }
2302 }
2303
2304 public function member_approved_posts( $member = [] ) {
2305 if( is_numeric( $member ) ) {
2306 if( $userid = wpforo_bigintval( $member ) ) {
2307 if( $userid === WPF()->current_userid ) return WPF()->current_user['posts'];
2308
2309 return (int) WPF()->db->get_var(
2310 WPF()->db->prepare(
2311 "SELECT COUNT(*) as posts
2312 FROM `" . WPF()->tables->posts . "`
2313 WHERE `status` = 0
2314 AND `userid` = %d",
2315 $userid
2316 )
2317 );
2318 }
2319 }
2320
2321 return (int) wpfval( $member, 'posts' );
2322 }
2323
2324 public function current_user_is_new() {
2325 if( WPF()->usergroup->can( 'em' ) ) {
2326 //This is an admin or moderator. The number of posts doesn't matter.
2327 return false;
2328 } else {
2329 $new_user_max_posts = wpforo_setting( 'antispam', 'new_user_max_posts' );
2330 $posts = $this->member_approved_posts( WPF()->current_userid );
2331 if( $new_user_max_posts && $posts <= $new_user_max_posts ) {
2332 return true;
2333 } else {
2334 return false;
2335 }
2336 }
2337 }
2338
2339 /**
2340 * @return int
2341 */
2342 public function banned_count() {
2343 $key = [ 'member', 'banned_count' ];
2344 if( WPF()->ram_cache->exists( $key ) ) return WPF()->ram_cache->get( $key );
2345 $var = (int) WPF()->db->get_var(
2346 "SELECT count(*) FROM `" . WPF()->tables->profiles . "` WHERE `status` = 'banned'"
2347 );
2348 WPF()->ram_cache->set( $key, $var );
2349
2350 return $var;
2351 }
2352
2353 public function _get_guest_posts( $email ) {
2354 $sqls = [];
2355 foreach( WPF()->get_active_boards_tables( 'posts' ) as $table ) {
2356 $sqls[] = WPF()->db->prepare(
2357 "SELECT *
2358 FROM `$table`
2359 WHERE `status` = 0
2360 AND `email` = %s",
2361 $email
2362 );
2363 }
2364
2365 if( $sqls ) {
2366 return (array) WPF()->db->get_results(
2367 implode( ' UNION ALL ', $sqls ) . " ORDER BY `created` ASC, `postid` ASC",
2368 ARRAY_A
2369 );
2370 }
2371
2372 return [];
2373 }
2374
2375 public function get_guest_posts( $email ) {
2376 return wpforo_ram_get( [ $this, '_get_guest_posts' ], $email );
2377 }
2378
2379 public function _get_guest( $args = [] ) {
2380 if( ! wpfval( $args, 'name' ) ) $args['name'] = wpforo_phrase( 'Anonymous', false );
2381 if( ! wpfval( $args, 'email' ) ) $args['email'] = 'anonymous@example.com';
2382
2383 $args['name'] = strip_tags( (string) $args['name'] );
2384 $args['email'] = sanitize_email( $args['email'] );
2385 $args['user_registered'] = current_time( 'mysql', 1 );
2386 $args['posts'] = 0;
2387
2388 if( $args['email'] && $args['email'] !== 'anonymous@example.com' ) {
2389 if( $posts = $this->get_guest_posts( $args['email'] ) ) {
2390 $args['posts'] = count( $posts );
2391 if( $first_post_created = wpfval(
2392 $posts,
2393 0,
2394 'created'
2395 ) ) {
2396 $args['user_registered'] = $first_post_created;
2397 }
2398 }
2399 }
2400
2401 $guest = wpforo_array_args_cast_and_merge(
2402 [
2403 'groupid' => 4,
2404 'group_name' => wpforo_phrase( 'Guest', false ),
2405 'user_login' => $args['name'],
2406 'user_nicename' => sanitize_text_field( $args['name'] ),
2407 'user_email' => $args['email'],
2408 'user_registered' => $args['user_registered'],
2409 'display_name' => $args['name'],
2410 'posts' => $args['posts'],
2411 'status' => 'active',
2412 ],
2413 $this->default->member
2414 );
2415
2416 return $this->decode( $guest );
2417 }
2418
2419 public function get_guest( $args = [] ) {
2420 return wpforo_ram_get( [ $this, '_get_guest' ], $args );
2421 }
2422
2423 public function init_fields() {
2424 if( ! empty( $this->fields ) ) return;
2425
2426 $this->init_countries();
2427 $this->init_timezones();
2428
2429 $this->fields = apply_filters( 'wpforo_member_before_init_fields', $this->fields );
2430
2431 $usergroupids = [];
2432 $usergroups = WPF()->usergroup->get_usergroups();
2433 foreach( $usergroups as $usergroup ) {
2434 $usergroupids[] = $usergroup['groupid'];
2435 }
2436 $usergroupids_can_edit_fields = WPF()->usergroup->get_groupids_by_can( 'em' );
2437 $usergroupids_can_view_social_net = WPF()->usergroup->get_groupids_by_can( 'vmsn' );
2438
2439 /**
2440 * start init tinymce settings
2441 */
2442 $wp_editor_settings = WPF()->tpl->editor_buttons();
2443 $wp_editor_settings['tinymce']['toolbar1'] = 'bold,italic,link,unlink,undo,redo,source_code,emoticons';
2444 $wp_editor_settings['plugins'] = '';
2445 unset(
2446 $wp_editor_settings['external_plugins']['wpforo_pre_button'], $wp_editor_settings['external_plugins']['wpforo_spoiler_button']
2447 );
2448 $wp_editor_settings = apply_filters( 'wpforo_members_init_fields_tinymce_settings', $wp_editor_settings );
2449
2450 $this->fields['user_login'] = [
2451 'fieldKey' => 'user_login',
2452 'type' => 'text',
2453 'isDefault' => 1,
2454 'isRemovable' => 0,
2455 'isRequired' => 1,
2456 'isEditable' => 0,
2457 'label' => wpforo_phrase( 'Username', false ),
2458 'title' => wpforo_phrase( 'Username', false ),
2459 'placeholder' => wpforo_phrase( 'Username', false ),
2460 'description' => wpforo_phrase( 'Length must be between 3 characters and 15 characters.', false ),
2461 'minLength' => 3,
2462 'maxLength' => 30,
2463 'faIcon' => 'fas fa-user',
2464 'name' => 'user_login',
2465 'cantBeInactive' => [ 'register' ],
2466 'canEdit' => [],
2467 'canView' => WPF()->usergroup->get_groupids_by_can( 'vmu' ),
2468 'can' => 'vmu',
2469 'isSearchable' => 0,
2470 ];
2471
2472 $this->fields['user_email'] = [
2473 'fieldKey' => 'user_email',
2474 'type' => 'email',
2475 'isDefault' => 1,
2476 'isRemovable' => 0,
2477 'isRequired' => 1,
2478 'isEditable' => 1,
2479 'label' => wpforo_phrase( 'Email', false ),
2480 'title' => wpforo_phrase( 'Email', false ),
2481 'placeholder' => wpforo_phrase( 'Email', false ),
2482 'minLength' => 0,
2483 'maxLength' => 0,
2484 'faIcon' => 'fas fa-envelope',
2485 'name' => 'user_email',
2486 'cantBeInactive' => [ 'register' ],
2487 'canEdit' => $usergroupids_can_edit_fields,
2488 'canView' => WPF()->usergroup->get_groupids_by_can( 'vmm' ),
2489 'can' => 'vmm',
2490 'isSearchable' => 1,
2491 ];
2492
2493 $this->fields['user_pass'] = [
2494 'fieldKey' => 'user_pass',
2495 'type' => 'password',
2496 'isDefault' => 1,
2497 'isRemovable' => 0,
2498 'isRequired' => 1,
2499 'isEditable' => 1,
2500 'label' => wpforo_phrase( 'Password', false ),
2501 'title' => wpforo_phrase( 'Password', false ),
2502 'placeholder' => wpforo_phrase( 'Password', false ),
2503 'description' => wpforo_phrase( 'Must be minimum 6 characters.', false ),
2504 'minLength' => 6,
2505 'maxLength' => 20,
2506 'faIcon' => 'fas fa-key',
2507 'name' => 'user_pass',
2508 'cantBeInactive' => [
2509 'account',
2510 'register',
2511 ],
2512 'canEdit' => $usergroupids_can_edit_fields,
2513 'canView' => [],
2514 'can' => '',
2515 'isSearchable' => 0,
2516 ];
2517
2518 $this->fields['display_name'] = [
2519 'fieldKey' => 'display_name',
2520 'type' => 'text',
2521 'isDefault' => 1,
2522 'isRemovable' => 0,
2523 'isRequired' => 1,
2524 'isEditable' => 1,
2525 'label' => wpforo_phrase( 'Display Name', false ),
2526 'title' => wpforo_phrase( 'Display Name', false ),
2527 'placeholder' => wpforo_phrase( 'Display Name', false ),
2528 'faIcon' => 'fas fa-user',
2529 'name' => 'display_name',
2530 'cantBeInactive' => [],
2531 'canEdit' => $usergroupids_can_edit_fields,
2532 'canView' => $usergroupids,
2533 'can' => '',
2534 'isSearchable' => 1,
2535 ];
2536
2537 $this->fields['user_nicename'] = [
2538 'fieldKey' => 'user_nicename',
2539 'type' => 'text',
2540 'isDefault' => 1,
2541 'isRemovable' => 0,
2542 'isRequired' => 1,
2543 'isEditable' => 1,
2544 'label' => wpforo_phrase( 'Nickname', false ),
2545 'title' => wpforo_phrase( 'Nickname', false ),
2546 'placeholder' => wpforo_phrase( 'Nickname', false ),
2547 'description' => wpforo_phrase( 'URL Address Identifier', false ),
2548 'minLength' => 0,
2549 'maxLength' => 0,
2550 'faIcon' => 'fas fa-link',
2551 'name' => 'user_nicename',
2552 'cantBeInactive' => [],
2553 'canEdit' => $usergroupids_can_edit_fields,
2554 'canView' => $usergroupids,
2555 'can' => '',
2556 'isSearchable' => 1,
2557 ];
2558
2559 $this->fields['first_name'] = [
2560 'fieldKey' => 'first_name',
2561 'type' => 'text',
2562 'isDefault' => 1,
2563 'isRemovable' => 0,
2564 'isRequired' => 0,
2565 'isEditable' => 1,
2566 'label' => wpforo_phrase( 'First Name', false ),
2567 'title' => wpforo_phrase( 'First Name', false ),
2568 'placeholder' => wpforo_phrase( 'First Name', false ),
2569 'faIcon' => 'fas fa-address-card',
2570 'name' => 'first_name',
2571 'cantBeInactive' => [],
2572 'canEdit' => $usergroupids_can_edit_fields,
2573 'canView' => $usergroupids,
2574 'can' => '',
2575 'isSearchable' => 0,
2576 ];
2577
2578 $this->fields['last_name'] = [
2579 'fieldKey' => 'last_name',
2580 'type' => 'text',
2581 'isDefault' => 1,
2582 'isRemovable' => 0,
2583 'isRequired' => 0,
2584 'isEditable' => 1,
2585 'label' => wpforo_phrase( 'Last Name', false ),
2586 'title' => wpforo_phrase( 'Last Name', false ),
2587 'placeholder' => wpforo_phrase( 'Last Name', false ),
2588 'faIcon' => 'fas fa-address-card',
2589 'name' => 'last_name',
2590 'cantBeInactive' => [],
2591 'canEdit' => $usergroupids_can_edit_fields,
2592 'canView' => $usergroupids,
2593 'can' => '',
2594 'isSearchable' => 0,
2595 ];
2596
2597 $this->fields['title'] = [
2598 'fieldKey' => 'title',
2599 'type' => 'text',
2600 'isDefault' => 1,
2601 'isRemovable' => 0,
2602 'isRequired' => 1,
2603 'isEditable' => 1,
2604 'label' => wpforo_phrase( 'Title', false ),
2605 'title' => wpforo_phrase( 'Title', false ),
2606 'placeholder' => wpforo_phrase( 'Title', false ),
2607 'minLength' => 0,
2608 'maxLength' => 0,
2609 'faIcon' => 'fas fa-user',
2610 'name' => 'title',
2611 'cantBeInactive' => [],
2612 'canEdit' => $usergroupids_can_edit_fields,
2613 'canView' => WPF()->usergroup->get_groupids_by_can( 'vmt' ),
2614 'can' => 'vmt',
2615 'isSearchable' => 1,
2616 ];
2617
2618 $this->fields['groupid'] = [
2619 'fieldKey' => 'groupid',
2620 'type' => 'usergroup',
2621 'isDefault' => 1,
2622 'isRemovable' => 0,
2623 'isRequired' => 1,
2624 'isEditable' => 1,
2625 'label' => wpforo_phrase( 'User Group', false ),
2626 'title' => wpforo_phrase( 'User Group', false ),
2627 'placeholder' => wpforo_phrase( 'User Group', false ),
2628 'faIcon' => 'fas fa-users',
2629 'name' => 'groupid',
2630 'allowedGroupIds' => [ 3, 5 ],
2631 'cantBeInactive' => [],
2632 'canEdit' => $usergroupids_can_edit_fields,
2633 'canView' => $usergroupids,
2634 'can' => '',
2635 'isSearchable' => 1,
2636 ];
2637
2638 $this->fields['secondary_groupids'] = [
2639 'fieldKey' => 'secondary_groupids',
2640 'type' => 'secondary_groups',
2641 'isWrapItem' => 1,
2642 'isDefault' => 1,
2643 'isRemovable' => 0,
2644 'isRequired' => 0,
2645 'isEditable' => 1,
2646 'label' => wpforo_phrase( 'User Groups Secondary', false ),
2647 'title' => wpforo_phrase( 'User Groups Secondary', false ),
2648 'placeholder' => '',
2649 'faIcon' => '',
2650 'values' => '',
2651 'name' => 'secondary_groupids',
2652 'allowedGroupIds' => WPF()->usergroup->get_secondary_groupids(),
2653 'cantBeInactive' => [],
2654 'canEdit' => $usergroupids_can_edit_fields,
2655 'canView' => $usergroupids,
2656 'can' => '',
2657 'isSearchable' => 1,
2658 ];
2659
2660 $this->fields['avatar'] = [
2661 'fieldKey' => 'avatar',
2662 'type' => 'avatar',
2663 'isDefault' => 1,
2664 'isRemovable' => 0,
2665 'isRequired' => 0,
2666 'isEditable' => 1,
2667 'label' => wpforo_phrase( 'Avatar', false ),
2668 'title' => wpforo_phrase( 'Avatar', false ),
2669 'placeholder' => wpforo_phrase( 'Avatar', false ),
2670 'name' => 'avatar',
2671 'cantBeInactive' => [],
2672 'canEdit' => $usergroupids_can_edit_fields,
2673 'canView' => WPF()->usergroup->get_groupids_by_can( 'va' ),
2674 'can' => 'va',
2675 'isSearchable' => 0,
2676 ];
2677
2678 $this->fields['user_url'] = [
2679 'fieldKey' => 'user_url',
2680 'type' => 'url',
2681 'isDefault' => 1,
2682 'isRemovable' => 0,
2683 'isRequired' => 0,
2684 'isEditable' => 1,
2685 'label' => wpforo_phrase( 'Website', false ),
2686 'title' => wpforo_phrase( 'Website', false ),
2687 'placeholder' => wpforo_phrase( 'Website', false ),
2688 'faIcon' => 'fas fa-sitemap',
2689 'name' => 'user_url',
2690 'cantBeInactive' => [],
2691 'canEdit' => $usergroupids_can_edit_fields,
2692 'canView' => WPF()->usergroup->get_groupids_by_can( 'vmw' ),
2693 'can' => 'vmw',
2694 'isSearchable' => 1,
2695 ];
2696
2697 $this->fields['facebook'] = [
2698 'fieldKey' => 'facebook',
2699 'type' => 'url',
2700 'isDefault' => 0,
2701 'isRemovable' => 1,
2702 'isRequired' => 0,
2703 'isEditable' => 1,
2704 'label' => wpforo_phrase( 'Facebook', false ),
2705 'title' => wpforo_phrase( 'Facebook', false ),
2706 'placeholder' => wpforo_phrase( 'Facebook', false ),
2707 'faIcon' => 'fab fa-facebook',
2708 'name' => 'facebook',
2709 'cantBeInactive' => [],
2710 'canEdit' => $usergroupids_can_edit_fields,
2711 'canView' => $usergroupids_can_view_social_net,
2712 'can' => 'vmsn',
2713 'isSearchable' => 1,
2714 ];
2715
2716 $this->fields['twitter'] = [
2717 'fieldKey' => 'twitter',
2718 'type' => 'url',
2719 'isDefault' => 0,
2720 'isRemovable' => 1,
2721 'isRequired' => 0,
2722 'isEditable' => 1,
2723 'label' => wpforo_phrase( 'X.com', false ),
2724 'title' => wpforo_phrase( 'X.com', false ),
2725 'placeholder' => wpforo_phrase( 'X.com', false ),
2726 'faIcon' => 'fa-brands fa-square-x-twitter',
2727 'name' => 'twitter',
2728 'cantBeInactive' => [],
2729 'canEdit' => $usergroupids_can_edit_fields,
2730 'canView' => $usergroupids_can_view_social_net,
2731 'can' => 'vmsn',
2732 'isSearchable' => 1,
2733 ];
2734
2735 $this->fields['youtube'] = [
2736 'fieldKey' => 'youtube',
2737 'type' => 'url',
2738 'isDefault' => 0,
2739 'isRemovable' => 1,
2740 'isRequired' => 0,
2741 'isEditable' => 1,
2742 'label' => wpforo_phrase( 'YouTube', false ),
2743 'title' => wpforo_phrase( 'YouTube', false ),
2744 'placeholder' => wpforo_phrase( 'YouTube', false ),
2745 'faIcon' => 'fab fa-youtube',
2746 'name' => 'youtube',
2747 'cantBeInactive' => [],
2748 'canEdit' => $usergroupids_can_edit_fields,
2749 'canView' => $usergroupids_can_view_social_net,
2750 'can' => 'vmsn',
2751 'isSearchable' => 1,
2752 ];
2753
2754 $this->fields['vkontakte'] = [
2755 'fieldKey' => 'vkontakte',
2756 'type' => 'url',
2757 'isDefault' => 0,
2758 'isRemovable' => 1,
2759 'isRequired' => 0,
2760 'isEditable' => 1,
2761 'label' => wpforo_phrase( 'VKontakte', false ),
2762 'title' => wpforo_phrase( 'VKontakte', false ),
2763 'placeholder' => wpforo_phrase( 'VKontakte', false ),
2764 'faIcon' => 'fab fa-vk',
2765 'name' => 'vkontakte',
2766 'cantBeInactive' => [],
2767 'canEdit' => $usergroupids_can_edit_fields,
2768 'canView' => $usergroupids_can_view_social_net,
2769 'can' => 'vmsn',
2770 'isSearchable' => 1,
2771 ];
2772
2773 $this->fields['linkedin'] = [
2774 'fieldKey' => 'linkedin',
2775 'type' => 'url',
2776 'isDefault' => 0,
2777 'isRemovable' => 1,
2778 'isRequired' => 0,
2779 'isEditable' => 1,
2780 'label' => wpforo_phrase( 'LinkedIn', false ),
2781 'title' => wpforo_phrase( 'LinkedIn', false ),
2782 'placeholder' => wpforo_phrase( 'LinkedIn', false ),
2783 'faIcon' => 'fab fa-linkedin-in',
2784 'name' => 'linkedin',
2785 'cantBeInactive' => [],
2786 'canEdit' => $usergroupids_can_edit_fields,
2787 'canView' => $usergroupids_can_view_social_net,
2788 'can' => 'vmsn',
2789 'isSearchable' => 1,
2790 ];
2791
2792 $this->fields['telegram'] = [
2793 'fieldKey' => 'telegram',
2794 'type' => 'text',
2795 'isDefault' => 0,
2796 'isRemovable' => 1,
2797 'isRequired' => 0,
2798 'isEditable' => 1,
2799 'label' => wpforo_phrase( 'Telegram', false ),
2800 'title' => wpforo_phrase( 'Telegram', false ),
2801 'placeholder' => wpforo_phrase( 'Telegram', false ),
2802 'faIcon' => 'fab fa-telegram-plane',
2803 'name' => 'telegram',
2804 'cantBeInactive' => [],
2805 'canEdit' => $usergroupids_can_edit_fields,
2806 'canView' => $usergroupids_can_view_social_net,
2807 'can' => 'vmsn',
2808 'isSearchable' => 1,
2809 ];
2810
2811 $this->fields['instagram'] = [
2812 'fieldKey' => 'instagram',
2813 'type' => 'url',
2814 'isDefault' => 0,
2815 'isRemovable' => 1,
2816 'isRequired' => 0,
2817 'isEditable' => 1,
2818 'label' => wpforo_phrase( 'Instagram', false ),
2819 'title' => wpforo_phrase( 'Instagram', false ),
2820 'placeholder' => wpforo_phrase( 'Instagram', false ),
2821 'faIcon' => 'fab fa-instagram',
2822 'name' => 'instagram',
2823 'cantBeInactive' => [],
2824 'canEdit' => $usergroupids_can_edit_fields,
2825 'canView' => $usergroupids_can_view_social_net,
2826 'can' => 'vmsn',
2827 'isSearchable' => 1,
2828 ];
2829
2830 $this->fields['skype'] = [
2831 'fieldKey' => 'skype',
2832 'type' => 'text',
2833 'isDefault' => 0,
2834 'isRemovable' => 1,
2835 'isRequired' => 0,
2836 'isEditable' => 1,
2837 'label' => wpforo_phrase( 'Skype', false ),
2838 'title' => wpforo_phrase( 'Skype', false ),
2839 'placeholder' => wpforo_phrase( 'Skype', false ),
2840 'faIcon' => 'fab fa-skype',
2841 'name' => 'skype',
2842 'cantBeInactive' => [],
2843 'canEdit' => $usergroupids_can_edit_fields,
2844 'canView' => $usergroupids_can_view_social_net,
2845 'can' => 'vmsn',
2846 'isSearchable' => 1,
2847 ];
2848
2849 $this->fields['location'] = [
2850 'fieldKey' => 'location',
2851 'type' => 'select',
2852 'isDefault' => 1,
2853 'isRemovable' => 0,
2854 'isRequired' => 0,
2855 'isEditable' => 1,
2856 'label' => wpforo_phrase( 'Location', false ),
2857 'title' => wpforo_phrase( 'Location', false ),
2858 'placeholder' => wpforo_phrase( 'Location', false ),
2859 'faIcon' => 'fas fa-globe',
2860 'values' => $this->countries,
2861 'name' => 'location',
2862 'cantBeInactive' => [],
2863 'canEdit' => $usergroupids_can_edit_fields,
2864 'canView' => WPF()->usergroup->get_groupids_by_can( 'vml' ),
2865 'can' => 'vml',
2866 'isSearchable' => 1,
2867 ];
2868
2869 $this->fields['timezone'] = [
2870 'fieldKey' => 'timezone',
2871 'type' => 'select',
2872 'isDefault' => 1,
2873 'isRemovable' => 0,
2874 'isRequired' => 0,
2875 'isEditable' => 1,
2876 'label' => wpforo_phrase( 'Timezone', false ),
2877 'title' => wpforo_phrase( 'Timezone', false ),
2878 'placeholder' => wpforo_phrase( 'Timezone', false ),
2879 'faIcon' => 'fas fa-globe',
2880 'values' => $this->timezones,
2881 'name' => 'timezone',
2882 'cantBeInactive' => [],
2883 'canEdit' => $usergroupids_can_edit_fields,
2884 'canView' => $usergroupids,
2885 'can' => '',
2886 'isSearchable' => 1,
2887 ];
2888
2889 $this->fields['occupation'] = [
2890 'fieldKey' => 'occupation',
2891 'type' => 'text',
2892 'isDefault' => 1,
2893 'isRemovable' => 0,
2894 'isRequired' => 0,
2895 'isEditable' => 1,
2896 'label' => wpforo_phrase( 'Occupation', false ),
2897 'title' => wpforo_phrase( 'Occupation', false ),
2898 'placeholder' => wpforo_phrase( 'Occupation', false ),
2899 'faIcon' => 'fas fa-address-card',
2900 'name' => 'occupation',
2901 'cantBeInactive' => [],
2902 'canEdit' => $usergroupids_can_edit_fields,
2903 'canView' => WPF()->usergroup->get_groupids_by_can( 'vmo' ),
2904 'can' => 'vmo',
2905 'isSearchable' => 1,
2906 ];
2907
2908 $this->fields['signature'] = [
2909 'fieldKey' => 'signature',
2910 'type' => 'tinymce',
2911 'wp_editor_settings' => $wp_editor_settings,
2912 'isDefault' => 1,
2913 'isRemovable' => 0,
2914 'isRequired' => 0,
2915 'isEditable' => 1,
2916 'label' => wpforo_phrase( 'Signature', false ),
2917 'title' => wpforo_phrase( 'Signature', false ),
2918 'placeholder' => wpforo_phrase( 'Signature', false ),
2919 'faIcon' => 'fas fa-address-card',
2920 'name' => 'signature',
2921 'cantBeInactive' => [],
2922 'canEdit' => $usergroupids_can_edit_fields,
2923 'canView' => WPF()->usergroup->get_groupids_by_can( 'vms' ),
2924 'can' => 'vms',
2925 'isSearchable' => 1,
2926 ];
2927
2928 $this->fields['about'] = [
2929 'fieldKey' => 'about',
2930 'type' => 'tinymce',
2931 'wp_editor_settings' => $wp_editor_settings,
2932 'isDefault' => 1,
2933 'isRemovable' => 0,
2934 'isRequired' => 0,
2935 'isEditable' => 1,
2936 'label' => wpforo_phrase( 'About Me', false ),
2937 'title' => wpforo_phrase( 'About Me', false ),
2938 'placeholder' => wpforo_phrase( 'About Me', false ),
2939 'faIcon' => 'fas fa-address-card',
2940 'name' => 'about',
2941 'cantBeInactive' => [],
2942 'canEdit' => $usergroupids_can_edit_fields,
2943 'canView' => WPF()->usergroup->get_groupids_by_can( 'vmam' ),
2944 'can' => 'vmam',
2945 'isSearchable' => 1,
2946 ];
2947
2948 $this->fields['html_soc_net'] = [
2949 'fieldKey' => 'html_soc_net',
2950 'type' => 'html',
2951 'isDefault' => 1,
2952 'isRemovable' => 0,
2953 'isRequired' => 0,
2954 'isEditable' => 1,
2955 'label' => wpforo_phrase( 'Social Networks', false ),
2956 'title' => wpforo_phrase( 'Social Networks', false ),
2957 'placeholder' => wpforo_phrase( 'Social Networks', false ),
2958 'description' => wpforo_phrase( 'Social Networks', false ),
2959 'html' => '<div class="wpf-label">' . wpforo_phrase( 'Social Networks', false ) . '</div>',
2960 'name' => 'html_soc_net',
2961 'cantBeInactive' => [],
2962 'canEdit' => $usergroupids_can_edit_fields,
2963 'canView' => $usergroupids_can_view_social_net,
2964 'can' => 'vmsn',
2965 'isSearchable' => 0,
2966 ];
2967
2968 $this->fields = apply_filters( 'wpforo_member_after_init_fields', $this->fields );
2969 }
2970
2971 private function init_countries() {
2972 $this->countries = [
2973 "Afghanistan",
2974 "�
2975 land Islands",
2976 "Albania",
2977 "Algeria",
2978 "American Samoa",
2979 "Andorra",
2980 "Angola",
2981 "Anguilla",
2982 "Antarctica",
2983 "Antigua and Barbuda",
2984 "Argentina",
2985 "Armenia",
2986 "Aruba",
2987 "Australia",
2988 "Austria",
2989 "Azerbaijan",
2990 "Bahamas",
2991 "Bahrain",
2992 "Bangladesh",
2993 "Barbados",
2994 "Belarus",
2995 "Belgium",
2996 "Belize",
2997 "Benin",
2998 "Bermuda",
2999 "Bhutan",
3000 "Bolivia",
3001 "Bosnia and Herzegovina",
3002 "Botswana",
3003 "Bouvet Island",
3004 "Brazil",
3005 "British Indian Ocean Territory",
3006 "Brunei Darussalam",
3007 "Bulgaria",
3008 "Burkina Faso",
3009 "Burundi",
3010 "Cambodia",
3011 "Cameroon",
3012 "Canada",
3013 "Cape Verde",
3014 "Cayman Islands",
3015 "Central African Republic",
3016 "Chad",
3017 "Chile",
3018 "China",
3019 "Christmas Island",
3020 "Cocos (Keeling) Islands",
3021 "Colombia",
3022 "Comoros",
3023 "Congo",
3024 "Congo, The Democratic Republic of The",
3025 "Cook Islands",
3026 "Costa Rica",
3027 "Cote D'ivoire",
3028 "Croatia",
3029 "Cuba",
3030 "Cyprus",
3031 "Czech Republic",
3032 "Denmark",
3033 "Djibouti",
3034 "Dominica",
3035 "Dominican Republic",
3036 "Ecuador",
3037 "Egypt",
3038 "El Salvador",
3039 "Equatorial Guinea",
3040 "Eritrea",
3041 "Estonia",
3042 "Ethiopia",
3043 "Falkland Islands (Malvinas)",
3044 "Faroe Islands",
3045 "Fiji",
3046 "Finland",
3047 "France",
3048 "French Guiana",
3049 "French Polynesia",
3050 "French Southern Territories",
3051 "Gabon",
3052 "Gambia",
3053 "Georgia",
3054 "Germany",
3055 "Ghana",
3056 "Gibraltar",
3057 "Greece",
3058 "Greenland",
3059 "Grenada",
3060 "Guadeloupe",
3061 "Guam",
3062 "Guatemala",
3063 "Guernsey",
3064 "Guinea",
3065 "Guinea-bissau",
3066 "Guyana",
3067 "Haiti",
3068 "Heard Island and Mcdonald Islands",
3069 "Holy See (Vatican City State)",
3070 "Honduras",
3071 "Hong Kong",
3072 "Hungary",
3073 "Iceland",
3074 "India",
3075 "Indonesia",
3076 "Iran, Islamic Republic of",
3077 "Iraq",
3078 "Ireland",
3079 "Isle of Man",
3080 "Israel",
3081 "Italy",
3082 "Jamaica",
3083 "Japan",
3084 "Jersey",
3085 "Jordan",
3086 "Kazakhstan",
3087 "Kenya",
3088 "Kiribati",
3089 "Korea, Democratic People's Republic of",
3090 "Korea, Republic of",
3091 "Kuwait",
3092 "Kyrgyzstan",
3093 "Lao People's Democratic Republic",
3094 "Latvia",
3095 "Lebanon",
3096 "Lesotho",
3097 "Liberia",
3098 "Libyan Arab Jamahiriya",
3099 "Liechtenstein",
3100 "Lithuania",
3101 "Luxembourg",
3102 "Macao",
3103 "Macedonia, The Former Yugoslav Republic of",
3104 "Madagascar",
3105 "Malawi",
3106 "Malaysia",
3107 "Maldives",
3108 "Mali",
3109 "Malta",
3110 "Marshall Islands",
3111 "Martinique",
3112 "Mauritania",
3113 "Mauritius",
3114 "Mayotte",
3115 "Mexico",
3116 "Micronesia, Federated States of",
3117 "Moldova, Republic of",
3118 "Monaco",
3119 "Mongolia",
3120 "Montenegro",
3121 "Montserrat",
3122 "Morocco",
3123 "Mozambique",
3124 "Myanmar",
3125 "Namibia",
3126 "Nauru",
3127 "Nepal",
3128 "Netherlands",
3129 "Netherlands Antilles",
3130 "New Caledonia",
3131 "New Zealand",
3132 "Nicaragua",
3133 "Niger",
3134 "Nigeria",
3135 "Niue",
3136 "Norfolk Island",
3137 "Northern Mariana Islands",
3138 "Norway",
3139 "Oman",
3140 "Pakistan",
3141 "Palau",
3142 "Palestinian Territory, Occupied",
3143 "Panama",
3144 "Papua New Guinea",
3145 "Paraguay",
3146 "Peru",
3147 "Philippines",
3148 "Pitcairn",
3149 "Poland",
3150 "Portugal",
3151 "Puerto Rico",
3152 "Qatar",
3153 "Reunion",
3154 "Romania",
3155 "Russian Federation",
3156 "Rwanda",
3157 "Saint Helena",
3158 "Saint Kitts and Nevis",
3159 "Saint Lucia",
3160 "Saint Pierre and Miquelon",
3161 "Saint Vincent and The Grenadines",
3162 "Samoa",
3163 "San Marino",
3164 "Sao Tome and Principe",
3165 "Saudi Arabia",
3166 "Senegal",
3167 "Serbia",
3168 "Seychelles",
3169 "Sierra Leone",
3170 "Singapore",
3171 "Slovakia",
3172 "Slovenia",
3173 "Solomon Islands",
3174 "Somalia",
3175 "South Africa",
3176 "South Georgia and The South Sandwich Islands",
3177 "Spain",
3178 "Sri Lanka",
3179 "Sudan",
3180 "Suriname",
3181 "Svalbard and Jan Mayen",
3182 "Swaziland",
3183 "Sweden",
3184 "Switzerland",
3185 "Syrian Arab Republic",
3186 "Taiwan, Province of China",
3187 "Tajikistan",
3188 "Tanzania, United Republic of",
3189 "Thailand",
3190 "Timor-leste",
3191 "Togo",
3192 "Tokelau",
3193 "Tonga",
3194 "Trinidad and Tobago",
3195 "Tunisia",
3196 "Turkey",
3197 "Turkmenistan",
3198 "Turks and Caicos Islands",
3199 "Tuvalu",
3200 "Uganda",
3201 "Ukraine",
3202 "United Arab Emirates",
3203 "United Kingdom",
3204 "United States",
3205 "United States Minor Outlying Islands",
3206 "Uruguay",
3207 "Uzbekistan",
3208 "Vanuatu",
3209 "Venezuela",
3210 "Viet Nam",
3211 "Virgin Islands, British",
3212 "Virgin Islands, U.S.",
3213 "Wallis and Futuna",
3214 "Western Sahara",
3215 "Yemen",
3216 "Zambia",
3217 "Zimbabwe",
3218 ];
3219 }
3220
3221 private function init_timezones() {
3222 $this->timezones = timezone_identifiers_list();
3223 $offset_range = [
3224 - 12,
3225 - 11.5,
3226 - 11,
3227 - 10.5,
3228 - 10,
3229 - 9.5,
3230 - 9,
3231 - 8.5,
3232 - 8,
3233 - 7.5,
3234 - 7,
3235 - 6.5,
3236 - 6,
3237 - 5.5,
3238 - 5,
3239 - 4.5,
3240 - 4,
3241 - 3.5,
3242 - 3,
3243 - 2.5,
3244 - 2,
3245 - 1.5,
3246 - 1,
3247 - 0.5,
3248 0,
3249 0.5,
3250 1,
3251 1.5,
3252 2,
3253 2.5,
3254 3,
3255 3.5,
3256 4,
3257 4.5,
3258 5,
3259 5.5,
3260 5.75,
3261 6,
3262 6.5,
3263 7,
3264 7.5,
3265 8,
3266 8.5,
3267 8.75,
3268 9,
3269 9.5,
3270 10,
3271 10.5,
3272 11,
3273 11.5,
3274 12,
3275 12.75,
3276 13,
3277 13.75,
3278 14,
3279 ];
3280 foreach( $offset_range as $offset ) {
3281 if( 0 <= $offset ) {
3282 $offset_name = '+' . $offset;
3283 } else {
3284 $offset_name = (string) $offset;
3285 }
3286
3287 $offset_value = $offset_name;
3288 $offset_value = 'UTC' . $offset_value;
3289 $this->timezones[] = 'UTC/' . $offset_value;
3290 }
3291
3292 $zones = $this->timezones;
3293 $timezones = [];
3294 foreach( $zones as $zone ) {
3295 if( strpos( (string) $zone, '/' ) === false ) continue;
3296
3297 $zone = str_replace( '_', ' ', $zone );
3298
3299 $group = function_exists( 'mb_substr' ) ? mb_substr(
3300 (string) $zone,
3301 0,
3302 strpos( (string) $zone, '/' )
3303 ) : substr( (string) $zone, 0, strpos( (string) $zone, '/' ) );
3304 $index = function_exists( 'mb_strlen' ) ? mb_strlen( (string) $group ) + 1 : strlen(
3305 (string) $group
3306 ) + 1;
3307 $optionValue = substr( (string) $zone, $index );
3308
3309 if( strpos( (string) $optionValue, 'UTC' ) !== false ) {
3310 $optionTitle = str_replace( [ '.25', '.5', '.75', ], [ ':15', ':30', ':45', ], $optionValue );
3311 $optionValue = "$optionValue=>$optionTitle";
3312 } else {
3313 $optionValue = "$zone=>$optionValue";
3314 }
3315
3316 $timezones[ $group ][] = $optionValue;
3317 }
3318
3319 $this->timezones = $timezones;
3320 }
3321
3322 public function get_fields( $only_defaults = false ) {
3323 $this->init_fields();
3324 $fields = $this->fields;
3325 if( $only_defaults ) {
3326 foreach( $fields as $k => $v ) if( ! wpfval( $v, 'isDefault' ) ) unset( $fields[ $k ] );
3327 } else {
3328 $this->fields = $fields = apply_filters( 'wpforo_get_fields', $fields );
3329 }
3330
3331 return $fields;
3332 }
3333
3334 public function get_field( $key ) {
3335 if( is_string( $key ) ) {
3336 $this->init_fields();
3337
3338 return (array) wpfval( $this->fields, $key );
3339 } elseif( $this->is_field( $key ) ) {
3340 return $key;
3341 }
3342
3343 return [];
3344 }
3345
3346 public function is_field( $field ) {
3347 return wpfval( $field, 'fieldKey' ) && wpfval( $field, 'type' ) && wpfkey( $field, 'isDefault' );
3348 }
3349
3350 public function get_field_key( $field ) {
3351 return is_string( $field ) ? $field : (string) wpfval( $field, 'fieldKey' );
3352 }
3353
3354 public function fields_structure_full_array( $fields, $need_password = null ) {
3355 if( is_string( $fields ) ) $fields = maybe_unserialize( $fields );
3356 $fs = [ [ [] ] ];
3357 if( ! is_array( $fields ) ) return $fs;
3358 if( is_null( $need_password ) ) {
3359 foreach( $fields as $kr => $row ) {
3360 if( is_array( $row ) ) {
3361 foreach( $row as $kc => $cols ) {
3362 if( is_array( $cols ) ) {
3363 foreach( $cols as $field ) {
3364 $field_key = $this->get_field_key( $field );
3365 $fs[ $kr ][ $kc ][ $field_key ] = $this->get_field( $field );
3366 }
3367 }
3368 }
3369 }
3370 }
3371 } else {
3372 $has_password = false;
3373 foreach( $fields as $kr => $row ) {
3374 if( is_array( $row ) ) {
3375 foreach( $row as $kc => $cols ) {
3376 if( is_array( $cols ) ) {
3377 foreach( $cols as $field ) {
3378 $field_key = $this->get_field_key( $field );
3379 if( $field_key === 'user_pass' ) {
3380 if( $need_password ) {
3381 $has_password = true;
3382 $fs[ $kr ][ $kc ][ $field_key ] = $this->get_field( $field );
3383 }
3384 } else {
3385 $fs[ $kr ][ $kc ][ $field_key ] = $this->get_field( $field );
3386 }
3387 }
3388 }
3389 }
3390 }
3391 }
3392 if( $need_password && ! $has_password ) $fs[][][] = $this->get_field( 'user_pass' );
3393 }
3394
3395 return $fs;
3396 }
3397
3398 public function get_register_fields_structure( $only_defaults = false ) {
3399 $need_password = ! wpforo_setting( 'authorization', 'user_register_email_confirm' );
3400 $regform = [ 'user_login', 'user_email' ];
3401 if( $need_password ) $regform[] = 'user_pass';
3402 $fields = [ [ $regform ] ];
3403 if( ! $only_defaults ) $fields = apply_filters( 'wpforo_get_register_fields', $fields );
3404
3405 return $fields;
3406 }
3407
3408 public function get_register_fields( $only_defaults = false ) {
3409 return $this->fields_structure_full_array(
3410 $this->get_register_fields_structure( $only_defaults ),
3411 ! wpforo_setting( 'authorization', 'user_register_email_confirm' )
3412 );
3413 }
3414
3415 public function get_account_fields_structure( $only_defaults = false ) {
3416 $fields = [
3417 [
3418 [
3419 'user_login',
3420 'display_name',
3421 'user_nicename',
3422 'user_email',
3423 'title',
3424 'groupid',
3425 'avatar',
3426 'about',
3427 'user_url',
3428 'occupation',
3429 'signature',
3430 ],
3431 ],
3432 [
3433 [
3434 'html_soc_net',
3435 ],
3436 [
3437 'facebook',
3438 'linkedin',
3439 'instagram',
3440 'vkontakte',
3441 ],
3442 [
3443 'twitter',
3444 'youtube',
3445 'telegram',
3446 'skype',
3447 ],
3448 ],
3449 [
3450 [
3451 'location',
3452 'timezone',
3453 'user_pass',
3454 ],
3455 ],
3456 ];
3457 if( ! $only_defaults ) $fields = apply_filters( 'wpforo_get_account_fields', $fields );
3458
3459 return $fields;
3460 }
3461
3462 public function get_account_fields( $only_defaults = false ) {
3463 return $this->fields_structure_full_array( $this->get_account_fields_structure( $only_defaults ) );
3464 }
3465
3466 public function get_profile_fields_structure( $only_defaults = false ) {
3467 $fields = [
3468 [
3469 [
3470 'about',
3471 'user_url',
3472 ],
3473 ],
3474 [
3475 [
3476 'location',
3477 'timezone',
3478 'occupation',
3479 'signature',
3480 ],
3481 ],
3482 [
3483 [
3484 'html_soc_net',
3485 ],
3486 ],
3487 [
3488 [
3489 'facebook',
3490 'linkedin',
3491 'instagram',
3492 'vkontakte',
3493 ],
3494 [
3495 'twitter',
3496 'youtube',
3497 'telegram',
3498 'skype',
3499 ],
3500 ],
3501 ];
3502 if( ! $only_defaults ) $fields = apply_filters( 'wpforo_get_profile_fields', $fields );
3503
3504 return $fields;
3505 }
3506
3507 public function get_profile_fields( $only_defaults = false ) {
3508 return $this->fields_structure_full_array( $this->get_profile_fields_structure( $only_defaults ) );
3509 }
3510
3511 public function get_search_fields_structure( $only_defaults = false ) {
3512 $fields = [ [ [ 'display_name', 'user_nicename' ] ] ];
3513 if( ! $only_defaults ) $fields = apply_filters( 'wpforo_get_search_fields', $fields );
3514
3515 return $fields;
3516 }
3517
3518 public function get_search_fields( $only_defaults = false ) {
3519 $fields = $this->fields_structure_full_array( $this->get_search_fields_structure( $only_defaults ) );
3520 foreach( $fields as $row_key => $row ) {
3521 foreach( $row as $col_key => $col ) {
3522 foreach( $col as $field_key => $field ) {
3523 if( $this->is_field( $field ) ) {
3524 $fields[ $row_key ][ $col_key ][ $field_key ]['isRequired'] = 0;
3525 $fields[ $row_key ][ $col_key ][ $field_key ]['class'] = 'wpf-member-search-field';
3526 if( in_array( $field['type'], [ 'text', 'textarea', 'email', 'url' ], true ) ) {
3527 $fields[ $row_key ][ $col_key ][ $field_key ]['type'] = 'search';
3528 }
3529 }
3530 }
3531 }
3532 }
3533
3534 return $fields;
3535 }
3536
3537 public function get_search_fields_names( $only_defaults = false ) {
3538 $names = [];
3539 $fields = $this->get_search_fields( $only_defaults );
3540
3541 foreach( $fields as $row ) {
3542 foreach( $row as $col ) {
3543 foreach( $col as $field ) {
3544 if( $only_defaults && ! $field['isDefault'] ) continue;
3545 $names[] = $field['name'];
3546 }
3547 }
3548 }
3549
3550 return $names;
3551 }
3552
3553 public function get_participant_fields_list( $fields, $only_defaults = false ): array {
3554 $names = [];
3555
3556 foreach( $fields as $row ) {
3557 foreach( $row as $col ) {
3558 foreach( $col as $field ) {
3559 if( $only_defaults && ! $field['isDefault'] ) continue;
3560 $names[] = $field['name'];
3561 }
3562 }
3563 }
3564
3565 return $names;
3566 }
3567
3568 public function set_guest_cookies( $args ) {
3569 if( ! wpforo_setting( 'legal', 'cookies' ) ) return;
3570 if( isset( $args['name'] ) && isset( $args['email'] ) ) {
3571 $comment_cookie_lifetime = apply_filters( 'comment_cookie_lifetime', 30000000 );
3572 $secure = ( 'https' === parse_url( home_url(), PHP_URL_SCHEME ) );
3573 setcookie(
3574 'comment_author_' . COOKIEHASH,
3575 $args['name'],
3576 time() + $comment_cookie_lifetime,
3577 COOKIEPATH,
3578 COOKIE_DOMAIN,
3579 $secure
3580 );
3581 setcookie(
3582 'comment_author_email_' . COOKIEHASH,
3583 $args['email'],
3584 time() + $comment_cookie_lifetime,
3585 COOKIEPATH,
3586 COOKIE_DOMAIN,
3587 $secure
3588 );
3589
3590 WPF()->current_user_display_name = $args['name'];
3591 WPF()->current_user_email = $args['email'];
3592 }
3593 }
3594
3595 public function get_guest_cookies() {
3596 $guest = [ 'name' => '', 'email' => '' ];
3597 if( wpforo_setting( 'legal', 'cookies' ) ) {
3598 if( ! WPF()->current_userid && WPF()->current_user_email ) {
3599 $guest['name'] = WPF()->current_user_display_name;
3600 $guest['email'] = WPF()->current_user_email;
3601 } else {
3602 $guest_cookies = wp_get_current_commenter();
3603 $guest['name'] = ( isset( $guest_cookies['comment_author'] ) ) ? $guest_cookies['comment_author'] : '';
3604 $guest['email'] = ( isset( $guest_cookies['comment_author_email'] ) ) ? $guest_cookies['comment_author_email'] : '';
3605 }
3606 }
3607
3608 return $guest;
3609 }
3610
3611 public function set_is_email_confirmed( $userid, $status ) {
3612 if( false !== WPF()->db->update(
3613 WPF()->tables->profiles,
3614 [ 'is_email_confirmed' => intval( $status ) ],
3615 [ 'userid' => wpforo_bigintval( $userid ) ],
3616 [ '%d' ],
3617 [ '%d' ]
3618 ) ) {
3619 WPF()->notice->add( 'Email has been confirmed', 'success' );
3620
3621 return true;
3622 }
3623 WPF()->notice->add( 'Email confirm error', 'error' );
3624
3625 return false;
3626 }
3627
3628 public function get_is_email_confirmed( $userid ) {
3629 $sql = "SELECT `is_email_confirmed` FROM `" . WPF()->tables->profiles . "` WHERE `userid` = %d";
3630
3631 return (bool) WPF()->db->get_var( WPF()->db->prepare( $sql, $userid ) );
3632 }
3633
3634 /**
3635 * @param int $userid
3636 *
3637 * @return int
3638 */
3639 public function get_groupid( $userid ) {
3640 return (int) WPF()->db->get_var(
3641 WPF()->db->prepare(
3642 "SELECT `groupid`
3643 FROM `" . WPF()->tables->profiles . "`
3644 WHERE `userid` = %d",
3645 $userid
3646 )
3647 );
3648 }
3649
3650
3651 /**
3652 * @param int $userid
3653 * @param boolean $array
3654 *
3655 * @return string|array|null
3656 */
3657 public function get_secondary_groupids( $userid, $array = true ) {
3658 $secondary_groupids = WPF()->db->get_var(
3659 WPF()->db->prepare(
3660 "SELECT `secondary_groupids`
3661 FROM `" . WPF()->tables->profiles . "`
3662 WHERE `userid` = %d",
3663 $userid
3664 )
3665 );
3666
3667 if( $array && ! empty( $secondary_groupids ) ) return explode( ',', $secondary_groupids );
3668
3669 return $secondary_groupids;
3670 }
3671
3672 public function set_groupid( $userid, $groupid ) {
3673 $userid = wpforo_bigintval( $userid );
3674 $groupid = intval( $groupid );
3675 if( $userid && $groupid ) {
3676 $sql = "UPDATE `" . WPF()->tables->profiles . "` SET `groupid` = %d WHERE `userid` = %d";
3677 if( false !== WPF()->db->query( WPF()->db->prepare( $sql, $groupid, $userid ) ) ) {
3678 $this->reset( $userid );
3679 do_action( 'wpforo_set_groupid', $userid, $groupid );
3680
3681 return true;
3682 }
3683 }
3684
3685 return false;
3686 }
3687
3688 /**
3689 * @param int $userid
3690 * @param array|int $groupids
3691 *
3692 * @return bool
3693 */
3694 public function set_secondary_groupids( $userid, $groupids ) {
3695 $userid = wpforo_bigintval( $userid );
3696 if( $userid ) {
3697 $groupids = implode( ',', array_unique( array_filter( array_map( 'intval', (array) $groupids ) ) ) );
3698 $sql = "UPDATE `" . WPF()->tables->profiles . "` SET `secondary_groupids` = %s WHERE `userid` = %d";
3699 if( false !== WPF()->db->query( WPF()->db->prepare( $sql, $groupids, $userid ) ) ) {
3700 $this->reset( $userid );
3701
3702 return true;
3703 }
3704 }
3705
3706 return false;
3707 }
3708
3709 /**
3710 * @param int $userid
3711 * @param array|int $groupids
3712 *
3713 * @return bool
3714 */
3715 public function append_secondary_groupids( $userid, $groupids ) {
3716 $userid = wpforo_bigintval( $userid );
3717 if( $userid ) {
3718 if( $member = $this->get_member( $userid ) ) {
3719 $groupids = array_filter( array_map( 'intval', (array) $groupids ) );
3720 $groupids = array_merge( $member['secondary_groupids'], $groupids );
3721
3722 return $this->set_secondary_groupids( $userid, $groupids );
3723 }
3724 }
3725
3726 return false;
3727 }
3728
3729 public function after_register_new_user( $userid ) {
3730 if( wpforo_setting( 'authorization', 'manually_approval' ) || (int) trim(
3731 (string) get_user_meta( $userid, 'default_password_nag', true )
3732 ) ) {
3733 $this->update_profile_fields( $userid, [ 'status' => 'inactive' ], false );
3734 }
3735 }
3736
3737 public function after_password_reset( $user ) {
3738 $status = $this->get_status( $user->ID );
3739 if( $status !== 'banned' ) {
3740 $data = [ 'status' => 'active', 'is_email_confirmed' => 1 ];
3741 if( wpforo_setting( 'authorization', 'manually_approval' ) ) $data['status'] = $status;
3742 $this->update_profile_fields( $user->ID, $data, false );
3743 $this->reset( $user->ID );
3744 }
3745 }
3746
3747 public function wp_login( $user_login, $user ) {
3748 $this->inactive_to_active( wpforo_bigintval( $user->ID ), $user_login );
3749 }
3750
3751 public function get_distinct_status() {
3752 $sql = "SELECT DISTINCT `status` as statuses FROM `" . WPF()->tables->profiles . "`";
3753
3754 return WPF()->db->get_col( $sql );
3755 }
3756
3757 /**
3758 * @param array $args
3759 *
3760 * @return array selected userids
3761 */
3762 public function get_userids( $args ) {
3763 $sql = "SELECT `userid` FROM `" . WPF()->tables->profiles . "`";
3764 if( $args ) {
3765 $wheres = [];
3766 foreach( $args as $field => $value ) {
3767 $wheres[] = "`" . $field . "` = '" . esc_sql( $value ) . "'";
3768 }
3769 if( $wheres ) $sql .= " WHERE " . implode( " AND ", $wheres );
3770 }
3771
3772 $userids = WPF()->db->get_col( $sql );
3773
3774 return apply_filters( 'wpforo_member_after_get_userids', $userids );
3775 }
3776
3777 public function get_inlist_enabled_statuses() {
3778 return wpforo_setting( 'members', 'hide_inactive' ) ? [ 'active' ] : [ 'active', 'inactive', 'banned' ];
3779 }
3780
3781 /**
3782 * @param int $userid
3783 *
3784 * @return int
3785 */
3786 public function calc_approved_posts( $userid ) {
3787 if( $userid = wpforo_bigintval( $userid ) ) {
3788 $sqls = [];
3789 foreach( WPF()->get_active_boards_tables( 'posts' ) as $table ) {
3790 $sqls[] = WPF()->db->prepare(
3791 "SELECT COUNT(*)
3792 FROM `$table`
3793 WHERE `status` = 0
3794 AND `userid` = %d",
3795 $userid
3796 );
3797 }
3798
3799 if( $sqls ) {
3800 return (int) WPF()->db->get_var(
3801 "SELECT SUM(`COUNT(*)`) FROM (" . implode( ' UNION ALL ', $sqls ) . ") AS temp"
3802 );
3803 }
3804 }
3805
3806 return 0;
3807 }
3808
3809 /**
3810 * @param int $userid
3811 *
3812 * @return int
3813 */
3814 public function calc_approved_topics( $userid ) {
3815 if( $userid = wpforo_bigintval( $userid ) ) {
3816 $sqls = [];
3817 foreach( WPF()->get_active_boards_tables( 'topics' ) as $table ) {
3818 $sqls[] = WPF()->db->prepare(
3819 "SELECT COUNT(*)
3820 FROM `$table`
3821 WHERE `status` = 0
3822 AND `userid` = %d",
3823 $userid
3824 );
3825 }
3826
3827 if( $sqls ) {
3828 return (int) WPF()->db->get_var(
3829 "SELECT SUM(`COUNT(*)`) FROM (" . implode( ' UNION ALL ', $sqls ) . ") AS temp"
3830 );
3831 }
3832 }
3833
3834 return 0;
3835 }
3836
3837 /**
3838 * @param int $userid
3839 *
3840 * @return int
3841 */
3842 public function calc_approved_questions( $userid ) {
3843 if( $userid = wpforo_bigintval( $userid ) ) {
3844 $sqls = [];
3845 foreach( WPF()->get_active_boards_tables( 'topics' ) as $table ) {
3846 if( $forumids = Forums::get_forumids( str_replace( 'topics', 'forums', $table ), 3 ) ) {
3847 $sqls[] = WPF()->db->prepare(
3848 "SELECT COUNT(*)
3849 FROM `$table`
3850 WHERE `status` = 0
3851 AND `userid` = %d
3852 AND `forumid` IN( " . implode( ',', $forumids ) . " )",
3853 $userid
3854 );
3855 }
3856 }
3857
3858 if( $sqls ) {
3859 return (int) WPF()->db->get_var(
3860 "SELECT SUM(`COUNT(*)`) FROM (" . implode( ' UNION ALL ', $sqls ) . ") AS temp"
3861 );
3862 }
3863 }
3864
3865 return 0;
3866 }
3867
3868 /**
3869 * @param int $userid
3870 *
3871 * @return int
3872 */
3873 public function calc_approved_answers( $userid ) {
3874 if( $userid = wpforo_bigintval( $userid ) ) {
3875 $sqls = [];
3876 foreach( WPF()->get_active_boards_tables( 'posts' ) as $table ) {
3877 if( $forumids = Forums::get_forumids( str_replace( 'posts', 'forums', $table ), 3 ) ) {
3878 $sqls[] = WPF()->db->prepare(
3879 "SELECT COUNT(*)
3880 FROM `$table`
3881 WHERE `status` = 0
3882 AND `is_first_post` = 0
3883 AND `parentid` = 0
3884 AND `userid` = %d
3885 AND `forumid` IN( " . implode( ',', $forumids ) . " )",
3886 $userid
3887 );
3888 }
3889 }
3890
3891 if( $sqls ) {
3892 return (int) WPF()->db->get_var(
3893 "SELECT SUM(`COUNT(*)`) FROM (" . implode( ' UNION ALL ', $sqls ) . ") AS temp"
3894 );
3895 }
3896 }
3897
3898 return 0;
3899 }
3900
3901 /**
3902 * @param int $userid
3903 *
3904 * @return int
3905 */
3906 public function calc_approved_comments( $userid ) {
3907 if( $userid = wpforo_bigintval( $userid ) ) {
3908 $sqls = [];
3909 foreach( WPF()->get_active_boards_tables( 'posts' ) as $table ) {
3910 if( $forumids = Forums::get_forumids( str_replace( 'posts', 'forums', $table ), 3 ) ) {
3911 $sqls[] = WPF()->db->prepare(
3912 "SELECT COUNT(*)
3913 FROM `$table`
3914 WHERE `status` = 0
3915 AND `is_first_post` = 0
3916 AND `parentid` <> 0
3917 AND `userid` = %d
3918 AND `forumid` IN( " . implode( ',', $forumids ) . " )",
3919 $userid
3920 );
3921 }
3922 }
3923
3924 if( $sqls ) {
3925 return (int) WPF()->db->get_var(
3926 "SELECT SUM(`COUNT(*)`) FROM (" . implode( ' UNION ALL ', $sqls ) . ") AS temp"
3927 );
3928 }
3929 }
3930
3931 return 0;
3932 }
3933
3934 /**
3935 * @param int $userid
3936 *
3937 * @return array
3938 */
3939 public function calc_reactions_in( int $userid ): array {
3940 $reactions_in = array_map( '__return_zero', array_flip( Reactions::get_type_list() ) );
3941 if( $userid = wpforo_bigintval( $userid ) ) {
3942 $sqls = [];
3943 foreach( WPF()->get_active_boards_tables( 'reactions' ) as $table ) {
3944 $sqls[] = WPF()->db->prepare(
3945 "SELECT `type`
3946 FROM `$table`
3947 WHERE `post_userid` = %d",
3948 $userid
3949 );
3950 }
3951
3952 if( $sqls ) {
3953 $r = (array) WPF()->db->get_results(
3954 "SELECT `type`, COUNT(`type`) as `count` FROM (" . implode(
3955 ' UNION ALL ',
3956 $sqls
3957 ) . ") AS temp GROUP BY `type`",
3958 ARRAY_A
3959 );
3960 foreach( $r as $_r ) $reactions_in[ $_r['type'] ] = intval( $_r['count'] );
3961 }
3962 }
3963
3964 return $reactions_in;
3965 }
3966
3967 /**
3968 * @param int $userid
3969 *
3970 * @return array
3971 */
3972 public function calc_reactions_out( int $userid ): array {
3973 $reactions_out = array_map( '__return_zero', array_flip( Reactions::get_type_list() ) );
3974 if( $userid = wpforo_bigintval( $userid ) ) {
3975 $sqls = [];
3976 foreach( WPF()->get_active_boards_tables( 'reactions' ) as $table ) {
3977 $sqls[] = WPF()->db->prepare(
3978 "SELECT `type`
3979 FROM `$table`
3980 WHERE `userid` = %d",
3981 $userid
3982 );
3983 }
3984
3985 if( $sqls ) {
3986 $r = (array) WPF()->db->get_results(
3987 "SELECT `type`, COUNT(`type`) as `count` FROM (" . implode(
3988 ' UNION ALL ',
3989 $sqls
3990 ) . ") AS temp GROUP BY `type`",
3991 ARRAY_A
3992 );
3993 foreach( $r as $_r ) $reactions_out[ $_r['type'] ] = intval( $_r['count'] );
3994 }
3995 }
3996
3997 return $reactions_out;
3998 }
3999
4000 /**
4001 * @param int $userid
4002 *
4003 * @return void
4004 */
4005 public function rebuild_stats( int $userid ) {
4006 $posts = $this->calc_approved_posts( $userid );
4007 $topics = $this->calc_approved_topics( $userid );
4008 $questions = $this->calc_approved_questions( $userid );
4009 $answers = $this->calc_approved_answers( $userid );
4010 $comments = $this->calc_approved_comments( $userid );
4011 $reactions_in = $this->calc_reactions_in( $userid );
4012 $reactions_out = $this->calc_reactions_out( $userid );
4013 $points = $this->calc_points(
4014 compact( 'posts', 'topics', 'questions', 'answers', 'comments', 'reactions_in', 'reactions_out' )
4015 );
4016
4017 if( WPF()->db->update(
4018 WPF()->tables->profiles,
4019 [
4020 'posts' => $posts,
4021 'topics' => $topics,
4022 'questions' => $questions,
4023 'answers' => $answers,
4024 'comments' => $comments,
4025 'reactions_in' => json_encode( $reactions_in ),
4026 'reactions_out' => json_encode( $reactions_out ),
4027 'points' => $points,
4028 ],
4029 [ 'userid' => $userid ],
4030 [ '%d', '%d', '%d', '%d', '%d', '%s', '%s', '%d' ],
4031 '%d'
4032 ) ) {
4033 $this->reset( $userid );
4034 }
4035 }
4036
4037 public function after_add_topic( $topic ) {
4038 if( ! intval( $topic['status'] ) ) $this->rebuild_stats( $topic['userid'] );
4039 }
4040
4041 public function after_delete_topic( $topic ) {
4042 if( ! intval( $topic['status'] ) ) $this->rebuild_stats( $topic['userid'] );
4043 }
4044
4045 public function after_topic_status_update( $topic ) {
4046 $this->rebuild_stats( $topic['userid'] );
4047 }
4048
4049 public function before_merge_topic( $target, $current, $postids ) {
4050 $sql = "SELECT DISTINCT `userid` FROM `" . WPF()->tables->posts . "` WHERE `topicid` = %d";
4051 $sql = WPF()->db->prepare( $sql, $current['topicid'] );
4052 if( $postids ) $sql .= " AND `postid` IN(" . implode( ',', $postids ) . ")";
4053 $this->touched_userids = array_merge( $this->touched_userids, WPF()->db->get_col( $sql ) );
4054 }
4055
4056 public function after_merge_topic() {
4057 foreach( array_unique( array_filter( $this->touched_userids ) ) as $userid ) $this->rebuild_stats( $userid );
4058 }
4059
4060 public function after_move_topic( $topic ) {
4061 $sql = "SELECT DISTINCT `userid` FROM `" . WPF()->tables->posts . "` WHERE `topicid` = %d";
4062 $sql = WPF()->db->prepare( $sql, $topic['topicid'] );
4063 foreach( WPF()->db->get_col( $sql ) as $userid ) $this->rebuild_stats( $userid );
4064 }
4065
4066 public function after_add_post( $post ) {
4067 if( ! intval( $post['status'] ) ) $this->rebuild_stats( $post['userid'] );
4068 }
4069
4070 public function after_delete_post( $post ) {
4071 if( ! intval( $post['status'] ) ) $this->rebuild_stats( $post['userid'] );
4072 }
4073
4074 public function after_post_status_update( $post ) {
4075 $this->rebuild_stats( $post['userid'] );
4076 }
4077
4078 public function after_add_reaction( $reaction ) {
4079 $this->rebuild_stats( $reaction['userid'] );
4080 $this->rebuild_stats( $reaction['post_userid'] );
4081 }
4082
4083 public function after_edit_reaction( $fields, $where ) {
4084 $field_userid = wpfval( $fields, 'userid' );
4085 $field_post_userid = wpfval( $fields, 'post_userid' );
4086 if( $field_userid || $field_post_userid ) {
4087 $userids = [
4088 $field_userid,
4089 $field_post_userid,
4090 wpfval( $where, 'userid' ),
4091 wpfval( $where, 'post_userid' ),
4092 ];
4093 $userids = array_filter( $userids );
4094 $userids = array_unique( $userids );
4095 foreach( $userids as $userid ) $this->rebuild_stats( $userid );
4096 }
4097 }
4098
4099 public function before_delete_reaction( $args, $operator ) {
4100 $reactions = WPF()->reaction->get_reactions( $args, $operator );
4101 foreach( $reactions as $reaction ) {
4102 $this->touched_userids[] = $reaction['userid'];
4103 $this->touched_userids[] = $reaction['post_userid'];
4104 }
4105 }
4106
4107 public function after_delete_reaction() {
4108 foreach( array_unique( array_filter( $this->touched_userids ) ) as $userid ) $this->rebuild_stats( $userid );
4109 }
4110
4111 public function after_delete_user( $userid, $reassign ) {
4112 if( $reassign ) $this->rebuild_stats( $reassign );
4113 }
4114
4115 public function after_activate_user( $userid ) {
4116 $user = get_user_by( 'ID', $userid );
4117 if( $user ) {
4118 $sbj = wpforo_setting( 'email', 'after_user_approve_email_subject' );
4119 $msg = wpforo_setting( 'email', 'after_user_approve_email_message' );
4120 $blogname = get_option( 'blogname', '' );
4121 $login_url = wpforo_login_url( '' );
4122 $login_link = sprintf( '<a href="%1$s">%2$s</a>', $login_url, $blogname );
4123
4124 $sbj = str_replace( [ '[blogname]', '[user_login]', '[login_link]', '[login_url]' ],
4125 [ $blogname, $user->user_login, $login_link, $login_url ],
4126 $sbj );
4127 $msg = str_replace( [ '[blogname]', '[user_login]', '[login_link]', '[login_url]' ],
4128 [ $blogname, $user->user_login, $login_link, $login_url ],
4129 $msg );
4130 wpforo_send_email( $user->user_email, $sbj, $msg );
4131 }
4132 }
4133
4134 public function get_activity_url( $filter = '', $boardid = null, $arg = null ) {
4135 if( ! $arg ) $arg = WPF()->current_object['user'];
4136 $url = rtrim( $this->get_profile_url( $arg, 'activity' ), '/' );
4137 if( is_wpforo_multiboard() ) {
4138 if( is_null( $boardid ) ) {
4139 $boardid = wpfkey( WPF()->GET, 'boardid' ) ? (int) wpfval(
4140 WPF()->GET,
4141 'boardid'
4142 ) : WPF()->board->get_current( 'boardid' );
4143 }
4144 if( $filter ) {
4145 $url .= sprintf( '/?boardid=%1$d&filter=%2$s', $boardid, $filter );
4146 } else {
4147 $url .= sprintf( '/?boardid=%1$d', $boardid );
4148 }
4149 } elseif( $filter ) {
4150 $url .= sprintf( '/?filter=%1$s', $filter );
4151 }
4152
4153 return WPF()->user_trailingslashit( $url );
4154 }
4155
4156 public function get_favored_url( $filter = '', $boardid = null, $arg = null ) {
4157 if( ! $arg ) $arg = WPF()->current_object['user'];
4158 $url = rtrim( $this->get_profile_url( $arg, 'favored' ), '/' );
4159 if( is_wpforo_multiboard() ) {
4160 if( is_null( $boardid ) ) {
4161 $boardid = wpfkey( WPF()->GET, 'boardid' ) ? (int) wpfval(
4162 WPF()->GET,
4163 'boardid'
4164 ) : WPF()->board->get_current( 'boardid' );
4165 }
4166 if( $filter ) {
4167 $url .= sprintf( '/?boardid=%1$d&filter=%2$s', $boardid, $filter );
4168 } else {
4169 $url .= sprintf( '/?boardid=%1$d', $boardid );
4170 }
4171 } elseif( $filter ) {
4172 $url .= sprintf( '/?filter=%1$s', $filter );
4173 }
4174
4175 return WPF()->user_trailingslashit( $url );
4176 }
4177
4178 public function get_newest_member( $status_filter = true ) {
4179 if( ! ( $visible_usergroup_ids = WPF()->usergroup->get_visible_usergroup_ids() ) ) return [];
4180
4181 $groupids = implode( ", ", $visible_usergroup_ids );
4182
4183 if( $status_filter ) {
4184 $status = implode( "', '", $this->get_inlist_enabled_statuses() );
4185 $sql = "SELECT `userid` FROM `" . WPF()->tables->profiles . "`
4186 WHERE `status` IN ('" . $status . "')
4187 AND `groupid` IN (" . $groupids . ")
4188 ORDER BY `userid` DESC LIMIT 1";
4189 } else {
4190 $sql = "SELECT `userid` FROM `" . WPF()->tables->profiles . "`
4191 WHERE `groupid` IN (" . $groupids . ")
4192 ORDER BY `userid` DESC LIMIT 1";
4193 }
4194
4195 $memberid = WPF()->db->get_var( $sql );
4196 $member = wpforo_member( $memberid );
4197
4198 if( empty( $member ) ) {
4199
4200 WPF()->db->query(
4201 "DELETE p FROM `" . WPF()->tables->profiles . "` p LEFT JOIN `" . WPF(
4202 )->db->users . "` u ON u.ID = p.userid WHERE u.ID IS NULL"
4203 );
4204
4205 $memberid = WPF()->db->get_var( $sql );
4206 $member = wpforo_member( $memberid );
4207
4208 if( empty( $member ) ) {
4209 if( $status_filter ) {
4210 $members = $this->get_members(
4211 [
4212 'orderby' => 'userid',
4213 'status' => [ 'active' ],
4214 'order' => 'DESC',
4215 'row_count' => 1,
4216 'groupids' => $visible_usergroup_ids,
4217 ]
4218 );
4219 } else {
4220 $members = $this->get_members(
4221 [
4222 'orderby' => 'userid',
4223 'order' => 'DESC',
4224 'row_count' => 1,
4225 'groupids' => $visible_usergroup_ids,
4226 ]
4227 );
4228 }
4229 if( isset( $members[0] ) && ! empty( $members[0] ) ) {
4230 $member = $members[0];
4231 } else {
4232 $member = [];
4233 }
4234 }
4235 }
4236 $member['profile_url'] = wpfval( $member, 'profile_url' ) ?: $this->get_profile_url( $memberid );
4237
4238 return $member;
4239 }
4240
4241 public function after_front_delete_user( $user ) {
4242 if( $user['userid'] === WPF()->current_userid ) {
4243 if( wpforo_setting( 'authorization', 'send_email_after_user_delete' ) ) {
4244 $sbj = wpforo_setting( 'email', 'after_user_delete_notification_email_admin_subject' );
4245 $sbj = str_replace(
4246 [ '[datetime]', '[blogname]' ],
4247 [ _wpforo_date( 0, 'mysql', 'wp' ), '[' . get_bloginfo( 'name' ) . ']' ],
4248 $sbj
4249 );
4250 $sbj = wpforo_apply_email_shortcodes( $sbj, [], [], [], $user, '' );
4251
4252 $msg = wpforo_setting( 'email', 'after_user_delete_notification_email_admin_message' );
4253 $msg = str_replace(
4254 [ '[datetime]', '[blogname]' ],
4255 [ _wpforo_date( 0, 'mysql', 'wp' ), '[' . get_bloginfo( 'name' ) . ']' ],
4256 $msg
4257 );
4258 $msg = wpforo_apply_email_shortcodes( $msg, [], [], [], $user, '' );
4259 $msg = wpautop( $msg );
4260
4261 wpforo_send_email( wpforo_setting( 'email', 'admin_emails' ), $sbj, $msg );
4262 }
4263 }
4264 }
4265 }
4266