PluginProbe
Tutor LMS – eLearning and online course solution / 1.8.10
Tutor LMS – eLearning and online course solution v1.8.10
4.0.7 4.0.6 4.0.5 4.0.4 4.0.3 4.0.2 4.0.1 4.0.0 3.9.15 3.9.14 3.9.13 3.9.12 3.9.11 trunk 1.0.0 1.0.0-alpha 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 All 191 releases
← All changes | classes/User.php +75 -835 4.0.11.8.10 View file →
@@ -1,895 +1,135 @@
1 1 <?php
2 -/**
3 - * Manage user
4 - *
5 - * @package Tutor\User
6 - * @author Themeum <support@themeum.com>
7 - * @link https://themeum.com
8 - * @since 1.0.0
9 - */
10 2
11 3 namespace TUTOR;
12 4
13 -defined( 'ABSPATH' ) || exit;
5 +if ( ! defined( 'ABSPATH' ) )
6 + exit;
14 7
15 -use Tutor\Helpers\HttpHelper;
16 -use Tutor\Models\UserModel;
17 -use Tutor\Traits\JsonResponse;
18 -use TUTOR\InstructorList;
19 8
20 -/**
21 - * User class
22 - *
23 - * @since 1.0.0
24 - */
25 9 class User {
26 - use JsonResponse;
27 10
28 - const STUDENT = 'subscriber';
29 - const INSTRUCTOR = 'tutor_instructor';
30 - const ADMIN = 'administrator';
11 + public function __construct() {
12 + add_action('edit_user_profile', array($this, 'edit_user_profile'));
13 + add_action('show_user_profile', array($this, 'edit_user_profile'), 10, 1);
31 14
32 - /**
33 - * User meta keys.
34 - */
35 - const REVIEW_POPUP_META = 'tutor_review_course_popup';
36 - const LAST_LOGIN_META = 'tutor_last_login';
37 - const TIMEZONE_META = '_tutor_timezone';
38 - const PROFILE_PHOTO_META = '_tutor_profile_photo';
39 - const PHONE_NUMBER_META = 'phone_number';
40 - const COVER_PHOTO_META = '_tutor_cover_photo';
41 - const PROFILE_BIO_META = '_tutor_profile_bio';
42 - const PROFILE_JOB_TITLE_META = '_tutor_profile_job_title';
43 - const TUTOR_STUDENT_META = '_is_tutor_student';
44 - const TOUR_COMPLETED_META = '_tutor_tour_completed';
45 - const APPLICATION_SOURCE_META = '_tutor_application_source';
46 - const INSTRUCTOR_APPROVAL_NOTICE_META = 'tutor_instructor_show_approval_message';
15 + add_action('profile_update', array($this, 'profile_update'));
16 + add_action('set_user_role', array($this, 'set_user_role'), 10, 3);
47 17
48 - const SOURCE_INSTRUCTOR_REGISTRATION = 'instructor_registration';
49 - const SOURCE_STUDENT_DASHBOARD = 'student_dashboard';
50 -
51 - /**
52 - * View as constants
53 - *
54 - * @since 4.0.0
55 - */
56 - const VIEW_AS_INSTRUCTOR = 'instructor';
57 - const VIEW_AS_STUDENT = 'student';
58 -
59 - /**
60 - * User meta key for storing view as mode
61 - *
62 - * @since 4.0.0
63 - *
64 - * @var string
65 - */
66 - const VIEW_MODE_USER_META = 'tutor_profile_view_mode';
67 -
68 - /**
69 - * User model
70 - *
71 - * @since 3.0.0
72 - *
73 - * @var UserModel
74 - */
75 - private $model;
76 -
77 - /**
78 - * Registration notice
79 - *
80 - * @since 1.0.0
81 - *
82 - * @var boolean
83 - */
84 - private static $hide_registration_notice = false;
85 -
86 - /**
87 - * Register hooks
88 - *
89 - * @since 1.0.0
90 - * @since 2.2.0 $register_hooks param added to resuse the class without hooks register.
91 - *
92 - * @param bool $register_hooks register hooks.
93 - *
94 - * @return void
95 - */
96 - public function __construct( $register_hooks = true ) {
97 - $this->model = new UserModel();
98 - if ( ! $register_hooks ) {
99 - return;
100 - }
101 -
102 - add_action( 'edit_user_profile', array( $this, 'edit_user_profile' ) );
103 - add_action( 'show_user_profile', array( $this, 'edit_user_profile' ), 10, 1 );
104 -
105 - add_action( 'profile_update', array( $this, 'profile_update' ) );
106 - add_action( 'set_user_role', array( $this, 'set_user_role' ), 10, 3 );
107 -
108 - add_action( 'wp_ajax_tutor_user_photo_remove', array( $this, 'tutor_user_photo_remove' ) );
109 - add_action( 'wp_ajax_tutor_user_photo_upload', array( $this, 'update_user_photo' ) );
110 -
111 - add_action( 'admin_notices', array( $this, 'show_registration_disabled' ) );
112 - add_action( 'admin_init', array( $this, 'hide_notices' ) );
113 - add_action( 'wp_login', array( $this, 'update_user_last_login' ), 10, 2 );
114 - add_action( 'login_form', array( $this, 'add_timezone_input' ) );
115 - add_action( 'wp_login', array( $this, 'set_timezone' ), 10, 2 );
116 -
117 - add_action( 'wp_ajax_tutor_user_list', array( $this, 'ajax_user_list' ) );
118 - add_action( 'wp_ajax_tutor_switch_profile', array( $this, 'ajax_switch_profile' ) );
119 - add_action( 'wp_ajax_tutor_complete_tour', array( $this, 'ajax_complete_tour' ) );
18 + add_action('wp_ajax_tutor_user_photo_remove', array($this, 'tutor_user_photo_remove'));
19 + add_action('wp_ajax_tutor_user_photo_upload', array($this, 'update_user_photo'));
20 +
21 + add_action('tutor_options_after_instructors', array($this, 'tutor_instructor_profile_layout'));
22 + // add_action('tutor_options_after_students', array($this, 'tutor_student_profile_layout'));
120 23 }
121 24
122 - /**
123 - * Get meta key name for review popup.
124 - *
125 - * @since 2.4.0
126 - *
127 - * @param int $course_id course id.
128 - *
129 - * @return string user meta key name.
130 - */
131 - public static function get_review_popup_meta( $course_id ) {
132 - return self::REVIEW_POPUP_META . '_' . $course_id;
133 - }
134 -
135 - /**
136 - * Check user has provided role.
137 - *
138 - * @since 2.2.0
139 - *
140 - * @param string $role role.
141 - *
142 - * @return boolean
143 - */
144 - public static function is( string $role ) {
145 - return current_user_can( $role );
146 - }
147 -
148 - /**
149 - * Check current user has capability.
150 - *
151 - * Example usage:
152 - *
153 - * User::can( 'edit_posts' );
154 - * User::can( 'edit_post', $post->ID );
155 - * User::can( 'edit_post_meta', $post->ID, $meta_key );
156 - *
157 - * @since 4.0.0
158 - *
159 - * @param string $capability capability.
160 - * @param mixed ...$args args.
161 - *
162 - * @return boolean
163 - */
164 - public static function can( string $capability = 'manage_options', ...$args ) {
165 - return current_user_can( $capability, ...$args );
166 - }
167 -
168 - /**
169 - * Check user has any role.
170 - *
171 - * @since 2.2.0
172 - * @since 2.6.2 $user_id param added.
173 - *
174 - * @param array $roles roles.
175 - * @param int $user_id user id.
176 - *
177 - * @return boolean
178 - */
179 - public static function has_any_role( array $roles, $user_id = 0 ) {
180 - $user = get_userdata( tutor_utils()->get_user_id( $user_id ) );
181 - if ( empty( $user->roles ) || empty( $roles ) ) {
182 - return false;
183 - }
184 -
185 - foreach ( $roles as $role ) {
186 - if ( in_array( $role, $user->roles, true ) ) {
187 - return true;
188 - }
189 - }
190 -
191 - return false;
192 - }
193 -
194 - /**
195 - * Check user is student.
196 - *
197 - * @since 2.2.0
198 - * @since 2.6.2 $user_id param added.
199 - *
200 - * @param int $user_id user id.
201 - *
202 - * @return boolean
203 - */
204 - public static function is_student( $user_id = 0 ) {
205 - $is_tutor_student = get_user_meta( tutor_utils()->get_user_id( $user_id ), self::TUTOR_STUDENT_META, true );
206 - return $is_tutor_student ? true : false;
207 - }
208 -
209 - /**
210 - * Check user is admin.
211 - *
212 - * @since 2.2.0
213 - * @since 3.2.0 user_id param added.
214 - *
215 - * @param int $user_id user id.
216 - *
217 - * @return boolean
218 - */
219 - public static function is_admin( $user_id = 0 ) {
220 - return user_can( tutor_utils()->get_user_id( $user_id ), self::ADMIN );
221 - }
222 -
223 - /**
224 - * Check current user is instructor.
225 - *
226 - * @since 2.2.0
227 - * @since 3.2.0 user_id param added.
228 - *
229 - * @param int $user_id user id.
230 - * @param bool $is_approved instructor is approved or not.
231 - *
232 - * @return boolean
233 - */
234 - public static function is_instructor( $user_id = 0, $is_approved = true ) {
235 - return tutils()->is_instructor( $user_id, $is_approved );
236 - }
237 -
238 - /**
239 - * Get Tutor application source for a user.
240 - *
241 - * @since 4.0.0
242 - *
243 - * @param int $user_id user id.
244 - *
245 - * @return string
246 - */
247 - public static function get_application_source( $user_id = 0 ): string {
248 - return (string) get_user_meta(
249 - tutor_utils()->get_user_id( $user_id ),
250 - self::APPLICATION_SOURCE_META,
251 - true
252 - );
253 - }
254 -
255 - /**
256 - * Check if the user came through instructor registration.
257 - *
258 - * @since 4.0.0
259 - *
260 - * @param int $user_id user id.
261 - *
262 - * @return boolean
263 - */
264 - public static function used_instructor_registration( $user_id = 0 ): bool {
265 - return self::SOURCE_INSTRUCTOR_REGISTRATION === self::get_application_source( $user_id );
266 - }
267 -
268 - /**
269 - * Check if a user can view instructor dashboard screens.
270 - *
271 - * @since 4.0.0
272 - *
273 - * @param int $user_id user id.
274 - *
275 - * @return boolean
276 - */
277 - public static function can_view_instructor_dashboard( $user_id = 0 ): bool {
278 - $user_id = tutor_utils()->get_user_id( $user_id );
279 -
280 - if ( self::is_admin( $user_id ) || self::is_instructor( $user_id ) ) {
281 - return true;
282 - }
283 -
284 - if ( ! self::used_instructor_registration( $user_id ) ) {
285 - return false;
286 - }
287 -
288 - return in_array(
289 - tutor_utils()->instructor_status( $user_id, false ),
290 - array( Instructors_List::STATUS_PENDING, Instructors_List::STATUS_APPROVED ),
291 - true
292 - );
293 - }
294 -
295 - /**
296 - * Check if user has a pending instructor application.
297 - *
298 - * @since 4.0.0
299 - *
300 - * @param int $user_id user id.
301 - *
302 - * @return boolean
303 - */
304 - public static function has_pending_instructor_application( $user_id = 0 ): bool {
305 - return Instructors_List::STATUS_PENDING === tutor_utils()->instructor_status( $user_id, false );
306 - }
307 -
308 - /**
309 - * Check current user is only instructor as admin also has instructor role.
310 - *
311 - * @since 3.2.0
312 - *
313 - * @param int $user_id user id.
314 - * @param bool $is_approved instructor is approved or not.
315 - *
316 - * @return boolean
317 - */
318 - public static function is_only_instructor( $user_id = 0, $is_approved = true ) {
319 - return ! self::is_admin( $user_id ) && self::is_instructor( $user_id, $is_approved );
320 - }
321 -
322 - /**
323 - * Profile layouts
324 - *
325 - * @since 1.0.0
326 - *
327 - * @var array
328 - */
329 25 private $profile_layout = array(
330 26 'pp-circle',
331 27 'pp-rectangle',
332 - 'no-cp',
28 + 'no-cp'
333 29 );
334 30
335 31 /**
336 - * Include edit user template
337 - *
338 - * @since 1.0.0
339 - *
340 - * @param mixed $user user.
341 - *
342 - * @return void
32 + * Show layout selection dashboard in instructor and student setting
343 33 */
344 - public function edit_user_profile( $user ) {
345 - include tutor()->path . 'views/metabox/user-profile-fields.php';
34 + public function tutor_instructor_profile_layout(){
35 + tutor_load_template('public-profile-setting', array('profile_templates'=>$this->profile_layout, 'layout_option_name'=>'instructor'));
346 36 }
37 + public function tutor_student_profile_layout(){
38 + tutor_load_template('public-profile-setting', array('profile_templates'=>$this->profile_layout, 'layout_option_name'=>'student'));
39 + }
347 40
348 - /**
349 - * Delete existing user's photo
350 - *
351 - * @since 1.0.0
352 - *
353 - * @param int $user_id user id.
354 - * @param string $type photo type.
355 - *
356 - * @return void
357 - */
358 - private function delete_existing_user_photo( $user_id, $type ) {
359 - $meta_key = 'cover_photo' == $type ? '_tutor_cover_photo' : '_tutor_profile_photo';
360 - $photo_id = get_user_meta( $user_id, $meta_key, true );
361 - if ( is_numeric( $photo_id ) ) {
362 - $attachment = get_post( $photo_id );
363 - $post_author = (int) $attachment->post_author ?? 0;
364 - if ( $user_id === $post_author ) {
365 - wp_delete_attachment( $photo_id, true );
366 - }
367 - }
368 - delete_user_meta( $user_id, $meta_key );
41 + public function edit_user_profile($user){
42 + include tutor()->path.'views/metabox/user-profile-fields.php';
369 43 }
370 44
371 - /**
372 - * User photo remove
373 - *
374 - * @since 1.0.0
375 - *
376 - * @return void
377 - */
378 - public function tutor_user_photo_remove() {
379 - tutor_utils()->checking_nonce();
380 - $this->delete_existing_user_photo(
381 - get_current_user_id(),
382 - Input::post( 'photo_type', '' )
383 - );
45 + private function delete_existing_user_photo($user_id, $type){
46 + $meta_key = $type=='cover_photo' ? '_tutor_cover_photo' : '_tutor_profile_photo';
47 + $photo_id = get_user_meta($user_id, $meta_key, true);
48 + is_numeric($photo_id) ? wp_delete_attachment( $photo_id, true) : 0;
49 + delete_user_meta( $user_id, $meta_key);
384 50 }
385 51
386 - /**
387 - * User photo update
388 - *
389 - * @since 1.0.0
390 - *
391 - * @return void
392 - */
393 - public function update_user_photo() {
394 - tutor_utils()->checking_nonce();
52 + public function tutor_user_photo_remove(){
53 + tutils()->checking_nonce();
54 +
55 + $this->delete_existing_user_photo(get_current_user_id(), $_POST['photo_type']);
56 + }
395 57
396 - $user_id = get_current_user_id();
397 - $photo_type = Input::post( 'photo_type', '' );
398 - $meta_key = 'cover_photo' === $photo_type ? '_tutor_cover_photo' : '_tutor_profile_photo';
58 + public function update_user_photo(){
59 + tutils()->checking_nonce();
399 60
61 + $user_id = get_current_user_id();
62 + $meta_key = $_POST['photo_type']=='cover_photo' ? '_tutor_cover_photo' : '_tutor_profile_photo';
63 +
400 64 /**
401 65 * Photo Update from profile
66 + *
402 67 */
403 - $photo = tutor_utils()->array_get( 'photo_file', $_FILES ); //phpcs:ignore -- already sanitized.
404 - $photo_size = tutor_utils()->array_get( 'size', $photo );
405 - $photo_type = tutor_utils()->array_get( 'type', $photo );
68 + $photo = tutils()->array_get('photo_file', $_FILES);
69 + $photo_size = tutils()->array_get('size', $photo);
70 + $photo_type = tutils()->array_get('type', $photo);
406 71
407 - if ( $photo_size && strpos( $photo_type, 'image' ) !== false ) {
72 + if ($photo_size && strpos($photo_type, 'image') !== false) {
408 73 if ( ! function_exists( 'wp_handle_upload' ) ) {
409 - require_once ABSPATH . 'wp-admin/includes/file.php';
74 + require_once( ABSPATH . 'wp-admin/includes/file.php' );
410 75 }
76 +
411 77 $upload_overrides = array( 'test_form' => false );
412 78 $movefile = wp_handle_upload( $photo, $upload_overrides );
413 79
414 80 if ( $movefile && ! isset( $movefile['error'] ) ) {
415 - $file_path = tutor_utils()->array_get( 'file', $movefile );
416 - $file_url = tutor_utils()->array_get( 'url', $movefile );
417 - $mime_type = '';
418 - if ( file_exists( $file_path ) ) {
419 - $image_info = getimagesize( $file_path );
420 - $mime_type = is_array( $image_info ) && count( $image_info ) ? $image_info['mime'] : '';
421 - }
81 + $file_path = tutils()->array_get( 'file', $movefile );
82 + $file_url = tutils()->array_get( 'url', $movefile );
422 83
423 - $media_id = wp_insert_attachment(
424 - array(
425 - 'guid' => $file_path,
426 - 'post_mime_type' => $mime_type,
427 - 'post_title' => preg_replace( '/\.[^.]+$/', '', basename( $file_url ) ),
428 - 'post_content' => '',
429 - 'post_status' => 'inherit',
430 - ),
431 - $file_path,
432 - 0
433 - );
84 + $media_id = wp_insert_attachment( array(
85 + 'guid' => $file_path,
86 + 'post_mime_type' => mime_content_type( $file_path ),
87 + 'post_title' => preg_replace( '/\.[^.]+$/', '', basename( $file_url ) ),
88 + 'post_content' => '',
89 + 'post_status' => 'inherit'
90 + ), $file_path, 0 );
434 91
435 - if ( $media_id ) {
436 - // wp_generate_attachment_metadata() won't work if you do not include this file.
437 - require_once ABSPATH . 'wp-admin/includes/image.php';
92 + if ($media_id) {
93 + // wp_generate_attachment_metadata() won't work if you do not include this file
94 + require_once( ABSPATH . 'wp-admin/includes/image.php' );
438 95
439 - // Generate and save the attachment metas into the database.
96 + // Generate and save the attachment metas into the database
440 97 wp_update_attachment_metadata( $media_id, wp_generate_attachment_metadata( $media_id, $file_path ) );
441 98
442 - // Update it to user profile.
443 - $this->delete_existing_user_photo( $user_id, Input::post( 'photo_type', '' ) );
444 - update_user_meta( $user_id, $meta_key, $media_id );
99 + //Update it to user profile
100 + $this->delete_existing_user_photo($user_id, $_POST['photo_type']);
101 + update_user_meta($user_id, $meta_key, $media_id );
445 102
446 - exit( wp_json_encode( array( 'status' => 'success' ) ) );
103 + exit(json_encode(array('status'=>'success')));
447 104 }
448 105 }
449 106 }
450 107 }
451 108
452 - /**
453 - * Get user timezone string.
454 - *
455 - * @param int|object $user user id or user object. Default: current user.
456 - *
457 - * @return string user timezone string, fallback site timezone string.
458 - */
459 - public static function get_user_timezone_string( $user = 0 ) {
460 - if ( is_numeric( $user ) ) {
461 - $user = get_user_by( 'id', tutor_utils()->get_user_id( $user ) );
462 - }
463 -
464 - if ( ! is_a( $user, 'WP_User' ) ) {
465 - return wp_timezone_string();
466 - }
467 -
468 - $timezone = get_user_meta( $user->ID, self::TIMEZONE_META, true );
469 - if ( self::is_admin() || empty( $timezone ) ) {
470 - $timezone = wp_timezone_string();
471 - }
472 -
473 - return $timezone;
474 - }
475 -
476 - /**
477 - * Profile update
478 - *
479 - * @since 1.0.0
480 - *
481 - * @param int $user_id user id.
482 - *
483 - * @return void
484 - */
485 - public function profile_update( $user_id ) {
486 - if ( 'tutor_profile_update_by_wp' !== Input::post( 'tutor_action' ) ) {
109 + public function profile_update($user_id){
110 + if (tutils()->array_get('tutor_action', $_POST) !== 'tutor_profile_update_by_wp' ){
487 111 return;
488 112 }
489 113
490 - $timezone = Input::post( 'timezone', '' );
491 - $_tutor_profile_job_title = Input::post( self::PROFILE_JOB_TITLE_META, '' );
492 - $_tutor_profile_bio = Input::post( self::PROFILE_BIO_META, '', Input::TYPE_KSES_POST );
493 - $_tutor_profile_image = Input::post( self::PROFILE_PHOTO_META, '', Input::TYPE_KSES_POST );
114 + $_tutor_profile_job_title = sanitize_text_field(tutor_utils()->avalue_dot('_tutor_profile_job_title', $_POST));
115 + $_tutor_profile_bio = wp_kses_post(tutor_utils()->avalue_dot('_tutor_profile_bio', $_POST));
116 + $_tutor_profile_image = wp_kses_post(tutor_utils()->avalue_dot('_tutor_profile_photo', $_POST));
494 117
495 - update_user_meta( $user_id, self::PROFILE_JOB_TITLE_META, $_tutor_profile_job_title );
496 - update_user_meta( $user_id, self::PROFILE_BIO_META, $_tutor_profile_bio );
497 - update_user_meta( $user_id, self::PROFILE_PHOTO_META, $_tutor_profile_image );
498 - update_user_meta( $user_id, self::TIMEZONE_META, $timezone );
118 + update_user_meta($user_id, '_tutor_profile_job_title', $_tutor_profile_job_title);
119 + update_user_meta($user_id, '_tutor_profile_bio', $_tutor_profile_bio);
120 + update_user_meta($user_id, '_tutor_profile_photo', $_tutor_profile_image);
499 121 }
500 122
501 - /**
502 - * Set user role
503 - *
504 - * @since 1.0.0
505 - *
506 - * @param int $user_id user id.
507 - * @param string $role user role.
508 - * @param array $old_roles old role.
509 - *
510 - * @return void
511 - */
512 - public function set_user_role( $user_id, $role, $old_roles ) {
123 + public function set_user_role($user_id, $role, $old_roles ){
513 124 $instructor_role = tutor()->instructor_role;
514 125
515 - if ( $role === $instructor_role || in_array( $instructor_role, $old_roles ) ) {
516 - tutor_utils()->add_instructor_role( $user_id );
126 + if (in_array($instructor_role, $old_roles)){
127 + // tutor_utils()->remove_instructor_role($user_id);
517 128 }
518 - }
519 129
520 - /**
521 - * Hide notices
522 - *
523 - * @since 1.0.0
524 - *
525 - * @return void
526 - */
527 - public function hide_notices() {
528 - $hide_notice = Input::get( 'tutor-hide-notice', '' );
529 - $is_register_enabled = Input::get( 'tutor-registration', '' );
530 - $has_manage_cap = current_user_can( 'manage_options' );
531 -
532 - if ( $has_manage_cap && is_admin() && 'registration' === $hide_notice ) {
533 - tutor_utils()->checking_nonce( 'get' );
534 -
535 - if ( 'enable' === $is_register_enabled ) {
536 - update_option( 'users_can_register', 1 );
537 - } else {
538 - self::$hide_registration_notice = true;
539 - setcookie( 'tutor_notice_hide_registration', 1, time() + MONTH_IN_SECONDS, tutor()->basepath );
540 - }
130 + // if ($role === $instructor_role){
131 + if ($role === $instructor_role || in_array($instructor_role, $old_roles)){
132 + tutor_utils()->add_instructor_role($user_id);
541 133 }
542 134 }
543 -
544 - /**
545 - * Show registration disabled
546 - *
547 - * @since 1.0.0
548 - *
549 - * @return void
550 - */
551 - public function show_registration_disabled() {
552 - if ( self::$hide_registration_notice ||
553 - ( '0' !== get_option( 'users_can_register' ) ) ||
554 - isset( $_COOKIE['tutor_notice_hide_registration'] ) ||
555 - ! current_user_can( 'manage_options' )
556 - ) {
557 - return;
558 - }
559 -
560 - $hide_url = wp_nonce_url( add_query_arg( 'tutor-hide-notice', 'registration' ), tutor()->nonce_action, tutor()->nonce );
561 - ?>
562 - <div class="wrap tutor-user-registration-notice-wrapper">
563 - <div class="tutor-user-registration-notice">
564 - <div>
565 - <img src="<?php echo esc_url( tutor()->url . 'assets/images/icon-info-round.svg' ); ?>"/>
566 - </div>
567 - <div>
568 - <?php
569 - echo wp_kses(
570 - __( 'As membership is turned off, students and instructors will not be able to sign up. <strong>Press Enable</strong> or go to <strong>Settings > General > Membership</strong> and enable "Anyone can register".', 'tutor' ),
571 - array( 'strong' => true )
572 - );
573 - ?>
574 - </div>
575 - <div>
576 - <a href="<?php echo esc_url( add_query_arg( 'tutor-registration', 'enable', $hide_url ) ); ?>">
577 - <?php esc_html_e( 'Enable', 'tutor' ); ?>
578 - </a>
579 - <hr/>
580 - <a href="<?php echo esc_url( $hide_url ); ?>">
581 - <?php esc_html_e( 'Dismiss', 'tutor' ); ?>
582 - </a>
583 - </div>
584 - </div>
585 - </div>
586 - <?php
587 - }
588 -
589 - /**
590 - * Set the user last active timestamp to now.
591 - *
592 - * @since 2.5.0
593 - *
594 - * @param string $user_login active user name.
595 - * @param \WP_User $user User object data.
596 - *
597 - * @return void
598 - */
599 - public function update_user_last_login( $user_login, $user ) {
600 - update_user_meta( $user->ID, self::LAST_LOGIN_META, time() );
601 - }
602 -
603 - /**
604 - * Add timezone input field to login form.
605 - *
606 - * @since 3.0.0
607 - */
608 - public function add_timezone_input() {
609 - ?>
610 - <input type="hidden" name="timezone" value="<?php echo esc_attr( wp_timezone_string() ); ?>" />
611 - <script>
612 - document.addEventListener('DOMContentLoaded', function() {
613 - const timezone = document.querySelector('input[name="timezone"]');
614 - if ( timezone) {
615 - const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
616 - timezone.value = tz
617 - }
618 - });
619 - </script>
620 - <?php
621 - }
622 -
623 - /**
624 - * Set user timezone if not it set.
625 - *
626 - * @since 3.0.0
627 - *
628 - * @param string $user_login active user name.
629 - * @param \WP_User $user User object data.
630 - *
631 - * @return void
632 - */
633 - public function set_timezone( $user_login, $user ) {
634 - if ( Input::has( 'timezone' ) ) {
635 - $timezone = get_user_meta( $user->ID, self::TIMEZONE_META, true );
636 - if ( empty( $timezone ) ) {
637 - update_user_meta( $user->ID, self::TIMEZONE_META, Input::post( 'timezone', wp_timezone_string() ) );
638 - }
639 - }
640 - }
641 -
642 - /**
643 - * Get profile settings data
644 - *
645 - * @since 4.0.0
646 - *
647 - * @param int $user_id user id.
648 - *
649 - * @return array
650 - */
651 - public static function get_profile_settings_data( $user_id = 0 ) {
652 - $user_id = tutor_utils()->get_user_id( $user_id );
653 - $user = get_userdata( $user_id );
654 -
655 - // Prepare profile pic.
656 - $profile_placeholder = apply_filters( 'tutor_login_default_avatar', tutor()->url . 'assets/images/profile-photo.png' );
657 - $profile_photo_src = $profile_placeholder;
658 - $profile_photo_id = get_user_meta( $user->ID, self::PROFILE_PHOTO_META, true );
659 -
660 - if ( $profile_photo_id ) {
661 - $url = wp_get_attachment_image_url( $profile_photo_id, 'full' );
662 - if ( ! empty( $url ) ) {
663 - $profile_photo_src = $url;
664 - }
665 - }
666 -
667 - $timezone = self::get_user_timezone_string( $user );
668 -
669 - // Prepare cover photo.
670 - $cover_placeholder = tutor()->url . 'assets/images/cover-photo.webp';
671 - $cover_photo_src = $cover_placeholder;
672 - $cover_photo_id = get_user_meta( $user->ID, self::COVER_PHOTO_META, true );
673 -
674 - if ( $cover_photo_id ) {
675 - $url = wp_get_attachment_image_url( $cover_photo_id, 'full' );
676 - if ( ! empty( $url ) ) {
677 - $cover_photo_src = $url;
678 - }
679 - }
680 -
681 - // Prepare display name.
682 - $public_display = array();
683 - $public_display['display_nickname'] = $user->nickname;
684 - $public_display['display_username'] = $user->user_login;
685 -
686 - if ( ! empty( $user->first_name ) ) {
687 - $public_display['display_firstname'] = $user->first_name;
688 - }
689 -
690 - if ( ! empty( $user->last_name ) ) {
691 - $public_display['display_lastname'] = $user->last_name;
692 - }
693 -
694 - if ( ! empty( $user->first_name ) && ! empty( $user->last_name ) ) {
695 - $public_display['display_firstlast'] = $user->first_name . ' ' . $user->last_name;
696 - $public_display['display_lastfirst'] = $user->last_name . ' ' . $user->first_name;
697 - }
698 -
699 - if ( ! in_array( $user->display_name, $public_display, true ) ) { // Only add this if it isn't duplicated elsewhere.
700 - $public_display = array( 'display_displayname' => $user->display_name ) + $public_display;
701 - }
702 -
703 - $public_display = array_map( 'trim', $public_display );
704 - $public_display = array_unique( $public_display );
705 - $max_filesize = floatval( ini_get( 'upload_max_filesize' ) ) * ( 1024 * 1024 );
706 -
707 - $profile_bio = wp_kses_post( get_user_meta( $user->ID, self::PROFILE_BIO_META, true ) );
708 - $job_title = get_user_meta( $user->ID, self::PROFILE_JOB_TITLE_META, true );
709 - $phone = get_user_meta( $user->ID, self::PHONE_NUMBER_META, true );
710 -
711 - return array(
712 - 'user' => $user,
713 - 'profile_placeholder' => $profile_placeholder,
714 - 'profile_photo_src' => $profile_photo_src,
715 - 'profile_photo_id' => $profile_photo_id,
716 - 'cover_placeholder' => $cover_placeholder,
717 - 'cover_photo_src' => $cover_photo_src,
718 - 'cover_photo_id' => $cover_photo_id,
719 - 'timezone' => $timezone,
720 - 'public_display' => $public_display,
721 - 'max_filesize' => $max_filesize,
722 - 'profile_bio' => $profile_bio,
723 - 'job_title' => $job_title,
724 - 'phone_number' => $phone,
725 - );
726 - }
727 -
728 - /**
729 - * Get user list with pagination & support
730 - * search term
731 - *
732 - * @since 3.0.0
733 - *
734 - * @return void
735 - */
736 - public function ajax_user_list() {
737 - tutor_utils()->check_nonce();
738 -
739 - $can_access = apply_filters( 'tutor_user_list_access', current_user_can( 'manage_options' ) );
740 - if ( ! $can_access ) {
741 - $this->json_response( tutor_utils()->error_message( 'forbidden' ), HttpHelper::STATUS_FORBIDDEN );
742 - }
743 -
744 - $response = array(
745 - 'results' => array(),
746 - 'total_items' => 0,
747 - );
748 -
749 - $limit = Input::post( 'limit', 10, Input::TYPE_INT );
750 - $offset = Input::post( 'offset', 0, Input::TYPE_INT );
751 -
752 - $args = array(
753 - 'limit' => $limit,
754 - 'offset' => $offset,
755 - );
756 -
757 - $filter = json_decode( wp_unslash( $_POST['filter'] ?? '{}' ) );//phpcs:ignore
758 - if ( ! empty( $filter ) && property_exists( $filter, 'search' ) && ! empty( $filter->search ) ) {
759 - $args['search'] = '*' . Input::sanitize( $filter->search ) . '*';
760 - $args['search_columns'] = array( 'user_login', 'user_email', 'user_nicename', 'display_name', 'ID' );
761 - }
762 -
763 - $user_list = $this->model->get_users_list( $args );
764 -
765 - if ( is_object( $user_list ) ) {
766 - foreach ( $user_list->get_results() as $user ) {
767 - // Set user avatar.
768 - $user->avatar_url = get_avatar_url( $user->ID, array( 'size' => 32 ) );
769 - $response['results'][] = $user;
770 - }
771 -
772 - $response['total_items'] = $user_list->get_total();
773 - }
774 -
775 - $this->json_response(
776 - __( 'User list fetched successfully!', 'tutor' ),
777 - $response
778 - );
779 - }
780 -
781 - /**
782 - * Switch user profile ajax-handler
783 - *
784 - * @since 4.0.0
785 - *
786 - * @return void send wp_json response
787 - */
788 - public function ajax_switch_profile() {
789 - tutor_utils()->checking_nonce();
790 -
791 - $user_id = get_current_user_id();
792 - if ( ! self::can_switch_mode( $user_id ) ) {
793 - $this->json_response(
794 - tutor_utils()->error_message(),
795 - null,
796 - HttpHelper::STATUS_UNAUTHORIZED
797 - );
798 - }
799 -
800 - $switch_mode = '';
801 - $current_mode = Input::post( 'current_mode' );
802 -
803 - if ( ! in_array( $current_mode, array( self::VIEW_AS_INSTRUCTOR, self::VIEW_AS_STUDENT ), true ) ) {
804 - $this->response_bad_request( tutor_utils()->error_message( 'invalid_req' ) );
805 - }
806 -
807 - if ( self::VIEW_AS_INSTRUCTOR === $current_mode ) {
808 - $switch_mode = self::VIEW_AS_STUDENT;
809 - } elseif ( self::VIEW_AS_STUDENT === $current_mode ) {
810 - $switch_mode = self::VIEW_AS_INSTRUCTOR;
811 - }
812 -
813 - update_user_meta( $user_id, self::VIEW_MODE_USER_META, $switch_mode );
814 -
815 - // translators:%s for switching mode.
816 - $this->response_success( sprintf( __( 'Profile switched to %s!', 'tutor' ), $switch_mode ) );
817 - }
818 -
819 - /**
820 - * Get current view mode STUDENT/INSTRUCTOR
821 - *
822 - * @since 4.0.0
823 - *
824 - * @return string
825 - */
826 - public static function get_current_view_mode(): string {
827 - $user_id = get_current_user_id();
828 - $can_switch = self::can_switch_mode( $user_id );
829 - $default_mode = $can_switch ? self::VIEW_AS_INSTRUCTOR : self::VIEW_AS_STUDENT;
830 - $current_mode = get_user_meta( $user_id, self::VIEW_MODE_USER_META, true );
831 -
832 - if ( $can_switch && in_array( $current_mode, array( self::VIEW_AS_INSTRUCTOR, self::VIEW_AS_STUDENT ), true ) ) {
833 - return $current_mode;
834 - }
835 -
836 - if ( self::used_instructor_registration( $user_id ) ) {
837 - $instructor_status = tutor_utils()->instructor_status( $user_id, false );
838 - if ( in_array( $instructor_status, array( Instructors_List::STATUS_PENDING, Instructors_List::STATUS_APPROVED ), true ) ) {
839 - return self::VIEW_AS_INSTRUCTOR;
840 - }
841 - }
842 -
843 - return $default_mode;
844 - }
845 -
846 - /**
847 - * Check if the user is in instructor view
848 - *
849 - * @since 4.0.0
850 - *
851 - * @return bool
852 - */
853 - public static function is_instructor_view(): bool {
854 - return self::VIEW_AS_INSTRUCTOR === self::get_current_view_mode();
855 - }
856 -
857 - /**
858 - * Check if the user is in student view
859 - *
860 - * @since 4.0.0
861 - *
862 - * @return bool
863 - */
864 - public static function is_student_view(): bool {
865 - return self::VIEW_AS_STUDENT === self::get_current_view_mode();
866 - }
867 -
868 - /**
869 - * Check if the user can switch between learner and instructor dashboard modes.
870 - *
871 - * @since 4.0.0
872 - *
873 - * @param int $user_id User ID.
874 - *
875 - * @return bool
876 - */
877 - public static function can_switch_mode( int $user_id = 0 ): bool {
878 - return self::is_admin( $user_id ) || self::is_instructor( $user_id );
879 - }
880 -
881 - /**
882 - * Mark dashboard tour as completed for the current user.
883 - *
884 - * @since 4.0.0
885 - *
886 - * @return void JSON response.
887 - */
888 - public function ajax_complete_tour() {
889 - tutor_utils()->check_nonce();
890 -
891 - update_user_meta( get_current_user_id(), self::TOUR_COMPLETED_META, true );
892 -
893 - $this->json_response( __( 'Tour completed', 'tutor' ) );
894 - }
895 -}
135 +}