PluginProbe ʕ •ᴥ•ʔ
Tutor LMS – eLearning and online course solution / 2.0.0
Tutor LMS – eLearning and online course solution v2.0.0
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 / Course_List.php
tutor / classes Last commit date
Addons.php 4 years ago Admin.php 4 years ago Ajax.php 4 years ago Announcements.php 4 years ago Assets.php 4 years ago Backend_Page_Trait.php 4 years ago Course.php 4 years ago Course_Filter.php 4 years ago Course_List.php 4 years ago Course_Settings_Tabs.php 4 years ago Course_Widget.php 4 years ago Custom_Validation.php 5 years ago Dashboard.php 4 years ago FormHandler.php 4 years ago Frontend.php 4 years ago Gutenberg.php 4 years ago Instructor.php 4 years ago Instructors_List.php 4 years ago Lesson.php 4 years ago Options_V2.php 4 years ago Post_types.php 4 years ago Private_Course_Access.php 4 years ago Q_and_A.php 4 years ago Question_Answers_List.php 4 years ago Quiz.php 4 years ago Quiz_Attempts_List.php 4 years ago RestAPI.php 4 years ago Reviews.php 4 years ago Rewrite_Rules.php 4 years ago Shortcode.php 4 years ago Student.php 4 years ago Students_List.php 4 years ago Taxonomies.php 4 years ago Template.php 4 years ago Theme_Compatibility.php 5 years ago Tools.php 4 years ago Tools_V2.php 4 years ago Tutor.php 4 years ago TutorEDD.php 4 years ago Tutor_Base.php 5 years ago Tutor_List_Table.php 4 years ago Tutor_Setup.php 4 years ago Upgrader.php 4 years ago User.php 4 years ago Utils.php 4 years ago Video_Stream.php 4 years ago Withdraw.php 4 years ago Withdraw_Requests_List.php 4 years ago WooCommerce.php 4 years ago
Course_List.php
496 lines
1 <?php
2 /**
3 * Course List class
4 *
5 * @package Course List
6 * @since v2.0.0
7 */
8
9 namespace TUTOR;
10
11 if ( ! defined( 'ABSPATH' ) ) {
12 exit;
13 }
14 /**
15 * Announcements class for handling logics
16 */
17 class Course_List {
18 /**
19 * Trait for utilities
20 *
21 * @var $page_title
22 */
23
24 use Backend_Page_Trait;
25 /**
26 * Page Title
27 *
28 * @var $page_title
29 */
30 public $page_title;
31
32 /**
33 * Bulk Action
34 *
35 * @var $bulk_action
36 */
37 public $bulk_action = true;
38
39 /**
40 * Handle dependencies
41 */
42 public function __construct() {
43 $this->page_title = __( 'Courses', 'tutor' );
44 /**
45 * Handle bulk action
46 *
47 * @since v2.0.0
48 */
49 add_action( 'wp_ajax_tutor_course_list_bulk_action', array( $this, 'course_list_bulk_action' ) );
50 /**
51 * Handle ajax request for updating course status
52 *
53 * @since v2.0.0
54 */
55 add_action( 'wp_ajax_tutor_change_course_status', array( __CLASS__, 'tutor_change_course_status' ) );
56 /**
57 * Handle ajax request for delete course
58 *
59 * @since v2.0.0
60 */
61 add_action( 'wp_ajax_tutor_course_delete', array( __CLASS__, 'tutor_course_delete' ) );
62 add_action( 'wp_ajax_tabs_key_value_all', array( __CLASS__, 'tabs_key_value_all' ) );
63 }
64
65 /**
66 * Prepare bulk actions that will show on dropdown options
67 *
68 * @return array
69 * @since v2.0.0
70 */
71 public function prepare_bulk_actions(): array {
72 $actions = array(
73 $this->bulk_action_default(),
74 $this->bulk_action_publish(),
75 $this->bulk_action_pending(),
76 $this->bulk_action_draft(),
77 );
78 $active_tab = isset( $_GET['data'] ) ? $_GET['data'] : '';
79 if ( 'trash' === $active_tab ) {
80 array_push( $actions, $this->bulk_action_delete() );
81 }
82 if ( 'trash' !== $active_tab ) {
83 array_push( $actions, $this->bulk_action_trash() );
84 }
85 return apply_filters( 'tutor_course_bulk_actions', $actions );
86 }
87
88 /**
89 * Available tabs that will visible on the right side of page navbar
90 *
91 * @param string $course_id selected course id | optional.
92 * @param string $date selected date | optional.
93 * @param string $search search by user name or email | optional.
94 * @return array
95 * @since v2.0.0
96 */
97 public function tabs_key_value( $course_id, $date, $search ): array {
98 $url = get_pagenum_link();
99
100 $all = self::count_course( 'all', $course_id, $date, $search );
101 $mine = self::count_course( 'mine', $course_id, $date, $search );
102 $published = self::count_course( 'publish', $course_id, $date, $search );
103 $draft = self::count_course( 'draft', $course_id, $date, $search );
104 $pending = self::count_course( 'pending', $course_id, $date, $search );
105 $trash = self::count_course( 'trash', $course_id, $date, $search );
106
107 $tabs = array(
108 array(
109 'key' => 'all',
110 'title' => __( 'All', 'tutor' ),
111 'value' => $all,
112 'url' => $url . '&data=all',
113 ),
114 array(
115 'key' => 'mine',
116 'title' => __( 'Mine', 'tutor' ),
117 'value' => $mine,
118 'url' => $url . '&data=mine',
119 ),
120 array(
121 'key' => 'published',
122 'title' => __( 'Published', 'tutor' ),
123 'value' => $published,
124 'url' => $url . '&data=published',
125 ),
126 array(
127 'key' => 'draft',
128 'title' => __( 'Draft', 'tutor' ),
129 'value' => $draft,
130 'url' => $url . '&data=draft',
131 ),
132 array(
133 'key' => 'pending',
134 'title' => __( 'Pending', 'tutor' ),
135 'value' => $pending,
136 'url' => $url . '&data=pending',
137 ),
138 array(
139 'key' => 'trash',
140 'title' => __( 'Trash', 'tutor' ),
141 'value' => $trash,
142 'url' => $url . '&data=trash',
143 ),
144 );
145 return apply_filters( 'tutor_course_tabs', $tabs );
146 }
147
148 public function tabs_key_value_all() {
149
150 $all = self::count_course( 'all' );
151 $mine = self::count_course( 'mine' );
152 $published = self::count_course( 'publish' );
153 $draft = self::count_course( 'draft' );
154 $pending = self::count_course( 'pending' );
155 $trash = self::count_course( 'trash' );
156
157 $tabs = array(
158 array(
159 'key' => 'all',
160 'title' => __( 'All', 'tutor' ),
161 'value' => $all,
162 ),
163 array(
164 'key' => 'mine',
165 'title' => __( 'Mine', 'tutor' ),
166 'value' => $mine,
167 ),
168 array(
169 'key' => 'published',
170 'title' => __( 'Published', 'tutor' ),
171 'value' => $published,
172 ),
173 array(
174 'key' => 'draft',
175 'title' => __( 'Draft', 'tutor' ),
176 'value' => $draft,
177 ),
178 array(
179 'key' => 'pending',
180 'title' => __( 'Pending', 'tutor' ),
181 'value' => $pending,
182 ),
183 array(
184 'key' => 'trash',
185 'title' => __( 'Trash', 'tutor' ),
186 'value' => $trash,
187 ),
188 );
189
190 return $tabs;
191 // return apply_filters( 'tutor_course_tabs', $tabs );
192 }
193
194 /**
195 * Count courses by status & filters
196 * Count all | min | published | pending | draft
197 *
198 * @param string $status | required.
199 * @param string $category_slug course category | optional.
200 * @param string $course_id selected course id | optional.
201 * @param string $date selected date | optional.
202 * @param string $search_term search by user name or email | optional.
203 * @return int
204 * @since v2.0.0
205 */
206 protected static function count_course( string $status, $category_slug = '', $course_id = '', $date = '', $search_term = '' ): int {
207 $user_id = get_current_user_id();
208 $status = sanitize_text_field( $status );
209 $course_id = sanitize_text_field( $course_id );
210 $date = sanitize_text_field( $date );
211 $search_term = sanitize_text_field( $search_term );
212 $category_slug = sanitize_text_field( $category_slug );
213
214 $args = array(
215 'post_type' => tutor()->course_post_type,
216 );
217
218 if ( 'all' === $status || 'mine' === $status ) {
219 $args['post_status'] = array( 'publish', 'pending', 'draft', 'trash', 'private' );
220 } else {
221 $status = $status === 'published' ? 'publish' : $status;
222 $args['post_status'] = array( $status );
223 }
224
225 // Author query.
226 if ( 'mine' === $status || ! current_user_can( 'administrator' ) ) {
227 $args['author'] = $user_id;
228 }
229
230 $date_filter = sanitize_text_field( $date );
231
232 $year = date( 'Y', strtotime( $date_filter ) );
233 $month = date( 'm', strtotime( $date_filter ) );
234 $day = date( 'd', strtotime( $date_filter ) );
235
236 // Add date query.
237 if ( '' !== $date_filter ) {
238 $args['date_query'] = array(
239 array(
240 'year' => $year,
241 'month' => $month,
242 'day' => $day,
243 ),
244 );
245 }
246
247 if ( '' !== $course_id ) {
248 $args['p'] = $course_id;
249 }
250
251 // Search filter.
252 if ( '' !== $search_term ) {
253 $args['s'] = $search_term;
254 }
255
256 // Category filter.
257 if ( '' !== $category_slug ) {
258 $args['tax_query'] = array(
259 array(
260 'taxonomy' => 'course-category',
261 'field' => 'slug',
262 'terms' => $category_slug,
263 ),
264 );
265 }
266
267 $the_query = new \WP_Query( $args );
268
269 return ! is_null( $the_query ) && isset( $the_query->found_posts ) ? $the_query->found_posts : $the_query;
270
271 }
272
273 /**
274 * Handle bulk action for enrollment cancel | delete
275 *
276 * @return string JSON response.
277 * @since v2.0.0
278 */
279 public function course_list_bulk_action() {
280 // check nonce.
281 tutor_utils()->checking_nonce();
282 $action = isset( $_POST['bulk-action'] ) ? sanitize_text_field( $_POST['bulk-action'] ) : '';
283 $bulk_ids = isset( $_POST['bulk-ids'] ) ? sanitize_text_field( $_POST['bulk-ids'] ) : '';
284
285 if ( '' === $action || '' === $bulk_ids ) {
286 wp_send_json_error(array('message' => __('Please select appropriate action', 'tutor')));
287 exit;
288 }
289
290 if ( 'delete' === $action ) {
291 // Do action before delete.
292 do_action( 'before_tutor_course_bulk_action_delete', $bulk_ids );
293
294 $delete_courses = self::delete_course( $bulk_ids );
295
296 do_action( 'after_tutor_course_bulk_action_delete', $bulk_ids );
297 $delete_courses ? wp_send_json_success() : wp_send_json_error(array('message' => __('Could not delete selected courses', 'tutor')));
298 exit;
299 }
300
301 /**
302 * Do action before course update
303 *
304 * @param string $action (publish | pending | draft | trash).
305 * @param array $bulk_ids, course id.
306 */
307 do_action( 'before_tutor_course_bulk_action_update', $action, $bulk_ids );
308
309 $update_status = self::update_course_status( $action, $bulk_ids );
310
311 do_action( 'after_tutor_course_bulk_action_update', $action, $bulk_ids );
312
313 $update_status ? wp_send_json_success() : wp_send_json_error(array('message' => 'Could not update course status', 'tutor'));
314
315 exit;
316 }
317
318 /**
319 * Handle ajax request for updating course status
320 *
321 * @return json response
322 * @since v2.0.0
323 */
324 public static function tutor_change_course_status() {
325 tutor_utils()->checking_nonce();
326 $status = sanitize_text_field( $_POST['status'] );
327 $id = sanitize_text_field( $_POST['id'] );
328
329 self::update_course_status( $status, $id );
330
331 wp_send_json_success();
332 exit;
333 }
334
335 /**
336 * Handle ajax request for deleting course
337 *
338 * @return json response
339 * @since v2.0.0
340 */
341 public static function tutor_course_delete() {
342 tutor_utils()->checking_nonce();
343 $id = sanitize_text_field( $_POST['id'] );
344 $announcements = get_posts(array('post_type'=>'tutor_announcements','post_parent'=>$id));
345 foreach ($announcements as $announcement) {
346 wp_delete_post( $announcement->ID, true );
347 }
348 $delete = self::delete_course( $id );
349
350
351 // $delete = Announcements::delete_announcements( $action, $bulk_ids )( $id );
352 return wp_send_json( $delete );
353 exit;
354 }
355
356 /**
357 * Execute bulk action for enrollments ex: complete | cancel
358 *
359 * @param string $bulk_ids ids that need to update.
360 * @return bool
361 * @since v2.0.0
362 */
363 public static function delete_course( $bulk_ids ): bool {
364 global $wpdb;
365 $post_table = $wpdb->posts;
366 $bulk_ids = sanitize_text_field( $bulk_ids );
367 $delete = $wpdb->query(
368 $wpdb->prepare(
369 " DELETE FROM {$post_table}
370 WHERE ID IN ($bulk_ids)
371 AND 1 = %d
372 ",
373 1
374 )
375 );
376
377 // Delete course meta.
378 $delete ? self::permanently_delete_course_meta( $bulk_ids ) : 0;
379
380 return false === $delete ? false : true;
381 }
382
383 /**
384 * Update course status
385 *
386 * @param string $status for updating course status.
387 * @param string $bulk_ids comma separated ids.
388 * @return bool
389 * @since v2.0.0
390 */
391 public static function update_course_status( string $status, $bulk_ids ): bool {
392 global $wpdb;
393 $post_table = $wpdb->posts;
394 $status = sanitize_text_field( $status );
395 $bulk_ids = sanitize_text_field( $bulk_ids );
396
397 $update = $wpdb->query(
398 $wpdb->prepare(
399 "UPDATE {$post_table}
400 SET post_status = %s
401 WHERE ID IN ($bulk_ids)",
402 $status
403 )
404 );
405
406 return true;
407 }
408 /**
409 * Count quiz for a course
410 *
411 * @param int $course_id | required.
412 */
413 public static function get_all_quiz_by_course( int $course_id ): int {
414 global $wpdb;
415 $quiz_number = $wpdb->get_var(
416 $wpdb->prepare(
417 "SELECT COUNT(ID) FROM {$wpdb->posts}
418 WHERE post_parent IN (SELECT ID FROM {$wpdb->posts} WHERE post_type ='topics' AND post_parent = %d AND post_status = 'publish')
419 AND post_type ='tutor_quiz'
420 AND post_status = 'publish'",
421 $course_id
422 )
423 );
424 return $quiz_number ? $quiz_number : 0;
425 }
426
427 /**
428 * Get course enrollments with student info
429 *
430 * @param int $course_id int | required.
431 * @return array
432 * @since v2.0.0
433 */
434 public static function course_enrollments_with_student_details( int $course_id ) {
435 global $wpdb;
436 $course_id = sanitize_text_field( $course_id );
437 $course_completed = 0;
438 $course_inprogress = 0;
439
440 $enrollments = $wpdb->get_results(
441 $wpdb->prepare(
442 "SELECT enroll.ID AS enroll_id, enroll.post_author AS enroll_author, user.*, course.ID AS course_id
443 FROM {$wpdb->posts} AS enroll
444 LEFT JOIN {$wpdb->users} AS user ON user.ID = enroll.post_author
445 LEFT JOIN {$wpdb->posts} AS course ON course.ID = enroll.post_parent
446 WHERE enroll.post_type = %s
447 AND enroll.post_status = %s
448 AND enroll.post_parent = %d
449 ",
450 'tutor_enrolled',
451 'completed',
452 $course_id
453 )
454 );
455
456 foreach ( $enrollments as $enrollment ) {
457 $course_progress = tutor_utils()->get_course_completed_percent( $course_id, $enrollment->enroll_author );
458 if ( $course_progress == 100 ) {
459 $course_completed++;
460 } else {
461 $course_inprogress++;
462 }
463 }
464
465 return array(
466 'enrollments' => $enrollments,
467 'total_completed' => $course_completed,
468 'total_inprogress' => $course_inprogress,
469 'total_enrollments' => count( $enrollments ),
470 );
471 }
472
473 /**
474 * Delete post meta permanently
475 *
476 * @param string $bulk_ids | comma separated ids.
477 *
478 * @return bool
479 *
480 * @since v2.0.0
481 */
482 public static function permanently_delete_course_meta( $bulk_ids ): bool {
483 global $wpdb;
484 $wpdb->query(
485 $wpdb->prepare(
486 " DELETE FROM {$wpdb->postmeta}
487 WHERE post_id IN ($bulk_ids)
488 AND 1 = %d
489 ",
490 1
491 )
492 );
493 return true;
494 }
495 }
496