PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.2.1
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.2.1
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 4.2.1 All 138 releases
learnpress / inc / custom-post-types / course.php

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

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