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