PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.1.6.9.4
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.1.6.9.4
4.4.8 4.4.7 4.4.6 4.4.5 4.4.4 4.4.3 4.4.2 4.4.1 4.4.0 4.3.9.1 4.3.9 4.3.8 4.3.7 4.1.6.9 4.1.6.9.1 4.1.6.9.2 4.1.6.9.3 4.1.6.9.4 4.1.7 4.1.7.1 4.1.7.2 4.1.7.3 4.1.7.3.1 4.1.7.3.2 4.2.0 All 139 releases
learnpress / inc / custom-post-types / course.php

course.php in LearnPress – WordPress LMS Plugin for Create and Sell Online Courses 4.1.6.9.4, at inc/custom-post-types/course.php

619 lines 18.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Class LP_Course_Post_Type
4 *
5 * @author ThimPress
6 * @package LearnPress/Classes
7 * @version 3.0.0
8 */
9
10 defined( 'ABSPATH' ) || exit();
11
12 if ( ! class_exists( 'LP_Course_Post_Type' ) ) {
13
14 /**
15 * Class LP_Course_Post_Type
16 */
17 final class LP_Course_Post_Type extends LP_Abstract_Post_Type {
18 /**
19 * @var null
20 */
21 protected static $_instance = null;
22
23 /**
24 * @var string
25 */
26 protected $_post_type = LP_COURSE_CPT;
27
28 /**
29 * Constructor
30 *
31 * @param string
32 */
33 public function __construct() {
34 parent::__construct();
35
36 add_action( 'init', array( $this, 'register_taxonomy' ) );
37 add_filter( 'posts_where_paged', array( $this, '_posts_where_paged_course_items' ), 10 );
38 add_filter( 'posts_join_paged', array( $this, '_posts_join_paged_course_items' ), 10 );
39
40 // Comment by tungnx
41 // add_action( 'learn-press/admin/after-enqueue-scripts', array( $this, 'data_course_editor' ) );
42 add_action( 'admin_enqueue_scripts', array( $this, 'add_script_data' ) );
43 }
44
45 public function add_script_data() {
46 global $post, $pagenow;
47
48 if ( empty( $post ) || ( get_post_type() !== $this->_post_type ) || ! in_array( $pagenow, array( 'post.php', 'post-new.php' ) ) ) {
49 return;
50 }
51
52 $course = learn_press_get_course( $post->ID );
53 $hidden_sections = get_post_meta( $post->ID, '_admin_hidden_sections', true );
54
55 $data = apply_filters(
56 'learn-press/admin-localize-course-editor',
57 array(
58 'root' => array(
59 'course_id' => $post->ID,
60 'auto_draft' => get_post_status( $post->ID ) == 'auto-draft',
61 'ajax' => admin_url( 'index.php' ),
62 'disable_curriculum' => false,
63 'action' => 'admin_course_editor',
64 'nonce' => wp_create_nonce( 'learnpress_update_curriculum' ),
65 ),
66 'chooseItems' => array(
67 'types' => learn_press_course_get_support_item_types(),
68 'open' => false,
69 'addedItems' => array(),
70 'items' => array(),
71 ),
72 'i18n' => array(
73 'item' => __( 'item', 'learnpress' ),
74 'new_section_item' => __( 'Create a new', 'learnpress' ),
75 'back' => __( 'Back', 'learnpress' ),
76 'selected_items' => __( 'Selected items', 'learnpress' ),
77 'confirm_trash_item' => __( 'Do you want to remove item "{{ITEM_NAME}}" to trash?', 'learnpress' ),
78 'item_labels' => array(
79 'singular' => __( 'Item', 'learnpress' ),
80 'plural' => __( 'Items', 'learnpress' ),
81 ),
82 'notice_sale_price' => __( 'Course sale price must less than the regular price', 'learnpress' ),
83 'notice_price' => __( 'Course price must greater than the sale price', 'learnpress' ),
84 'notice_sale_start_date' => __( 'Sale start date must before sale end date', 'learnpress' ),
85 'notice_sale_end_date' => __( 'Sale end date must after sale start date', 'learnpress' ),
86 'notice_invalid_date' => __( 'Invalid date', 'learnpress' ),
87 ),
88 'sections' => array(
89 'sections' => $course->get_curriculum_raw(),
90 'hidden_sections' => ! empty( $hidden_sections ) ? $hidden_sections : array(),
91 'urlEdit' => admin_url( 'post.php?action=edit&post=' ),
92 ),
93 )
94 );
95
96 learn_press_admin_assets()->add_script_data( 'learn-press-admin-course-editor', $data );
97 }
98
99 /**
100 * Register course post type.
101 */
102 public function args_register_post_type() : array {
103 $settings = LP_Settings::instance();
104 $labels = array(
105 'name' => _x( 'Courses', 'Post Type General Name', 'learnpress' ),
106 'singular_name' => _x( 'Course', 'Post Type Singular Name', 'learnpress' ),
107 'menu_name' => __( 'Courses', 'learnpress' ),
108 'parent_item_colon' => __( 'Parent Item:', 'learnpress' ),
109 'all_items' => __( 'Courses', 'learnpress' ),
110 'view_item' => __( 'View Course', 'learnpress' ),
111 'add_new_item' => __( 'Add New Course', 'learnpress' ),
112 'add_new' => __( 'Add New', 'learnpress' ),
113 'edit_item' => __( 'Edit Course', 'learnpress' ),
114 'update_item' => __( 'Update Course', 'learnpress' ),
115 'search_items' => __( 'Search Courses', 'learnpress' ),
116 'not_found' => sprintf( __( 'You haven\'t had any courses yet. Click <a href="%s">Add new</a> to start', 'learnpress' ), admin_url( 'post-new.php?post_type=lp_course' ) ),
117 'not_found_in_trash' => __( 'No course found in Trash', 'learnpress' ),
118 );
119 $course_base = $settings->get( 'course_base' );
120 $course_permalink = empty( $course_base ) ? _x( 'courses', 'slug', 'learnpress' ) : $course_base;
121
122 $courses_page_id = learn_press_get_page_id( 'courses' );
123
124 $has_archive = $courses_page_id && get_post( $courses_page_id ) ? urldecode( get_page_uri( $courses_page_id ) ) : 'courses';
125
126 $args = array(
127 'labels' => $labels,
128 'public' => true,
129 'query_var' => true,
130 'publicly_queryable' => true,
131 'show_ui' => true,
132 'has_archive' => $has_archive,
133 'capability_type' => $this->_post_type,
134 'map_meta_cap' => true,
135 'show_in_menu' => 'learn_press',
136 'show_in_admin_bar' => true,
137 'show_in_nav_menus' => true,
138 'show_in_rest' => true,
139 'taxonomies' => array( 'course_category', 'course_tag' ),
140 'supports' => array( 'title', 'editor', 'thumbnail', 'revisions', 'comments', 'excerpt' ),
141 'hierarchical' => false,
142 'rewrite' => $course_permalink ? array(
143 'slug' => untrailingslashit( $course_permalink ),
144 'with_front' => false,
145 ) : false,
146 );
147
148 return $args;
149 }
150
151 /**
152 * Register course taxonomy.
153 */
154 public function register_taxonomy() {
155 $settings = LP_Settings::instance();
156
157 $category_base = $settings->get( 'course_category_base' );
158
159 register_taxonomy(
160 'course_category',
161 array( LP_COURSE_CPT ),
162 array(
163 'label' => __( 'Course Categories', 'learnpress' ),
164 'labels' => array(
165 'name' => __( 'Course Categories', 'learnpress' ),
166 'menu_name' => __( 'Course Category', 'learnpress' ),
167 'singular_name' => __( 'Category', 'learnpress' ),
168 'add_new_item' => __( 'Add New Course Category', 'learnpress' ),
169 'all_items' => __( 'All Categories', 'learnpress' ),
170 ),
171 'query_var' => true,
172 'public' => true,
173 'hierarchical' => true,
174 'show_ui' => true,
175 'show_in_menu' => 'learn_press',
176 'show_admin_column' => true,
177 'show_in_admin_bar' => true,
178 'show_in_nav_menus' => true,
179 'show_in_rest' => true,
180 'rewrite' => array(
181 'slug' => empty( $category_base ) ? _x( 'course-category', 'slug', 'learnpress' ) : $category_base,
182 'hierarchical' => true,
183 'with_front' => false,
184 ),
185 )
186 );
187
188 $tag_base = $settings->get( 'course_tag_base' );
189
190 register_taxonomy(
191 'course_tag',
192 array( LP_COURSE_CPT ),
193 array(
194 'labels' => array(
195 'name' => __( 'Course Tags', 'learnpress' ),
196 'singular_name' => __( 'Tag', 'learnpress' ),
197 'search_items' => __( 'Search Course Tags', 'learnpress' ),
198 'popular_items' => __( 'Popular Course Tags', 'learnpress' ),
199 'all_items' => __( 'All Course Tags', 'learnpress' ),
200 'parent_item' => null,
201 'parent_item_colon' => null,
202 'edit_item' => __( 'Edit Course Tag', 'learnpress' ),
203 'update_item' => __( 'Update Course Tag', 'learnpress' ),
204 'add_new_item' => __( 'Add New Course Tag', 'learnpress' ),
205 'new_item_name' => __( 'New Course Tag Name', 'learnpress' ),
206 'separate_items_with_commas' => __( 'Separate tags with commas', 'learnpress' ),
207 'add_or_remove_items' => __( 'Add or remove tags', 'learnpress' ),
208 'choose_from_most_used' => __( 'Choose from the most used tags', 'learnpress' ),
209 'menu_name' => __( 'Course Tags', 'learnpress' ),
210 ),
211 'public' => true,
212 'hierarchical' => false,
213 'show_ui' => true,
214 'show_in_menu' => 'learn_press',
215 'update_count_callback' => '_update_post_term_count',
216 'query_var' => true,
217 'show_in_rest' => true,
218 'rewrite' => array(
219 'slug' => empty( $tag_base ) ? _x( 'course-tag', 'slug', 'learnpress' ) : $tag_base,
220 'with_front' => false,
221 ),
222 )
223 );
224 }
225
226 /**
227 * Load data for course editor.
228 *
229 * @since 3.0.0
230 * @editor tungnx
231 * @reason not use
232 */
233 /*
234 public function data_course_editor() {
235 if ( LP_COURSE_CPT !== get_post_type() ) {
236 return;
237 }
238
239 }*/
240
241 /**
242 * Delete course sections before delete course.
243 *
244 * @param int $post_id
245 * @since 3.0.0
246 * @editor tungnx
247 * @since modify 4.0.9
248 */
249 public function before_delete( int $post_id ) {
250 // course curd
251 // $curd = new LP_Course_CURD();
252 // $curd->remove_course( $post_id );
253 $course = learn_press_get_course( $post_id );
254 if ( ! $course ) {
255 return;
256 }
257 $course->delete_relate_data_when_delete_course();
258 }
259
260 /**
261 * @param string $fields
262 *
263 * @return string
264 */
265 public function posts_fields( $fields ): string {
266 if ( ! $this->is_page_list_posts_on_backend() ) {
267 return $fields;
268 }
269
270 $fields = ' DISTINCT ' . $fields;
271 if ( $this->get_order_by() == 'price' ) {
272 $fields .= ', pm_price.meta_value as course_price';
273 }
274
275 return $fields;
276 }
277
278 public function _posts_join_paged_course_items( $join ) {
279 global $wpdb;
280
281 $course_id = $this->_filter_items_by_course();
282 if ( $course_id || ( LP_Request::get( 'orderby' ) == 'course-name' ) ) {
283 $join .= " LEFT JOIN {$wpdb->prefix}learnpress_section_items si ON {$wpdb->posts}.ID = si.item_id";
284 $join .= " LEFT JOIN {$wpdb->prefix}learnpress_sections s ON s.section_id = si.section_id";
285 $join .= " LEFT JOIN {$wpdb->posts} c ON c.ID = s.section_course_id";
286 }
287
288 return $join;
289 }
290
291 public function _posts_where_paged_course_items( $where ) {
292 global $wpdb;
293
294 $course_id = $this->_filter_items_by_course();
295 if ( $course_id ) {
296 $where .= $wpdb->prepare( ' AND (c.ID = %d)', $course_id );
297 $where .= $wpdb->prepare( " AND {$wpdb->posts}.post_status = %s", 'publish' );
298 }
299
300 return $where;
301 }
302
303 /**
304 * @param $join
305 *
306 * @return string
307 */
308 public function posts_join_paged( $join ) {
309 global $wpdb;
310
311 if ( ! $this->is_page_list_posts_on_backend() ) {
312 return $join;
313 }
314
315 $join .= " LEFT JOIN {$wpdb->postmeta} pm_price ON pm_price.post_id = {$wpdb->posts}.ID AND pm_price.meta_key = '_lp_price'";
316
317 return $join;
318 }
319
320 /**
321 * @param $where
322 *
323 * @return mixed|string
324 */
325 public function posts_where_paged( $where ) {
326 global $wpdb;
327
328 if ( ! $this->is_page_list_posts_on_backend() ) {
329 return $where;
330 }
331
332 $filter_price = LP_Helper::sanitize_params_submitted( $_REQUEST['filter_price'] ?? 0 );
333
334 if ( array_key_exists( 'filter_price', $_REQUEST ) ) {
335 if ( $filter_price == 0 ) {
336 $where .= ' AND ( pm_price.meta_value IS NULL || pm_price.meta_value = 0 )';
337 } else {
338 $where .= $wpdb->prepare( ' AND ( pm_price.meta_value = %s )', $filter_price );
339 }
340 }
341
342 $not_in = $wpdb->prepare(
343 "
344 SELECT ID
345 FROM {$wpdb->posts} p
346 INNER JOIN {$wpdb->postmeta} pm ON pm.post_id = p.ID AND pm.meta_key = %s
347 WHERE pm.meta_value = %s
348 ",
349 '_lp_preview_course',
350 'yes'
351 );
352
353 $where .= " AND {$wpdb->posts}.ID NOT IN( {$not_in} )";
354
355 return $where;
356 }
357
358 /**
359 * @param $orderby
360 *
361 * @return string
362 */
363 public function posts_orderby( $orderby ) {
364 if ( ! $this->is_page_list_posts_on_backend() ) {
365 return $orderby;
366 }
367
368 $order = $this->get_order_sort();
369 switch ( $this->get_order_by() ) {
370 case 'price':
371 $orderby = "pm_price.meta_value {$order}";
372 }
373
374 return $orderby;
375 }
376
377 /**
378 * @param $columns
379 *
380 * @return mixed
381 */
382 public function sortable_columns( $columns ) {
383 $columns['instructor'] = 'author';
384 $columns['price'] = 'price';
385
386 return $columns;
387 }
388
389 /**
390 * Use when enable Gutenberg.
391 *
392 * @return void
393 */
394 public function admin_editor() {
395 $course = LP_Course::get_course();
396
397 learn_press_admin_view( 'course/editor' );
398 }
399
400 /**
401 * Delete all sections in a course and reset auto increment
402 */
403 private function _reset_sections() {
404 global $wpdb, $post;
405
406 $wpdb->query(
407 $wpdb->prepare(
408 "
409 DELETE FROM si
410 USING {$wpdb->learnpress_section_items} si
411 INNER JOIN {$wpdb->learnpress_sections} s ON s.section_id = si.section_id
412 INNER JOIN {$wpdb->posts} p ON p.ID = s.section_course_id
413 WHERE p.ID = %d
414 ",
415 $post->ID
416 )
417 );
418 $wpdb->query(
419 "
420 ALTER TABLE {$wpdb->learnpress_section_items} AUTO_INCREMENT = 1
421 "
422 );
423
424 $wpdb->query(
425 $wpdb->prepare(
426 "
427 DELETE FROM {$wpdb->learnpress_sections}
428 WHERE section_course_id = %d
429 ",
430 $post->ID
431 )
432 );
433 $wpdb->query(
434 "
435 ALTER TABLE {$wpdb->learnpress_sections} AUTO_INCREMENT = 1
436 "
437 );
438 }
439
440 private function _send_mail() {
441 if ( ! LP()->user->is_instructor() ) {
442 return;
443 }
444 $mail = LP()->mail;
445
446 }
447
448 /**
449 * Add columns to admin manage course page
450 *
451 * @param array $columns
452 *
453 * @return array
454 */
455 public function columns_head( $columns ) {
456 $user = wp_get_current_user();
457 $keys = array_keys( $columns );
458 $values = array_values( $columns );
459 $pos = array_search( 'title', $keys );
460
461 if ( ! empty( $columns['author'] ) ) {
462 unset( $columns['author'] );
463 }
464
465 if ( $pos !== false ) {
466 array_splice( $keys, $pos + 1, 0, array( 'instructor', 'sections', 'students', 'price' ) );
467 array_splice(
468 $values,
469 $pos + 1,
470 0,
471 array(
472 esc_html__( 'Author', 'learnpress' ),
473 esc_html__( 'Content', 'learnpress' ),
474 esc_html__( 'Students', 'learnpress' ),
475 esc_html__( 'Price', 'learnpress' ),
476 )
477 );
478
479 if ( $pos === 0 ) {
480 array_unshift( $keys, 'thumbnail' );
481 array_unshift( $values, esc_html__( 'Thumbnail', 'learnpress' ) );
482 } else {
483 array_splice( $keys, $pos, 0, array( 'thumbnail' ) );
484 array_splice( $values, $pos, 0, array( esc_html__( 'Thumbnail', 'learnpress' ) ) );
485 }
486
487 $columns = array_combine( $keys, $values );
488 } else {
489 $columns['instructor'] = esc_html__( 'Author', 'learnpress' );
490 $columns['sections'] = esc_html__( 'Content', 'learnpress' );
491 $columns['students'] = esc_html__( 'Students', 'learnpress' );
492 $columns['price'] = esc_html__( 'Price', 'learnpress' );
493 }
494
495 $columns['taxonomy-course_category'] = esc_html__( 'Categories', 'learnpress' );
496
497 if ( in_array( 'lp_teacher', $user->roles ) ) {
498 unset( $columns['instructor'] );
499 }
500
501 return apply_filters( 'lp/admin/courses/columns', $columns );
502 }
503
504 /**
505 * Print content for custom column
506 *
507 * @param string
508 * @param int
509 */
510 public function columns_content( $column, $post_id = 0 ) {
511 global $post;
512
513 $course = learn_press_get_course( $post->ID );
514
515 switch ( $column ) {
516 case 'thumbnail':
517 echo wp_kses_post( $course->get_image( 'thumbnail' ) );
518 break;
519 case 'instructor':
520 $this->column_instructor( $post->ID );
521 break;
522 case 'sections':
523 $curd = new LP_Course_CURD();
524 $number_sections = $curd->count_sections( $post_id );
525 if ( $number_sections ) {
526 $output = sprintf( _n( '<strong>%d</strong> section', '<strong>%d</strong> sections', $number_sections, 'learnpress' ), $number_sections );
527 $html_items = array();
528 $post_types = get_post_types( null, 'objects' );
529
530 foreach ( learn_press_get_course_item_types() as $item_type ) {
531 $count_item = $course->count_items( $item_type );
532
533 if ( ! $count_item ) {
534 continue;
535 }
536
537 $post_type_object = $post_types[ $item_type ];
538 $singular_name = $post_type_object->labels->singular_name;
539 $plural_name = $post_type_object->label;
540 $html_items[] = sprintf( _n( '<strong>%d</strong> ' . $singular_name, '<strong>%d</strong> ' . $plural_name, $count_item, 'learnpress' ), $count_item );
541 }
542
543 $html_items = apply_filters( 'learn-press/course-count-items', $html_items );
544
545 if ( $html_items ) {
546 $output .= ' (' . implode( ', ', $html_items ) . ')';
547 }
548
549 echo wp_kses_post( $output );
550 } else {
551 esc_html_e( 'No content', 'learnpress' );
552 }
553
554 break;
555
556 case 'price':
557 echo wp_kses_post( $course->get_course_price_html() );
558 break;
559 case 'students':
560 $count = $course->get_total_user_enrolled_or_purchased();
561 echo '<span class="lp-label-counter' . ( ! $count ? ' disabled' : '' ) . '">' . ( $count ? $count : 0 ) . '</span>';
562 break;
563 }
564 }
565
566 public function meta_boxes() {
567 return array(
568 'course-editor' => array(
569 'title' => esc_html__( 'Curriculum', 'learnpress' ),
570 'callback' => array( $this, 'admin_editor' ),
571 'context' => 'normal',
572 'priority' => 'high',
573 ),
574 );
575 }
576
577 /**
578 * Save course post
579 * Should write run background if handle big and need more time
580 *
581 * @param int $post_id
582 * @param WP_Post $post
583 * @since 4.0.9
584 * @version 1.0.0
585 * @editor tungnx
586 * @see LP_Background_Single_Course::handle()
587 */
588 public function save( int $post_id = 0, WP_Post $post = null ) {
589 // Save in background.
590 $bg = LP_Background_Single_Course::instance();
591
592 $bg->data(
593 array(
594 'handle_name' => 'save_post',
595 'course_id' => $post_id,
596 'data' => $_POST ?? array(),
597 )
598 )->dispatch();
599 }
600
601 /**
602 * Instance LP_Course_Post_Type.
603 *
604 * @return LP_Course_Post_Type|null
605 */
606 public static function instance() {
607 if ( ! self::$_instance ) {
608 self::$_instance = new self();
609 }
610
611 return self::$_instance;
612 }
613 }
614
615 $course_post_type = LP_Course_Post_Type::instance();
616
617 // $course_post_type->add_meta_box( 'course-editor', esc_html__( 'Curriculum', 'learnpress' ), 'admin_editor', 'normal', 'high' );
618 }
619