PluginProbe ʕ •ᴥ•ʔ
Tutor LMS – eLearning and online course solution / 2.2.4
Tutor LMS – eLearning and online course solution v2.2.4
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 1.1.0 1.1.1 1.2.0 1.2.1 1.2.11 1.2.12 1.2.13 1.2.20 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 1.7.3 1.7.4 1.7.5 1.7.6 1.7.7 1.7.8 1.7.9 1.8.0 1.8.1 1.8.10 1.8.2 1.8.3 1.8.4 1.8.5 1.8.6 1.8.7 1.8.8 1.8.9 1.9.0 1.9.1 1.9.10 1.9.11 1.9.12 1.9.13 1.9.14 1.9.15 1.9.16 1.9.2 1.9.3 1.9.4 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 2.0.1 2.0.10 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 2.0.9 2.1.0 2.1.1 2.1.10 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.1.9 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.3.0 2.4.0 2.5.0 2.6.0 2.6.1 2.6.2 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 3.0.0 3.0.1 3.0.2 3.1.0 3.2.0 3.2.1 3.2.2 3.2.3 3.3.0 3.3.1 3.4.0 3.4.1 3.4.2 3.5.0 3.6.0 3.6.1 3.6.2 3.6.3 3.6.4 3.7.0 3.7.1 3.7.2 3.7.3 3.7.4 3.8.0 3.8.1 3.8.2 3.8.3 3.9.0 3.9.1 3.9.10 3.9.2 3.9.3 3.9.4 3.9.5 3.9.6 3.9.7 3.9.8 3.9.9
tutor / classes / Instructor.php
tutor / classes Last commit date
Addons.php 2 years ago Admin.php 2 years ago Ajax.php 3 years ago Announcements.php 3 years ago Assets.php 3 years ago Backend_Page_Trait.php 3 years ago Course.php 3 years ago Course_Embed.php 3 years ago Course_Filter.php 3 years ago Course_List.php 2 years ago Course_Settings_Tabs.php 3 years ago Course_Widget.php 3 years ago Custom_Validation.php 3 years ago Dashboard.php 3 years ago FormHandler.php 2 years ago Frontend.php 3 years ago Gutenberg.php 3 years ago Input.php 3 years ago Instructor.php 2 years ago Instructors_List.php 3 years ago Lesson.php 2 years ago Options_V2.php 2 years ago Post_types.php 3 years ago Private_Course_Access.php 3 years ago Q_and_A.php 3 years ago Question_Answers_List.php 3 years ago Quiz.php 2 years ago Quiz_Attempts_List.php 2 years ago RestAPI.php 3 years ago Reviews.php 3 years ago Rewrite_Rules.php 3 years ago Shortcode.php 2 years ago Student.php 2 years ago Students_List.php 3 years ago Taxonomies.php 3 years ago Template.php 2 years ago Theme_Compatibility.php 3 years ago Tools.php 3 years ago Tools_V2.php 3 years ago Tutor.php 3 years ago TutorEDD.php 2 years ago Tutor_Base.php 3 years ago Tutor_Setup.php 3 years ago Upgrader.php 3 years ago User.php 3 years ago Utils.php 2 years ago Video_Stream.php 3 years ago Withdraw.php 2 years ago Withdraw_Requests_List.php 3 years ago WooCommerce.php 2 years ago
Instructor.php
419 lines
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' ) ) {
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 = wp_kses_post( tutor_utils()->input_old( 'tutor_profile_bio' ) );
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 *
317 * @since 1.0.0
318 * @return void
319 */
320 public function instructor_approval_action() {
321 tutor_utils()->checking_nonce();
322
323 if ( ! current_user_can( 'manage_options' ) ) {
324 wp_send_json_error( array( 'message' => __( 'Access Denied', 'tutor' ) ) );
325 }
326
327 $instructor_id = Input::post( 'instructor_id', 0, Input::TYPE_INT );
328 $action = Input::post( 'action_name' );
329
330 if ( 'approve' === $action ) {
331 do_action( 'tutor_before_approved_instructor', $instructor_id );
332
333 update_user_meta( $instructor_id, '_tutor_instructor_status', 'approved' );
334 update_user_meta( $instructor_id, '_tutor_instructor_approved', tutor_time() );
335
336 $instructor = new \WP_User( $instructor_id );
337 $instructor->add_role( tutor()->instructor_role );
338
339 // Send E-Mail to this user about instructor approval via hook.
340 do_action( 'tutor_after_approved_instructor', $instructor_id );
341 }
342
343 if ( 'blocked' === $action ) {
344 do_action( 'tutor_before_blocked_instructor', $instructor_id );
345 update_user_meta( $instructor_id, '_tutor_instructor_status', 'blocked' );
346
347 $instructor = new \WP_User( $instructor_id );
348 $instructor->remove_role( tutor()->instructor_role );
349 do_action( 'tutor_after_blocked_instructor', $instructor_id );
350
351 // TODO: send E-Mail to this user about instructor blocked, should via hook.
352 }
353
354 if ( 'remove-instructor' === $action ) {
355 do_action( 'tutor_before_rejected_instructor', $instructor_id );
356
357 $user = new \WP_User( $instructor_id );
358 $user->remove_role( tutor()->instructor_role );
359
360 tutor_utils()->remove_instructor_role( $instructor_id );
361 update_user_meta( $instructor_id, '_is_tutor_instructor_rejected', tutor_time() );
362 update_user_meta( $instructor_id, 'tutor_instructor_show_rejection_message', true );
363
364 // Send E-Mail to this user about instructor rejection via hook.
365 do_action( 'tutor_after_rejected_instructor', $instructor_id );
366 }
367
368 wp_send_json_success();
369 }
370
371 /**
372 * Hide instructor notice
373 *
374 * @since 1.0.0
375 * @return void
376 */
377 public function hide_instructor_notice() {
378 if ( 'hide_instructor_notice' === Input::get( 'tutor_action' ) ) {
379 delete_user_meta( get_current_user_id(), 'tutor_instructor_show_rejection_message' );
380 }
381 }
382
383 /**
384 * Can instructor publish courses directly
385 * Fixed in Gutenberg
386 *
387 * @since 1.5.9
388 * @return void
389 */
390 public function can_publish_tutor_courses() {
391 $can_publish_course = (bool) tutor_utils()->get_option( 'instructor_can_publish_course' );
392
393 $instructor_role = tutor()->instructor_role;
394 $instructor = get_role( $instructor_role );
395
396 if ( $can_publish_course ) {
397 $instructor->add_cap( 'publish_tutor_courses' );
398 } else {
399 $instructor->remove_cap( 'publish_tutor_courses' );
400 }
401 }
402
403 /**
404 * Update instructor meta just after register
405 *
406 * @since 2.1.9
407 *
408 * @param integer $user_id user id.
409 *
410 * @return void
411 */
412 public function update_instructor_meta( int $user_id ) {
413 update_user_meta( $user_id, '_is_tutor_instructor', tutor_time() );
414 update_user_meta( $user_id, '_tutor_instructor_status', apply_filters( 'tutor_initial_instructor_status', 'pending' ) );
415
416 do_action( 'tutor_new_instructor_after', $user_id );
417 }
418 }
419