PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.4.8
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.4.8
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.8, at inc/Ajax/EditQuestionAjax.php

313 lines 9.6 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\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 }
313