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/rest-api/v1/frontend/class-lp-rest-users-controller.php +123 -83 4.1.7.3.1 → 4.4.9 View file →
@@ -1,6 +1,11 @@
1 1 <?php
2 2
3 +use LearnPress\Models\CourseModel;
4 +use LearnPress\Models\Question\QuestionPostModel;
5 +use LearnPress\Models\Quiz\QuizQuestionModel;
6 +use LearnPress\Models\UserItems\UserQuizModel;
7 +
3 8 /**
4 9 * Class LP_REST_Users_Controller
5 10 *
6 11 * @since 3.3.0
@@ -53,24 +58,13 @@
53 58 ),
54 59 'submit-quiz' => array(
55 60 array(
56 61 'methods' => WP_REST_Server::EDITABLE,
57 - // 'callback' => array( $this, 'submit_quiz' ),
58 - 'callback' => array( $this, 'submit_quiz_new' ),
59 - // 'permission_callback' => array( $this, 'check_admin_permission' ),
62 + 'callback' => array( $this, 'submit_quiz' ),
60 63 'permission_callback' => '__return_true',
61 64 'args' => $this->get_item_endpoint_args(),
62 65 ),
63 66 ),
64 - 'hint-answer' => array(
65 - array(
66 - 'methods' => WP_REST_Server::EDITABLE,
67 - 'callback' => array( $this, 'hint_answer' ),
68 - // 'permission_callback' => array( $this, 'check_admin_permission' ),
69 - 'permission_callback' => '__return_true',
70 - 'args' => $this->get_item_endpoint_args(),
71 - ),
72 - ),
73 67 'check-answer' => array(
74 68 array(
75 69 'methods' => WP_REST_Server::EDITABLE,
76 70 'callback' => array( $this, 'check_answer' ),
@@ -134,9 +128,9 @@
134 128 *
135 129 * @param WP_REST_Request $request
136 130 *
137 131 * @editor tungnx
138 - * @version 1.0.1
132 + * @version 1.0.4
139 133 * @sicne 4.0.0
140 134 * @return WP_REST_Response
141 135 */
142 136 public function start_quiz( WP_REST_Request $request ): WP_REST_Response {
@@ -157,46 +151,62 @@
157 151 $user = learn_press_get_user( $user_id );
158 152 $course = learn_press_get_course( $course_id );
159 153 $quiz = learn_press_get_quiz( $item_id );
160 154
161 - if ( ! $course ) {
162 - throw new Exception( __( 'The course is invalid!', 'learnpress' ) );
155 + $courseModel = CourseModel::find( $course_id, true );
156 + if ( ! $courseModel ) {
157 + throw new Exception( esc_html__( 'The course is invalid', 'learnpress' ) );
163 158 }
164 159
165 - if ( ! $quiz ) {
166 - throw new Exception( __( 'The quiz is invalid!', 'learnpress' ) );
160 + $quizPostModel = $courseModel->get_item_model( $item_id, LP_QUIZ_CPT );
161 + if ( ! $quizPostModel ) {
162 + throw new Exception( esc_html__( 'The quiz is invalid', 'learnpress' ) );
167 163 }
168 164
165 + $quiz->set_course( $course );
166 +
169 167 do_action( 'learn-press/user/before/start-quiz', $item_id, $course_id, $user_id );
170 168
171 - // For no required enroll course
169 + $link = LP_Helper::get_link_no_cache( $courseModel->get_item_link( $item_id, LP_QUIZ_CPT ) );
170 +
171 + // For no required enroll course (no need login)
172 172 if ( $user->is_guest() && $course->is_no_required_enroll() ) {
173 - if ( $quiz->get_retake_count() >= 0 ) {
174 - //learn_press_remove_cookie( 'quiz_submit_status_' . $course_id . '_' . $item_id . '' );
175 - }
176 - $no_required_enroll = new LP_Course_No_Required_Enroll( $course );
177 - $response = $no_required_enroll->guest_start_quiz( $quiz );
173 + $no_required_enroll = new LP_Course_No_Required_Enroll( $course );
174 + $response = $no_required_enroll->guest_start_quiz( $quiz );
175 + $response['redirect_url'] = $link;
178 176
179 177 return rest_ensure_response( $response );
180 178 }
181 179
182 - // Require enroll course
183 - if ( $user->has_started_quiz( $item_id, $course_id ) ) {
184 - /**
185 - * @var LP_User_Item_Quiz $user_quiz
186 - */
187 - $user_quiz = $user->retake_quiz( $item_id, $course_id, true );
188 - $results['answered'] = []; // Reset answered before on js
189 - } else {
190 - /**
191 - * @var LP_User_Item_Quiz $user_quiz
192 - */
193 - $user_quiz = $user->start_quiz( $item_id, $course_id, true );
180 + /**
181 + * Require enroll course
182 + *
183 + * @var UserQuizModel $user_quiz
184 + */
185 + $retaken_count = 0;
186 + $attempts = [];
187 + $filter_user_quiz = new LP_User_Items_Filter();
188 + $filter_user_quiz->user_id = $user_id;
189 + $filter_user_quiz->item_id = $item_id;
190 + $filter_user_quiz->ref_id = $course_id;
191 + $user_quiz_exists = UserQuizModel::get_user_item_model_from_db( $filter_user_quiz );
192 + if ( $user_quiz_exists instanceof UserQuizModel
193 + && $user_quiz_exists->status === LP_ITEM_COMPLETED ) {
194 + $user_quiz = $user_quiz_exists;
195 + $user_quiz->retake();
196 + $results['answered'] = []; // Reset answered for js
197 + $retaken_count = $user_quiz->get_retaken_count();
198 + $attempts = $user_quiz->get_attempts();
199 + } else { // Create new user quiz and insert to database.
200 + $user_quiz_new = new UserQuizModel();
201 + $user_quiz_new->user_id = $user_id;
202 + $user_quiz_new->item_id = $item_id;
203 + $user_quiz_new->ref_id = $course_id;
204 + $user_quiz_new->start_quiz();
205 + $user_quiz = $user_quiz_new;
194 206 }
195 207
196 - if ( is_wp_error( $user_quiz ) ) {
197 - throw new Exception( $user_quiz->get_error_message() );
198 - }
208 + $user_item_id = $user_quiz->get_user_item_id();
199 209
200 210 /**
201 211 * Clear cache result quiz
202 212 * Cache set on @see LP_User_Item_Quiz::get_results
@@ -205,41 +215,38 @@
205 215 $key_cache = sprintf( '%d/user/%d/course/%d', $item_id, $user_id, $course_id );
206 216 $lp_quiz_cache->clear( $key_cache );
207 217 // End
208 218
209 - $quiz->set_course( $course );
210 -
211 219 $show_check = $quiz->get_instant_check();
212 220 $duration = $quiz->get_duration();
213 221 $show_correct_review = $quiz->get_show_correct_review();
214 222 $question_ids = $quiz->get_question_ids();
215 223 $status = $user_quiz->get_status();
216 - $checked_questions = $user_quiz->get_checked_questions();
217 - $hinted_questions = $user_quiz->get_hint_questions();
218 - $time_remaining = $user_quiz->get_timestamp_remaining();
224 + $time_remaining = $user_quiz->get_time_remaining();
219 225
220 226 $questions = learn_press_rest_prepare_user_questions(
221 227 $question_ids,
222 228 array(
223 229 'instant_check' => $show_check,
224 - 'quiz_status' => $status,
225 - 'checked_questions' => $checked_questions,
226 - 'hinted_questions' => $hinted_questions,
230 + //'quiz_status' => $status,
231 + //'checked_questions' => $checked_questions,
232 + //'hinted_questions' => $hinted_questions,
227 233 'answered' => [],
228 234 'show_correct_review' => $show_correct_review,
229 235 )
230 236 );
231 237
232 - $results['question_ids'] = $question_ids;
233 - $results['questions'] = $questions;
234 - $results['total_time'] = $time_remaining;
235 - $results['duration'] = $duration ? $duration->get() : false;
236 - $results['status'] = $status; // Must be started
237 - $results['retaken'] = absint( $user_quiz->get_retaken_count() );
238 - $results['attempts'] = $user_quiz->get_attempts();
239 - $results['user_item_id'] = $user_quiz->get_user_item_id();
240 - $response['status'] = 'success';
241 - $response['results'] = $results;
238 + $results['question_ids'] = $question_ids;
239 + $results['questions'] = $questions;
240 + $results['total_time'] = $time_remaining;
241 + $results['duration'] = $duration ? $duration->get() : false;
242 + $results['status'] = $status; // Must be started
243 + $results['retaken'] = $retaken_count;
244 + $results['attempts'] = $attempts;
245 + $results['user_item_id'] = $user_item_id;
246 + $response['status'] = 'success';
247 + $response['results'] = $results;
248 + $response['redirect_url'] = $link;
242 249 } catch ( Throwable $e ) {
243 250 $response['message'] = $e->getMessage();
244 251 }
245 252
@@ -253,11 +260,11 @@
253 260 *
254 261 * @return WP_Error|WP_HTTP_Response|WP_REST_Response
255 262 * @editor tungnx
256 263 * @modify 4.1.4.1
257 - * @version 1.0.2
264 + * @version 1.0.3
258 265 */
259 - public function submit_quiz_new( WP_REST_Request $request ) {
266 + public function submit_quiz( WP_REST_Request $request ) {
260 267 //$response = new LP_REST_Response();
261 268 $response = array(
262 269 'status' => 'error',
263 270 'message' => '',
@@ -271,19 +278,26 @@
271 278 $time_spend = $request['time_spend'] ?? 0;
272 279 $user = learn_press_get_user( $user_id );
273 280 $course = learn_press_get_course( $course_id );
274 281
275 - if ( ! $course ) {
276 - throw new Exception( 'The course is invalid!' );
282 + $courseModel = CourseModel::find( $course_id, true );
283 + if ( ! $courseModel ) {
284 + throw new Exception( esc_html__( 'The course is invalid', 'learnpress' ) );
277 285 }
286 +
287 + $quizPostModel = $courseModel->get_item_model( $item_id, LP_QUIZ_CPT );
288 + if ( ! $quizPostModel ) {
289 + throw new Exception( esc_html__( 'The quiz is invalid', 'learnpress' ) );
290 + }
291 +
278 292 // Use for Review Quiz.
279 293 $quiz = learn_press_get_quiz( $item_id );
280 294 if ( ! $quiz ) {
281 - throw new Exception( __( 'The quiz is invalid!', 'learnpress' ) );
295 + throw new Exception( esc_html__( 'The quiz is invalid!', 'learnpress' ) );
282 296 }
283 297 $quiz->set_course( $course );
284 298
285 - // Course is no required enroll
299 + // Course is no required enroll (no need login)
286 300 if ( $course->is_no_required_enroll() ) {
287 301 $no_required_enroll = new LP_Course_No_Required_Enroll( $course );
288 302
289 303 $result = $no_required_enroll->get_result_quiz( $quiz, $answered );
@@ -345,10 +359,18 @@
345 359 }
346 360
347 361 $user_quiz->complete();
348 362
349 - do_action( 'learn-press/user/quiz-finished', $item_id, $course_id, $user_id );
363 + /**
364 + * Clear cache result quiz
365 + * Cache set on @see LP_User_Item_Quiz::get_results, and start_quiz() clears the same
366 + * key. Without this the next read still serves the in-progress result and the
367 + * submitted answers all come back as skipped.
368 + */
369 + $user_quiz->clear_results_cache();
350 370
371 + do_action( 'learn-press/user/quiz-finished', $item_id, $course_id, $user_id, $user_quiz );
372 +
351 373 $result['status'] = $user_quiz->get_status(); // Must be completed
352 374 $result['attempts'] = $user_quiz->get_attempts();
353 375 $result['answered'] = $result['questions'];
354 376 $result['results'] = $result;
@@ -361,27 +383,17 @@
361 383 return rest_ensure_response( $response );
362 384 }
363 385
364 386 /**
365 - * Hint the question and response hint content.
387 + * Check answer
366 388 *
367 389 * @param WP_REST_Request $request
368 - *
369 - * @return mixed|WP_REST_Response
390 + * @return WP_Error|WP_HTTP_Response|WP_REST_Response
391 + * @since 4.1.4.1
392 + * @version 1.0.2
370 393 */
371 - public function hint_answer( $request ) {
372 - $question_id = $request['question_id'];
373 - $question = learn_press_get_question( $question_id );
374 -
394 + public function check_answer( WP_REST_Request $request ) {
375 395 $response = array(
376 - 'hint' => $question->get_hint(),
377 - );
378 -
379 - return rest_ensure_response( $response );
380 - }
381 -
382 - public function check_answer( $request ) {
383 - $response = array(
384 396 'status' => 'error',
385 397 'message' => '',
386 398 );
387 399
@@ -392,25 +404,47 @@
392 404 $quiz_id = $request['item_id'] ?? 0;
393 405 $course = learn_press_get_course( $course_id );
394 406 $checked = [];
395 407
408 + $courseModel = CourseModel::find( $course_id, true );
409 + if ( ! $courseModel ) {
410 + throw new Exception( esc_html__( 'The course is invalid', 'learnpress' ) );
411 + }
412 +
413 + $quizPostModel = $courseModel->get_item_model( $quiz_id, LP_QUIZ_CPT );
414 + if ( ! $quizPostModel ) {
415 + throw new Exception( esc_html__( 'The quiz is invalid', 'learnpress' ) );
416 + }
417 +
418 + // Check question has in quiz
419 + $quizQuestionModel = QuizQuestionModel::find( $quiz_id, $question_id );
420 + if ( ! $quizQuestionModel ) {
421 + throw new Exception( esc_html__( 'The quiz question is invalid', 'learnpress' ) );
422 + }
423 +
424 + $questionModel = QuestionPostModel::find( $question_id, true );
425 + if ( ! $questionModel ) {
426 + throw new Exception( esc_html__( 'The question is invalid', 'learnpress' ) );
427 + }
428 +
429 + // For case user not login
396 430 if ( $course->is_no_required_enroll() ) {
397 431 $no_required_enroll = new LP_Course_No_Required_Enroll( $course );
398 432 $checked = $no_required_enroll->guest_check_question( $question_id, $answered );
399 - } else {
433 + } else { // For case user logged in
400 434 $user = learn_press_get_current_user();
401 435 if ( $user->is_guest() ) {
402 - throw new Exception( 'The user is invalid', 'learnrpess' );
436 + throw new Exception( esc_html__( 'You must be logged in to check answer.', 'learnpress' ) );
403 437 }
404 438
405 439 $user_course = $user->get_course_data( $course_id );
406 440 if ( ! $user_course ) {
407 - throw new Exception( 'User\'s course no data!', 'learnrpess' );
441 + throw new Exception( esc_html__( 'User\'s course no data!', 'learnpress' ) );
408 442 }
409 443
410 444 $user_quiz = $user_course->get_item( $quiz_id );
411 445 if ( ! $user_quiz ) {
412 - throw new Exception( 'User\'s quiz no data!', 'learnrpess' );
446 + throw new Exception( esc_html__( 'User\'s quiz no data!', 'learnpress' ) );
413 447 }
414 448
415 449 $checked = $user_quiz->instant_check_question( $question_id, $answered );
416 450 }
@@ -416,9 +450,15 @@
416 450 }
417 451
418 452 $question = learn_press_get_question( $question_id );
419 453 $response['explanation'] = $question->get_explanation();
420 - $response['options'] = learn_press_get_question_options_for_js( $question, array( 'answer' => $answered ) );
454 + $response['options'] = learn_press_get_question_options_for_js(
455 + $question,
456 + array(
457 + 'include_is_true' => $quizPostModel->has_instant_check(),
458 + 'answer' => $answered,
459 + )
460 + );
421 461 $response['result'] = $checked;
422 462 $response['status'] = 'success';
423 463 } catch ( Throwable $e ) {
424 464 $response['message'] = $e->getMessage();