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/Ajax/CourseBuilder/CourseBuilderAjax.php +297 -325 4.3.7 → 4.4.9 View file →
@@ -13,8 +13,10 @@
13 13 use Exception;
14 14 use LearnPress\Ajax\AbstractAjax;
15 15 use LearnPress\CourseBuilder\CourseBuilder;
16 16 use LearnPress\CourseBuilder\CourseBuilderAccessPolicy;
17 +use LearnPress\Helpers\Response;
18 +use LearnPress\Helpers\Template;
17 19 use LearnPress\Models\CourseModel;
18 20 use LearnPress\Models\CoursePostModel;
19 21 use LearnPress\Models\CourseSectionItemModel;
20 22 use LearnPress\Models\LessonPostModel;
@@ -53,22 +55,25 @@
53 55 if ( empty( $params ) ) {
54 56 throw new Exception( 'Error: params invalid!' );
55 57 }
56 58
57 - $params = LP_Helper::json_decode( $params, true );
58 - $course_id = ! empty( $params['course_id'] ) ? (int) $params['course_id'] : 0;
59 - $course_model = CourseModel::find( $course_id, true );
60 - if ( empty( $course_model ) ) {
59 + $params = LP_Helper::json_decode( $params, true );
60 + $course_id = ! empty( $params['course_id'] ) ? (int) $params['course_id'] : 0;
61 + $courseModel = CourseModel::find( $course_id, true );
62 + if ( empty( $courseModel ) ) {
61 63 $params['insert'] = true;
62 64 $params['course_model'] = '';
63 65 } else {
64 66 $params['insert'] = false;
65 - $params['course_model'] = $course_model;
67 + $params['course_model'] = $courseModel;
66 68 }
67 69
68 70 return $params;
69 71 }
70 72
73 + /**
74 + * @throws Exception
75 + */
71 76 public static function check_valid_lesson() {
72 77 $params = wp_unslash( $_REQUEST['data'] ?? '' );
73 78 if ( empty( $params ) ) {
74 79 throw new Exception( 'Error: params invalid!' );
@@ -74,9 +79,9 @@
74 79 throw new Exception( 'Error: params invalid!' );
75 80 }
76 81
77 82 $params = LP_Helper::json_decode( $params, true );
78 - $lesson_id = ! empty( $params['lesson_id'] ) ? (int) $params['lesson_id'] : 0;
83 + $lesson_id = absint( $params['lesson_id'] ?? 0 );
79 84 $lesson_model = LessonPostModel::find( $lesson_id, true );
80 85 if ( empty( $lesson_model ) ) {
81 86 $params['insert'] = true;
82 87 $params['lesson_model'] = '';
@@ -213,13 +218,13 @@
213 218 * Mirrors wp-admin behavior for instructors without publish capability.
214 219 *
215 220 * @param string $requested_status
216 221 * @param bool $insert
217 - * @param CourseModel|null $course_model
222 + * @param CourseModel|null $courseModel
218 223 *
219 224 * @return string
220 225 */
221 - protected function normalize_course_status_for_save( string $requested_status, bool $insert, ?CourseModel $course_model ): string {
226 + protected function normalize_course_status_for_save( string $requested_status, bool $insert, ?CourseModel $courseModel ): string {
222 227 $allowed_statuses = [ 'publish', 'future', 'draft', 'pending', 'private' ];
223 228 if ( ! in_array( $requested_status, $allowed_statuses, true ) ) {
224 229 $requested_status = 'draft';
225 230 }
@@ -232,9 +237,9 @@
232 237 $is_instructor_user = current_user_can( LP_TEACHER_ROLE );
233 238 $required_review = LP_Settings::get_option( 'required_review', 'yes' ) === 'yes';
234 239 $can_publish_course = current_user_can( 'publish_' . LP_COURSE_CPT . 's' );
235 240
236 - $current_status = $insert ? 'auto-draft' : (string) ( $course_model->post_status ?? 'draft' );
241 + $current_status = $insert ? 'auto-draft' : (string) ( $courseModel->post_status ?? 'draft' );
237 242 $is_public_state = $this->is_public_post_status( $current_status );
238 243
239 244 // Require moderation for instructors when review is enabled.
240 245 if ( $is_instructor_user && $required_review && ! $is_public_state && in_array( $requested_status, [ 'publish', 'private', 'future' ], true ) ) {
@@ -334,9 +339,9 @@
334 339
335 340 $insert_post_data = array(
336 341 'post_type' => LP_COURSE_CPT,
337 342 'post_title' => $course_title,
338 - 'post_content' => wp_unslash( $data['course_description'] ?? '' ),
343 + 'post_content' => Template::sanitize_html_content( $data['course_description'] ?? '' ),
339 344 'post_status' => $course_status,
340 345 'tax_input' => array(
341 346 'course_category' => $categories,
342 347 'course_tag' => $tags,
@@ -404,9 +409,9 @@
404 409 $categories = ! empty( $data['course_categories'] ) ? array_map( 'absint', explode( ',', $data['course_categories'] ) ) : array();
405 410 $tags = ! empty( $data['course_tags'] ) ? array_map( 'absint', explode( ',', $data['course_tags'] ) ) : array();
406 411
407 412 $courseModel->post_title = $course_title;
408 - $courseModel->post_content = wp_unslash( $data['course_description'] ?? '' );
413 + $courseModel->post_content = Template::sanitize_html_content( $data['course_description'] ?? '' );
409 414
410 415 wp_set_post_terms( $courseModel->ID, $categories, 'course_category' );
411 416 wp_set_post_terms( $courseModel->ID, $tags, 'course_tag' );
412 417 }
@@ -577,8 +582,19 @@
577 582 $this->save_assessment_settings_to_model( $courseModel, $data );
578 583
579 584 // Author settings
580 585 $this->save_author_settings_to_model( $courseModel, $data );
586 +
587 + /**
588 + * Allow addons to persist their own course settings fields added to the
589 + * settings metabox tabs (e.g. Co-Instructor) when saving from Course Builder.
590 + *
591 + * @param CoursePostModel $courseModel Course model being saved.
592 + * @param array $data Submitted settings data.
593 + *
594 + * @since 4.3.8
595 + */
596 + do_action( 'learn-press/course-builder/save-course-settings', $courseModel, $data );
581 597 }
582 598
583 599 /**
584 600 * Save general settings to CourseModel
@@ -712,8 +728,27 @@
712 728 }
713 729 }
714 730
715 731 /**
732 + * Normalize an extra-info field value to an array.
733 + *
734 + * The Course Builder sends these fields as arrays (one entry per input);
735 + * older paths may send a comma-separated string. Splitting on comma must
736 + * never be applied to array input, or values that legitimately contain a
737 + * comma get broken into multiple entries.
738 + *
739 + * @param mixed $value
740 + * @return array
741 + */
742 + protected function extra_field_to_array( $value ): array {
743 + if ( is_array( $value ) ) {
744 + return $value;
745 + }
746 +
747 + return $value !== '' ? explode( ',', (string) $value ) : [];
748 + }
749 +
750 + /**
716 751 * Save extra info settings to CourseModel
717 752 *
718 753 * @param CoursePostModel $courseModel
719 754 * @param array $data
@@ -720,11 +755,10 @@
720 755 */
721 756 protected function save_extra_settings_to_model( CoursePostModel &$courseModel, array $data ) {
722 757 // Requirements
723 758 if ( isset( $data['_lp_requirements'] ) ) {
724 - $requirements = ! empty( $data['_lp_requirements'] ) ? explode( ',', $data['_lp_requirements'] ) : [];
725 759 $requirements = array_filter(
726 - $requirements,
760 + $this->extra_field_to_array( $data['_lp_requirements'] ),
727 761 function ( $item ) {
728 762 return ! is_null( $item ) && $item !== '';
729 763 }
730 764 );
@@ -731,11 +765,10 @@
731 765 $courseModel->meta_data->{CoursePostModel::META_KEY_REQUIREMENTS} = array_map( 'sanitize_text_field', array_values( $requirements ) );
732 766 }
733 767
734 768 if ( isset( $data['_lp_target_audiences'] ) ) {
735 - $target_audiences = ! empty( $data['_lp_target_audiences'] ) ? explode( ',', $data['_lp_target_audiences'] ) : [];
736 769 $target_audiences = array_filter(
737 - $target_audiences,
770 + $this->extra_field_to_array( $data['_lp_target_audiences'] ),
738 771 function ( $item ) {
739 772 return ! is_null( $item ) && $item !== '';
740 773 }
741 774 );
@@ -742,11 +775,10 @@
742 775 $courseModel->meta_data->{CoursePostModel::META_KEY_TARGET} = array_map( 'sanitize_text_field', array_values( $target_audiences ) );
743 776 }
744 777
745 778 if ( isset( $data['_lp_key_features'] ) ) {
746 - $key_features = ! empty( $data['_lp_key_features'] ) ? explode( ',', $data['_lp_key_features'] ) : [];
747 779 $key_features = array_filter(
748 - $key_features,
780 + $this->extra_field_to_array( $data['_lp_key_features'] ),
749 781 function ( $item ) {
750 782 return ! is_null( $item ) && $item !== '';
751 783 }
752 784 );
@@ -754,10 +786,10 @@
754 786 }
755 787
756 788 // FAQs
757 789 if ( isset( $data['_lp_faqs_question'] ) ) {
758 - $questions = ! empty( $data['_lp_faqs_question'] ) ? explode( ',', $data['_lp_faqs_question'] ) : [];
759 - $answers = ! empty( $data['_lp_faqs_answer'] ) ? explode( ',', $data['_lp_faqs_answer'] ) : [];
790 + $questions = $this->extra_field_to_array( $data['_lp_faqs_question'] );
791 + $answers = ! empty( $data['_lp_faqs_answer'] ) ? $this->extra_field_to_array( $data['_lp_faqs_answer'] ) : [];
760 792 $faqs = [];
761 793
762 794 if ( ! empty( $questions ) ) {
763 795 foreach ( $questions as $index => $question ) {
@@ -823,13 +855,13 @@
823 855 $response = new LP_REST_Response();
824 856 $response->data = new stdClass();
825 857
826 858 try {
827 - $data = self::check_valid_course();
828 - $course_id = $data['course_id'] ?? 0;
829 - $course_model = $data['course_model'];
859 + $data = self::check_valid_course();
860 + $course_id = $data['course_id'] ?? 0;
861 + $courseModel = $data['course_model'];
830 862
831 - if ( absint( $course_model->post_author ) !== get_current_user_id() && ! current_user_can( 'manage_options' ) ) {
863 + if ( absint( $courseModel->post_author ) !== get_current_user_id() && ! current_user_can( 'manage_options' ) ) {
832 864 throw new Exception( __( 'You are not allowed to duplicate this course', 'learnpress' ) );
833 865 }
834 866
835 867 if ( ! function_exists( 'learn_press_duplicate_post' ) ) {
@@ -856,10 +888,10 @@
856 888 if ( is_wp_error( $new_item_id ) ) {
857 889 throw new Exception( $new_item_id->get_error_message() );
858 890 }
859 891
860 - $course_model = CourseModel::find( $new_item_id, true );
861 - $html = BuilderListCoursesTemplate::render_course( $course_model );
892 + $courseModel = CourseModel::find( $new_item_id, true );
893 + $html = BuilderListCoursesTemplate::render_course( $courseModel );
862 894 $response->status = 'success';
863 895 $response->data->html = $html;
864 896 $response->data->course_id_new = $new_item_id;
865 897 $response->data->redirect_url = CourseBuilder::get_link_course_builder( "courses/{$new_item_id}" );
@@ -876,17 +908,17 @@
876 908 $response = new LP_REST_Response();
877 909 $response->data = new stdClass();
878 910
879 911 try {
880 - $data = self::check_valid_course();
881 - $course_id = $data['course_id'] ?? 0;
882 - $course_model = $data['course_model'];
883 - $status = $data['status'] ?? 'trash';
912 + $data = self::check_valid_course();
913 + $course_id = $data['course_id'] ?? 0;
914 + $courseModel = $data['course_model'];
915 + $status = $data['status'] ?? 'trash';
884 916
885 917 $co_instructor_ids = get_post_meta( $course_id, '_lp_co_teacher', false );
886 918 $co_instructor_ids = ! empty( $co_instructor_ids ) ? $co_instructor_ids : array();
887 919
888 - if ( absint( $course_model->post_author ) !== get_current_user_id() && ! current_user_can( 'manage_options' ) && ! in_array( get_current_user_id(), $co_instructor_ids ) ) {
920 + if ( absint( $courseModel->post_author ) !== get_current_user_id() && ! current_user_can( 'manage_options' ) && ! in_array( get_current_user_id(), $co_instructor_ids ) ) {
889 921 throw new Exception( __( 'You are not allowed to delete this course', 'learnpress' ) );
890 922 }
891 923
892 924 if ( $status === 'delete' ) {
@@ -912,9 +944,9 @@
912 944
913 945 $message = __( 'Course has been moved to draft', 'learnpress' );
914 946 } else {
915 947 // Store original slug before trashing (wp_trash_post adds __trashed suffix)
916 - $original_slug = $course_model->post_name;
948 + $original_slug = $courseModel->post_name;
917 949
918 950 $delete = wp_trash_post( $course_id );
919 951
920 952 if ( ! $delete ) {
@@ -950,18 +982,9 @@
950 982 $response = new LP_REST_Response();
951 983 $response->data = new stdClass();
952 984
953 985 try {
954 - $data = self::check_valid_course();
955 - $course_id = absint( $data['course_id'] ?? 0 );
956 - if ( $course_id > 0 ) {
957 - if ( ! CourseBuilderAccessPolicy::can_edit_course_by_id( $course_id ) ) {
958 - throw new Exception( __( 'You are not allowed to update this course', 'learnpress' ) );
959 - }
960 - } elseif ( ! CourseBuilderAccessPolicy::can_create_item_type( LP_COURSE_CPT ) ) {
961 - throw new Exception( __( 'You are not allowed to create courses', 'learnpress' ) );
962 - }
963 -
986 + $data = self::check_valid_course();
964 987 if ( ! current_user_can( 'edit_lp_courses' ) ) {
965 988 throw new Exception( __( 'You are not allowed to create categories', 'learnpress' ) );
966 989 }
967 990
@@ -1008,18 +1031,9 @@
1008 1031 $response = new LP_REST_Response();
1009 1032 $response->data = new stdClass();
1010 1033
1011 1034 try {
1012 - $data = self::check_valid_course();
1013 - $course_id = absint( $data['course_id'] ?? 0 );
1014 - if ( $course_id > 0 ) {
1015 - if ( ! CourseBuilderAccessPolicy::can_edit_course_by_id( $course_id ) ) {
1016 - throw new Exception( __( 'You are not allowed to update this course', 'learnpress' ) );
1017 - }
1018 - } elseif ( ! CourseBuilderAccessPolicy::can_create_item_type( LP_COURSE_CPT ) ) {
1019 - throw new Exception( __( 'You are not allowed to create courses', 'learnpress' ) );
1020 - }
1021 -
1035 + $data = self::check_valid_course();
1022 1036 if ( ! current_user_can( 'edit_lp_courses' ) ) {
1023 1037 throw new Exception( __( 'You are not allowed to create tags', 'learnpress' ) );
1024 1038 }
1025 1039
@@ -1087,120 +1101,117 @@
1087 1101 * Update Lesson from Course Builder.
1088 1102 * Supports partial updates (title only, description only, or settings only).
1089 1103 *
1090 1104 * @since 4.3
1091 - * @version 1.0.2
1105 + * @version 1.0.3
1092 1106 */
1093 1107 public function builder_update_lesson() {
1094 - $response = new LP_REST_Response();
1108 + $response = new Response();
1095 1109 $response->data = new stdClass();
1096 1110
1097 1111 try {
1098 1112 $data = self::check_valid_lesson();
1099 1113 $lesson_id = $data['lesson_id'] ?? 0;
1100 - $title = $data['lesson_title'] ?? null;
1101 - $description = $data['lesson_description'] ?? null;
1114 + $title = LP_Helper::sanitize_params_submitted( $data['lesson_title'] ?? '' );
1115 + $description = LP_Helper::sanitize_params_submitted(
1116 + $data['lesson_description'] ?? '',
1117 + 'html'
1118 + );
1102 1119 $settings = $data['lesson_settings'] ?? false;
1103 1120 $is_elementor = $data['is_elementor'] ?? false;
1104 1121 $return_html = ( $data['return_html'] ?? 'no' ) === 'yes';
1105 1122 $insert = $data['insert'];
1106 - $lesson_slug = ! empty( $data['lesson_permalink'] )
1107 - ? sanitize_title( wp_unslash( (string) $data['lesson_permalink'] ) )
1108 - : '';
1123 + $lesson_slug = LP_Helper::sanitize_params_submitted(
1124 + $data['lesson_permalink'] ?? '',
1125 + 'key'
1126 + );
1109 1127 $course_id = absint( $data['course_id'] ?? 0 );
1110 1128
1111 1129 // Determine target status (draft or publish)
1112 - $target_status = ! empty( $data['lesson_status'] ) && in_array( $data['lesson_status'], [ 'draft', 'publish' ], true )
1113 - ? sanitize_text_field( $data['lesson_status'] )
1114 - : 'publish';
1130 + $target_status = LP_Helper::sanitize_params_submitted(
1131 + $data['lesson_status'] ?? '',
1132 + 'key'
1133 + );
1115 1134 $restore_with_custom_slug = false;
1116 1135
1136 + if ( empty( $title ) ) {
1137 + throw new Exception( __( 'Lesson title is required', 'learnpress' ) );
1138 + }
1139 +
1117 1140 if ( $insert ) {
1118 - if ( ! CourseBuilderAccessPolicy::can_create_item_type( LP_LESSON_CPT ) ) {
1119 - throw new Exception( __( 'You are not allowed to create lessons', 'learnpress' ) );
1120 - }
1121 -
1122 1141 $insert_arg = array(
1123 - 'post_type' => LP_LESSON_CPT,
1124 - 'post_title' => sanitize_text_field( $title ?? '' ),
1125 - 'post_content' => wp_kses_post( $description ?? '' ),
1142 + 'post_title' => $title,
1143 + 'post_content' => $description,
1126 1144 'post_status' => $target_status,
1145 + 'post_author' => get_current_user_id(),
1127 1146 );
1128 1147
1129 - if ( ! empty( $lesson_slug ) ) {
1130 - $insert_arg['post_name'] = $lesson_slug;
1131 - }
1148 + $lessonPostModelNew = new LessonPostModel( $insert_arg );
1149 + $lessonPostModelNew->check_capabilities_create_item_course();
1132 1150
1133 - $lesson_id = wp_insert_post( $insert_arg, true );
1151 + $lessonPostModelNew->save();
1152 + $lesson_id = $lessonPostModelNew->ID;
1134 1153
1135 - if ( is_wp_error( $lesson_id ) ) {
1136 - throw new Exception( $lesson_id->get_error_message() );
1137 - }
1138 -
1139 - $lesson_model = LessonPostModel::find( $lesson_id, true );
1154 + $lesson_model = $lessonPostModelNew;
1155 + $response->message = __( 'Create lesson successfully', 'learnpress' );
1140 1156 } else {
1141 - $lesson_model = $data['lesson_model'];
1142 -
1143 - if ( ! $lesson_model ) {
1157 + $lesson_model = $data['lesson_model'] ?? null;
1158 + if ( ! $lesson_model instanceof LessonPostModel ) {
1144 1159 throw new Exception( __( 'Lesson not found', 'learnpress' ) );
1145 1160 }
1146 1161
1162 + $lesson_model->check_capabilities_update_item_course();
1163 +
1147 1164 if ( ! $course_id ) {
1148 1165 $course_id = absint( $this->get_course_by_item_id( $lesson_id ) );
1149 1166 }
1150 1167
1151 1168 // Support for co-instructor.
1152 - $co_instructor_ids = get_post_meta( $course_id, '_lp_co_teacher', false );
1169 + /*$co_instructor_ids = get_post_meta( $course_id, '_lp_co_teacher', false );
1153 1170 $co_instructor_ids = ! empty( $co_instructor_ids ) ? $co_instructor_ids : array();
1154 1171
1155 1172 if ( absint( $lesson_model->post_author ) !== get_current_user_id() && ! current_user_can( 'manage_options' ) && ! in_array( get_current_user_id(), $co_instructor_ids ) ) {
1156 1173 throw new Exception( __( 'You are not allowed to update this lesson', 'learnpress' ) );
1157 - }
1174 + }*/
1158 1175
1159 - $update_arg = array(
1176 + /*$update_arg = array(
1160 1177 'ID' => $lesson_id,
1161 1178 'post_type' => LP_LESSON_CPT,
1162 1179 'post_status' => $target_status,
1163 - );
1180 + );*/
1164 1181
1165 1182 if ( defined( 'ELEMENTOR_VERSION' ) ) {
1166 1183 \Elementor\Plugin::$instance->documents->get( $lesson_id )->set_is_built_with_elementor( ! empty( $is_elementor ) );
1167 1184 }
1168 1185
1169 - if ( isset( $data['lesson_title'] ) ) {
1170 - $update_arg['post_title'] = sanitize_text_field( $title );
1171 - }
1172 -
1173 - if ( isset( $data['lesson_description'] ) ) {
1174 - $update_arg['post_content'] = wp_kses_post( $description );
1175 - }
1176 -
1186 + $lesson_model->post_title = $title;
1187 + $lesson_model->post_content = $description;
1188 + $lesson_model->post_status = $target_status;
1177 1189 if ( ! empty( $lesson_slug ) ) {
1178 - $update_arg['post_name'] = $lesson_slug;
1190 + $lesson_model->post_name = $lesson_slug;
1179 1191 }
1180 1192
1181 - $restore_with_custom_slug = $this->prepare_desired_slug_for_restore( $lesson_id, $target_status, $lesson_slug );
1193 + //$restore_with_custom_slug = $this->prepare_desired_slug_for_restore( $lesson_id, $target_status, $lesson_slug );
1182 1194
1183 - $update = wp_update_post( $update_arg );
1195 + //$update = wp_update_post( $update_arg );
1196 + $lesson_model->save();
1184 1197
1185 - if ( is_wp_error( $update ) ) {
1186 - throw new Exception( $update->get_error_message() );
1187 - }
1188 -
1189 - if ( $restore_with_custom_slug ) {
1198 + /*if ( $restore_with_custom_slug ) {
1190 1199 $this->sync_slug_after_restore( $lesson_id, $lesson_slug );
1191 - }
1200 + }*/
1192 1201
1193 1202 if ( $course_id ) {
1194 - $course_model_cache = CourseModel::find( $course_id, true );
1195 - if ( $course_model_cache ) {
1196 - $course_model_cache->sections_items = null;
1197 - $course_model_cache->save();
1203 + $courseModelCache = CourseModel::find( $course_id, true );
1204 + if ( $courseModelCache ) {
1205 + $courseModelCache->sections_items = null;
1206 + $courseModelCache->save();
1198 1207 }
1199 1208 }
1209 +
1210 + $response->message = __( 'Update lesson successfully', 'learnpress' );
1200 1211 }
1201 1212
1202 - if ( $settings && $lesson_model ) {
1213 + if ( $settings ) {
1203 1214 $this->save_lesson_settings_to_model( $lesson_model, $data );
1204 1215 }
1205 1216
1206 1217 // Remove lesson from curriculum if status is not public
@@ -1207,32 +1218,24 @@
1207 1218 if ( $target_status !== 'publish' ) {
1208 1219 $this->remove_course_item_from_curriculum( $lesson_id, $course_id );
1209 1220 }
1210 1221
1211 - do_action( 'learn-press/course-builder/update-lesson', $data, $lesson_model );
1212 -
1213 - $saved_lesson_status = get_post_status( $lesson_id );
1214 - if ( ! is_string( $saved_lesson_status ) || '' === $saved_lesson_status ) {
1215 - $saved_lesson_status = $target_status;
1216 - }
1217 -
1218 1222 $response->status = 'success';
1219 - $response->data->status = $saved_lesson_status;
1220 - $response->data->button_title = $saved_lesson_status === 'publish' ? __( 'Update', 'learnpress' ) : __( 'Publish', 'learnpress' );
1223 + $response->data->status = $lesson_model->post_status;
1224 + $response->data->button_title = $lesson_model->post_status === 'publish' ?
1225 + __( 'Update', 'learnpress' ) :
1226 + __( 'Publish', 'learnpress' );
1221 1227 $response->data->lesson_id_new = $insert ? $lesson_id : '';
1222 1228 $response->message = $target_status === 'draft'
1223 1229 ? esc_html__( 'Lesson saved as draft', 'learnpress' )
1224 1230 : ( $insert ? esc_html__( 'Insert lesson successfully', 'learnpress' ) : esc_html__( 'Update lesson successfully', 'learnpress' ) );
1225 1231
1226 - $saved_lesson_post = get_post( $lesson_id );
1227 - if ( $saved_lesson_post ) {
1228 - $response->data->lesson_slug = $saved_lesson_post->post_name;
1229 - }
1232 + $response->data->lesson_slug = $lesson_model->post_name;
1230 1233
1231 1234 $course_id_of_item = $this->get_course_by_item_id( $lesson_id );
1232 1235 $response->data->permalink_available = false;
1233 1236 $response->data->permalink_notice = $this->get_item_permalink_unavailable_message();
1234 - if ( 'publish' === $saved_lesson_status && $course_id_of_item ) {
1237 + if ( 'publish' === $lesson_model->post_status && $course_id_of_item ) {
1235 1238 $course = learn_press_get_course( $course_id_of_item );
1236 1239 if ( $course ) {
1237 1240 $response->data->permalink_available = true;
1238 1241 $response->data->lesson_permalink = urldecode( $course->get_item_link( $lesson_id ) );
@@ -1245,26 +1248,26 @@
1245 1248 ? BuilderListLessonsTemplate::render_lesson( $lesson_model_for_html )
1246 1249 : '';
1247 1250
1248 1251 if ( $course_id ) {
1249 - $course_model_for_html = CourseModel::find( $course_id, true );
1250 - if ( $course_model_for_html && $lesson_model_for_html ) {
1252 + $courseModelForHtml = CourseModel::find( $course_id, true );
1253 + if ( $courseModelForHtml && $lesson_model_for_html ) {
1251 1254 $item = new stdClass();
1252 1255 $item->item_id = $lesson_id;
1253 1256 $item->title = $lesson_model_for_html->post_title;
1254 1257 $item->item_type = LP_LESSON_CPT;
1255 1258 AdminEditCurriculumTemplate::instance()->context_data = [ 'is_course_builder' => true ];
1256 - $response->data->section_item_html = AdminEditCurriculumTemplate::instance()->html_section_item( $course_model_for_html, $item );
1259 + $response->data->section_item_html = AdminEditCurriculumTemplate::instance()->html_section_item( $courseModelForHtml, $item );
1257 1260 }
1258 1261 }
1259 1262 }
1260 1263
1261 - wp_send_json( $response );
1262 - } catch ( Throwable $th ) {
1263 - $response->status = 'error';
1264 - $response->message = $th->getMessage();
1265 - wp_send_json( $response );
1264 + $response->status = Response::STATUS_SUCCESS;
1265 + } catch ( Throwable $e ) {
1266 + $response->message = $e->getMessage();
1266 1267 }
1268 +
1269 + wp_send_json( $response );
1267 1270 }
1268 1271
1269 1272 public function move_trash_lesson() {
1270 1273 $response = new LP_REST_Response();
@@ -1393,10 +1396,13 @@
1393 1396 }
1394 1397
1395 1398 /**
1396 1399 * Save Lesson Settings
1400 + * @throws Exception
1397 1401 */
1398 1402 protected function save_lesson_settings_to_model( LessonPostModel $lessonModel, array $data ) {
1403 + $must_save = 0;
1404 +
1399 1405 if ( isset( $data['_lp_duration'] ) ) {
1400 1406 $duration = ! empty( $data['_lp_duration'] ) ? str_replace( ',', ' ', $data['_lp_duration'] ) : '0 minute';
1401 1407 $explode = explode( ' ', $duration );
1402 1408 $number = (float) $explode[0] < 0 ? 0 : absint( $explode[0] );
@@ -1401,15 +1407,32 @@
1401 1407 $explode = explode( ' ', $duration );
1402 1408 $number = (float) $explode[0] < 0 ? 0 : absint( $explode[0] );
1403 1409 $unit = $explode[1] ?? 'minute';
1404 1410
1405 - $lessonModel->save_meta_value_by_key( '_lp_duration', $number . ' ' . $unit );
1411 + $lessonModel->set_meta_value_by_key( $lessonModel::META_KEY_DURATION, $number . ' ' . $unit );
1412 + $must_save = 1;
1406 1413 }
1407 1414
1408 1415 if ( isset( $data['_lp_preview'] ) ) {
1409 1416 $enable = $data['_lp_preview'] === 'yes';
1410 1417 $lessonModel->set_preview( $enable );
1418 + $must_save = 1;
1411 1419 }
1420 +
1421 + if ( $must_save ) {
1422 + $lessonModel->save();
1423 + }
1424 +
1425 + /**
1426 + * Allow addons to persist their own lesson settings fields added to the
1427 + * settings metabox tabs when saving from Course Builder.
1428 + *
1429 + * @param LessonPostModel $lessonModel Lesson model being saved.
1430 + * @param array $data Submitted settings data.
1431 + *
1432 + * @since 4.3.8
1433 + */
1434 + do_action( 'learn-press/course-builder/save-lesson-settings', $lessonModel, $data );
1412 1435 }
1413 1436
1414 1437 /**
1415 1438 * Save Quiz Settings to QuizPostModel
@@ -1461,8 +1484,19 @@
1461 1484 }
1462 1485 $quizModel->save_meta_value_by_key( $key, $value );
1463 1486 }
1464 1487 }
1488 +
1489 + /**
1490 + * Allow addons to persist their own quiz settings fields added to the
1491 + * settings metabox tabs when saving from Course Builder.
1492 + *
1493 + * @param QuizPostModel $quizModel Quiz model being saved.
1494 + * @param array $data Submitted settings data.
1495 + *
1496 + * @since 4.3.8
1497 + */
1498 + do_action( 'learn-press/course-builder/save-quiz-settings', $quizModel, $data );
1465 1499 }
1466 1500
1467 1501 /**
1468 1502 * Update Quiz from Course Builder.
@@ -1471,117 +1505,92 @@
1471 1505 * @since 4.3
1472 1506 * @version 1.0.2
1473 1507 */
1474 1508 public function builder_update_quiz() {
1475 - $response = new LP_REST_Response();
1509 + $response = new Response();
1476 1510 $response->data = new stdClass();
1477 1511
1478 1512 try {
1479 1513 $data = self::check_valid_quiz();
1480 1514 $quiz_id = $data['quiz_id'] ?? 0;
1481 - $title = $data['quiz_title'] ?? null;
1482 - $description = $data['quiz_description'] ?? null;
1515 + $title = LP_Helper::sanitize_params_submitted( $data['quiz_title'] ?? '' );
1516 + $description = LP_Helper::sanitize_params_submitted(
1517 + $data['quiz_description'] ?? '',
1518 + 'html'
1519 + );
1483 1520 $settings = $data['quiz_settings'] ?? false;
1484 1521 $is_elementor = $data['is_elementor'] ?? false;
1485 1522 $return_html = ( $data['return_html'] ?? 'no' ) === 'yes';
1486 1523 $insert = $data['insert'];
1487 - $quiz_slug = ! empty( $data['quiz_permalink'] )
1488 - ? sanitize_title( wp_unslash( (string) $data['quiz_permalink'] ) )
1489 - : '';
1524 + $quiz_slug = LP_Helper::sanitize_params_submitted(
1525 + $data['quiz_permalink'] ?? '',
1526 + 'key'
1527 + );
1490 1528 $course_id = absint( $data['course_id'] ?? 0 );
1491 1529
1492 1530 // Determine target status (draft or publish)
1493 - $target_status = ! empty( $data['quiz_status'] ) && in_array( $data['quiz_status'], [ 'draft', 'publish' ], true )
1494 - ? sanitize_text_field( $data['quiz_status'] )
1495 - : 'publish';
1496 - $restore_with_custom_slug = false;
1531 + $target_status = LP_Helper::sanitize_params_submitted(
1532 + $data['quiz_status'] ?? '',
1533 + 'key'
1534 + );
1497 1535
1536 + if ( empty( $title ) ) {
1537 + throw new Exception( __( 'Quiz title is required', 'learnpress' ) );
1538 + }
1539 +
1498 1540 if ( $insert ) {
1499 - if ( ! CourseBuilderAccessPolicy::can_create_item_type( LP_QUIZ_CPT ) ) {
1500 - throw new Exception( __( 'You are not allowed to create quizzes', 'learnpress' ) );
1501 - }
1502 -
1503 1541 $insert_arg = array(
1504 - 'post_type' => LP_QUIZ_CPT,
1505 - 'post_title' => sanitize_text_field( $title ?? '' ),
1506 - 'post_content' => wp_kses_post( $description ?? '' ),
1542 + 'post_title' => $title,
1543 + 'post_content' => $description,
1507 1544 'post_status' => $target_status,
1545 + 'post_author' => get_current_user_id(),
1508 1546 );
1509 1547
1510 - if ( ! empty( $quiz_slug ) ) {
1511 - $insert_arg['post_name'] = $quiz_slug;
1512 - }
1548 + $quizPostModelNew = new QuizPostModel( $insert_arg );
1549 + $quizPostModelNew->check_capabilities_create_item_course();
1513 1550
1514 - $quiz_id = wp_insert_post( $insert_arg, true );
1551 + $quizPostModelNew->save();
1552 + $quiz_id = $quizPostModelNew->ID;
1515 1553
1516 - if ( is_wp_error( $quiz_id ) ) {
1517 - throw new Exception( $quiz_id->get_error_message() );
1518 - }
1519 -
1520 - $quiz_model = QuizPostModel::find( $quiz_id, true );
1554 + $quiz_model = $quizPostModelNew;
1555 + $response->message = __( 'Create quiz successfully', 'learnpress' );
1521 1556 } else {
1522 - $quiz_model = $data['quiz_model'];
1523 -
1524 - if ( ! $quiz_model ) {
1557 + $quiz_model = $data['quiz_model'] ?? null;
1558 + if ( ! $quiz_model instanceof QuizPostModel ) {
1525 1559 throw new Exception( __( 'Quiz not found', 'learnpress' ) );
1526 1560 }
1527 1561
1562 + $quiz_model->check_capabilities_update_item_course();
1563 +
1528 1564 if ( ! $course_id ) {
1529 1565 $course_id = absint( $this->get_course_by_item_id( $quiz_id ) );
1530 1566 }
1531 1567
1532 - // Support for co-instructor.
1533 - $co_instructor_ids = get_post_meta( $course_id, '_lp_co_teacher', false );
1534 - $co_instructor_ids = ! empty( $co_instructor_ids ) ? $co_instructor_ids : array();
1535 -
1536 - if ( absint( $quiz_model->post_author ) !== get_current_user_id() && ! current_user_can( 'manage_options' ) && ! in_array( get_current_user_id(), $co_instructor_ids ) ) {
1537 - throw new Exception( __( 'You are not allowed to update this quiz', 'learnpress' ) );
1538 - }
1539 -
1540 - $update_arg = array(
1541 - 'ID' => $quiz_id,
1542 - 'post_type' => LP_QUIZ_CPT,
1543 - 'post_status' => $target_status,
1544 - );
1545 -
1546 - if ( isset( $data['quiz_title'] ) ) {
1547 - $update_arg['post_title'] = sanitize_text_field( $title );
1548 - }
1549 -
1550 - if ( isset( $data['quiz_description'] ) ) {
1551 - $update_arg['post_content'] = wp_kses_post( $description );
1552 - }
1553 -
1554 - if ( ! empty( $quiz_slug ) ) {
1555 - $update_arg['post_name'] = $quiz_slug;
1556 - }
1557 -
1558 1568 if ( defined( 'ELEMENTOR_VERSION' ) ) {
1559 1569 \Elementor\Plugin::$instance->documents->get( $quiz_id )->set_is_built_with_elementor( ! empty( $is_elementor ) );
1560 1570 }
1561 1571
1562 - $restore_with_custom_slug = $this->prepare_desired_slug_for_restore( $quiz_id, $target_status, $quiz_slug );
1563 -
1564 - $update = wp_update_post( $update_arg );
1565 -
1566 - if ( is_wp_error( $update ) ) {
1567 - throw new Exception( $update->get_error_message() );
1572 + $quiz_model->post_title = $title;
1573 + $quiz_model->post_content = $description;
1574 + $quiz_model->post_status = $target_status;
1575 + if ( ! empty( $quiz_slug ) ) {
1576 + $quiz_model->post_name = $quiz_slug;
1568 1577 }
1569 1578
1570 - if ( $restore_with_custom_slug ) {
1571 - $this->sync_slug_after_restore( $quiz_id, $quiz_slug );
1572 - }
1579 + $quiz_model->save();
1573 1580
1574 1581 if ( $course_id ) {
1575 - $course_model_cache = CourseModel::find( $course_id, true );
1576 - if ( $course_model_cache ) {
1577 - $course_model_cache->sections_items = null;
1578 - $course_model_cache->save();
1582 + $courseModelCache = CourseModel::find( $course_id, true );
1583 + if ( $courseModelCache ) {
1584 + $courseModelCache->sections_items = null;
1585 + $courseModelCache->save();
1579 1586 }
1580 1587 }
1588 +
1589 + $response->message = __( 'Update quiz successfully', 'learnpress' );
1581 1590 }
1582 1591
1583 - if ( $settings && $quiz_model ) {
1592 + if ( $settings ) {
1584 1593 $this->save_quiz_settings_to_model( $quiz_model, $data );
1585 1594 }
1586 1595
1587 1596 // Remove quiz from curriculum if status is not public
@@ -1588,37 +1597,27 @@
1588 1597 if ( $target_status !== 'publish' ) {
1589 1598 $this->remove_course_item_from_curriculum( $quiz_id, $course_id );
1590 1599 }
1591 1600
1592 - do_action( 'learn-press/course-builder/update-quiz', $data, $quiz_model );
1593 -
1594 - $saved_quiz_status = get_post_status( $quiz_id );
1595 - if ( ! is_string( $saved_quiz_status ) || '' === $saved_quiz_status ) {
1596 - $saved_quiz_status = $target_status;
1601 + $response->status = 'success';
1602 + $response->data->status = $quiz_model->post_status;
1603 + $response->data->button_title = $quiz_model->post_status === 'publish' ?
1604 + __( 'Update', 'learnpress' ) :
1605 + __( 'Publish', 'learnpress' );
1606 + $response->data->quiz_id_new = $insert ? $quiz_id : '';
1607 + if ( $insert && $quiz_id ) {
1608 + $response->data->redirect_url = CourseBuilder::get_link_course_builder( CourseBuilderTemplate::MENU_QUIZZES . "/{$quiz_id}" );
1597 1609 }
1598 -
1599 - if ( $insert ) {
1600 - $response->data->redirect_url = CourseBuilder::get_link_course_builder(
1601 - CourseBuilderTemplate::MENU_QUIZZES . "/{$quiz_id}"
1602 - );
1603 - }
1604 -
1605 - $response->status = 'success';
1606 - $response->data->status = $saved_quiz_status;
1607 - $response->data->button_title = $saved_quiz_status === 'publish' ? __( 'Update', 'learnpress' ) : __( 'Publish', 'learnpress' );
1608 - $response->message = $target_status === 'draft'
1610 + $response->message = $target_status === 'draft'
1609 1611 ? esc_html__( 'Quiz saved as draft', 'learnpress' )
1610 1612 : ( $insert ? esc_html__( 'Insert quiz successfully', 'learnpress' ) : esc_html__( 'Update quiz successfully', 'learnpress' ) );
1611 1613
1612 - $saved_quiz_post = get_post( $quiz_id );
1613 - if ( $saved_quiz_post ) {
1614 - $response->data->quiz_slug = $saved_quiz_post->post_name;
1615 - }
1614 + $response->data->quiz_slug = $quiz_model->post_name;
1616 1615
1617 1616 $course_id_of_item = $this->get_course_by_item_id( $quiz_id );
1618 1617 $response->data->permalink_available = false;
1619 1618 $response->data->permalink_notice = $this->get_item_permalink_unavailable_message();
1620 - if ( 'publish' === $saved_quiz_status && $course_id_of_item ) {
1619 + if ( 'publish' === $quiz_model->post_status && $course_id_of_item ) {
1621 1620 $course = learn_press_get_course( $course_id_of_item );
1622 1621 if ( $course ) {
1623 1622 $response->data->permalink_available = true;
1624 1623 $response->data->quiz_permalink = urldecode( $course->get_item_link( $quiz_id ) );
@@ -1624,33 +1623,33 @@
1624 1623 $response->data->quiz_permalink = urldecode( $course->get_item_link( $quiz_id ) );
1625 1624 }
1626 1625 }
1627 1626
1627 + $quiz_model_for_html = QuizPostModel::find( $quiz_id, true );
1628 1628 if ( $return_html ) {
1629 - $quiz_model_new = QuizPostModel::find( $quiz_id, true );
1630 - $response->data->list_item_html = $quiz_model_new
1631 - ? BuilderListQuizzesTemplate::render_quiz( $quiz_model_new )
1629 + $response->data->list_item_html = $quiz_model_for_html
1630 + ? BuilderListQuizzesTemplate::render_quiz( $quiz_model_for_html )
1632 1631 : '';
1633 1632
1634 1633 if ( $course_id ) {
1635 - $course_model_for_html = CourseModel::find( $course_id, true );
1636 - if ( $course_model_for_html && $quiz_model_new ) {
1634 + $courseModelForHtml = CourseModel::find( $course_id, true );
1635 + if ( $courseModelForHtml && $quiz_model_for_html ) {
1637 1636 $item = new stdClass();
1638 1637 $item->item_id = $quiz_id;
1639 - $item->title = $quiz_model_new->post_title;
1638 + $item->title = $quiz_model_for_html->post_title;
1640 1639 $item->item_type = LP_QUIZ_CPT;
1641 1640 AdminEditCurriculumTemplate::instance()->context_data = [ 'is_course_builder' => true ];
1642 - $response->data->section_item_html = AdminEditCurriculumTemplate::instance()->html_section_item( $course_model_for_html, $item );
1641 + $response->data->section_item_html = AdminEditCurriculumTemplate::instance()->html_section_item( $courseModelForHtml, $item );
1643 1642 }
1644 1643 }
1645 1644 }
1646 1645
1647 - wp_send_json( $response );
1648 - } catch ( Throwable $th ) {
1649 - $response->status = 'error';
1650 - $response->message = $th->getMessage();
1651 - wp_send_json( $response );
1646 + $response->status = Response::STATUS_SUCCESS;
1647 + } catch ( Throwable $e ) {
1648 + $response->message = $e->getMessage();
1652 1649 }
1650 +
1651 + wp_send_json( $response );
1653 1652 }
1654 1653
1655 1654 public function duplicate_quiz() {
1656 1655 $response = new LP_REST_Response();
@@ -1850,93 +1849,75 @@
1850 1849 }
1851 1850 }
1852 1851
1853 1852 public function builder_update_question() {
1854 - $response = new LP_REST_Response();
1853 + $response = new Response();
1855 1854 $response->data = new stdClass();
1856 1855
1857 1856 try {
1858 1857 $data = self::check_valid_question();
1859 1858 $question_id = $data['question_id'] ?? 0;
1860 - $title = $data['question_title'] ?? '';
1861 - $description = $data['question_description'] ?? '';
1859 + $title = LP_Helper::sanitize_params_submitted( $data['question_title'] ?? '' );
1860 + $description = LP_Helper::sanitize_params_submitted(
1861 + $data['question_description'] ?? '',
1862 + 'html'
1863 + );
1862 1864 $is_elementor = $data['is_elementor'] ?? false;
1863 1865 $return_html = ( $data['return_html'] ?? 'no' ) === 'yes';
1864 1866 $insert = $data['insert'];
1865 - $question_slug = ! empty( $data['question_permalink'] )
1866 - ? sanitize_title( wp_unslash( (string) $data['question_permalink'] ) )
1867 - : '';
1867 + $question_slug = LP_Helper::sanitize_params_submitted(
1868 + $data['question_permalink'] ?? '',
1869 + 'key'
1870 + );
1868 1871
1869 1872 // Determine target status (draft or publish)
1870 - $target_status = ! empty( $data['question_status'] ) && in_array( $data['question_status'], [ 'draft', 'publish' ], true )
1871 - ? sanitize_text_field( $data['question_status'] )
1872 - : 'publish';
1873 + $target_status = LP_Helper::sanitize_params_submitted(
1874 + $data['question_status'] ?? '',
1875 + 'key'
1876 + );
1873 1877
1878 + if ( empty( $title ) ) {
1879 + throw new Exception( __( 'Question title is required', 'learnpress' ) );
1880 + }
1881 +
1874 1882 if ( $insert ) {
1875 - if ( ! CourseBuilderAccessPolicy::can_create_item_type( LP_QUESTION_CPT ) ) {
1876 - throw new Exception( __( 'You are not allowed to create questions', 'learnpress' ) );
1877 - }
1878 -
1879 1883 $insert_arg = array(
1880 - 'post_type' => LP_QUESTION_CPT,
1881 - 'post_title' => sanitize_text_field( $title ?? '' ),
1882 - 'post_content' => $description ?? '',
1884 + 'post_title' => $title,
1885 + 'post_content' => $description,
1883 1886 'post_status' => $target_status,
1887 + 'post_author' => get_current_user_id(),
1884 1888 );
1885 1889
1886 - if ( ! empty( $question_slug ) ) {
1887 - $insert_arg['post_name'] = $question_slug;
1888 - }
1890 + $questionPostModelNew = new QuestionPostModel( $insert_arg );
1891 + $questionPostModelNew->check_capabilities_create_item_course();
1889 1892
1890 - $question_id = wp_insert_post( $insert_arg, true );
1893 + $questionPostModelNew->save();
1894 + $question_id = $questionPostModelNew->ID;
1891 1895
1892 - if ( is_wp_error( $question_id ) ) {
1893 - throw new Exception( $question_id->get_error_message() );
1894 - }
1896 + $question_model = $questionPostModelNew;
1897 + $response->message = __( 'Create question successfully', 'learnpress' );
1895 1898 } else {
1896 - $question_model = $data['question_model'];
1897 -
1898 - if ( ! $question_model ) {
1899 + $question_model = $data['question_model'] ?? null;
1900 + if ( ! $question_model instanceof QuestionPostModel ) {
1899 1901 throw new Exception( __( 'Question not found', 'learnpress' ) );
1900 1902 }
1901 1903
1902 - $course_id = $this->get_course_by_item_id( $question_id );
1904 + $question_model->check_capabilities_update_item_course();
1903 1905
1904 - // Support for co-instructor.
1905 - $co_instructor_ids = get_post_meta( $course_id, '_lp_co_teacher', false );
1906 - $co_instructor_ids = ! empty( $co_instructor_ids ) ? $co_instructor_ids : array();
1907 -
1908 - if ( absint( $question_model->post_author ) !== get_current_user_id() && ! current_user_can( 'manage_options' ) && ! in_array( get_current_user_id(), $co_instructor_ids ) ) {
1909 - throw new Exception( __( 'You are not allowed to update this question', 'learnpress' ) );
1910 - }
1911 -
1912 - $update_arg = array(
1913 - 'ID' => $question_id,
1914 - 'post_type' => LP_QUESTION_CPT,
1915 - 'post_status' => $target_status,
1916 - );
1917 -
1918 1906 if ( defined( 'ELEMENTOR_VERSION' ) ) {
1919 1907 \Elementor\Plugin::$instance->documents->get( $question_id )->set_is_built_with_elementor( ! empty( $is_elementor ) );
1920 1908 }
1921 1909
1922 - if ( isset( $data['question_title'] ) ) {
1923 - $update_arg['post_title'] = sanitize_text_field( $title );
1924 - }
1925 -
1926 - if ( isset( $data['question_description'] ) ) {
1927 - $update_arg['post_content'] = wp_kses_post( $description );
1928 - }
1929 -
1910 + $question_model->post_title = $title;
1911 + $question_model->post_content = $description;
1912 + $question_model->post_status = $target_status;
1930 1913 if ( ! empty( $question_slug ) ) {
1931 - $update_arg['post_name'] = $question_slug;
1914 + $question_model->post_name = $question_slug;
1932 1915 }
1933 1916
1934 - $update = wp_update_post( $update_arg );
1917 + $question_model->save();
1935 1918
1936 - if ( is_wp_error( $update ) ) {
1937 - throw new Exception( $update->get_error_message() );
1938 - }
1919 + $response->message = __( 'Update question successfully', 'learnpress' );
1939 1920 }
1940 1921
1941 1922 // Remove question from quizzes if status is not public
1942 1923 if ( $target_status !== 'publish' ) {
@@ -1942,48 +1923,39 @@
1942 1923 if ( $target_status !== 'publish' ) {
1943 1924 $this->remove_question_from_assigned_quizzes( $question_id );
1944 1925 }
1945 1926
1946 - do_action( 'learn-press/course-builder/update-question', $data, $question_model ?? null );
1927 + do_action( 'learn-press/course-builder/update-question', $data, $question_model );
1947 1928
1948 - $saved_question_status = get_post_status( $question_id );
1949 - if ( ! is_string( $saved_question_status ) || '' === $saved_question_status ) {
1950 - $saved_question_status = $target_status;
1929 + $response->status = 'success';
1930 + $response->data->status = $question_model->post_status;
1931 + $response->data->button_title = $question_model->post_status === 'publish' ?
1932 + __( 'Update', 'learnpress' ) :
1933 + __( 'Publish', 'learnpress' );
1934 + $response->data->question_id_new = $insert ? $question_id : '';
1935 + if ( $insert && $question_id ) {
1936 + $response->data->redirect_url = CourseBuilder::get_link_course_builder( CourseBuilderTemplate::MENU_QUESTIONS . "/{$question_id}" );
1951 1937 }
1952 -
1953 - if ( $insert ) {
1954 - $response->data->redirect_url = CourseBuilder::get_link_course_builder(
1955 - CourseBuilderTemplate::MENU_QUESTIONS . "/{$question_id}"
1956 - );
1957 - }
1958 -
1959 - $response->status = 'success';
1960 - $response->data->status = $saved_question_status;
1961 - $response->data->button_title = $saved_question_status === 'publish' ? __( 'Update', 'learnpress' ) : __( 'Publish', 'learnpress' );
1962 -
1963 1938 $response->message = $target_status === 'draft'
1964 1939 ? esc_html__( 'Question saved as draft', 'learnpress' )
1965 1940 : ( $insert ? esc_html__( 'Insert question successfully', 'learnpress' ) : esc_html__( 'Update question successfully', 'learnpress' ) );
1966 1941
1967 - $saved_question = get_post( $question_id );
1968 - if ( $saved_question ) {
1969 - $response->data->question_slug = $saved_question->post_name;
1970 - $response->data->question_permalink = get_permalink( $question_id );
1971 - }
1942 + $response->data->question_slug = $question_model->post_name;
1943 + $response->data->question_permalink = get_permalink( $question_id );
1972 1944
1945 + $question_model_for_html = QuestionPostModel::find( $question_id, true );
1973 1946 if ( $return_html ) {
1974 - $question_model_new = QuestionPostModel::find( $question_id, true );
1975 - $response->data->list_item_html = $question_model_new
1976 - ? BuilderListQuestionsTemplate::render_question( $question_model_new )
1947 + $response->data->list_item_html = $question_model_for_html
1948 + ? BuilderListQuestionsTemplate::render_question( $question_model_for_html )
1977 1949 : '';
1978 1950 }
1979 1951
1980 - wp_send_json( $response );
1981 - } catch ( Throwable $th ) {
1982 - $response->status = 'error';
1983 - $response->message = $th->getMessage();
1984 - wp_send_json( $response );
1952 + $response->status = Response::STATUS_SUCCESS;
1953 + } catch ( Throwable $e ) {
1954 + $response->message = $e->getMessage();
1985 1955 }
1956 +
1957 + wp_send_json( $response );
1986 1958 }
1987 1959
1988 1960 public function move_trash_question() {
1989 1961 $response = new LP_REST_Response();
@@ -2138,16 +2110,16 @@
2138 2110 return;
2139 2111 }
2140 2112
2141 2113 try {
2142 - $course_model = CourseModel::find( $course_id, true );
2143 - if ( ! $course_model ) {
2114 + $courseModel = CourseModel::find( $course_id, true );
2115 + if ( ! $courseModel ) {
2144 2116 return;
2145 2117 }
2146 2118
2147 - $course_model->sections_items = null;
2148 - $course_model->total_items = null;
2149 - $course_model->save( true );
2119 + $courseModel->sections_items = null;
2120 + $courseModel->total_items = null;
2121 + $courseModel->save( true );
2150 2122 } catch ( Throwable $e ) {
2151 2123 error_log( __METHOD__ . ': ' . $e->getMessage() );
2152 2124 }
2153 2125 }
@@ -2227,10 +2199,10 @@
2227 2199 throw new Exception( __( 'Permission denied', 'learnpress' ) );
2228 2200 }
2229 2201
2230 2202 $hide_instructor_access_admin_screen = ! empty( $data['hide_instructor_access_admin_screen'] ) && $data['hide_instructor_access_admin_screen'] === 'yes' ? 'yes' : 'no';
2231 - $logo_remove = ! empty( $data['course_builder_logo_remove'] ) && $data['course_builder_logo_remove'] === 'yes';
2232 - $logo_id = absint( $data['course_builder_logo_id'] ?? 0 );
2203 + $logo_remove = ! empty( $data['course_builder_logo_remove'] ) && $data['course_builder_logo_remove'] === 'yes';
2204 + $logo_id = absint( $data['course_builder_logo_id'] ?? 0 );
2233 2205
2234 2206 if ( $logo_remove ) {
2235 2207 $logo_id = 0;
2236 2208 }
@@ -2242,13 +2214,13 @@
2242 2214 if ( $logo_id ) {
2243 2215 $logo_url = wp_get_attachment_image_url( $logo_id, 'full' );
2244 2216 }
2245 2217
2246 - $response->status = 'success';
2247 - $response->message = __( 'Course Builder settings updated.', 'learnpress' );
2248 - $response->data->hide_instructor_access_admin_screen = $hide_instructor_access_admin_screen;
2249 - $response->data->course_builder_logo_id = $logo_id;
2250 - $response->data->course_builder_logo_url = $logo_url;
2218 + $response->status = 'success';
2219 + $response->message = __( 'Course Builder settings updated.', 'learnpress' );
2220 + $response->data->hide_instructor_access_admin_screen = $hide_instructor_access_admin_screen;
2221 + $response->data->course_builder_logo_id = $logo_id;
2222 + $response->data->course_builder_logo_url = $logo_url;
2251 2223
2252 2224 wp_send_json( $response );
2253 2225 } catch ( Throwable $th ) {
2254 2226 $response->status = 'error';