PluginProbe ʕ •ᴥ•ʔ
Tutor LMS – eLearning and online course solution / 2.1.7
Tutor LMS – eLearning and online course solution v2.1.7
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 / Instructors_List.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
Instructors_List.php
411 lines
1 <?php
2 /**
3 * Manage Instructor List
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 use TUTOR\Students_List;
18 use TUTOR\Backend_Page_Trait;
19 use Tutor\Helpers\QueryHelper;
20
21 /**
22 * Instructors_List class
23 *
24 * @since 1.0.0
25 */
26 class Instructors_List {
27
28 const INSTRUCTOR_LIST_PAGE = 'tutor-instructors';
29 const INSTRUCTOR_LIST_CACHE_KEY = 'tutor-instructors-list';
30 const INSTRUCTOR_COUNT_CACHE_KEY = 'tutor-instructors-count';
31
32 /**
33 * Trait for utilities
34 *
35 * @var $page_title
36 */
37
38 use Backend_Page_Trait;
39
40 /**
41 * Page Title
42 *
43 * @var $page_title
44 */
45 public $page_title;
46
47 /**
48 * Bulk Action
49 *
50 * @var $bulk_action
51 */
52 public $bulk_action = true;
53
54 /**
55 * Constructor
56 *
57 * @since 1.0.0
58 * @return void
59 */
60 public function __construct() {
61 $this->page_title = __( 'Instructor', 'tutor' );
62
63 /**
64 * Handle bulk action
65 *
66 * @since 2.0.0
67 */
68 add_action( 'wp_ajax_tutor_instructor_bulk_action', array( $this, 'instructor_bulk_action' ) );
69 }
70
71 /**
72 * Available tabs that will visible on the right side of page navbar
73 *
74 * @since 2.0.0
75 *
76 * @param string $search instructor search | optional.
77 * @param string $course_id course id that belong to instructor | optional.
78 * @param string $date user registered date | optional.
79 *
80 * @return array
81 */
82 public function tabs_key_value( $search = '', $course_id = '', $date = '' ): array {
83 $url = get_pagenum_link();
84 $approve = self::count_total_instructors( array( 'approved' ), $search, $course_id, $date, 'approved' );
85 $pending = self::count_total_instructors( array( 'pending' ), $search, $course_id, $date, 'pending' );
86 $blocked = self::count_total_instructors( array( 'blocked' ), $search, $course_id, $date, 'blocked' );
87
88 $tabs = array(
89 array(
90 'key' => 'all',
91 'title' => __( 'All', 'tutor' ),
92 'value' => $approve + $pending + $blocked,
93 'url' => $url . '&data=all',
94 ),
95 array(
96 'key' => 'approved',
97 'title' => __( 'Approve', 'tutor' ),
98 'value' => $approve,
99 'url' => $url . '&data=approved',
100 ),
101 array(
102 'key' => 'pending',
103 'title' => __( 'Pending', 'tutor' ),
104 'value' => $pending,
105 'url' => $url . '&data=pending',
106 ),
107 array(
108 'key' => 'blocked',
109 'title' => __( 'Block', 'tutor' ),
110 'value' => $blocked,
111 'url' => $url . '&data=blocked',
112 ),
113 );
114 return $tabs;
115 }
116
117 /**
118 * Prepare bulk actions that will show on dropdown options
119 *
120 * @since 2.0.0
121 * @return array
122 */
123 public function prpare_bulk_actions(): array {
124 $actions = array(
125 $this->bulk_action_default(),
126 $this->bulk_action_approved(),
127 $this->bulk_action_pending(),
128 $this->bulk_action_blocked(),
129 );
130 return $actions;
131 }
132
133 /**
134 * Handle bulk action for instructor delete
135 *
136 * @since 2.0.0
137 * @return string JSON response.
138 */
139 public function instructor_bulk_action() {
140 tutor_utils()->checking_nonce();
141
142 $action = Input::post( 'bulk-action', '' );
143 $bulk_ids = Input::post( 'bulk-ids', '' );
144
145 Input::has( 'bulkIds' ) ? $bulk_ids = Input::post( 'bulkIds' ) : 0;
146
147 if ( '' === $action || '' === $bulk_ids ) {
148 return wp_send_json_error();
149 }
150 if ( 'delete' === $action ) {
151 // Delete user from student_list class.
152 do_action( 'tutor_before_instructor_delete', $bulk_ids );
153 $response = Students_List::delete_students( $bulk_ids );
154 do_action( 'tutor_after_instructor_delete', $bulk_ids );
155 } else {
156 do_action( 'tutor_before_instructor_update', $bulk_ids );
157 $response = self::update_instructors( $action, $bulk_ids );
158 do_action( 'tutor_after_instructor_delete', $bulk_ids );
159 }
160
161 $message = 'Instructor status updated';
162
163 return true === $response ? wp_send_json_success( array( 'status' => $message ) ) : wp_send_json_error();
164 }
165
166 /**
167 * Execute bulk action for enrollment list ex: complete | cancel
168 *
169 * @since 2.0.0
170 *
171 * @param string $status hold status for updating.
172 * @param string $user_ids ids that need to update.
173 *
174 * @return bool
175 */
176 public static function update_instructors( $status, $user_ids ): bool {
177 global $wpdb;
178 $status = sanitize_text_field( $status );
179 $instructor_table = $wpdb->usermeta;
180
181 //phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
182 $update = $wpdb->query(
183 $wpdb->prepare(
184 "UPDATE {$instructor_table} SET meta_value = %s
185 WHERE user_id IN ($user_ids)
186 AND meta_key = %s",
187 $status,
188 '_tutor_instructor_status'
189 )
190 );
191 //phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
192
193 // Remove role.
194 if ( 'pending' === $status || 'blocked' === $status ) {
195 $arr = explode( ',', $user_ids );
196 foreach ( $arr as $instructor_id ) {
197 $instructor_id = (int) sanitize_text_field( $instructor_id );
198 self::remove_instructor_role( $instructor_id, $status );
199 }
200 }
201
202 if ( 'approved' === $status ) {
203 $arr = explode( ',', $user_ids );
204 foreach ( $arr as $instructor_id ) {
205 $instructor_id = (int) sanitize_text_field( $instructor_id );
206 self::add_instructor_role( $instructor_id, $status );
207 }
208 }
209 return false === $update ? false : true;
210 }
211
212 /**
213 * Get total course.
214 *
215 * @since 1.0.0
216 *
217 * @param object $item item.
218 * @return void
219 */
220 public function column_total_course( $item ) {
221 global $wpdb;
222 $course_post_type = tutor()->course_post_type;
223
224 $total_course = (int) $wpdb->get_var(
225 $wpdb->prepare(
226 "SELECT count(ID) from {$wpdb->posts}
227 WHERE post_author=%d AND post_type=%s ",
228 $item->ID,
229 $course_post_type
230 )
231 );
232
233 echo esc_html( $total_course );
234 }
235
236 /**
237 * Initialize instructor_role to a user
238 *
239 * @since 1.0.0
240 *
241 * @param integer $instructor_id | user id that need to add role.
242 * @param string $status | status that will added with role (approved).
243 *
244 * @return void
245 */
246 protected static function add_instructor_role( int $instructor_id, string $status ) {
247 $instructor_id = sanitize_text_field( $instructor_id );
248 $status = sanitize_text_field( $status );
249
250 do_action( 'tutor_before_approved_instructor', $instructor_id );
251
252 update_user_meta( $instructor_id, '_tutor_instructor_status', $status );
253 update_user_meta( $instructor_id, '_tutor_instructor_approved', tutor_time() );
254
255 $instructor = new \WP_User( $instructor_id );
256 $instructor->add_role( tutor()->instructor_role );
257
258 // TODO: send E-Mail to this user about instructor approval, should via hook.
259 do_action( 'tutor_after_approved_instructor', $instructor_id );
260 }
261
262 /**
263 * Initialize instructor_role to a user
264 *
265 * @since 1.0.0
266 *
267 * @param int $instructor_id | user id that need to add role.
268 * @param string $status | status that will added with role (approved).
269 *
270 * @return void
271 */
272 protected static function remove_instructor_role( int $instructor_id, string $status ) {
273 $instructor_id = sanitize_text_field( $instructor_id );
274 $status = sanitize_text_field( $status );
275
276 do_action( 'tutor_before_blocked_instructor', $instructor_id );
277 update_user_meta( $instructor_id, '_tutor_instructor_status', $status );
278
279 $instructor = new \WP_User( $instructor_id );
280 $instructor->remove_role( tutor()->instructor_role );
281 do_action( 'tutor_after_blocked_instructor', $instructor_id );
282 }
283
284 /**
285 * Get instructors list
286 *
287 * @since 2.1.7
288 *
289 * @param array $status instructor status: approved, pending, block.
290 * @param int $offset offset for pagination.
291 * @param int $per_page per page limit.
292 * @param string $search search keyword.
293 * @param string $course_id course id.
294 * @param string $date instructor registration date.
295 * @param string $order sorting order.
296 *
297 * @return wpdb::results
298 */
299 public static function get_instructors( array $status, $offset, $per_page, $search = '', $course_id = '', $date = '', $order = 'DESC' ) {
300 global $wpdb;
301
302 $wild = '%';
303
304 $search_clause = $wild . $wpdb->esc_like( $search ) . $wild;
305 $course_clause = '' !== $course_id ? "AND umeta.meta_value = {$course_id}" : '';
306 $date_clause = '' !== $date ? "AND DATE(user.user_registered) = CAST('$date' AS DATE )" : '';
307 $order_clause = '' !== $order ? "ORDER BY user.ID {$order}" : '';
308 $in_clause = QueryHelper::prepare_in_clause( $status );
309
310 $query = "SELECT
311 DISTINCT user.*,
312 ins_status.meta_value AS status,
313 (
314 SELECT
315 COUNT(*)
316 FROM {$wpdb->posts}
317 WHERE post_author = user.ID
318 AND post_type = 'courses'
319 ) total_courses
320 FROM {$wpdb->users} AS user
321
322 INNER JOIN {$wpdb->usermeta} AS ins_status
323 ON ( user.ID = ins_status.user_id )
324 AND ins_status.meta_key = '_tutor_instructor_status'
325 LEFT JOIN {$wpdb->usermeta} AS umeta
326 ON umeta.user_id = user.ID
327 AND umeta.meta_key = '_tutor_instructor_course_id'
328 WHERE ins_status.meta_value IN ($in_clause)
329 AND (user.user_email LIKE %s OR user.display_name LIKE %s)
330 {$course_clause}
331 {$date_clause}
332 {$order_clause}
333 LIMIT %d, %d;
334 ";
335 $result = wp_cache_get( self::INSTRUCTOR_LIST_CACHE_KEY );
336 if ( false === $result ) {
337 wp_cache_set(
338 self::INSTRUCTOR_LIST_CACHE_KEY,
339 $result = $wpdb->get_results(
340 $wpdb->prepare(
341 $query,
342 $search_clause,
343 $search_clause,
344 $offset,
345 $per_page
346 )
347 )
348 );
349 }
350
351 return $result;
352 }
353
354 /**
355 * Count total instructors
356 *
357 * @since 2.1.7
358 *
359 * @param array $status instructor status: approved, pending, block.
360 * @param string $search search keyword.
361 * @param string $course_id course id.
362 * @param string $date instructor registration date.
363 * @param string $unique_cache_key unique key will be append with
364 * self::INSTRUCTOR_COUNT_CACHE_KEY so that multiple count value could be
365 * stored as unique data.
366 *
367 * @return int count value of instructors
368 */
369 public static function count_total_instructors( array $status, $search = '', $course_id = '', $date = '', $unique_cache_key = '' ) {
370 global $wpdb;
371
372 $wild = '%';
373
374 $search_clause = $wild . $wpdb->esc_like( $search ) . $wild;
375 $course_clause = '' !== $course_id ? "AND umeta.meta_value = {$course_id}" : '';
376 $date_clause = '' !== $date ? "AND DATE(user.user_registered) = CAST('$date' AS DATE )" : '';
377 $in_clause = QueryHelper::prepare_in_clause( $status );
378
379 $query = "SELECT
380 COUNT(DISTINCT user.ID)
381
382 FROM {$wpdb->users} AS user
383
384 INNER JOIN {$wpdb->usermeta} AS ins_status
385 ON ( user.ID = ins_status.user_id )
386 AND ins_status.meta_key = '_tutor_instructor_status'
387 LEFT JOIN {$wpdb->usermeta} AS umeta
388 ON umeta.user_id = user.ID
389 AND umeta.meta_key = '_tutor_instructor_course_id'
390 WHERE ins_status.meta_value IN ($in_clause)
391 AND (user.user_email LIKE %s OR user.display_name LIKE %s)
392 {$course_clause}
393 {$date_clause}
394 ";
395 $result = wp_cache_get( self::INSTRUCTOR_COUNT_CACHE_KEY . $unique_cache_key );
396 if ( false === $result ) {
397 wp_cache_set(
398 self::INSTRUCTOR_COUNT_CACHE_KEY,
399 $result = $wpdb->get_var(
400 $wpdb->prepare(
401 $query,
402 $search_clause,
403 $search_clause
404 )
405 )
406 );
407 }
408 return $result;
409 }
410 }
411