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 / 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
417 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 ids that need to update.
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 //phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
188 $update = $wpdb->query(
189 $wpdb->prepare(
190 "UPDATE {$instructor_table} SET meta_value = %s
191 WHERE user_id IN ($user_ids)
192 AND meta_key = %s",
193 $status,
194 '_tutor_instructor_status'
195 )
196 );
197 //phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
198
199 // Remove role.
200 if ( 'pending' === $status || 'blocked' === $status ) {
201 $arr = explode( ',', $user_ids );
202 foreach ( $arr as $instructor_id ) {
203 $instructor_id = (int) sanitize_text_field( $instructor_id );
204 self::remove_instructor_role( $instructor_id, $status );
205 }
206 }
207
208 if ( 'approved' === $status ) {
209 $arr = explode( ',', $user_ids );
210 foreach ( $arr as $instructor_id ) {
211 $instructor_id = (int) sanitize_text_field( $instructor_id );
212 self::add_instructor_role( $instructor_id, $status );
213 }
214 }
215 return false === $update ? false : true;
216 }
217
218 /**
219 * Get total course.
220 *
221 * @since 1.0.0
222 *
223 * @param object $item item.
224 * @return void
225 */
226 public function column_total_course( $item ) {
227 global $wpdb;
228 $course_post_type = tutor()->course_post_type;
229
230 $total_course = (int) $wpdb->get_var(
231 $wpdb->prepare(
232 "SELECT count(ID) from {$wpdb->posts}
233 WHERE post_author=%d AND post_type=%s ",
234 $item->ID,
235 $course_post_type
236 )
237 );
238
239 echo esc_html( $total_course );
240 }
241
242 /**
243 * Initialize instructor_role to a user
244 *
245 * @since 1.0.0
246 *
247 * @param integer $instructor_id | user id that need to add role.
248 * @param string $status | status that will added with role (approved).
249 *
250 * @return void
251 */
252 protected static function add_instructor_role( int $instructor_id, string $status ) {
253 $instructor_id = sanitize_text_field( $instructor_id );
254 $status = sanitize_text_field( $status );
255
256 do_action( 'tutor_before_approved_instructor', $instructor_id );
257
258 update_user_meta( $instructor_id, '_tutor_instructor_status', $status );
259 update_user_meta( $instructor_id, '_tutor_instructor_approved', tutor_time() );
260
261 $instructor = new \WP_User( $instructor_id );
262 $instructor->add_role( tutor()->instructor_role );
263
264 // TODO: send E-Mail to this user about instructor approval, should via hook.
265 do_action( 'tutor_after_approved_instructor', $instructor_id );
266 }
267
268 /**
269 * Initialize instructor_role to a user
270 *
271 * @since 1.0.0
272 *
273 * @param int $instructor_id | user id that need to add role.
274 * @param string $status | status that will added with role (approved).
275 *
276 * @return void
277 */
278 protected static function remove_instructor_role( int $instructor_id, string $status ) {
279 $instructor_id = sanitize_text_field( $instructor_id );
280 $status = sanitize_text_field( $status );
281
282 do_action( 'tutor_before_blocked_instructor', $instructor_id );
283 update_user_meta( $instructor_id, '_tutor_instructor_status', $status );
284
285 $instructor = new \WP_User( $instructor_id );
286 $instructor->remove_role( tutor()->instructor_role );
287 do_action( 'tutor_after_blocked_instructor', $instructor_id );
288 }
289
290 /**
291 * Get instructors list
292 *
293 * @since 2.1.7
294 *
295 * @param array $status instructor status: approved, pending, block.
296 * @param int $offset offset for pagination.
297 * @param int $per_page per page limit.
298 * @param string $search search keyword.
299 * @param string $course_id course id.
300 * @param string $date instructor registration date.
301 * @param string $order sorting order.
302 *
303 * @return wpdb::results
304 */
305 public static function get_instructors( array $status, $offset, $per_page, $search = '', $course_id = '', $date = '', $order = 'DESC' ) {
306 global $wpdb;
307
308 $wild = '%';
309
310 $search_clause = $wild . $wpdb->esc_like( $search ) . $wild;
311 $course_clause = '' !== $course_id ? "AND umeta.meta_value = {$course_id}" : '';
312 $date_clause = '' !== $date ? "AND DATE(user.user_registered) = CAST('$date' AS DATE )" : '';
313 $order_clause = '' !== $order ? "ORDER BY user.ID {$order}" : '';
314 $in_clause = QueryHelper::prepare_in_clause( $status );
315
316 $query = "SELECT
317 DISTINCT user.*,
318 ins_status.meta_value AS status,
319 (
320 SELECT
321 COUNT(*)
322 FROM {$wpdb->posts}
323 WHERE post_author = user.ID
324 AND post_type = 'courses'
325 ) total_courses
326 FROM {$wpdb->users} AS user
327
328 INNER JOIN {$wpdb->usermeta} AS ins_status
329 ON ( user.ID = ins_status.user_id )
330 AND ins_status.meta_key = '_tutor_instructor_status'
331 LEFT JOIN {$wpdb->usermeta} AS umeta
332 ON umeta.user_id = user.ID
333 AND umeta.meta_key = '_tutor_instructor_course_id'
334 WHERE ins_status.meta_value IN ($in_clause)
335 AND (user.user_email LIKE %s OR user.display_name LIKE %s)
336 {$course_clause}
337 {$date_clause}
338 {$order_clause}
339 LIMIT %d, %d;
340 ";
341 $result = TutorCache::get( self::INSTRUCTOR_LIST_CACHE_KEY );
342 if ( false === $result ) {
343 TutorCache::set(
344 self::INSTRUCTOR_LIST_CACHE_KEY,
345 $result = $wpdb->get_results(
346 $wpdb->prepare(
347 $query,
348 $search_clause,
349 $search_clause,
350 $offset,
351 $per_page
352 )
353 )
354 );
355 }
356
357 return $result;
358 }
359
360 /**
361 * Count total instructors
362 *
363 * @since 2.1.7
364 *
365 * @param array $status instructor status: approved, pending, block.
366 * @param string $search search keyword.
367 * @param string $course_id course id.
368 * @param string $date instructor registration date.
369 * @param string $unique_cache_key unique key will be append with
370 * self::INSTRUCTOR_COUNT_CACHE_KEY so that multiple count value could be
371 * stored as unique data.
372 *
373 * @return int count value of instructors
374 */
375 public static function count_total_instructors( array $status, $search = '', $course_id = '', $date = '', $unique_cache_key = '' ) {
376 global $wpdb;
377
378 $wild = '%';
379
380 $search_clause = $wild . $wpdb->esc_like( $search ) . $wild;
381 $course_clause = '' !== $course_id ? "AND umeta.meta_value = {$course_id}" : '';
382 $date_clause = '' !== $date ? "AND DATE(user.user_registered) = CAST('$date' AS DATE )" : '';
383 $in_clause = QueryHelper::prepare_in_clause( $status );
384
385 $query = "SELECT
386 COUNT(DISTINCT user.ID)
387
388 FROM {$wpdb->users} AS user
389
390 INNER JOIN {$wpdb->usermeta} AS ins_status
391 ON ( user.ID = ins_status.user_id )
392 AND ins_status.meta_key = '_tutor_instructor_status'
393 LEFT JOIN {$wpdb->usermeta} AS umeta
394 ON umeta.user_id = user.ID
395 AND umeta.meta_key = '_tutor_instructor_course_id'
396 WHERE ins_status.meta_value IN ($in_clause)
397 AND (user.user_email LIKE %s OR user.display_name LIKE %s)
398 {$course_clause}
399 {$date_clause}
400 ";
401 $result = TutorCache::get( self::INSTRUCTOR_COUNT_CACHE_KEY . $unique_cache_key );
402 if ( false === $result ) {
403 TutorCache::set(
404 self::INSTRUCTOR_COUNT_CACHE_KEY,
405 $result = $wpdb->get_var(
406 $wpdb->prepare(
407 $query,
408 $search_clause,
409 $search_clause
410 )
411 )
412 );
413 }
414 return $result;
415 }
416 }
417