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