PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.4.9
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.4.9
4.4.9 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 All 140 releases
← All changes | inc/course/abstract-course.php +193 -84 4.1.7.3.1 → 4.4.9 View file →
@@ -6,8 +6,12 @@
6 6 * @package LearnPress/Classes
7 7 * @version 4.0.0
8 8 */
9 9
10 +use LearnPress\Models\CourseModel;
11 +use LearnPress\TemplateHooks\Course\SingleCourseTemplate;
12 +use LearnPress\TemplateHooks\Instructor\SingleInstructorTemplate;
13 +
10 14 defined( 'ABSPATH' ) || exit();
11 15
12 16 if ( ! function_exists( 'LP_Abstract_Course' ) ) {
13 17
@@ -161,8 +165,14 @@
161 165 if ( metadata_exists( 'post', $this->get_id(), '_lp_regular_price' ) ) {
162 166 $regular_price = get_post_meta( $id, '_lp_regular_price', true );
163 167 }
164 168
169 + $block_course_finished = get_post_meta(
170 + $id,
171 + '_lp_block_finished',
172 + true
173 + );
174 +
165 175 $this->_set_data(
166 176 array(
167 177 'status' => $post_object->post_status,
168 178 'no_required_enroll' => get_post_meta( $id, '_lp_no_required_enroll', true ),
@@ -185,15 +195,12 @@
185 195 $id,
186 196 '_lp_block_expire_duration',
187 197 true
188 198 ),
189 - 'block_course_finished' => get_post_meta(
190 - $id,
191 - '_lp_block_finished',
192 - true
193 - ),
199 + 'block_course_finished' => $block_course_finished ? $block_course_finished : 'yes',
194 200 'allow_repurchase' => get_post_meta( $id, '_lp_allow_course_repurchase', true ),
195 201 'allow_repurchase_course_option' => get_post_meta( $id, '_lp_course_repurchase_option', true ),
202 + 'excerpt' => $post_object->post_excerpt,
196 203 )
197 204 );
198 205 }
199 206
@@ -297,13 +304,9 @@
297 304 $url = get_the_post_thumbnail_url( $parent_id, $size );
298 305 }
299 306
300 307 if ( ! $url ) {
301 - if ( 'course_thumbnail' == $size ) {
302 - $url = LearnPress::instance()->image( 'no-image.png' );
303 - } else {
304 - $url = LearnPress::instance()->image( 'placeholder-500x300' );
305 - }
308 + $url = LearnPress::instance()->image( 'no-image.png' );
306 309 }
307 310
308 311 return apply_filters( 'learn-press/course-thumbnail-url', $url, $this->get_id(), $size );
309 312 }
@@ -340,21 +343,25 @@
340 343 return ! $this->is_no_required_enroll();
341 344 }
342 345
343 346 /**
347 + * @deprecated 4.2.0
348 + */
349 + public function is_require_enrollment() {
350 + _deprecated_function( __METHOD__, '4.2.0' );
351 + return ! $this->is_no_required_enroll();
352 + }
353 +
354 + /**
344 355 * Check if this course is required enroll or not.
345 356 *
346 357 * @author hungkv
347 358 * @since 4.0.5
348 359 * @return bool
349 - * @version 1.0.0
360 + * @version 1.0.1
350 361 */
351 362 public function is_no_required_enroll(): bool {
352 - $return = false;
353 - if ( $this->get_data( 'no_required_enroll', 'no' ) == 'yes' && ! is_user_logged_in() ) {
354 - $return = true;
355 - }
356 - return apply_filters( 'learn-press/course/require-enrollment', $return, $this->get_id() );
363 + return $this->get_data( 'no_required_enroll', 'no' ) === 'yes' && ! is_user_logged_in();
357 364 }
358 365
359 366 /**
360 367 * @deprecated 4.1.6.9
@@ -443,9 +450,9 @@
443 450 * Get total students fake.
444 451 *
445 452 * @return int
446 453 */
447 - public function get_fake_students() : int {
454 + public function get_fake_students(): int {
448 455 return absint( $this->get_data( 'fake_students', 0 ) );
449 456 }
450 457
451 458 /**
@@ -498,33 +505,43 @@
498 505 return apply_filters( 'learn-press/course/instructor-name', $name, $this->get_id() );
499 506 }
500 507
501 508 /**
509 + * Get instructor html of course.
510 + *
502 511 * @param int|bool $with_avatar
503 512 * @param string $link_class
504 513 *
505 514 * @return string
506 515 */
507 - public function get_instructor_html( $with_avatar = false, $link_class = '' ) {
508 - $instructor = $this->get_instructor_name();
516 + public function get_instructor_html( $with_avatar = false, $link_class = '' ): string {
517 + $html = '';
509 518
510 - $html = sprintf(
511 - '<a href="%s"%s>%s<span>%s</span></a>',
512 - learn_press_user_profile_link( get_post_field( 'post_author', $this->get_id() ) ),
513 - $link_class ? sprintf( 'class="%s"', $link_class ) : '',
514 - $with_avatar ? get_avatar(
515 - $this->get_instructor( 'id' ),
516 - $with_avatar === true ? 48 : $with_avatar
517 - ) : '',
518 - $instructor
519 - );
519 + try {
520 + $instructor = $this->get_author();
521 + if ( ! $instructor ) {
522 + return '';
523 + }
520 524
521 - return apply_filters(
522 - 'learn_press_course_instructor_html',
523 - $html,
524 - get_post_field( 'post_author', $this->get_id() ),
525 - $this->get_id()
526 - );
525 + $singleInstructorTemplate = SingleInstructorTemplate::instance();
526 +
527 + $html = apply_filters(
528 + 'learn-press/course/instructor-html',
529 + sprintf(
530 + '<a href="%s"%s>%s %s</a>',
531 + $instructor->get_url_instructor(),
532 + $link_class ? sprintf( 'class="%s"', $link_class ) : '',
533 + $with_avatar ? $instructor->get_profile_picture() : '',
534 + $singleInstructorTemplate->html_display_name( $instructor )
535 + ),
536 + $instructor,
537 + $singleInstructorTemplate
538 + );
539 + } catch ( Throwable $e ) {
540 + error_log( $e->getMessage() );
541 + }
542 +
543 + return $html;
527 544 }
528 545
529 546 /**
530 547 * Check if a course is Free
@@ -544,9 +561,9 @@
544 561 public function get_sale_price() {
545 562 $sale_price_value = $this->get_data( 'sale_price', '' );
546 563
547 564 if ( '' !== $sale_price_value ) {
548 - return floatval( $sale_price_value );
565 + return apply_filters( 'learn-press/course/sale-price', floatval( $sale_price_value ), $this->get_id() );
549 566 }
550 567
551 568 return $sale_price_value;
552 569 }
@@ -568,11 +585,14 @@
568 585 }
569 586
570 587 // Check in days sale
571 588 if ( $has_sale_price && '' !== $start_date && '' !== $end_date ) {
572 - $now = strtotime( get_date_from_gmt( gmdate( 'Y-m-d H:i:s', time() ), 'Y-m-d H:i:s' ) );
573 - $end = strtotime( $end_date );
574 - $start = strtotime( $start_date );
589 + $nowObj = new LP_Datetime();
590 + // Compare via timezone WP
591 + $nowStr = $nowObj->toSql( true );
592 + $now = strtotime( $nowStr );
593 + $end = strtotime( $end_date );
594 + $start = strtotime( $start_date );
575 595
576 596 $has_sale_price = $now >= $start && $now <= $end;
577 597 }
578 598
@@ -600,9 +620,9 @@
600 620 */
601 621 public function get_regular_price_html() {
602 622 $price = learn_press_format_price( $this->get_regular_price(), true );
603 623
604 - return apply_filters( 'learn-press/course/regular-price', $price, $this->get_id() );
624 + return apply_filters( 'learn-press/course/regular-price-html', $price, $this->get_id() );
605 625 }
606 626
607 627 /**
608 628 * Get the price of course.
@@ -615,18 +635,20 @@
615 635
616 636 if ( false === $price ) {
617 637 if ( $this->has_sale_price() ) {
618 638 $price = $this->get_sale_price();
619 - // Add key _lp_course_is_sale for query
620 - update_post_meta( $this->get_id(), '_lp_course_is_sale', 1 );
639 + // Add key _lp_course_is_sale for query - Todo: Check performance, need write function get all courses, and set on Admin, on background
640 + //update_post_meta( $this->get_id(), '_lp_course_is_sale', 1 );
621 641 } else {
622 642 // Delete key _lp_course_is_sale
623 - delete_post_meta( $this->get_id(), '_lp_course_is_sale' );
643 + //delete_post_meta( $this->get_id(), '_lp_course_is_sale' );
624 644 $price = $this->get_regular_price();
625 645 }
626 646
627 - // For case set sale by days range
628 - update_post_meta( $this->get_id(), '_lp_price', $price );
647 + // Save price only on page Single Course
648 + /*if ( LP_PAGE_SINGLE_COURSE === LP_Page_Controller::page_current() ) {
649 + update_post_meta( $this->get_id(), '_lp_price', $price );
650 + }*/
629 651
630 652 LP_Course_Cache::cache_load_first( 'set', $key_cache, $price );
631 653 }
632 654
@@ -637,12 +659,12 @@
637 659 * Get html course price
638 660 *
639 661 * @author tungnx
640 662 * @since 4.1.5
641 - * @version 1.0.0
642 - * @return mixed|void
663 + * @version 1.0.2
664 + * @return string
643 665 */
644 - public function get_course_price_html() {
666 + public function get_course_price_html(): string {
645 667 $price_html = '';
646 668
647 669 if ( $this->is_free() ) {
648 670 if ( is_float( $this->get_sale_price() ) ) {
@@ -650,18 +672,28 @@
650 672 }
651 673
652 674 $price_html .= sprintf( '<span class="free">%s</span>', esc_html__( 'Free', 'learnpress' ) );
653 675 $price_html = apply_filters( 'learn_press_course_price_html_free', $price_html, $this );
676 + } elseif ( $this->get_data( 'no_required_enroll', 'no' ) === 'yes' ) {
677 + $price_html .= '';
654 678 } else {
655 679 if ( $this->has_sale_price() ) {
656 680 $price_html .= sprintf( '<span class="origin-price">%s</span>', $this->get_regular_price_html() );
657 681 }
658 682
659 - $price_html .= sprintf( '<span class="price">%s</span>', learn_press_format_price( $this->get_price(), true ) );
660 - $price_html = apply_filters( 'learn_press_course_price_html', $price_html, $this->has_sale_price(), $this->get_id() );
683 + $price_html .= sprintf( '<span class="price">%s</span>', learn_press_format_price( $this->get_price(), true ) );
684 + $course = CourseModel::find( $this->get_id(), true );
685 + $singleCourseTemplate = SingleCourseTemplate::instance();
686 + $price_html = sprintf(
687 + '%1$s %2$s %3$s',
688 + $singleCourseTemplate->html_price_prefix( $course ),
689 + $price_html,
690 + $singleCourseTemplate->html_price_suffix( $course )
691 + );
692 + $price_html = apply_filters( 'learn_press_course_price_html', $price_html, $this->has_sale_price(), $this->get_id() );
661 693 }
662 694
663 - return $price_html;
695 + return sprintf( '<span class="course-item-price">%s</span>', $price_html );
664 696 }
665 697
666 698 /**
667 699 * Get the price of course with html
@@ -795,11 +827,14 @@
795 827 return apply_filters( 'learn-press/is-purchasable', $is_purchasable, $this->get_id() );
796 828 }
797 829
798 830 /**
799 - * Check if students have enrolled or purchased course is reached.
831 + * Check if students have purchased course is reached.
832 + * For case check course can purchase.
800 833 *
801 834 * @return mixed
835 + * @since 3.0.0
836 + * @version 1.0.1
802 837 */
803 838 public function is_in_stock() {
804 839 $in_stock = true;
805 840 $max_allowed = $this->get_max_students();
@@ -811,8 +846,27 @@
811 846 return apply_filters( 'learn-press/is-in-stock', $in_stock, $this->get_id() );
812 847 }
813 848
814 849 /**
850 + * Check max student can enroll.
851 + * For case check course can enroll.
852 + *
853 + * @return mixed
854 + * @since 4.2.5.7
855 + * @version 1.0.0
856 + */
857 + public function is_in_stock_enroll() {
858 + $in_stock = true;
859 + $max_allowed = $this->get_max_students();
860 +
861 + if ( $max_allowed ) {
862 + $in_stock = $max_allowed > $this->get_total_user_enrolled_or_purchased();
863 + }
864 +
865 + return apply_filters( 'learn-press/is-in-stock', $in_stock, $this->get_id() );
866 + }
867 +
868 + /**
815 869 * Get max students can enroll to course.
816 870 *
817 871 * @return int
818 872 *
@@ -832,24 +886,16 @@
832 886 * and add the fake value if both are set.
833 887 *
834 888 * @return int
835 889 * @editor tungnx
890 + * @version 1.0.1
891 + * @since 3.0.0
836 892 * @Todo: view and rewrite this function
837 893 */
838 894 public function count_students(): int {
839 - $key_cache = "{$this->get_id()}/total-students";
840 - $total = LP_Course_Cache::instance()->get_cache( $key_cache );
895 + $total = $this->get_total_user_enrolled_or_purchased();
896 + $total += $this->get_fake_students();
841 897
842 - if ( $total ) {
843 - return $total;
844 - }
845 -
846 - $lp_course_db = LP_Course_DB::getInstance();
847 - $total = $lp_course_db->get_total_user_enrolled( $this->get_id() );
848 - $total += $this->get_fake_students();
849 -
850 - LP_Course_Cache::instance()->set_cache( $key_cache, $total, 6 * HOUR_IN_SECONDS );
851 -
852 898 return $total;
853 899 }
854 900
855 901 /**
@@ -854,32 +900,83 @@
854 900
855 901 /**
856 902 * Get total user enrolled
857 903 *
904 + * @since 4.1.4
905 + * @version 1.0.1
858 906 * @return int
859 907 */
860 908 public function get_total_user_enrolled(): int {
861 - $lp_course_db = LP_Course_DB::getInstance();
862 - return $lp_course_db->get_total_user_enrolled( $this->get_id() );
909 + $total = 0;
910 + $lp_course_cache = new LP_Course_Cache( true );
911 +
912 + try {
913 + $total = $lp_course_cache->get_total_students_enrolled( $this->get_id() );
914 + if ( false !== $total ) {
915 + return $total;
916 + }
917 +
918 + $lp_course_db = LP_Course_DB::getInstance();
919 + $total = $lp_course_db->get_total_user_enrolled( $this->get_id() );
920 + $lp_course_cache->set_total_students_enrolled( $this->get_id(), $total );
921 + } catch ( Throwable $e ) {
922 + error_log( $e->getMessage() );
923 + }
924 +
925 + return $total;
863 926 }
864 927
865 928 /**
866 - * Get total user enrolled or finished
929 + * Get total user enrolled include fake
930 + * @since 4.2.2
931 + * @return int
932 + */
933 + /*public function get_total_user_enrolled_include_fake() {
934 + $total_user_enrolled = 0;
935 + $key_cache = "{$this->get_id()}/total-students-include-fake";
936 +
937 + try {
938 + $total_user_enrolled = LP_Course_Cache::cache_load_first( 'get', $key_cache );
939 +
940 + if ( false === $total_user_enrolled ) {
941 + $lp_course_db = LP_Course_DB::getInstance();
942 + $total_user_enrolled = $lp_course_db->get_total_user_enrolled( $this->get_id() );
943 + $total_user_enrolled += $this->get_fake_students();
944 +
945 + LP_Course_Cache::cache_load_first( 'set', $key_cache, $total_user_enrolled );
946 + }
947 + } catch ( Throwable $e ) {
948 + error_log( $e->getMessage() );
949 + }
950 +
951 + return $total_user_enrolled;
952 + }*/
953 +
954 + /**
955 + * Get total user enrolled, purchased or finished
867 956 *
957 + * @since 4.1.4
958 + * @version 1.0.1
868 959 * @return int
869 960 */
870 961 public function get_total_user_enrolled_or_purchased(): int {
871 - $key_cache = "{$this->get_id()}/total-students-attended";
872 - $total_user_enrolled = LP_Course_Cache::cache_load_first( 'get', $key_cache );
962 + $total = 0;
963 + $lp_course_cache = new LP_Course_Cache( true );
873 964
874 - if ( false === $total_user_enrolled ) {
875 - $lp_course_db = LP_Course_DB::getInstance();
876 - $total_user_enrolled = $lp_course_db->get_total_user_enrolled_or_purchased( $this->get_id() );
965 + try {
966 + $total = $lp_course_cache->get_total_students_enrolled_or_purchased( $this->get_id() );
967 + if ( false !== $total ) {
968 + return $total;
969 + }
877 970
878 - LP_Course_Cache::cache_load_first( 'set', $key_cache, $total_user_enrolled );
971 + $lp_course_db = LP_Course_DB::getInstance();
972 + $total = $lp_course_db->get_total_user_enrolled_or_purchased( $this->get_id() );
973 + $lp_course_cache->set_total_students_enrolled_or_purchased( $this->get_id(), $total );
974 + } catch ( Throwable $e ) {
975 + error_log( $e->getMessage() );
879 976 }
880 977
881 - return $total_user_enrolled;
978 + return $total;
882 979 }
883 980
884 981 /**
885 982 * @param string|array $statuses
@@ -959,9 +1056,9 @@
959 1056 * @param string $context
960 1057 *
961 1058 * @return array|mixed|string
962 1059 */
963 - public function get_passing_condition( $format = false, $context = '' ) {
1060 + public function get_passing_condition( $format = false ) {
964 1061 $value = absint( $this->get_data( 'passing_condition' ) );
965 1062
966 1063 if ( $format ) {
967 1064 $value = "{$value}%";
@@ -966,9 +1063,9 @@
966 1063 if ( $format ) {
967 1064 $value = "{$value}%";
968 1065 }
969 1066
970 - return 'edit' === $context ? $value : apply_filters(
1067 + return apply_filters(
971 1068 'learn-press/course-passing-condition',
972 1069 $value,
973 1070 $format,
974 1071 $this->get_id()
@@ -994,18 +1091,17 @@
994 1091
995 1092 $slug_prefixes = apply_filters(
996 1093 'learn-press/course/custom-item-prefixes',
997 1094 array(
998 - LP_QUIZ_CPT => sanitize_title_with_dashes( LP_Settings::instance()->get( 'quiz_slug', 'quizzes' ) ),
999 - LP_LESSON_CPT => sanitize_title_with_dashes( LP_Settings::instance()->get( 'lesson_slug', 'lessons' ) ),
1095 + LP_QUIZ_CPT => sanitize_title_with_dashes( LP_Settings::get_option( 'quiz_slug', 'quizzes' ) ),
1096 + LP_LESSON_CPT => sanitize_title_with_dashes( LP_Settings::get_option( 'lesson_slug', 'lessons' ) ),
1000 1097 ),
1001 1098 $this->get_id()
1002 1099 );
1003 1100
1004 1101 $slug_prefix = trailingslashit( $slug_prefixes[ $item_type ] ?? '' );
1102 + $item_link = trailingslashit( $course_permalink . $slug_prefix . $item_slug );
1005 1103
1006 - $item_link = $course_permalink . $slug_prefix . $item_slug;
1007 -
1008 1104 return apply_filters( 'learn-press/course/item-link', $item_link, $item_id, $this );
1009 1105 }
1010 1106
1011 1107 /**
@@ -1066,9 +1162,9 @@
1066 1162 */
1067 1163 public function get_next_item( $args = null ) {
1068 1164 $item_nav = $this->get_item_nav();
1069 1165
1070 - return apply_filters( 'learn-press/course/next-item', $item_nav[2], $this->get_id(), $args );
1166 + return apply_filters( 'learn-press/course/next-item', $item_nav ? $item_nav[2] : 0, $this->get_id(), $args );
1071 1167 }
1072 1168
1073 1169 /**
1074 1170 * Get item standing before the item is viewing.
@@ -1078,8 +1174,11 @@
1078 1174 * @return int
1079 1175 */
1080 1176 public function get_prev_item( $args = null ) {
1081 1177 $item_nav = $this->get_item_nav();
1178 + if ( ! is_array( $item_nav ) || empty( $item_nav ) ) {
1179 + return 0;
1180 + }
1082 1181
1083 1182 return apply_filters( 'learn-press/course/prev-item', $item_nav[0], $this->get_id(), $args );
1084 1183 }
1085 1184
@@ -1113,9 +1212,9 @@
1113 1212 $user = learn_press_get_current_user();
1114 1213 $pos_tmp = $pos;
1115 1214
1116 1215 while ( $pos_tmp < $max ) {
1117 - $pos_tmp ++;
1216 + ++$pos_tmp;
1118 1217
1119 1218 if ( ! $viewable ) {
1120 1219 $next_id = $item_ids[ $pos_tmp ];
1121 1220
@@ -1125,9 +1224,9 @@
1125 1224
1126 1225 $pos_tmp = $pos;
1127 1226
1128 1227 while ( $pos_tmp > 0 ) {
1129 - $pos_tmp --;
1228 + --$pos_tmp;
1130 1229
1131 1230 if ( ! $viewable ) {
1132 1231 $prev_id = $item_ids[ $pos_tmp ];
1133 1232
@@ -1176,9 +1275,8 @@
1176 1275 return false;
1177 1276 }
1178 1277
1179 1278 public function get_prev_item_html( $args = null ) {
1180 -
1181 1279 }
1182 1280
1183 1281 public function get_preview_items() {
1184 1282 return LP_Object_Cache::get( 'course-' . $this->get_id(), 'learn-press/course-preview-items' );
@@ -1360,6 +1458,17 @@
1360 1458 $this->get_id(),
1361 1459 $this
1362 1460 );
1363 1461 }
1462 +
1463 + /**
1464 + * [get_downloadable_material get all material files of this course and lesson of this course]
1465 + * @return [array] [array of material files or empty array]
1466 + * @deprecated 4.2.6.4
1467 + */
1468 + /*public function get_downloadable_material(): array {
1469 + $material = LP_Material_Files_DB::getInstance();
1470 + $materials = $material->get_material_by_item_id( $this->get_id(), 1 );
1471 + return apply_filters( 'learn-press/course-materials', $materials, $this->get_id() );
1472 + }*/
1364 1473 }
1365 1474 }