PluginProbe
Tutor LMS – eLearning and online course solution / 2.7.3
Tutor LMS – eLearning and online course solution v2.7.3
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 +104 -92 trunk2.7.3 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
@@ -29,8 +30,15 @@
29 30
30 31 use Backend_Page_Trait;
31 32
32 33 /**
34 + * Page Title
35 + *
36 + * @var $page_title
37 + */
38 + public $page_title;
39 +
40 + /**
33 41 * Bulk Action
34 42 *
35 43 * @var $bulk_action
36 44 */
@@ -39,53 +47,37 @@
39 47 /**
40 48 * Constructor
41 49 *
42 50 * @return void
43 - *
44 51 * @since 2.0.0
45 52 */
46 53 public function __construct() {
54 + $this->page_title = __( 'Courses', 'tutor' );
47 55 /**
48 56 * Handle bulk action
49 57 *
50 - * @since 2.0.0
58 + * @since v2.0.0
51 59 */
52 60 add_action( 'wp_ajax_tutor_course_list_bulk_action', array( $this, 'course_list_bulk_action' ) );
53 61 /**
54 62 * Handle ajax request for updating course status
55 63 *
56 - * @since 2.0.0
64 + * @since v2.0.0
57 65 */
58 66 add_action( 'wp_ajax_tutor_change_course_status', array( $this, 'tutor_change_course_status' ) );
59 67 /**
60 68 * Handle ajax request for delete course
61 69 *
62 - * @since 2.0.0
70 + * @since v2.0.0
63 71 */
64 72 add_action( 'wp_ajax_tutor_course_delete', array( $this, 'tutor_course_delete' ) );
65 73 }
66 74
67 75 /**
68 - * Page title fallback
69 - *
70 - * @since 3.5.0
71 - *
72 - * @param string $name Property name.
73 - *
74 - * @return string
75 - */
76 - public function __get( $name ) {
77 - if ( 'page_title' === $name ) {
78 - return esc_html__( 'Courses', 'tutor' );
79 - }
80 - }
81 -
82 - /**
83 76 * Prepare bulk actions that will show on dropdown options
84 77 *
78 + * @return array
85 79 * @since 2.0.0
86 - *
87 - * @return array
88 80 */
89 81 public function prepare_bulk_actions(): array {
90 82 $actions = array(
91 83 $this->bulk_action_default(),
@@ -95,19 +87,24 @@
95 87 );
96 88
97 89 $active_tab = Input::get( 'data', '' );
98 90
99 - if ( CourseModel::STATUS_TRASH === $active_tab ) {
91 + if ( 'trash' === $active_tab ) {
100 92 array_push( $actions, $this->bulk_action_delete() );
101 93 }
102 - if ( CourseModel::STATUS_TRASH !== $active_tab ) {
94 + if ( 'trash' !== $active_tab ) {
103 95 array_push( $actions, $this->bulk_action_trash() );
104 96 }
105 97
106 - if ( ! User::is_admin() ) {
107 - $can_trash_post = tutor_utils()->get_option( 'instructor_can_delete_course' ) && current_user_can( 'edit_tutor_courses' );
98 + if ( ! current_user_can( 'administrator' ) ) {
99 + $can_trash_post = tutor_utils()->get_option( 'instructor_can_delete_course' ) && current_user_can( 'edit_tutor_course' );
108 100 if ( ! $can_trash_post ) {
109 - $actions = array_filter( $actions, fn ( $val ) => CourseModel::STATUS_TRASH !== $val['value'] );
101 + $actions = array_filter(
102 + $actions,
103 + function ( $val ) {
104 + return 'trash' !== $val['value'];
105 + }
106 + );
110 107 }
111 108 }
112 109 return apply_filters( 'tutor_course_bulk_actions', $actions );
113 110 }
@@ -114,10 +111,8 @@
114 111
115 112 /**
116 113 * Available tabs that will visible on the right side of page navbar
117 114 *
118 - * @since 2.0.0
119 - *
120 115 * @param string $category_slug category slug.
121 116 * @param integer $course_id course ID.
122 117 * @param string $date selected date | optional.
123 118 * @param string $search search by user name or email | optional.
@@ -122,11 +117,13 @@
122 117 * @param string $date selected date | optional.
123 118 * @param string $search search by user name or email | optional.
124 119 *
125 120 * @return array
121 + *
122 + * @since v2.0.0
126 123 */
127 124 public function tabs_key_value( $category_slug, $course_id, $date, $search ): array {
128 - $url = apply_filters( 'tutor_data_tab_base_url', get_pagenum_link() );
125 + $url = get_pagenum_link();
129 126
130 127 $all = self::count_course( 'all', $category_slug, $course_id, $date, $search );
131 128 $mine = self::count_course( 'mine', $category_slug, $course_id, $date, $search );
132 129 $published = self::count_course( 'publish', $category_slug, $course_id, $date, $search );
@@ -137,9 +134,9 @@
137 134 $future = self::count_course( 'future', $category_slug, $course_id, $date, $search );
138 135
139 136 $tabs = array(
140 137 array(
141 - 'key' => '',
138 + 'key' => 'all',
142 139 'title' => __( 'All', 'tutor' ),
143 140 'value' => $all,
144 141 'url' => $url . '&data=all',
145 142 ),
@@ -195,10 +192,8 @@
195 192 /**
196 193 * Count courses by status & filters
197 194 * Count all | min | published | pending | draft
198 195 *
199 - * @since 2.0.0
200 - *
201 196 * @param string $status | required.
202 197 * @param string $category_slug course category | optional.
203 198 * @param string $course_id selected course id | optional.
204 199 * @param string $date selected date | optional.
@@ -204,8 +199,10 @@
204 199 * @param string $date selected date | optional.
205 200 * @param string $search_term search by user name or email | optional.
206 201 *
207 202 * @return int
203 + *
204 + * @since 2.0.0
208 205 */
209 206 protected static function count_course( string $status, $category_slug = '', $course_id = '', $date = '', $search_term = '' ): int {
210 207 $user_id = get_current_user_id();
211 208 $status = sanitize_text_field( $status );
@@ -230,11 +227,11 @@
230 227 }
231 228
232 229 $date_filter = sanitize_text_field( $date );
233 230
234 - $year = gmdate( 'Y', strtotime( $date_filter ) );
235 - $month = gmdate( 'm', strtotime( $date_filter ) );
236 - $day = gmdate( 'd', strtotime( $date_filter ) );
231 + $year = date( 'Y', strtotime( $date_filter ) );
232 + $month = date( 'm', strtotime( $date_filter ) );
233 + $day = date( 'd', strtotime( $date_filter ) );
237 234
238 235 // Add date query.
239 236 if ( '' !== $date_filter ) {
240 237 $args['date_query'] = array(
@@ -258,9 +255,9 @@
258 255 // Category filter.
259 256 if ( '' !== $category_slug ) {
260 257 $args['tax_query'] = array(
261 258 array(
262 - 'taxonomy' => CourseModel::COURSE_CATEGORY,
259 + 'taxonomy' => 'course-category',
263 260 'field' => 'slug',
264 261 'terms' => $category_slug,
265 262 ),
266 263 );
@@ -265,19 +262,19 @@
265 262 ),
266 263 );
267 264 }
268 265
269 - $the_query = self::course_list_query( $args, $user_id, $status );
266 + $the_query = new \WP_Query( $args );
270 267
271 268 return ! is_null( $the_query ) && isset( $the_query->found_posts ) ? $the_query->found_posts : $the_query;
269 +
272 270 }
273 271
274 272 /**
275 273 * Handle bulk action for enrollment cancel | delete
276 274 *
275 + * @return void
277 276 * @since 2.0.0
278 - *
279 - * @return void
280 277 */
281 278 public function course_list_bulk_action() {
282 279
283 280 tutor_utils()->checking_nonce();
@@ -285,31 +282,18 @@
285 282 $action = Input::post( 'bulk-action', '' );
286 283 $bulk_ids = Input::post( 'bulk-ids', '' );
287 284
288 285 // 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' ) ) {
286 + if ( ! current_user_can( 'administrator' ) ) {
287 + if ( current_user_can( 'edit_tutor_course' ) ) {
293 288 $can_publish_course = tutor_utils()->get_option( 'instructor_can_publish_course' );
294 289
295 - if ( CourseModel::STATUS_PUBLISH === $action && ! $can_publish_course ) {
290 + if ( 'publish' === $action && ! $can_publish_course ) {
296 291 wp_send_json_error( tutor_utils()->error_message() );
297 292 }
298 293 } else {
299 294 wp_send_json_error( tutor_utils()->error_message() );
300 295 }
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 296 }
313 297
314 298 if ( '' === $action || '' === $bulk_ids ) {
315 299 wp_send_json_error( array( 'message' => __( 'Please select appropriate action', 'tutor' ) ) );
@@ -338,9 +322,14 @@
338 322 $update_status = self::update_course_status( $action, $bulk_ids );
339 323
340 324 do_action( 'after_tutor_course_bulk_action_update', $action, $bulk_ids );
341 325
342 - $update_status ? wp_send_json_success() : wp_send_json_error( array( 'message' => __( 'Could not update course status', 'tutor' ) ) );
326 + $update_status ? wp_send_json_success() : wp_send_json_error(
327 + array(
328 + 'message' => 'Could not update course status',
329 + 'tutor',
330 + )
331 + );
343 332
344 333 exit;
345 334 }
346 335
@@ -346,21 +335,20 @@
346 335
347 336 /**
348 337 * Handle ajax request for updating course status
349 338 *
339 + * @return void
350 340 * @since 2.0.0
351 - *
352 - * @return void
353 341 */
354 342 public static function tutor_change_course_status() {
355 343 tutor_utils()->checking_nonce();
356 344
357 345 $status = Input::post( 'status' );
358 - $id = Input::post( 'id', 0, Input::TYPE_INT );
346 + $id = Input::post( 'id' );
359 347 $course = get_post( $id );
360 348
361 349 // Check if user is privileged.
362 - if ( ! User::is_admin() ) {
350 + if ( ! current_user_can( 'administrator' ) ) {
363 351
364 352 if ( ! tutor_utils()->can_user_edit_course( get_current_user_id(), $course->ID ) ) {
365 353 wp_send_json_error( tutor_utils()->error_message() );
366 354 }
@@ -367,13 +355,13 @@
367 355
368 356 $can_delete_course = tutor_utils()->get_option( 'instructor_can_delete_course' );
369 357 $can_publish_course = tutor_utils()->get_option( 'instructor_can_publish_course' );
370 358
371 - if ( CourseModel::STATUS_PUBLISH === $status && ! $can_publish_course ) {
359 + if ( 'publish' === $status && ! $can_publish_course ) {
372 360 wp_send_json_error( tutor_utils()->error_message() );
373 361 }
374 362
375 - if ( CourseModel::STATUS_TRASH === $status && $can_delete_course ) {
363 + if ( 'trash' === $status && $can_delete_course ) {
376 364 $args = array(
377 365 'ID' => $id,
378 366 'post_status' => $status,
379 367 );
@@ -384,9 +372,9 @@
384 372 }
385 373 }
386 374 }
387 375
388 - if ( ! CourseModel::get_post_types( $course ) ) {
376 + if ( CourseModel::POST_TYPE !== $course->post_type ) {
389 377 wp_send_json_error( tutor_utils()->error_message() );
390 378 }
391 379
392 380 $args = array(
@@ -436,13 +424,11 @@
436 424
437 425 /**
438 426 * Execute bulk delete action
439 427 *
440 - * @since 2.0.0
441 - *
442 428 * @param string $bulk_ids ids that need to update.
443 - *
444 429 * @return bool
430 + * @since 2.0.0
445 431 */
446 432 public static function bulk_delete_course( $bulk_ids ): bool {
447 433 $bulk_ids = explode( ',', sanitize_text_field( $bulk_ids ) );
448 434
@@ -455,14 +441,14 @@
455 441
456 442 /**
457 443 * Update course status
458 444 *
459 - * @since 2.0.0
460 - *
461 445 * @param string $status for updating course status.
462 446 * @param string $bulk_ids comma separated ids.
463 447 *
464 448 * @return bool
449 + *
450 + * @since 2.0.0
465 451 */
466 452 public static function update_course_status( string $status, $bulk_ids ): bool {
467 453 global $wpdb;
468 454 $post_table = $wpdb->posts;
@@ -471,9 +457,9 @@
471 457
472 458 $ids = array_map( 'intval', explode( ',', $bulk_ids ) );
473 459 $in_clause = QueryHelper::prepare_in_clause( $ids );
474 460
475 - $wpdb->query(
461 + $update = $wpdb->query(
476 462 $wpdb->prepare(
477 463 "UPDATE {$post_table} SET post_status = %s WHERE ID IN ($in_clause)", //phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
478 464 $status
479 465 )
@@ -482,35 +468,61 @@
482 468 return true;
483 469 }
484 470
485 471 /**
486 - * Check course is public or not
472 + * Get course enrollment list with student info
487 473 *
488 - * @since 1.0.0
474 + * @param int $course_id int | required.
475 + * @return array
476 + * @since 2.0.0
477 + */
478 + public static function course_enrollments_with_student_details( int $course_id ) {
479 + global $wpdb;
480 + $course_id = sanitize_text_field( $course_id );
481 + $course_completed = 0;
482 + $course_inprogress = 0;
483 +
484 + $enrollments = $wpdb->get_results(
485 + $wpdb->prepare(
486 + "SELECT enroll.ID AS enroll_id, enroll.post_author AS enroll_author, user.*, course.ID AS course_id
487 + FROM {$wpdb->posts} AS enroll
488 + LEFT JOIN {$wpdb->users} AS user ON user.ID = enroll.post_author
489 + LEFT JOIN {$wpdb->posts} AS course ON course.ID = enroll.post_parent
490 + WHERE enroll.post_type = %s
491 + AND enroll.post_status = %s
492 + AND enroll.post_parent = %d
493 + ",
494 + 'tutor_enrolled',
495 + 'completed',
496 + $course_id
497 + )
498 + );
499 +
500 + foreach ( $enrollments as $enrollment ) {
501 + $course_progress = tutor_utils()->get_course_completed_percent( $course_id, $enrollment->enroll_author );
502 + if ( 100 == $course_progress ) {
503 + $course_completed++;
504 + } else {
505 + $course_inprogress++;
506 + }
507 + }
508 +
509 + return array(
510 + 'enrollments' => $enrollments,
511 + 'total_completed' => $course_completed,
512 + 'total_inprogress' => $course_inprogress,
513 + 'total_enrollments' => count( $enrollments ),
514 + );
515 + }
516 +
517 + /**
518 + * Check wheather course is public or not
489 519 *
490 520 * @param integer $course_id course id to check with.
491 - *
492 521 * @return boolean true if public otherwise false.
522 + * @since 1.0.0
493 523 */
494 524 public static function is_public( int $course_id ): bool {
495 525 $is_public = get_post_meta( $course_id, '_tutor_is_public_course', true );
496 526 return 'yes' === $is_public ? true : false;
497 - }
498 -
499 - /**
500 - * Query for obtaining course list.
501 - *
502 - * @since 3.4.0
503 - *
504 - * @param array $args the query args.
505 - * @param int $user_id the user id.
506 - * @param string $status the post status.
507 - * @param bool $all_post_types should keep all post types.
508 - *
509 - * @return \WP_Query
510 - */
511 - public static function course_list_query( $args, $user_id, $status, $all_post_types = false ) {
512 -
513 - $course_list_query = new \WP_Query( apply_filters( 'tutor_admin_course_list', $args, $user_id, $status, $all_post_types ) );
514 - return $course_list_query;
515 527 }
516 528 }