PluginProbe
Tutor LMS – eLearning and online course solution / 3.9.2
Tutor LMS – eLearning and online course solution v3.9.2
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
tutor / classes / Instructor.php

Instructor.php in Tutor LMS – eLearning and online course solution 3.9.2, at classes/Instructor.php

420 lines 13.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Manage Instructor
4 *
5 * @package Tutor
6 * @author Themeum <support@themeum.com>
7 * @link https://themeum.com
8 * @since 1.0.0
9 */
10
11 namespace TUTOR;
12
13 if ( ! defined( 'ABSPATH' ) ) {
14 exit;
15 }
16
17 /**
18 * Instructor class
19 *
20 * @since 1.0.0
21 */
22 class Instructor {
23
24 /**
25 * Error message
26 *
27 * @var string
28 */
29 protected $error_msgs = '';
30
31 /**
32 * Constructor
33 *
34 * @since 1.0.0
35 *
36 * @param bool $register_hook register hook or not.
37 *
38 * @return void
39 */
40 public function __construct( $register_hook = true ) {
41 if ( ! $register_hook ) {
42 return;
43 }
44 add_action( 'template_redirect', array( $this, 'register_instructor' ) );
45 add_action( 'template_redirect', array( $this, 'apply_instructor' ) );
46
47 // Add instructor from admin panel.
48 add_action( 'wp_ajax_tutor_add_instructor', array( $this, 'add_new_instructor' ) );
49
50 /**
51 * Instructor Approval
52 * Block Unblock
53 *
54 * @since 1.5.3
55 */
56 add_action( 'wp_ajax_instructor_approval_action', array( $this, 'instructor_approval_action' ) );
57
58 /**
59 * Check if instructor can publish courses
60 *
61 * @since 1.5.9
62 */
63 add_action( 'tutor_option_save_after', array( $this, 'can_publish_tutor_courses' ) );
64
65 /**
66 * Hide instructor rejection message
67 *
68 * @since 1.9.2
69 */
70 add_action( 'wp_loaded', array( $this, 'hide_instructor_notice' ) );
71 }
72
73 /**
74 * Template Redirect Callback
75 * For Register new user and mark him as instructor
76 *
77 * @since 1.0.0
78 * @return void|null
79 */
80 public function register_instructor() {
81 // Here tutor_action checking required before nonce checking.
82 if ( 'tutor_register_instructor' !== Input::post( 'tutor_action' ) || ! get_option( 'users_can_register', false ) ) {
83 return;
84 }
85
86 // Checking nonce.
87 tutor_utils()->checking_nonce();
88
89 $required_fields = apply_filters(
90 'tutor_instructor_registration_required_fields',
91 array(
92 'first_name' => __( 'First name field is required', 'tutor' ),
93 'last_name' => __( 'Last name field is required', 'tutor' ),
94 'email' => __( 'E-Mail field is required', 'tutor' ),
95 'user_login' => __( 'User Name field is required', 'tutor' ),
96 'password' => __( 'Password field is required', 'tutor' ),
97 'password_confirmation' => __( 'Password Confirmation field is required', 'tutor' ),
98 )
99 );
100
101 $validation_errors = array();
102
103 /*
104 * Push into validation_errors
105 * Error registration_errors
106 */
107 $errors = apply_filters( 'registration_errors', new \WP_Error(), '', '' );
108 foreach ( $errors->errors as $key => $value ) {
109 $validation_errors[ $key ] = $value[0];
110 }
111
112 foreach ( $required_fields as $required_key => $required_value ) {
113 if ( empty( $_POST[ $required_key ] ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Missing
114 $validation_errors[ $required_key ] = $required_value;
115 }
116 }
117
118 if ( ! filter_var( tutor_utils()->input_old( 'email' ), FILTER_VALIDATE_EMAIL ) ) {
119 $validation_errors['email'] = __( 'Valid E-Mail is required', 'tutor' );
120 }
121 if ( tutor_utils()->input_old( 'password' ) !== tutor_utils()->input_old( 'password_confirmation' ) ) {
122 $validation_errors['password_confirmation'] = __( 'Your passwords should match each other. Please recheck.', 'tutor' );
123 }
124
125 if ( count( $validation_errors ) ) {
126 $this->error_msgs = $validation_errors;
127 add_filter( 'tutor_instructor_register_validation_errors', array( $this, 'tutor_instructor_form_validation_errors' ) );
128 return;
129 }
130
131 $first_name = sanitize_text_field( tutor_utils()->input_old( 'first_name' ) );
132 $last_name = sanitize_text_field( tutor_utils()->input_old( 'last_name' ) );
133 $email = sanitize_text_field( tutor_utils()->input_old( 'email' ) );
134 $user_login = sanitize_text_field( tutor_utils()->input_old( 'user_login' ) );
135 $password = sanitize_text_field( tutor_utils()->input_old( 'password' ) );
136
137 $userdata = array(
138 'user_login' => $user_login,
139 'user_email' => $email,
140 'first_name' => $first_name,
141 'last_name' => $last_name,
142 'user_pass' => $password,
143 );
144
145 global $wpdb;
146 $wpdb->query( 'START TRANSACTION' );
147
148 $user_id = wp_insert_user( $userdata );
149
150 if ( is_wp_error( $user_id ) ) {
151 $this->error_msgs = $user_id->get_error_messages();
152 add_filter( 'tutor_instructor_register_validation_errors', array( $this, 'tutor_instructor_form_validation_errors' ) );
153 return;
154 }
155
156 $is_req_email_verification = apply_filters( 'tutor_require_email_verification', false );
157
158 if ( $is_req_email_verification ) {
159 do_action( 'tutor_send_verification_mail', get_userdata( $user_id ), 'instructor-registration' );
160 $reg_done = apply_filters( 'tutor_registration_done', true );
161 if ( ! $reg_done ) {
162 $wpdb->query( 'ROLLBACK' );
163 return;
164 } else {
165 $wpdb->query( 'COMMIT' );
166 }
167 } else {
168 /**
169 * Tutor Free - regular instructor reg process.
170 */
171 $this->update_instructor_meta( $user_id );
172 $wpdb->query( 'COMMIT' );
173 $user = get_user_by( 'id', $user_id );
174 if ( $user ) {
175 wp_set_current_user( $user_id, $user->user_login );
176 wp_set_auth_cookie( $user_id );
177 do_action( 'tutor_after_instructor_signup', $user_id );
178 }
179 }
180
181 wp_redirect( tutor_utils()->input_old( '_wp_http_referer' ) );
182 die();
183 }
184
185 /**
186 * Get instructor reg validation errors.
187 *
188 * @since 1.0.0
189 * @return string
190 */
191 public function tutor_instructor_form_validation_errors() {
192 return $this->error_msgs;
193 }
194
195 /**
196 * Template Redirect Callback
197 * for instructor applying when a user already logged in
198 *
199 * @since 1.0.0
200 * @return void|null
201 */
202 public function apply_instructor() {
203 // Here tutor_action checking required before nonce checking.
204 if ( 'tutor_apply_instructor' !== Input::post( 'tutor_action' ) ) {
205 return;
206 }
207
208 // Checking nonce.
209 tutor_utils()->checking_nonce();
210
211 $user_id = get_current_user_id();
212 if ( $user_id ) {
213 if ( tutor_utils()->is_instructor() ) {
214 die( esc_html__( 'Already applied for instructor', 'tutor' ) );
215 } else {
216 update_user_meta( $user_id, '_is_tutor_instructor', tutor_time() );
217 update_user_meta( $user_id, '_tutor_instructor_status', apply_filters( 'tutor_initial_instructor_status', 'pending' ) );
218
219 do_action( 'tutor_new_instructor_after', $user_id );
220 }
221 } else {
222 die( esc_html__( 'Permission denied', 'tutor' ) );
223 }
224
225 wp_redirect( tutor_utils()->input_old( '_wp_http_referer' ) );
226 die();
227 }
228
229
230 /**
231 * Add new instructor
232 *
233 * @since 1.0.0
234 * @return void
235 */
236 public function add_new_instructor() {
237 tutor_utils()->checking_nonce();
238
239 // Only admin should be able to add instructor.
240 if ( ! current_user_can( 'manage_options' ) || ! get_option( 'users_can_register', false ) ) {
241 wp_send_json_error();
242 }
243
244 $required_fields = apply_filters(
245 'tutor_instructor_registration_required_fields',
246 array(
247 'first_name' => __( 'First name field is required', 'tutor' ),
248 'last_name' => __( 'Last name field is required', 'tutor' ),
249 'email' => __( 'E-Mail field is required', 'tutor' ),
250 'user_login' => __( 'User Name field is required', 'tutor' ),
251 'password' => __( 'Password field is required', 'tutor' ),
252 'password_confirmation' => __( 'Your passwords should match each other. Please recheck.', 'tutor' ),
253 )
254 );
255
256 $validation_errors = array();
257 foreach ( $required_fields as $required_key => $required_value ) {
258 if ( empty( $_POST[ $required_key ] ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Missing
259 $validation_errors[ $required_key ] = $required_value;
260 }
261 }
262
263 if ( ! filter_var( tutor_utils()->input_old( 'email' ), FILTER_VALIDATE_EMAIL ) ) {
264 $validation_errors['email'] = __( 'Valid E-Mail is required', 'tutor' );
265 }
266 if ( tutor_utils()->input_old( 'password' ) !== tutor_utils()->input_old( 'password_confirmation' ) ) {
267 $validation_errors['password_confirmation'] = __( 'Your passwords should match each other. Please recheck.', 'tutor' );
268 }
269
270 if ( count( $validation_errors ) ) {
271 wp_send_json_error( array( 'errors' => $validation_errors ) );
272 }
273
274 $first_name = sanitize_text_field( tutor_utils()->input_old( 'first_name' ) );
275 $last_name = sanitize_text_field( tutor_utils()->input_old( 'last_name' ) );
276 $email = sanitize_text_field( tutor_utils()->input_old( 'email' ) );
277 $user_login = sanitize_text_field( tutor_utils()->input_old( 'user_login' ) );
278 $phone_number = sanitize_text_field( tutor_utils()->input_old( 'phone_number' ) );
279 $password = sanitize_text_field( tutor_utils()->input_old( 'password' ) );
280 $tutor_profile_bio = Input::post( 'tutor_profile_bio', '', Input::TYPE_KSES_POST );
281 $tutor_profile_job_title = sanitize_text_field( tutor_utils()->input_old( 'tutor_profile_job_title' ) );
282
283 $userdata = apply_filters(
284 'add_new_instructor_data',
285 array(
286 'user_login' => $user_login,
287 'user_email' => $email,
288 'first_name' => $first_name,
289 'last_name' => $last_name,
290 'role' => tutor()->instructor_role,
291 'user_pass' => $password,
292 )
293 );
294
295 do_action( 'tutor_add_new_instructor_before' );
296
297 $user_id = wp_insert_user( $userdata );
298 if ( ! is_wp_error( $user_id ) ) {
299 update_user_meta( $user_id, 'phone_number', $phone_number );
300 update_user_meta( $user_id, 'description', $tutor_profile_bio );
301 update_user_meta( $user_id, '_tutor_profile_bio', $tutor_profile_bio );
302 update_user_meta( $user_id, '_tutor_profile_job_title', $tutor_profile_job_title );
303 update_user_meta( $user_id, '_is_tutor_instructor', tutor_time() );
304 update_user_meta( $user_id, '_tutor_instructor_status', apply_filters( 'tutor_initial_instructor_status', 'approved' ) );
305
306 do_action( 'tutor_add_new_instructor_after', $user_id );
307
308 wp_send_json_success( array( 'msg' => __( 'Instructor has been added successfully', 'tutor' ) ) );
309 }
310
311 wp_send_json_error( array( 'errors' => $user_id ) );
312 }
313
314 /**
315 * Handle instructor approval action
316 * This function not used maybe, will be removed
317 *
318 * @since 1.0.0
319 * @return void
320 */
321 public function instructor_approval_action() {
322 tutor_utils()->checking_nonce();
323
324 if ( ! current_user_can( 'manage_options' ) ) {
325 wp_send_json_error( array( 'message' => __( 'Access Denied', 'tutor' ) ) );
326 }
327
328 $instructor_id = Input::post( 'instructor_id', 0, Input::TYPE_INT );
329 $action = Input::post( 'action_name' );
330
331 if ( 'approve' === $action ) {
332 do_action( 'tutor_before_approved_instructor', $instructor_id );
333
334 update_user_meta( $instructor_id, '_tutor_instructor_status', 'approved' );
335 update_user_meta( $instructor_id, '_tutor_instructor_approved', tutor_time() );
336
337 $instructor = new \WP_User( $instructor_id );
338 $instructor->add_role( tutor()->instructor_role );
339
340 // Send E-Mail to this user about instructor approval via hook.
341 do_action( 'tutor_after_approved_instructor', $instructor_id );
342 }
343
344 if ( 'blocked' === $action ) {
345 do_action( 'tutor_before_blocked_instructor', $instructor_id );
346 update_user_meta( $instructor_id, '_tutor_instructor_status', 'blocked' );
347
348 $instructor = new \WP_User( $instructor_id );
349 $instructor->remove_role( tutor()->instructor_role );
350 do_action( 'tutor_after_blocked_instructor', $instructor_id );
351
352 // TODO: send E-Mail to this user about instructor blocked, should via hook.
353 }
354
355 if ( 'remove-instructor' === $action ) {
356 do_action( 'tutor_before_rejected_instructor', $instructor_id );
357
358 $user = new \WP_User( $instructor_id );
359 $user->remove_role( tutor()->instructor_role );
360
361 tutor_utils()->remove_instructor_role( $instructor_id );
362 update_user_meta( $instructor_id, '_is_tutor_instructor_rejected', tutor_time() );
363 update_user_meta( $instructor_id, 'tutor_instructor_show_rejection_message', true );
364
365 // Send E-Mail to this user about instructor rejection via hook.
366 do_action( 'tutor_after_rejected_instructor', $instructor_id );
367 }
368
369 wp_send_json_success();
370 }
371
372 /**
373 * Hide instructor notice
374 *
375 * @since 1.0.0
376 * @return void
377 */
378 public function hide_instructor_notice() {
379 if ( 'hide_instructor_notice' === Input::get( 'tutor_action' ) ) {
380 delete_user_meta( get_current_user_id(), 'tutor_instructor_show_rejection_message' );
381 }
382 }
383
384 /**
385 * Can instructor publish courses directly
386 * Fixed in Gutenberg
387 *
388 * @since 1.5.9
389 * @return void
390 */
391 public function can_publish_tutor_courses() {
392 $can_publish_course = (bool) tutor_utils()->get_option( 'instructor_can_publish_course' );
393
394 $instructor_role = tutor()->instructor_role;
395 $instructor = get_role( $instructor_role );
396
397 if ( $can_publish_course ) {
398 $instructor->add_cap( 'publish_tutor_courses' );
399 } else {
400 $instructor->remove_cap( 'publish_tutor_courses' );
401 }
402 }
403
404 /**
405 * Update instructor meta just after register
406 *
407 * @since 2.1.9
408 *
409 * @param integer $user_id user id.
410 *
411 * @return void
412 */
413 public function update_instructor_meta( int $user_id ) {
414 update_user_meta( $user_id, '_is_tutor_instructor', tutor_time() );
415 update_user_meta( $user_id, '_tutor_instructor_status', apply_filters( 'tutor_initial_instructor_status', 'pending' ) );
416
417 do_action( 'tutor_new_instructor_after', $user_id );
418 }
419 }
420