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