PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.4.2
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.4.2
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 4.2.0 All 139 releases
learnpress / inc / Ajax / EditQuestionAjax.php

EditQuestionAjax.php in LearnPress – WordPress LMS Plugin for Create and Sell Online Courses 4.4.2, at inc/Ajax/EditQuestionAjax.php

312 lines 9.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
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 }
312