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