PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.3.8
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.3.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 / rest-api / v1 / frontend / class-lp-rest-users-controller.php

class-lp-rest-users-controller.php in LearnPress – WordPress LMS Plugin for Create and Sell Online Courses 4.3.8, at inc/rest-api/v1/frontend/class-lp-rest-users-controller.php

444 lines 13.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 use LearnPress\Models\CourseModel;
4 use LearnPress\Models\UserItemMeta\UserQuizMetaModel;
5 use LearnPress\Models\UserItems\UserQuizModel;
6
7 /**
8 * Class LP_REST_Users_Controller
9 *
10 * @since 3.3.0
11 */
12 class LP_REST_Users_Controller extends LP_Abstract_REST_Controller {
13 /**
14 * @var LP_User
15 */
16 protected $user = null;
17
18 /**
19 * @var LP_Course
20 */
21 protected $course = null;
22
23 /**
24 * @var LP_Course_Item|LP_Quiz|LP_Lesson
25 */
26 protected $item = null;
27
28 /**
29 * @var LP_User_Item_Course
30 */
31 protected $user_course = null;
32
33 /**
34 * @var LP_User_Item|LP_User_Item_Quiz
35 */
36 protected $user_item = null;
37
38 public function __construct() {
39 $this->namespace = 'lp/v1';
40 $this->rest_base = 'users';
41 parent::__construct();
42 }
43
44 /**
45 * Register rest routes.
46 */
47 public function register_routes() {
48 $this->routes = array(
49 'start-quiz' => array(
50 array(
51 'methods' => WP_REST_Server::EDITABLE,
52 'callback' => array( $this, 'start_quiz' ),
53 // 'permission_callback' => array( $this, 'check_admin_permission' ),
54 'permission_callback' => '__return_true',
55 'args' => $this->get_item_endpoint_args(),
56 ),
57 ),
58 'submit-quiz' => array(
59 array(
60 'methods' => WP_REST_Server::EDITABLE,
61 'callback' => array( $this, 'submit_quiz' ),
62 'permission_callback' => '__return_true',
63 'args' => $this->get_item_endpoint_args(),
64 ),
65 ),
66 /*'hint-answer' => array(
67 array(
68 'methods' => WP_REST_Server::EDITABLE,
69 'callback' => array( $this, 'hint_answer' ),
70 // 'permission_callback' => array( $this, 'check_admin_permission' ),
71 'permission_callback' => '__return_true',
72 'args' => $this->get_item_endpoint_args(),
73 ),
74 ),*/
75 'check-answer' => array(
76 array(
77 'methods' => WP_REST_Server::EDITABLE,
78 'callback' => array( $this, 'check_answer' ),
79 // 'permission_callback' => array( $this, 'check_admin_permission' ),
80 'permission_callback' => '__return_true',
81 'args' => $this->get_item_endpoint_args(),
82 ),
83 ),
84 );
85
86 parent::register_routes();
87 }
88
89 /**
90 * Get args for user item endpoints.
91 *
92 * @return array
93 */
94 public function get_item_endpoint_args() {
95 return array(
96 'item_id' => array(
97 'description' => __( 'The ID of the course item object.', 'learnpress' ),
98 'type' => 'int',
99 'validate_callback' => array( $this, 'validate_arg' ),
100 'required' => true,
101 ),
102 'course_id' => array(
103 'description' => __( 'The ID of the course object.', 'learnpress' ),
104 'type' => 'int',
105 'validate_callback' => array( $this, 'validate_arg' ),
106 'required' => true,
107 ),
108 );
109 }
110
111 /**
112 * Validation callback to verify rest args.
113 *
114 * @param mixed $value
115 * @param WP_REST_Request $request
116 * @param string $param
117 *
118 * @return bool|WP_Error
119 */
120 public function validate_arg( $value, $request, $param ) {
121 $attributes = $request->get_attributes();
122
123 if ( ! isset( $attributes['args'][ $param ] ) ) {
124 return new WP_Error( 'rest_invalid_param', sprintf( __( '%s was not registered as a request argument.', 'learnpress' ), $param ), array( 'status' => 400 ) );
125 }
126
127 return true;
128 }
129
130 public function check_admin_permission() {
131 return LP_Abstract_API::check_admin_permission();
132 }
133
134 /**
135 * User starts a quiz.
136 *
137 * @param WP_REST_Request $request
138 *
139 * @editor tungnx
140 * @version 1.0.2
141 * @sicne 4.0.0
142 * @return WP_REST_Response
143 */
144 public function start_quiz( WP_REST_Request $request ): WP_REST_Response {
145 $user_id = get_current_user_id();
146 $item_id = $request['item_id'] ?? 0;
147 $course_id = $request['course_id'] ?? 0;
148 $results = array(
149 'question_ids' => array(),
150 'questions' => array(),
151 'total_time' => 0,
152 );
153 $response = array(
154 'status' => 'error',
155 'message' => '',
156 );
157
158 try {
159 $user = learn_press_get_user( $user_id );
160 $course = learn_press_get_course( $course_id );
161 $quiz = learn_press_get_quiz( $item_id );
162
163 if ( ! $course ) {
164 throw new Exception( __( 'The course is invalid!', 'learnpress' ) );
165 }
166
167 if ( ! $quiz ) {
168 throw new Exception( __( 'The quiz is invalid!', 'learnpress' ) );
169 }
170
171 $quiz->set_course( $course );
172
173 do_action( 'learn-press/user/before/start-quiz', $item_id, $course_id, $user_id );
174
175 $courseModel = CourseModel::find( $course_id, true );
176 $link = LP_Helper::get_link_no_cache( $courseModel->get_item_link( $item_id, LP_QUIZ_CPT ) );
177
178 // For no required enroll course
179 if ( $user->is_guest() && $course->is_no_required_enroll() ) {
180 $no_required_enroll = new LP_Course_No_Required_Enroll( $course );
181 $response = $no_required_enroll->guest_start_quiz( $quiz );
182 $response['redirect_url'] = $link;
183
184 return rest_ensure_response( $response );
185 }
186
187 /**
188 * Require enroll course
189 *
190 * @var UserQuizModel $user_quiz
191 */
192 $retaken_count = 0;
193 $attempts = [];
194 $filter_user_quiz = new LP_User_Items_Filter();
195 $filter_user_quiz->user_id = $user_id;
196 $filter_user_quiz->item_id = $item_id;
197 $filter_user_quiz->ref_id = $course_id;
198 $user_quiz_exists = UserQuizModel::get_user_item_model_from_db( $filter_user_quiz );
199 if ( $user_quiz_exists instanceof UserQuizModel
200 && $user_quiz_exists->status === LP_ITEM_COMPLETED ) {
201 $user_quiz = $user_quiz_exists;
202 $user_quiz->retake();
203 $results['answered'] = []; // Reset answered for js
204 $retaken_count = $user_quiz->get_retaken_count();
205 $attempts = $user_quiz->get_attempts();
206 } else { // Create new user quiz and insert to database.
207 $user_quiz_new = new UserQuizModel();
208 $user_quiz_new->user_id = $user_id;
209 $user_quiz_new->item_id = $item_id;
210 $user_quiz_new->ref_id = $course_id;
211 $user_quiz_new->start_quiz();
212 $user_quiz = $user_quiz_new;
213 }
214
215 $user_item_id = $user_quiz->get_user_item_id();
216
217 /**
218 * Clear cache result quiz
219 * Cache set on @see LP_User_Item_Quiz::get_results
220 */
221 $lp_quiz_cache = LP_Quiz_Cache::instance();
222 $key_cache = sprintf( '%d/user/%d/course/%d', $item_id, $user_id, $course_id );
223 $lp_quiz_cache->clear( $key_cache );
224 // End
225
226 $show_check = $quiz->get_instant_check();
227 $duration = $quiz->get_duration();
228 $show_correct_review = $quiz->get_show_correct_review();
229 $question_ids = $quiz->get_question_ids();
230 $status = $user_quiz->get_status();
231 $time_remaining = $user_quiz->get_time_remaining();
232
233 $questions = learn_press_rest_prepare_user_questions(
234 $question_ids,
235 array(
236 'instant_check' => $show_check,
237 //'quiz_status' => $status,
238 //'checked_questions' => $checked_questions,
239 //'hinted_questions' => $hinted_questions,
240 'answered' => [],
241 'show_correct_review' => $show_correct_review,
242 )
243 );
244
245 $results['question_ids'] = $question_ids;
246 $results['questions'] = $questions;
247 $results['total_time'] = $time_remaining;
248 $results['duration'] = $duration ? $duration->get() : false;
249 $results['status'] = $status; // Must be started
250 $results['retaken'] = $retaken_count;
251 $results['attempts'] = $attempts;
252 $results['user_item_id'] = $user_item_id;
253 $response['status'] = 'success';
254 $response['results'] = $results;
255 $response['redirect_url'] = $link;
256 } catch ( Throwable $e ) {
257 $response['message'] = $e->getMessage();
258 }
259
260 return rest_ensure_response( $response );
261 }
262
263 /**
264 * Submit quiz answer
265 *
266 * @param WP_REST_Request $request
267 *
268 * @return WP_Error|WP_HTTP_Response|WP_REST_Response
269 * @editor tungnx
270 * @modify 4.1.4.1
271 * @version 1.0.2
272 */
273 public function submit_quiz( WP_REST_Request $request ) {
274 //$response = new LP_REST_Response();
275 $response = array(
276 'status' => 'error',
277 'message' => '',
278 );
279
280 try {
281 $user_id = get_current_user_id();
282 $item_id = $request['item_id'] ?? 0;
283 $course_id = $request['course_id'] ?? 0;
284 $answered = $request['answered'] ?? [];
285 $time_spend = $request['time_spend'] ?? 0;
286 $user = learn_press_get_user( $user_id );
287 $course = learn_press_get_course( $course_id );
288
289 if ( ! $course ) {
290 throw new Exception( 'The course is invalid!' );
291 }
292 // Use for Review Quiz.
293 $quiz = learn_press_get_quiz( $item_id );
294 if ( ! $quiz ) {
295 throw new Exception( __( 'The quiz is invalid!', 'learnpress' ) );
296 }
297 $quiz->set_course( $course );
298
299 // Course is no required enroll
300 if ( $course->is_no_required_enroll() ) {
301 $no_required_enroll = new LP_Course_No_Required_Enroll( $course );
302
303 $result = $no_required_enroll->get_result_quiz( $quiz, $answered );
304
305 // Set time spent
306 $interval = new LP_Duration( $time_spend );
307 $interval = $interval->to_timer();
308 $result['time_spend'] = $interval;
309 // End
310
311 $result['status'] = LP_ITEM_COMPLETED;
312 //$result['answered'] = $result['questions'];
313 $result['attempts'] = [];
314 $result['results'] = $result;
315 $response['status'] = 'success';
316 $response['results'] = $result;
317
318 return rest_ensure_response( $response );
319 }
320
321 $user_course = $user->get_course_data( $course_id );
322
323 // Course required enroll
324 if ( ! $user_course ) {
325 throw new Exception( 'User not enrolled course!' );
326 }
327
328 /**
329 * @var LP_User_Item_Quiz $user_quiz
330 */
331 $user_quiz = $user_course->get_item( $item_id );
332 if ( ! $user_quiz ) {
333 throw new Exception();
334 }
335
336 // For case save result when check instant answer
337 $result_instant_check = LP_User_Items_Result_DB::instance()->get_result( $user_quiz->get_user_item_id() );
338 if ( $result_instant_check ) {
339 foreach ( $result_instant_check['questions'] as $question_answer_id => $question_answer ) {
340 if ( ! empty( $question_answer['answered'] ) ) {
341 $answered[ $question_answer_id ] = $question_answer['answered'];
342 }
343 }
344 }
345
346 // Set end time.
347 $start_time = $user_quiz->get_start_time()->getTimestamp();
348 $user_quiz->set_end_time( $start_time + $time_spend );
349
350 // Calculate quiz result and save.
351 $result = $user_quiz->calculate_quiz_result( $answered );
352 // Save
353 LP_User_Items_Result_DB::instance()->update( $user_quiz->get_user_item_id(), wp_json_encode( $result ) );
354
355 if ( $result['pass'] ) {
356 $user_quiz->set_graduation( LP_COURSE_GRADUATION_PASSED );
357 } else {
358 $user_quiz->set_graduation( LP_COURSE_GRADUATION_FAILED );
359 }
360
361 $user_quiz->complete();
362
363 do_action( 'learn-press/user/quiz-finished', $item_id, $course_id, $user_id, $user_quiz );
364
365 $result['status'] = $user_quiz->get_status(); // Must be completed
366 $result['attempts'] = $user_quiz->get_attempts();
367 $result['answered'] = $result['questions'];
368 $result['results'] = $result;
369 $response['status'] = 'success';
370 $response['results'] = $result;
371 } catch ( Throwable $e ) {
372 $response['message'] = $e->getMessage();
373 }
374
375 return rest_ensure_response( $response );
376 }
377
378 /**
379 * Hint the question and response hint content.
380 *
381 * @param WP_REST_Request $request
382 *
383 * @return mixed|WP_REST_Response
384 */
385 /*public function hint_answer( $request ) {
386 $question_id = $request['question_id'];
387 $question = learn_press_get_question( $question_id );
388
389 $response = array(
390 'hint' => $question->get_hint(),
391 );
392
393 return rest_ensure_response( $response );
394 }*/
395
396 public function check_answer( $request ) {
397 $response = array(
398 'status' => 'error',
399 'message' => '',
400 );
401
402 try {
403 $question_id = $request['question_id'] ?? 0;
404 $answered = $request['answered'] ?? '';
405 $course_id = $request['course_id'] ?? 0;
406 $quiz_id = $request['item_id'] ?? 0;
407 $course = learn_press_get_course( $course_id );
408 $checked = [];
409
410 if ( $course->is_no_required_enroll() ) {
411 $no_required_enroll = new LP_Course_No_Required_Enroll( $course );
412 $checked = $no_required_enroll->guest_check_question( $question_id, $answered );
413 } else {
414 $user = learn_press_get_current_user();
415 if ( $user->is_guest() ) {
416 throw new Exception( 'The user is invalid', 'learnrpess' );
417 }
418
419 $user_course = $user->get_course_data( $course_id );
420 if ( ! $user_course ) {
421 throw new Exception( 'User\'s course no data!', 'learnrpess' );
422 }
423
424 $user_quiz = $user_course->get_item( $quiz_id );
425 if ( ! $user_quiz ) {
426 throw new Exception( 'User\'s quiz no data!', 'learnrpess' );
427 }
428
429 $checked = $user_quiz->instant_check_question( $question_id, $answered );
430 }
431
432 $question = learn_press_get_question( $question_id );
433 $response['explanation'] = $question->get_explanation();
434 $response['options'] = learn_press_get_question_options_for_js( $question, array( 'answer' => $answered ) );
435 $response['result'] = $checked;
436 $response['status'] = 'success';
437 } catch ( Throwable $e ) {
438 $response['message'] = $e->getMessage();
439 }
440
441 return rest_ensure_response( $response );
442 }
443 }
444