PluginProbe
Tutor LMS – eLearning and online course solution / 3.7.2
Tutor LMS – eLearning and online course solution v3.7.2
4.0.7 4.0.6 4.0.5 4.0.4 4.0.3 4.0.2 4.0.1 4.0.0 3.9.15 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 All 191 releases
← All changes | classes/Course_List.php +85 -53 trunk3.7.2 View file →
@@ -9,13 +9,14 @@
9 9 */
10 10
11 11 namespace TUTOR;
12 12
13 -defined( 'ABSPATH' ) || exit;
14 -
15 13 use Tutor\Helpers\QueryHelper;
16 14 use Tutor\Models\CourseModel;
17 15
16 +if ( ! defined( 'ABSPATH' ) ) {
17 + exit;
18 +}
18 19 /**
19 20 * Course List class
20 21 *
21 22 * @since 2.0.0
@@ -39,9 +40,8 @@
39 40 /**
40 41 * Constructor
41 42 *
42 43 * @return void
43 - *
44 44 * @since 2.0.0
45 45 */
46 46 public function __construct() {
47 47 /**
@@ -46,21 +46,21 @@
46 46 public function __construct() {
47 47 /**
48 48 * Handle bulk action
49 49 *
50 - * @since 2.0.0
50 + * @since v2.0.0
51 51 */
52 52 add_action( 'wp_ajax_tutor_course_list_bulk_action', array( $this, 'course_list_bulk_action' ) );
53 53 /**
54 54 * Handle ajax request for updating course status
55 55 *
56 - * @since 2.0.0
56 + * @since v2.0.0
57 57 */
58 58 add_action( 'wp_ajax_tutor_change_course_status', array( $this, 'tutor_change_course_status' ) );
59 59 /**
60 60 * Handle ajax request for delete course
61 61 *
62 - * @since 2.0.0
62 + * @since v2.0.0
63 63 */
64 64 add_action( 'wp_ajax_tutor_course_delete', array( $this, 'tutor_course_delete' ) );
65 65 }
66 66
@@ -81,11 +81,10 @@
81 81
82 82 /**
83 83 * Prepare bulk actions that will show on dropdown options
84 84 *
85 + * @return array
85 86 * @since 2.0.0
86 - *
87 - * @return array
88 87 */
89 88 public function prepare_bulk_actions(): array {
90 89 $actions = array(
91 90 $this->bulk_action_default(),
@@ -95,19 +94,24 @@
95 94 );
96 95
97 96 $active_tab = Input::get( 'data', '' );
98 97
99 - if ( CourseModel::STATUS_TRASH === $active_tab ) {
98 + if ( 'trash' === $active_tab ) {
100 99 array_push( $actions, $this->bulk_action_delete() );
101 100 }
102 - if ( CourseModel::STATUS_TRASH !== $active_tab ) {
101 + if ( 'trash' !== $active_tab ) {
103 102 array_push( $actions, $this->bulk_action_trash() );
104 103 }
105 104
106 - if ( ! User::is_admin() ) {
107 - $can_trash_post = tutor_utils()->get_option( 'instructor_can_delete_course' ) && current_user_can( 'edit_tutor_courses' );
105 + if ( ! current_user_can( 'administrator' ) ) {
106 + $can_trash_post = tutor_utils()->get_option( 'instructor_can_delete_course' ) && current_user_can( 'edit_tutor_course' );
108 107 if ( ! $can_trash_post ) {
109 - $actions = array_filter( $actions, fn ( $val ) => CourseModel::STATUS_TRASH !== $val['value'] );
108 + $actions = array_filter(
109 + $actions,
110 + function ( $val ) {
111 + return 'trash' !== $val['value'];
112 + }
113 + );
110 114 }
111 115 }
112 116 return apply_filters( 'tutor_course_bulk_actions', $actions );
113 117 }
@@ -114,10 +118,8 @@
114 118
115 119 /**
116 120 * Available tabs that will visible on the right side of page navbar
117 121 *
118 - * @since 2.0.0
119 - *
120 122 * @param string $category_slug category slug.
121 123 * @param integer $course_id course ID.
122 124 * @param string $date selected date | optional.
123 125 * @param string $search search by user name or email | optional.
@@ -122,8 +124,10 @@
122 124 * @param string $date selected date | optional.
123 125 * @param string $search search by user name or email | optional.
124 126 *
125 127 * @return array
128 + *
129 + * @since v2.0.0
126 130 */
127 131 public function tabs_key_value( $category_slug, $course_id, $date, $search ): array {
128 132 $url = apply_filters( 'tutor_data_tab_base_url', get_pagenum_link() );
129 133
@@ -195,10 +199,8 @@
195 199 /**
196 200 * Count courses by status & filters
197 201 * Count all | min | published | pending | draft
198 202 *
199 - * @since 2.0.0
200 - *
201 203 * @param string $status | required.
202 204 * @param string $category_slug course category | optional.
203 205 * @param string $course_id selected course id | optional.
204 206 * @param string $date selected date | optional.
@@ -204,8 +206,10 @@
204 206 * @param string $date selected date | optional.
205 207 * @param string $search_term search by user name or email | optional.
206 208 *
207 209 * @return int
210 + *
211 + * @since 2.0.0
208 212 */
209 213 protected static function count_course( string $status, $category_slug = '', $course_id = '', $date = '', $search_term = '' ): int {
210 214 $user_id = get_current_user_id();
211 215 $status = sanitize_text_field( $status );
@@ -230,11 +234,11 @@
230 234 }
231 235
232 236 $date_filter = sanitize_text_field( $date );
233 237
234 - $year = gmdate( 'Y', strtotime( $date_filter ) );
235 - $month = gmdate( 'm', strtotime( $date_filter ) );
236 - $day = gmdate( 'd', strtotime( $date_filter ) );
238 + $year = date( 'Y', strtotime( $date_filter ) );
239 + $month = date( 'm', strtotime( $date_filter ) );
240 + $day = date( 'd', strtotime( $date_filter ) );
237 241
238 242 // Add date query.
239 243 if ( '' !== $date_filter ) {
240 244 $args['date_query'] = array(
@@ -268,16 +272,16 @@
268 272
269 273 $the_query = self::course_list_query( $args, $user_id, $status );
270 274
271 275 return ! is_null( $the_query ) && isset( $the_query->found_posts ) ? $the_query->found_posts : $the_query;
276 +
272 277 }
273 278
274 279 /**
275 280 * Handle bulk action for enrollment cancel | delete
276 281 *
282 + * @return void
277 283 * @since 2.0.0
278 - *
279 - * @return void
280 284 */
281 285 public function course_list_bulk_action() {
282 286
283 287 tutor_utils()->checking_nonce();
@@ -285,31 +289,18 @@
285 289 $action = Input::post( 'bulk-action', '' );
286 290 $bulk_ids = Input::post( 'bulk-ids', '' );
287 291
288 292 // Check if user is privileged.
289 - if ( ! User::is_admin() ) {
290 - $course_ids = explode( ',', $bulk_ids );
291 -
292 - if ( current_user_can( 'edit_tutor_courses' ) ) {
293 + if ( ! current_user_can( 'administrator' ) ) {
294 + if ( current_user_can( 'edit_tutor_course' ) ) {
293 295 $can_publish_course = tutor_utils()->get_option( 'instructor_can_publish_course' );
294 296
295 - if ( CourseModel::STATUS_PUBLISH === $action && ! $can_publish_course ) {
297 + if ( 'publish' === $action && ! $can_publish_course ) {
296 298 wp_send_json_error( tutor_utils()->error_message() );
297 299 }
298 300 } else {
299 301 wp_send_json_error( tutor_utils()->error_message() );
300 302 }
301 -
302 - // Check if the course ids are instructors own course.
303 - $course_ids = array_filter(
304 - $course_ids,
305 - function ( $course_id ) {
306 - return tutor_utils()->is_instructor_of_this_course( get_current_user_id(), $course_id );
307 - }
308 - );
309 -
310 - $bulk_ids = implode( ',', $course_ids );
311 -
312 303 }
313 304
314 305 if ( '' === $action || '' === $bulk_ids ) {
315 306 wp_send_json_error( array( 'message' => __( 'Please select appropriate action', 'tutor' ) ) );
@@ -346,21 +337,20 @@
346 337
347 338 /**
348 339 * Handle ajax request for updating course status
349 340 *
341 + * @return void
350 342 * @since 2.0.0
351 - *
352 - * @return void
353 343 */
354 344 public static function tutor_change_course_status() {
355 345 tutor_utils()->checking_nonce();
356 346
357 347 $status = Input::post( 'status' );
358 - $id = Input::post( 'id', 0, Input::TYPE_INT );
348 + $id = Input::post( 'id' );
359 349 $course = get_post( $id );
360 350
361 351 // Check if user is privileged.
362 - if ( ! User::is_admin() ) {
352 + if ( ! current_user_can( 'administrator' ) ) {
363 353
364 354 if ( ! tutor_utils()->can_user_edit_course( get_current_user_id(), $course->ID ) ) {
365 355 wp_send_json_error( tutor_utils()->error_message() );
366 356 }
@@ -367,13 +357,13 @@
367 357
368 358 $can_delete_course = tutor_utils()->get_option( 'instructor_can_delete_course' );
369 359 $can_publish_course = tutor_utils()->get_option( 'instructor_can_publish_course' );
370 360
371 - if ( CourseModel::STATUS_PUBLISH === $status && ! $can_publish_course ) {
361 + if ( 'publish' === $status && ! $can_publish_course ) {
372 362 wp_send_json_error( tutor_utils()->error_message() );
373 363 }
374 364
375 - if ( CourseModel::STATUS_TRASH === $status && $can_delete_course ) {
365 + if ( 'trash' === $status && $can_delete_course ) {
376 366 $args = array(
377 367 'ID' => $id,
378 368 'post_status' => $status,
379 369 );
@@ -436,13 +426,11 @@
436 426
437 427 /**
438 428 * Execute bulk delete action
439 429 *
440 - * @since 2.0.0
441 - *
442 430 * @param string $bulk_ids ids that need to update.
443 - *
444 431 * @return bool
432 + * @since 2.0.0
445 433 */
446 434 public static function bulk_delete_course( $bulk_ids ): bool {
447 435 $bulk_ids = explode( ',', sanitize_text_field( $bulk_ids ) );
448 436
@@ -455,14 +443,14 @@
455 443
456 444 /**
457 445 * Update course status
458 446 *
459 - * @since 2.0.0
460 - *
461 447 * @param string $status for updating course status.
462 448 * @param string $bulk_ids comma separated ids.
463 449 *
464 450 * @return bool
451 + *
452 + * @since 2.0.0
465 453 */
466 454 public static function update_course_status( string $status, $bulk_ids ): bool {
467 455 global $wpdb;
468 456 $post_table = $wpdb->posts;
@@ -471,9 +459,9 @@
471 459
472 460 $ids = array_map( 'intval', explode( ',', $bulk_ids ) );
473 461 $in_clause = QueryHelper::prepare_in_clause( $ids );
474 462
475 - $wpdb->query(
463 + $update = $wpdb->query(
476 464 $wpdb->prepare(
477 465 "UPDATE {$post_table} SET post_status = %s WHERE ID IN ($in_clause)", //phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
478 466 $status
479 467 )
@@ -482,15 +470,59 @@
482 470 return true;
483 471 }
484 472
485 473 /**
486 - * Check course is public or not
474 + * Get course enrollment list with student info
487 475 *
488 - * @since 1.0.0
476 + * @param int $course_id int | required.
477 + * @return array
478 + * @since 2.0.0
479 + */
480 + public static function course_enrollments_with_student_details( int $course_id ) {
481 + global $wpdb;
482 + $course_id = sanitize_text_field( $course_id );
483 + $course_completed = 0;
484 + $course_inprogress = 0;
485 +
486 + $enrollments = $wpdb->get_results(
487 + $wpdb->prepare(
488 + "SELECT enroll.ID AS enroll_id, enroll.post_author AS enroll_author, user.*, course.ID AS course_id
489 + FROM {$wpdb->posts} AS enroll
490 + LEFT JOIN {$wpdb->users} AS user ON user.ID = enroll.post_author
491 + LEFT JOIN {$wpdb->posts} AS course ON course.ID = enroll.post_parent
492 + WHERE enroll.post_type = %s
493 + AND enroll.post_status = %s
494 + AND enroll.post_parent = %d
495 + ",
496 + 'tutor_enrolled',
497 + 'completed',
498 + $course_id
499 + )
500 + );
501 +
502 + foreach ( $enrollments as $enrollment ) {
503 + $course_progress = tutor_utils()->get_course_completed_percent( $course_id, $enrollment->enroll_author );
504 + if ( 100 == $course_progress ) {
505 + $course_completed++;
506 + } else {
507 + $course_inprogress++;
508 + }
509 + }
510 +
511 + return array(
512 + 'enrollments' => $enrollments,
513 + 'total_completed' => $course_completed,
514 + 'total_inprogress' => $course_inprogress,
515 + 'total_enrollments' => count( $enrollments ),
516 + );
517 + }
518 +
519 + /**
520 + * Check wheather course is public or not
489 521 *
490 522 * @param integer $course_id course id to check with.
491 - *
492 523 * @return boolean true if public otherwise false.
524 + * @since 1.0.0
493 525 */
494 526 public static function is_public( int $course_id ): bool {
495 527 $is_public = get_post_meta( $course_id, '_tutor_is_public_course', true );
496 528 return 'yes' === $is_public ? true : false;