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/EditQuestionAjax.php +312 -311 4.3.9 → 4.4.9 View file →
@@ -1,311 +1,312 @@
1 -<?php
2 -/**
3 - * class EditCurriculumAjax
4 - *
5 - * This class handles the AJAX request to edit the curriculum of a course.
6 - *
7 - * @since 4.2.9
8 - * @version 1.0.0
9 - */
10 -
11 -namespace LearnPress\Ajax;
12 -
13 -use Exception;
14 -use LearnPress\Ajax\AbstractAjax;
15 -
16 -use LearnPress\Databases\QuestionAnswersDB;
17 -use LearnPress\Models\Question\QuestionAnswerModel;
18 -use LearnPress\Models\Question\QuestionPostFIBModel;
19 -use LearnPress\Models\Question\QuestionPostModel;
20 -use LearnPress\Models\Question\QuestionPostMultipleChoiceModel;
21 -use LearnPress\Models\Question\QuestionPostSingleChoiceModel;
22 -use LearnPress\Models\Question\QuestionSortingChoiceModel;
23 -use LearnPress\TemplateHooks\Admin\AdminEditQuestionTemplate;
24 -use LP_Helper;
25 -use LP_REST_Response;
26 -use Throwable;
27 -
28 -class EditQuestionAjax extends AbstractAjax {
29 - /**
30 - * Check permissions and validate parameters.
31 - *
32 - * @throws Exception
33 - *
34 - * @since 4.2.9
35 - * @version 1.0.0
36 - */
37 - public static function check_valid() {
38 - $params = wp_unslash( $_REQUEST['data'] ?? '' );
39 - if ( empty( $params ) ) {
40 - throw new Exception( 'Error: params invalid!' );
41 - }
42 -
43 - $params = LP_Helper::json_decode( $params, true );
44 - $question_id = $params['question_id'] ?? 0;
45 - $questionPostModel = QuestionPostModel::find( $question_id, true );
46 - if ( ! $questionPostModel ) {
47 - throw new Exception( __( 'Question not found', 'learnpress' ) );
48 - }
49 -
50 - $params['questionPostModel'] = $questionPostModel;
51 -
52 - return $params;
53 - }
54 -
55 - /**
56 - * Update question title.
57 - *
58 - * JS file edit-quiz.js: function updateQuestionTitle call this method.
59 - *
60 - */
61 - public static function update_question() {
62 - $response = new LP_REST_Response();
63 -
64 - try {
65 - $data = self::check_valid();
66 - $question_id = $data['question_id'] ?? 0;
67 - $question_title = $data['question_title'] ?? false;
68 - $question_description = $data['question_description'] ?? false;
69 - $question_hint = $data['question_hint'] ?? false;
70 - $question_explanation = $data['question_explanation'] ?? false;
71 - $question_mark = $data['question_mark'] ?? false;
72 - $question_type = $data['question_type'] ?? false;
73 -
74 - $questionPostModel = QuestionPostModel::find( $question_id, true );
75 - if ( ! $questionPostModel ) {
76 - throw new Exception( __( 'Question not found', 'learnpress' ) );
77 - }
78 -
79 - if ( false !== $question_title ) {
80 - if ( empty( $question_title ) ) {
81 - throw new Exception( __( 'Question title is required', 'learnpress' ) );
82 - }
83 -
84 - $questionPostModel->post_title = $question_title;
85 - }
86 -
87 - if ( false !== $question_description ) {
88 - $questionPostModel->post_content = $question_description;
89 - }
90 -
91 - if ( false !== $question_hint ) {
92 - $questionPostModel->save_meta_value_by_key( QuestionPostModel::META_KEY_HINT, $question_hint );
93 - }
94 -
95 - if ( false !== $question_explanation ) {
96 - $questionPostModel->save_meta_value_by_key( QuestionPostModel::META_KEY_EXPLANATION, $question_explanation );
97 - }
98 -
99 - if ( false !== $question_mark ) {
100 - $questionPostModel->save_meta_value_by_key( QuestionPostModel::META_KEY_MARK, $question_mark );
101 - }
102 -
103 - if ( false !== $question_type ) {
104 - if ( ! in_array( $question_type, array_keys( QuestionPostModel::get_types() ), true ) ) {
105 - throw new Exception( __( 'Invalid question type', 'learnpress' ) );
106 - }
107 -
108 - $questionPostModel->save_meta_value_by_key( QuestionPostModel::META_KEY_TYPE, $question_type );
109 -
110 - // Create default answers for question
111 - $questionClassName = $questionPostModel::get_question_obj_by_type( $question_type );
112 - if ( class_exists( $questionClassName ) ) {
113 - $questionPostTyeModel = new $questionClassName( $questionPostModel );
114 - if ( method_exists( $questionPostTyeModel, 'create_default_answers' ) ) {
115 - $questionPostTyeModel->create_default_answers();
116 - }
117 - } else {
118 - throw new Exception( __( 'Question type not found', 'learnpress' ) );
119 - }
120 -
121 - $response->data->html_option_answers = AdminEditQuestionTemplate::instance()->html_answer_option(
122 - $questionPostModel
123 - );
124 - }
125 -
126 - $questionPostModel->save();
127 - $response->status = 'success';
128 - $response->message = __( 'Question update successfully', 'learnpress' );
129 - } catch ( Throwable $e ) {
130 - $response->message = $e->getMessage();
131 - }
132 -
133 - wp_send_json( $response );
134 - }
135 -
136 - /**
137 - * Update answer config of question
138 - *
139 - * JS file edit-quiz.js: function addQuestionAnswer call this method.
140 - *
141 - * @return void
142 - */
143 - public static function add_question_answer() {
144 - $response = new LP_REST_Response();
145 -
146 - try {
147 - $data = self::check_valid();
148 - $answer_title = $data['answer_title'] ?? '';
149 - if ( empty( $answer_title ) ) {
150 - throw new Exception( __( 'Answer title is required', 'learnpress' ) );
151 - }
152 -
153 - /**
154 - * @var QuestionPostModel $questionPostModel
155 - */
156 - $questionPostModel = $data['questionPostModel'];
157 - $type = $questionPostModel->get_type();
158 -
159 - if ( $type === 'single_choice' ) {
160 - $questionAnswerModel = new QuestionPostSingleChoiceModel( $questionPostModel );
161 - } elseif ( $type === 'multiple_choice' ) {
162 - $questionAnswerModel = new QuestionPostMultipleChoiceModel( $questionPostModel );
163 - } else {
164 -
165 - }
166 -
167 - $db = QuestionAnswersDB::getInstance();
168 - $max_order = $db->get_last_number_order( $questionPostModel->get_id() );
169 -
170 - $answer = array(
171 - 'question_id' => $questionPostModel->get_id(),
172 - 'title' => $answer_title,
173 - 'value' => learn_press_random_value(),
174 - 'is_true' => $answer['is_true'] ?? '',
175 - 'order' => $max_order + 1,
176 - );
177 -
178 - $questionAnswerModel = new QuestionAnswerModel( $answer );
179 - $questionAnswerModel->save();
180 -
181 - $response->status = 'success';
182 - $response->data->question_answer = $questionAnswerModel;
183 - $response->message = __( 'Question answer added successfully', 'learnpress' );
184 - } catch ( Throwable $e ) {
185 - $response->message = $e->getMessage();
186 - }
187 -
188 - wp_send_json( $response );
189 - }
190 -
191 - /**
192 - * Update answer config of question
193 - *
194 - * JS file edit-question.js: function fibSaveContent call this method.
195 - *
196 - * @return void
197 - */
198 - public function update_question_answers_config() {
199 - $response = new LP_REST_Response();
200 -
201 - try {
202 - $data = self::check_valid();
203 - $question_id = $data['question_id'] ?? 0;
204 - $question_answers = $data['answers'] ?? [];
205 - $question_answers = LP_Helper::sanitize_params_submitted( $question_answers, 'html', false );
206 -
207 - $questionPostModel = QuestionPostModel::find( $question_id, true );
208 - if ( ! $questionPostModel ) {
209 - throw new Exception( __( 'Question not found', 'learnpress' ) );
210 - }
211 -
212 - if ( $questionPostModel->get_type() === 'fill_in_blanks' ) {
213 - $questionPostFIBModel = new QuestionPostFIBModel( $questionPostModel );
214 - // Update title
215 - $questionAnswerModel = new QuestionAnswerModel( $question_answers );
216 - $content = $question_answers['title'] ?? '';
217 - $meta_data = $question_answers['meta_data'] ?? [];
218 - $questionAnswerModel->title = $questionPostFIBModel->convert_content_from_editor_to_db( $content );
219 - $questionAnswerModel->save();
220 - // Update meta value for fill in blanks
221 - $pattern = '#<span class="lp-question-fib-input" data-id="([^"]+)">([^<]+)<\/span>#';
222 - preg_match_all( $pattern, $content, $matches );
223 - $ids = [];
224 -
225 - $fib_blank_options = [];
226 - if ( ! empty( $matches ) ) {
227 - $ids = $matches[1];
228 - $fills = $matches[2];
229 -
230 - foreach ( $ids as $index => $id ) {
231 - $fib_blank_options[ $id ] = [
232 - 'id' => $id,
233 - 'fill' => html_entity_decode( $fills[ $index ] ?? '' ),
234 - 'match_case' => 0,
235 - 'comparison' => 'equal',
236 - ];
237 - }
238 - }
239 -
240 - if ( ! empty( $meta_data ) ) {
241 - foreach ( $meta_data as $blank_id => $blank_options ) {
242 - if ( $meta_data[ $blank_id ]['comparison'] === '' ) {
243 - $meta_data[ $blank_id ]['comparison'] = 'equal';
244 - }
245 -
246 - if ( ! in_array( $blank_id, $ids, true ) ) {
247 - unset( $meta_data[ $blank_id ] );
248 - }
249 - }
250 - }
251 -
252 - // If not null ids, but meta_data is empty, we will set default options for blanks.
253 - if ( ! empty( $ids ) && empty( $meta_data ) ) {
254 - $meta_data = $fib_blank_options;
255 - }
256 -
257 - $questionAnswerModel->save_meta_value_by_key( QuestionAnswerModel::META_KEY_BLANKS, $meta_data );
258 - } else {
259 - foreach ( $question_answers as $answer ) {
260 - if ( empty( $answer ) ) {
261 - continue;
262 - }
263 -
264 - $questionAnswerModel = new QuestionAnswerModel( $answer );
265 - $questionAnswerModel->save();
266 - }
267 - }
268 -
269 - $response->status = 'success';
270 - $response->message = __( 'Answer of Question update successfully', 'learnpress' );
271 - } catch ( Throwable $e ) {
272 - $response->message = $e->getMessage();
273 - }
274 -
275 - wp_send_json( $response );
276 - }
277 -
278 - /**
279 - * Delete answer of question
280 - *
281 - * JS file edit-quiz.js: function deleteQuestionAnswer call this method.
282 - *
283 - * @return void
284 - */
285 - public static function delete_question_answer() {
286 - $response = new LP_REST_Response();
287 -
288 - try {
289 - $data = self::check_valid();
290 - $question_answer_id = $data['question_answer_id'] ?? '';
291 - if ( empty( $question_answer_id ) ) {
292 - throw new Exception( __( 'Invalid request!', 'learnpress' ) );
293 - }
294 -
295 - $questionAnswerModel = QuestionAnswerModel::find( $question_answer_id, true );
296 - if ( ! $questionAnswerModel ) {
297 - throw new Exception( __( 'Question answer not found', 'learnpress' ) );
298 - }
299 -
300 - // Delete question answer
301 - $questionAnswerModel->delete();
302 -
303 - $response->status = 'success';
304 - $response->message = __( 'Question answer deleted successfully', 'learnpress' );
305 - } catch ( Throwable $e ) {
306 - $response->message = $e->getMessage();
307 - }
308 -
309 - wp_send_json( $response );
310 - }
311 -}
1 +<?php
2 +/**
3 + * class EditCurriculumAjax
4 + *
5 + * This class handles the AJAX request to edit the curriculum of a course.
6 + *
7 + * @since 4.2.9
8 + * @version 1.0.0
9 + */
10 +
11 +namespace LearnPress\Ajax;
12 +
13 +use Exception;
14 +use LearnPress\Ajax\AbstractAjax;
15 +
16 +use LearnPress\Databases\QuestionAnswersDB;
17 +use LearnPress\Helpers\Template;
18 +use LearnPress\Models\Question\QuestionAnswerModel;
19 +use LearnPress\Models\Question\QuestionPostFIBModel;
20 +use LearnPress\Models\Question\QuestionPostModel;
21 +use LearnPress\Models\Question\QuestionPostMultipleChoiceModel;
22 +use LearnPress\Models\Question\QuestionPostSingleChoiceModel;
23 +use LearnPress\Models\Question\QuestionSortingChoiceModel;
24 +use LearnPress\TemplateHooks\Admin\AdminEditQuestionTemplate;
25 +use LP_Helper;
26 +use LP_REST_Response;
27 +use Throwable;
28 +
29 +class EditQuestionAjax extends AbstractAjax {
30 + /**
31 + * Check permissions and validate parameters.
32 + *
33 + * @throws Exception
34 + *
35 + * @since 4.2.9
36 + * @version 1.0.0
37 + */
38 + public static function check_valid() {
39 + $params = wp_unslash( $_REQUEST['data'] ?? '' );
40 + if ( empty( $params ) ) {
41 + throw new Exception( 'Error: params invalid!' );
42 + }
43 +
44 + $params = LP_Helper::json_decode( $params, true );
45 + $question_id = $params['question_id'] ?? 0;
46 + $questionPostModel = QuestionPostModel::find( $question_id, true );
47 + if ( ! $questionPostModel ) {
48 + throw new Exception( __( 'Question not found', 'learnpress' ) );
49 + }
50 +
51 + $params['questionPostModel'] = $questionPostModel;
52 +
53 + return $params;
54 + }
55 +
56 + /**
57 + * Update question title.
58 + *
59 + * JS file edit-quiz.js: function updateQuestionTitle call this method.
60 + *
61 + */
62 + public static function update_question() {
63 + $response = new LP_REST_Response();
64 +
65 + try {
66 + $data = self::check_valid();
67 + $question_id = $data['question_id'] ?? 0;
68 + $question_title = $data['question_title'] ?? false;
69 + $question_description = $data['question_description'] ?? false;
70 + $question_hint = $data['question_hint'] ?? false;
71 + $question_explanation = $data['question_explanation'] ?? false;
72 + $question_mark = $data['question_mark'] ?? false;
73 + $question_type = $data['question_type'] ?? false;
74 +
75 + $questionPostModel = QuestionPostModel::find( $question_id, true );
76 + if ( ! $questionPostModel ) {
77 + throw new Exception( __( 'Question not found', 'learnpress' ) );
78 + }
79 +
80 + if ( false !== $question_title ) {
81 + if ( empty( $question_title ) ) {
82 + throw new Exception( __( 'Question title is required', 'learnpress' ) );
83 + }
84 +
85 + $questionPostModel->post_title = $question_title;
86 + }
87 +
88 + if ( false !== $question_description ) {
89 + $questionPostModel->post_content = $question_description;
90 + }
91 +
92 + if ( false !== $question_hint ) {
93 + $questionPostModel->save_meta_value_by_key( QuestionPostModel::META_KEY_HINT, $question_hint );
94 + }
95 +
96 + if ( false !== $question_explanation ) {
97 + $questionPostModel->save_meta_value_by_key( QuestionPostModel::META_KEY_EXPLANATION, $question_explanation );
98 + }
99 +
100 + if ( false !== $question_mark ) {
101 + $questionPostModel->save_meta_value_by_key( QuestionPostModel::META_KEY_MARK, $question_mark );
102 + }
103 +
104 + if ( false !== $question_type ) {
105 + if ( ! in_array( $question_type, array_keys( QuestionPostModel::get_types() ), true ) ) {
106 + throw new Exception( __( 'Invalid question type', 'learnpress' ) );
107 + }
108 +
109 + $questionPostModel->save_meta_value_by_key( QuestionPostModel::META_KEY_TYPE, $question_type );
110 +
111 + // Create default answers for question
112 + $questionClassName = $questionPostModel::get_question_obj_by_type( $question_type );
113 + if ( class_exists( $questionClassName ) ) {
114 + $questionPostTyeModel = new $questionClassName( $questionPostModel );
115 + if ( method_exists( $questionPostTyeModel, 'create_default_answers' ) ) {
116 + $questionPostTyeModel->create_default_answers();
117 + }
118 + } else {
119 + throw new Exception( __( 'Question type not found', 'learnpress' ) );
120 + }
121 +
122 + $response->data->html_option_answers = AdminEditQuestionTemplate::instance()->html_answer_option(
123 + $questionPostModel
124 + );
125 + }
126 +
127 + $questionPostModel->save();
128 + $response->status = 'success';
129 + $response->message = __( 'Question update successfully', 'learnpress' );
130 + } catch ( Throwable $e ) {
131 + $response->message = $e->getMessage();
132 + }
133 +
134 + wp_send_json( $response );
135 + }
136 +
137 + /**
138 + * Update answer config of question
139 + *
140 + * JS file edit-quiz.js: function addQuestionAnswer call this method.
141 + *
142 + * @return void
143 + */
144 + public static function add_question_answer() {
145 + $response = new LP_REST_Response();
146 +
147 + try {
148 + $data = self::check_valid();
149 + $answer_title = Template::sanitize_html_content( $data['answer_title'] ?? '' );
150 + if ( empty( $answer_title ) ) {
151 + throw new Exception( __( 'Answer title is required', 'learnpress' ) );
152 + }
153 +
154 + /**
155 + * @var QuestionPostModel $questionPostModel
156 + */
157 + $questionPostModel = $data['questionPostModel'];
158 + $type = $questionPostModel->get_type();
159 +
160 + if ( $type === 'single_choice' ) {
161 + $questionAnswerModel = new QuestionPostSingleChoiceModel( $questionPostModel );
162 + } elseif ( $type === 'multiple_choice' ) {
163 + $questionAnswerModel = new QuestionPostMultipleChoiceModel( $questionPostModel );
164 + } else {
165 +
166 + }
167 +
168 + $db = QuestionAnswersDB::getInstance();
169 + $max_order = $db->get_last_number_order( $questionPostModel->get_id() );
170 +
171 + $answer = array(
172 + 'question_id' => $questionPostModel->get_id(),
173 + 'title' => $answer_title,
174 + 'value' => learn_press_random_value(),
175 + 'is_true' => $answer['is_true'] ?? '',
176 + 'order' => $max_order + 1,
177 + );
178 +
179 + $questionAnswerModel = new QuestionAnswerModel( $answer );
180 + $questionAnswerModel->save();
181 +
182 + $response->status = 'success';
183 + $response->data->question_answer = $questionAnswerModel;
184 + $response->message = __( 'Question answer added successfully', 'learnpress' );
185 + } catch ( Throwable $e ) {
186 + $response->message = $e->getMessage();
187 + }
188 +
189 + wp_send_json( $response );
190 + }
191 +
192 + /**
193 + * Update answer config of question
194 + *
195 + * JS file edit-question.js: function fibSaveContent call this method.
196 + *
197 + * @return void
198 + */
199 + public function update_question_answers_config() {
200 + $response = new LP_REST_Response();
201 +
202 + try {
203 + $data = self::check_valid();
204 + $question_id = $data['question_id'] ?? 0;
205 + $question_answers = $data['answers'] ?? [];
206 + $question_answers = LP_Helper::sanitize_params_submitted( $question_answers, 'html', false );
207 +
208 + $questionPostModel = QuestionPostModel::find( $question_id, true );
209 + if ( ! $questionPostModel ) {
210 + throw new Exception( __( 'Question not found', 'learnpress' ) );
211 + }
212 +
213 + if ( $questionPostModel->get_type() === 'fill_in_blanks' ) {
214 + $questionPostFIBModel = new QuestionPostFIBModel( $questionPostModel );
215 + // Update title
216 + $questionAnswerModel = new QuestionAnswerModel( $question_answers );
217 + $content = $question_answers['title'] ?? '';
218 + $meta_data = $question_answers['meta_data'] ?? [];
219 + $questionAnswerModel->title = $questionPostFIBModel->convert_content_from_editor_to_db( $content );
220 + $questionAnswerModel->save();
221 + // Update meta value for fill in blanks
222 + $pattern = '#<span class="lp-question-fib-input" data-id="([^"]+)">([^<]+)<\/span>#';
223 + preg_match_all( $pattern, $content, $matches );
224 + $ids = [];
225 +
226 + $fib_blank_options = [];
227 + if ( ! empty( $matches ) ) {
228 + $ids = $matches[1];
229 + $fills = $matches[2];
230 +
231 + foreach ( $ids as $index => $id ) {
232 + $fib_blank_options[ $id ] = [
233 + 'id' => $id,
234 + 'fill' => html_entity_decode( $fills[ $index ] ?? '' ),
235 + 'match_case' => 0,
236 + 'comparison' => 'equal',
237 + ];
238 + }
239 + }
240 +
241 + if ( ! empty( $meta_data ) ) {
242 + foreach ( $meta_data as $blank_id => $blank_options ) {
243 + if ( $meta_data[ $blank_id ]['comparison'] === '' ) {
244 + $meta_data[ $blank_id ]['comparison'] = 'equal';
245 + }
246 +
247 + if ( ! in_array( $blank_id, $ids, true ) ) {
248 + unset( $meta_data[ $blank_id ] );
249 + }
250 + }
251 + }
252 +
253 + // If not null ids, but meta_data is empty, we will set default options for blanks.
254 + if ( ! empty( $ids ) && empty( $meta_data ) ) {
255 + $meta_data = $fib_blank_options;
256 + }
257 +
258 + $questionAnswerModel->save_meta_value_by_key( QuestionAnswerModel::META_KEY_BLANKS, $meta_data );
259 + } else {
260 + foreach ( $question_answers as $answer ) {
261 + if ( empty( $answer ) ) {
262 + continue;
263 + }
264 +
265 + $questionAnswerModel = new QuestionAnswerModel( $answer );
266 + $questionAnswerModel->save();
267 + }
268 + }
269 +
270 + $response->status = 'success';
271 + $response->message = __( 'Answer of Question update successfully', 'learnpress' );
272 + } catch ( Throwable $e ) {
273 + $response->message = $e->getMessage();
274 + }
275 +
276 + wp_send_json( $response );
277 + }
278 +
279 + /**
280 + * Delete answer of question
281 + *
282 + * JS file edit-quiz.js: function deleteQuestionAnswer call this method.
283 + *
284 + * @return void
285 + */
286 + public static function delete_question_answer() {
287 + $response = new LP_REST_Response();
288 +
289 + try {
290 + $data = self::check_valid();
291 + $question_answer_id = $data['question_answer_id'] ?? '';
292 + if ( empty( $question_answer_id ) ) {
293 + throw new Exception( __( 'Invalid request!', 'learnpress' ) );
294 + }
295 +
296 + $questionAnswerModel = QuestionAnswerModel::find( $question_answer_id, true );
297 + if ( ! $questionAnswerModel ) {
298 + throw new Exception( __( 'Question answer not found', 'learnpress' ) );
299 + }
300 +
301 + // Delete question answer
302 + $questionAnswerModel->delete();
303 +
304 + $response->status = 'success';
305 + $response->message = __( 'Question answer deleted successfully', 'learnpress' );
306 + } catch ( Throwable $e ) {
307 + $response->message = $e->getMessage();
308 + }
309 +
310 + wp_send_json( $response );
311 + }
312 +}