PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.4.10
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.4.10
4.4.10 4.4.9.1 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 All 142 releases
← All changes | inc/Ajax/CourseBuilder/CourseBuilderAjax.php +102 -23 4.4.0 → 4.4.10 View file →
@@ -582,8 +582,19 @@
582 582 $this->save_assessment_settings_to_model( $courseModel, $data );
583 583
584 584 // Author settings
585 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 );
586 597 }
587 598
588 599 /**
589 600 * Save general settings to CourseModel
@@ -717,8 +728,27 @@
717 728 }
718 729 }
719 730
720 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 + /**
721 751 * Save extra info settings to CourseModel
722 752 *
723 753 * @param CoursePostModel $courseModel
724 754 * @param array $data
@@ -725,11 +755,10 @@
725 755 */
726 756 protected function save_extra_settings_to_model( CoursePostModel &$courseModel, array $data ) {
727 757 // Requirements
728 758 if ( isset( $data['_lp_requirements'] ) ) {
729 - $requirements = ! empty( $data['_lp_requirements'] ) ? explode( ',', $data['_lp_requirements'] ) : [];
730 759 $requirements = array_filter(
731 - $requirements,
760 + $this->extra_field_to_array( $data['_lp_requirements'] ),
732 761 function ( $item ) {
733 762 return ! is_null( $item ) && $item !== '';
734 763 }
735 764 );
@@ -736,11 +765,10 @@
736 765 $courseModel->meta_data->{CoursePostModel::META_KEY_REQUIREMENTS} = array_map( 'sanitize_text_field', array_values( $requirements ) );
737 766 }
738 767
739 768 if ( isset( $data['_lp_target_audiences'] ) ) {
740 - $target_audiences = ! empty( $data['_lp_target_audiences'] ) ? explode( ',', $data['_lp_target_audiences'] ) : [];
741 769 $target_audiences = array_filter(
742 - $target_audiences,
770 + $this->extra_field_to_array( $data['_lp_target_audiences'] ),
743 771 function ( $item ) {
744 772 return ! is_null( $item ) && $item !== '';
745 773 }
746 774 );
@@ -747,11 +775,10 @@
747 775 $courseModel->meta_data->{CoursePostModel::META_KEY_TARGET} = array_map( 'sanitize_text_field', array_values( $target_audiences ) );
748 776 }
749 777
750 778 if ( isset( $data['_lp_key_features'] ) ) {
751 - $key_features = ! empty( $data['_lp_key_features'] ) ? explode( ',', $data['_lp_key_features'] ) : [];
752 779 $key_features = array_filter(
753 - $key_features,
780 + $this->extra_field_to_array( $data['_lp_key_features'] ),
754 781 function ( $item ) {
755 782 return ! is_null( $item ) && $item !== '';
756 783 }
757 784 );
@@ -759,10 +786,10 @@
759 786 }
760 787
761 788 // FAQs
762 789 if ( isset( $data['_lp_faqs_question'] ) ) {
763 - $questions = ! empty( $data['_lp_faqs_question'] ) ? explode( ',', $data['_lp_faqs_question'] ) : [];
764 - $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'] ) : [];
765 792 $faqs = [];
766 793
767 794 if ( ! empty( $questions ) ) {
768 795 foreach ( $questions as $index => $question ) {
@@ -1083,8 +1110,10 @@
1083 1110
1084 1111 try {
1085 1112 $data = self::check_valid_lesson();
1086 1113 $lesson_id = $data['lesson_id'] ?? 0;
1114 + $has_title = array_key_exists( 'lesson_title', $data );
1115 + $has_content = array_key_exists( 'lesson_description', $data );
1087 1116 $title = LP_Helper::sanitize_params_submitted( $data['lesson_title'] ?? '' );
1088 1117 $description = LP_Helper::sanitize_params_submitted(
1089 1118 $data['lesson_description'] ?? '',
1090 1119 'html'
@@ -1105,9 +1134,9 @@
1105 1134 'key'
1106 1135 );
1107 1136 $restore_with_custom_slug = false;
1108 1137
1109 - if ( empty( $title ) ) {
1138 + if ( ( $insert || $has_title ) && empty( $title ) ) {
1110 1139 throw new Exception( __( 'Lesson title is required', 'learnpress' ) );
1111 1140 }
1112 1141
1113 1142 if ( $insert ) {
@@ -1114,8 +1143,9 @@
1114 1143 $insert_arg = array(
1115 1144 'post_title' => $title,
1116 1145 'post_content' => $description,
1117 1146 'post_status' => $target_status,
1147 + 'post_author' => get_current_user_id(),
1118 1148 );
1119 1149
1120 1150 $lessonPostModelNew = new LessonPostModel( $insert_arg );
1121 1151 $lessonPostModelNew->check_capabilities_create_item_course();
@@ -1150,23 +1180,39 @@
1150 1180 'post_type' => LP_LESSON_CPT,
1151 1181 'post_status' => $target_status,
1152 1182 );*/
1153 1183
1154 - if ( defined( 'ELEMENTOR_VERSION' ) ) {
1184 + if ( defined( 'ELEMENTOR_VERSION' ) && array_key_exists( 'is_elementor', $data ) ) {
1155 1185 \Elementor\Plugin::$instance->documents->get( $lesson_id )->set_is_built_with_elementor( ! empty( $is_elementor ) );
1156 1186 }
1157 1187
1158 - $lesson_model->post_title = $title;
1159 - $lesson_model->post_content = $description;
1160 - $lesson_model->post_status = $target_status;
1188 + $must_save_lesson = false;
1189 + if ( $has_title ) {
1190 + $lesson_model->post_title = $title;
1191 + $must_save_lesson = true;
1192 + }
1193 +
1194 + if ( $has_content ) {
1195 + $lesson_model->post_content = $description;
1196 + $must_save_lesson = true;
1197 + }
1198 +
1199 + if ( ! empty( $target_status ) ) {
1200 + $lesson_model->post_status = $target_status;
1201 + $must_save_lesson = true;
1202 + }
1203 +
1161 1204 if ( ! empty( $lesson_slug ) ) {
1162 1205 $lesson_model->post_name = $lesson_slug;
1206 + $must_save_lesson = true;
1163 1207 }
1164 1208
1165 1209 //$restore_with_custom_slug = $this->prepare_desired_slug_for_restore( $lesson_id, $target_status, $lesson_slug );
1166 1210
1167 1211 //$update = wp_update_post( $update_arg );
1168 - $lesson_model->save();
1212 + if ( $must_save_lesson ) {
1213 + $lesson_model->save();
1214 + }
1169 1215
1170 1216 /*if ( $restore_with_custom_slug ) {
1171 1217 $this->sync_slug_after_restore( $lesson_id, $lesson_slug );
1172 1218 }*/
@@ -1186,9 +1232,9 @@
1186 1232 $this->save_lesson_settings_to_model( $lesson_model, $data );
1187 1233 }
1188 1234
1189 1235 // Remove lesson from curriculum if status is not public
1190 - if ( $target_status !== 'publish' ) {
1236 + if ( ! empty( $target_status ) && $target_status !== 'publish' ) {
1191 1237 $this->remove_course_item_from_curriculum( $lesson_id, $course_id );
1192 1238 }
1193 1239
1194 1240 $response->status = 'success';
@@ -1213,9 +1259,9 @@
1213 1259 $response->data->lesson_permalink = urldecode( $course->get_item_link( $lesson_id ) );
1214 1260 }
1215 1261 }
1216 1262
1217 - $lesson_model_for_html = LessonPostModel::find( $lesson_id, true );
1263 + $lesson_model_for_html = LessonPostModel::find( $lesson_id, false );
1218 1264 if ( $return_html ) {
1219 1265 $response->data->list_item_html = $lesson_model_for_html
1220 1266 ? BuilderListLessonsTemplate::render_lesson( $lesson_model_for_html )
1221 1267 : '';
@@ -1248,9 +1294,9 @@
1248 1294 try {
1249 1295 $data = self::check_valid_lesson();
1250 1296 $lesson_id = $data['lesson_id'] ?? 0;
1251 1297 $status = $data['status'] ?? 'trash';
1252 - $lesson_model = $data['lesson_model'] ?? [];
1298 + $lesson_model = LessonPostModel::find( $lesson_id, false );
1253 1299 $lesson_slug = ! empty( $data['lesson_permalink'] )
1254 1300 ? sanitize_title( wp_unslash( (string) $data['lesson_permalink'] ) )
1255 1301 : '';
1256 1302
@@ -1352,9 +1398,9 @@
1352 1398 }
1353 1399 }
1354 1400
1355 1401 if ( 'delete' !== $status ) {
1356 - $lesson_model_new = LessonPostModel::find( $lesson_id, true );
1402 + $lesson_model_new = LessonPostModel::find( $lesson_id, false );
1357 1403 $response->data->html = $lesson_model_new ? BuilderListLessonsTemplate::render_lesson( $lesson_model_new ) : '';
1358 1404 }
1359 1405
1360 1406 $response->status = 'success';
@@ -1368,10 +1414,13 @@
1368 1414 }
1369 1415
1370 1416 /**
1371 1417 * Save Lesson Settings
1418 + * @throws Exception
1372 1419 */
1373 1420 protected function save_lesson_settings_to_model( LessonPostModel $lessonModel, array $data ) {
1421 + $must_save = 0;
1422 +
1374 1423 if ( isset( $data['_lp_duration'] ) ) {
1375 1424 $duration = ! empty( $data['_lp_duration'] ) ? str_replace( ',', ' ', $data['_lp_duration'] ) : '0 minute';
1376 1425 $explode = explode( ' ', $duration );
1377 1426 $number = (float) $explode[0] < 0 ? 0 : absint( $explode[0] );
@@ -1376,15 +1425,32 @@
1376 1425 $explode = explode( ' ', $duration );
1377 1426 $number = (float) $explode[0] < 0 ? 0 : absint( $explode[0] );
1378 1427 $unit = $explode[1] ?? 'minute';
1379 1428
1380 - $lessonModel->save_meta_value_by_key( '_lp_duration', $number . ' ' . $unit );
1429 + $lessonModel->set_meta_value_by_key( $lessonModel::META_KEY_DURATION, $number . ' ' . $unit );
1430 + $must_save = 1;
1381 1431 }
1382 1432
1383 1433 if ( isset( $data['_lp_preview'] ) ) {
1384 1434 $enable = $data['_lp_preview'] === 'yes';
1385 1435 $lessonModel->set_preview( $enable );
1436 + $must_save = 1;
1386 1437 }
1438 +
1439 + if ( $must_save ) {
1440 + $lessonModel->save();
1441 + }
1442 +
1443 + /**
1444 + * Allow addons to persist their own lesson settings fields added to the
1445 + * settings metabox tabs when saving from Course Builder.
1446 + *
1447 + * @param LessonPostModel $lessonModel Lesson model being saved.
1448 + * @param array $data Submitted settings data.
1449 + *
1450 + * @since 4.3.8
1451 + */
1452 + do_action( 'learn-press/course-builder/save-lesson-settings', $lessonModel, $data );
1387 1453 }
1388 1454
1389 1455 /**
1390 1456 * Save Quiz Settings to QuizPostModel
@@ -1436,8 +1502,19 @@
1436 1502 }
1437 1503 $quizModel->save_meta_value_by_key( $key, $value );
1438 1504 }
1439 1505 }
1506 +
1507 + /**
1508 + * Allow addons to persist their own quiz settings fields added to the
1509 + * settings metabox tabs when saving from Course Builder.
1510 + *
1511 + * @param QuizPostModel $quizModel Quiz model being saved.
1512 + * @param array $data Submitted settings data.
1513 + *
1514 + * @since 4.3.8
1515 + */
1516 + do_action( 'learn-press/course-builder/save-quiz-settings', $quizModel, $data );
1440 1517 }
1441 1518
1442 1519 /**
1443 1520 * Update Quiz from Course Builder.
@@ -1482,8 +1559,9 @@
1482 1559 $insert_arg = array(
1483 1560 'post_title' => $title,
1484 1561 'post_content' => $description,
1485 1562 'post_status' => $target_status,
1563 + 'post_author' => get_current_user_id(),
1486 1564 );
1487 1565
1488 1566 $quizPostModelNew = new QuizPostModel( $insert_arg );
1489 1567 $quizPostModelNew->check_capabilities_create_item_course();
@@ -1633,9 +1711,9 @@
1633 1711 try {
1634 1712 $data = self::check_valid_quiz();
1635 1713 $quiz_id = $data['quiz_id'] ?? 0;
1636 1714 $status = $data['status'] ?? 'trash';
1637 - $quiz_model = $data['quiz_model'] ?? [];
1715 + $quiz_model = QuizPostModel::find( $quiz_id, false );
1638 1716 $quiz_slug = ! empty( $data['quiz_permalink'] )
1639 1717 ? sanitize_title( wp_unslash( (string) $data['quiz_permalink'] ) )
1640 1718 : '';
1641 1719
@@ -1737,9 +1815,9 @@
1737 1815 }
1738 1816 }
1739 1817
1740 1818 if ( 'delete' !== $status ) {
1741 - $fresh_quiz_model = QuizPostModel::find( $quiz_id, true );
1819 + $fresh_quiz_model = QuizPostModel::find( $quiz_id, false );
1742 1820 $response->data->html = $fresh_quiz_model
1743 1821 ? BuilderListQuizzesTemplate::render_quiz( $fresh_quiz_model )
1744 1822 : '';
1745 1823 }
@@ -1823,8 +1901,9 @@
1823 1901 $insert_arg = array(
1824 1902 'post_title' => $title,
1825 1903 'post_content' => $description,
1826 1904 'post_status' => $target_status,
1905 + 'post_author' => get_current_user_id(),
1827 1906 );
1828 1907
1829 1908 $questionPostModelNew = new QuestionPostModel( $insert_arg );
1830 1909 $questionPostModelNew->check_capabilities_create_item_course();
@@ -1903,9 +1982,9 @@
1903 1982 try {
1904 1983 $data = self::check_valid_question();
1905 1984 $question_id = $data['question_id'] ?? 0;
1906 1985 $status = $data['status'] ?? 'trash';
1907 - $question_model = $data['question_model'] ?? [];
1986 + $question_model = QuestionPostModel::find( $question_id, false );
1908 1987
1909 1988 if ( ! $question_model ) {
1910 1989 throw new Exception( __( 'Question not found', 'learnpress' ) );
1911 1990 }
@@ -1969,9 +2048,9 @@
1969 2048 $response->data->status = $status;
1970 2049 $response->data->button_title = __( 'Publish', 'learnpress' );
1971 2050
1972 2051 if ( 'delete' !== $status ) {
1973 - $fresh_question_model = QuestionPostModel::find( $question_id, true );
2052 + $fresh_question_model = QuestionPostModel::find( $question_id, false );
1974 2053 $response->data->html = $fresh_question_model
1975 2054 ? BuilderListQuestionsTemplate::render_question( $fresh_question_model )
1976 2055 : '';
1977 2056 }