| @@ -1,6 +1,10 @@ | ||
| 1 | 1 | <?php |
| 2 | 2 | |
| 3 | +use LearnPress\Filters\FilterBase; | |
| 4 | +use LearnPress\Filters\UserItemsFilter; | |
| 5 | +use LearnPress\Models\UserModel; | |
| 6 | + | |
| 3 | 7 | /** |
| 4 | 8 | * Class LP_User |
| 5 | 9 | * |
| 6 | 10 | * @author ThimPress |
| @@ -18,14 +22,13 @@ | ||
| 18 | 22 | */ |
| 19 | 23 | public function can_view_content_course( int $course_id = 0 ): LP_Model_User_Can_View_Course_Item { |
| 20 | 24 | $view = new LP_Model_User_Can_View_Course_Item(); |
| 21 | 25 | $view->message = esc_html__( |
| 22 | - 'This content is protected, please enroll course to view this content!', | |
| 26 | + 'This content is protected. Please enroll in the course to view this content!', | |
| 23 | 27 | 'learnpress' |
| 24 | 28 | ); |
| 25 | 29 | |
| 26 | 30 | $course = learn_press_get_course( $course_id ); |
| 27 | - | |
| 28 | 31 | if ( ! $course ) { |
| 29 | 32 | return $view; |
| 30 | 33 | } |
| 31 | 34 | |
| @@ -42,9 +45,9 @@ | ||
| 42 | 45 | |
| 43 | 46 | return $view; |
| 44 | 47 | } elseif ( ! is_user_logged_in() ) { |
| 45 | 48 | $view->message = __( |
| 46 | - 'This content is protected, please login, enroll course to view this content!', | |
| 49 | + 'This content is protected. Please log in or enroll in the course to view this content!', | |
| 47 | 50 | 'learnpress' |
| 48 | 51 | ); |
| 49 | 52 | |
| 50 | 53 | return $view; |
| @@ -59,21 +62,21 @@ | ||
| 59 | 62 | |
| 60 | 63 | if ( $is_finished_course && $enable_block_item_when_finish ) { |
| 61 | 64 | $view->key = LP_BLOCK_COURSE_FINISHED; |
| 62 | 65 | $view->message = __( |
| 63 | - 'You finished this course. This content is protected, please enroll course to view this content!', | |
| 66 | + 'You finished this course. This content is protected. Please enroll in the course to view this content!', | |
| 64 | 67 | 'learnpress' |
| 65 | 68 | ); |
| 66 | 69 | } elseif ( 0 === $course->timestamp_remaining_duration() ) { |
| 67 | 70 | $view->key = LP_BLOCK_COURSE_DURATION_EXPIRE; |
| 68 | 71 | $view->message = __( |
| 69 | - 'Content of this item has blocked because the course has exceeded duration.', | |
| 72 | + 'The content of this item has been blocked because the course has exceeded its duration.', | |
| 70 | 73 | 'learnpress' |
| 71 | 74 | ); |
| 72 | 75 | } elseif ( $this->get_course_status( $course_id ) === LP_COURSE_PURCHASED ) { |
| 73 | 76 | $view->key = LP_BLOCK_COURSE_PURCHASE; |
| 74 | 77 | $view->message = __( |
| 75 | - 'This content is protected, please enroll course to view this content!', | |
| 78 | + 'This content is protected. Please enroll in the course to view this content!', | |
| 76 | 79 | 'learnpress' |
| 77 | 80 | ); |
| 78 | 81 | } else { |
| 79 | 82 | $view->key = 'can_view_course'; |
| @@ -90,9 +93,9 @@ | ||
| 90 | 93 | |
| 91 | 94 | /** |
| 92 | 95 | * Check the user can access to an item inside course. |
| 93 | 96 | * |
| 94 | - * @param int $item_id Course's item Id. | |
| 97 | + * @param int $item_id Course's item Id. | |
| 95 | 98 | * @param LP_Model_User_Can_View_Course_Item $view Course Id. |
| 96 | 99 | * |
| 97 | 100 | * @author tungnx |
| 98 | 101 | * @return LP_Model_User_Can_View_Course_Item |
| @@ -121,9 +124,9 @@ | ||
| 121 | 124 | if ( $view_new ) { |
| 122 | 125 | $view = $view_new; |
| 123 | 126 | } |
| 124 | 127 | |
| 125 | - return apply_filters( 'learnpress/course/item/can-view', $view, $item ); | |
| 128 | + return apply_filters( 'learnpress/course/item/can-view', $view, $item, $this ); | |
| 126 | 129 | } |
| 127 | 130 | |
| 128 | 131 | /** |
| 129 | 132 | * Check if user can retry course. |
| @@ -130,9 +133,8 @@ | ||
| 130 | 133 | * |
| 131 | 134 | * @param int $course_id . |
| 132 | 135 | * |
| 133 | 136 | * @return int |
| 134 | - * @throws Exception . | |
| 135 | 137 | * @since 4.0.0 |
| 136 | 138 | * @author tungnx |
| 137 | 139 | */ |
| 138 | 140 | public function can_retry_course( int $course_id = 0 ): int { |
| @@ -158,9 +160,8 @@ | ||
| 158 | 160 | } |
| 159 | 161 | } |
| 160 | 162 | |
| 161 | 163 | $user_course_data = $this->get_course_data( $course_id ); |
| 162 | - | |
| 163 | 164 | if ( $user_course_data instanceof LP_User_Item_Course ) { |
| 164 | 165 | $retaken = $user_course_data->get_retaken_count(); |
| 165 | 166 | $can_retake_times = $retake_option - $retaken; |
| 166 | 167 | |
| @@ -196,8 +197,9 @@ | ||
| 196 | 197 | * Check course is enrolled |
| 197 | 198 | * |
| 198 | 199 | * @param integer $course_id Course ID |
| 199 | 200 | * @param boolean $return_bool |
| 201 | + * | |
| 200 | 202 | * @return bool|object |
| 201 | 203 | * @editor tungnx |
| 202 | 204 | * @since 4.1.2 |
| 203 | 205 | * @version 1.0.2 |
| @@ -216,11 +218,10 @@ | ||
| 216 | 218 | throw new Exception( esc_html__( 'Order is not completed', 'learnpress' ) ); |
| 217 | 219 | }*/ |
| 218 | 220 | |
| 219 | 221 | $user_course = $this->get_course_data( $course_id ); |
| 220 | - | |
| 221 | 222 | if ( ! $user_course || ! $user_course->is_enrolled() ) { |
| 222 | - throw new Exception( esc_html__( 'Course is not enrolled', 'learnpress' ) ); | |
| 223 | + throw new Exception( esc_html__( 'The course is not enrolled.', 'learnpress' ) ); | |
| 223 | 224 | } |
| 224 | 225 | } catch ( Throwable $th ) { |
| 225 | 226 | $result_check->check = false; |
| 226 | 227 | $result_check->message = $th->getMessage(); |
| @@ -236,9 +237,9 @@ | ||
| 236 | 237 | * |
| 237 | 238 | * @return bool |
| 238 | 239 | * @throws Exception |
| 239 | 240 | */ |
| 240 | - public function has_finished_course( int $course_id ) : bool { | |
| 241 | + public function has_finished_course( int $course_id ): bool { | |
| 241 | 242 | $user_course = $this->get_course_data( $course_id ); |
| 242 | 243 | |
| 243 | 244 | return apply_filters( 'learn-press/user-has-finished-course', $user_course && $user_course->is_finished(), $this->get_id(), $course_id ); |
| 244 | 245 | } |
| @@ -270,10 +271,11 @@ | ||
| 270 | 271 | |
| 271 | 272 | /** |
| 272 | 273 | * Check user can enroll course |
| 273 | 274 | * |
| 274 | - * @param int $course_id | |
| 275 | + * @param int $course_id | |
| 275 | 276 | * @param bool $return_bool |
| 277 | + * | |
| 276 | 278 | * @return mixed|object|bool |
| 277 | 279 | */ |
| 278 | 280 | public function can_enroll_course( int $course_id, bool $return_bool = true ) { |
| 279 | 281 | $course = learn_press_get_course( $course_id ); |
| @@ -281,35 +283,53 @@ | ||
| 281 | 283 | $output->check = true; |
| 282 | 284 | $output->message = ''; |
| 283 | 285 | |
| 284 | 286 | try { |
| 287 | + $is_no_required_enroll = $course->get_data( 'no_required_enroll', 'no' ) === 'yes'; | |
| 285 | 288 | if ( ! $course ) { |
| 289 | + $output->code = 'course_unavailable'; | |
| 286 | 290 | throw new Exception( esc_html__( 'No Course or User available', 'learnpress' ) ); |
| 287 | 291 | } |
| 288 | 292 | |
| 289 | 293 | if ( ! $course->is_publish() ) { |
| 290 | - throw new Exception( esc_html__( 'Course is not public', 'learnpress' ) ); | |
| 294 | + $output->code = 'course_not_publish'; | |
| 295 | + throw new Exception( esc_html__( 'The course is not public', 'learnpress' ) ); | |
| 291 | 296 | } |
| 292 | 297 | |
| 293 | - if ( $course->get_external_link() && ! $this->has_purchased_course( $course_id ) ) { | |
| 294 | - throw new Exception( esc_html__( 'Course is External', 'learnpress' ) ); | |
| 298 | + if ( $this->has_enrolled_course( $course_id ) ) { | |
| 299 | + $output->code = 'course_is_enrolled'; | |
| 300 | + throw new Exception( esc_html__( 'This course is already enrolled.', 'learnpress' ) ); | |
| 295 | 301 | } |
| 296 | 302 | |
| 297 | - if ( ! $course->is_in_stock() ) { | |
| 298 | - throw new Exception( esc_html__( 'Course is full students', 'learnpress' ) ); | |
| 303 | + if ( ! $course->is_in_stock_enroll() && ! $this->has_purchased_course( $course_id ) | |
| 304 | + && ! $this->has_enrolled_or_finished( $course_id ) && ! $is_no_required_enroll ) { | |
| 305 | + $output->code = 'course_out_of_stock'; | |
| 306 | + throw new Exception( esc_html__( 'The course is full of students.', 'learnpress' ) ); | |
| 299 | 307 | } |
| 300 | 308 | |
| 301 | - if ( $course->is_no_required_enroll() ) { | |
| 302 | - throw new Exception( esc_html__( 'Course is not require enrolling.', 'learnpress' ) ); | |
| 309 | + if ( $course->get_external_link() | |
| 310 | + && ! $this->has_purchased_course( $course_id ) | |
| 311 | + && ! $course->is_offline() ) { | |
| 312 | + $output->code = 'course_is_external'; | |
| 313 | + throw new Exception( esc_html__( 'The course is external', 'learnpress' ) ); | |
| 303 | 314 | } |
| 304 | 315 | |
| 305 | - if ( ! $course->is_free() && ! $this->has_purchased_course( $course_id ) ) { | |
| 306 | - throw new Exception( esc_html__( 'Course is not purchased.', 'learnpress' ) ); | |
| 316 | + if ( $this->can_retry_course( $course_id ) ) { | |
| 317 | + $output->code = 'course_can_retry'; | |
| 318 | + throw new Exception( esc_html__( 'Course can retake.', 'learnpress' ) ); | |
| 307 | 319 | } |
| 308 | 320 | |
| 309 | - if ( $this->has_enrolled_course( $course_id ) ) { | |
| 310 | - throw new Exception( esc_html__( 'This course is already enrolled.', 'learnpress' ) ); | |
| 321 | + if ( $is_no_required_enroll && ! is_user_logged_in() ) { | |
| 322 | + $output->code = 'course_is_no_required_enroll_not_login'; | |
| 323 | + throw new Exception( | |
| 324 | + esc_html__( 'Enrollment in the course is not mandatory. You can access course for learning now.', 'learnpress' ) | |
| 325 | + ); | |
| 311 | 326 | } |
| 327 | + | |
| 328 | + if ( ! $course->is_free() && ! $is_no_required_enroll && ! $this->has_purchased_course( $course_id ) ) { | |
| 329 | + $output->code = 'course_is_not_purchased'; | |
| 330 | + throw new Exception( esc_html__( 'The course is not purchased.', 'learnpress' ) ); | |
| 331 | + } | |
| 312 | 332 | } catch ( \Throwable $th ) { |
| 313 | 333 | $output->check = false; |
| 314 | 334 | $output->message = $th->getMessage(); |
| 315 | 335 | } |
| @@ -324,92 +344,75 @@ | ||
| 324 | 344 | /** |
| 325 | 345 | * Check can show purchase course button |
| 326 | 346 | * |
| 327 | 347 | * @param int $course_id |
| 328 | - * @return bool | |
| 329 | - * @throws Exception | |
| 348 | + * | |
| 349 | + * @return bool|WP_Error | |
| 330 | 350 | * @author nhamdv |
| 331 | 351 | * @editor tungnx |
| 332 | - * @modify 4.1.4 | |
| 333 | - * @version 1.0.3 | |
| 352 | + * @since 4.0.8 | |
| 353 | + * @version 1.0.6 | |
| 334 | 354 | */ |
| 335 | - public function can_purchase_course( int $course_id = 0 ): bool { | |
| 355 | + public function can_purchase_course( int $course_id = 0 ) { | |
| 336 | 356 | $can_purchase = true; |
| 337 | 357 | $course = learn_press_get_course( $course_id ); |
| 358 | + $code_err = ''; | |
| 338 | 359 | |
| 339 | 360 | try { |
| 340 | - if ( ! $course ) { | |
| 341 | - throw new Exception( 'Course is unavailable' ); | |
| 361 | + $can_enroll_course = $this->can_enroll_course( $course_id, false ); | |
| 362 | + if ( ! $can_enroll_course->check && | |
| 363 | + ! in_array( $can_enroll_course->code, [ 'course_is_not_purchased', 'course_is_enrolled' ] ) ) { | |
| 364 | + $code_err = $can_enroll_course->code; | |
| 365 | + throw new Exception( $can_enroll_course->message ); | |
| 342 | 366 | } |
| 343 | 367 | |
| 344 | - if ( ! $course->is_publish() ) { | |
| 345 | - throw new Exception( 'Course is not publish' ); | |
| 346 | - } | |
| 347 | - | |
| 348 | 368 | if ( $course->is_free() ) { |
| 349 | - throw new Exception( 'Course is free' ); | |
| 369 | + $code_err = 'course_is_free'; | |
| 370 | + throw new Exception( __( 'Course is free, so you can not purchase', 'learnpress' ) ); | |
| 350 | 371 | } |
| 351 | 372 | |
| 352 | - if ( $course->get_external_link() ) { | |
| 353 | - throw new Exception( 'Course is type external, so can not purchase' ); | |
| 354 | - } | |
| 355 | - | |
| 356 | 373 | // Course is not require enrolling. |
| 357 | - if ( $course->is_no_required_enroll() ) { | |
| 358 | - throw new Exception( 'Course is type no required enroll' ); | |
| 359 | - } | |
| 360 | - | |
| 361 | - if ( $this->can_retry_course( $course_id ) ) { | |
| 362 | - throw new Exception( 'Course is has retake' ); | |
| 363 | - } | |
| 364 | - | |
| 365 | - // If course is reached limitation. | |
| 366 | - if ( ! $course->is_in_stock() ) { | |
| 367 | - $message = apply_filters( | |
| 368 | - 'learn-press/maximum-students-reach', | |
| 369 | - esc_html__( 'This course is out of stock', 'learnpress' ) | |
| 374 | + // Not use $course->is_no_required_enroll() because it is not correct, it check with user logged. | |
| 375 | + if ( $course->get_data( 'no_required_enroll', 'no' ) === 'yes' ) { | |
| 376 | + $code_err = 'no_required_enroll'; | |
| 377 | + throw new Exception( | |
| 378 | + __( | |
| 379 | + 'Enrollment in the course is not mandatory. You can access materials for learning or to take quizzes now.', | |
| 380 | + 'learnpress' | |
| 381 | + ) | |
| 370 | 382 | ); |
| 371 | - | |
| 372 | - if ( $message ) { | |
| 373 | - learn_press_display_message( $message ); | |
| 374 | - } | |
| 375 | - | |
| 376 | - throw new Exception( $message ); | |
| 377 | 383 | } |
| 378 | 384 | |
| 379 | 385 | // If the order contains course is processing |
| 380 | 386 | $order = $this->get_course_order( $course_id ); |
| 381 | - if ( $order && $order->get_status() === 'processing' ) { | |
| 382 | - $message = apply_filters( | |
| 383 | - 'learn-press/order-processing-message', | |
| 384 | - __( 'Your order is waiting for processing', 'learnpress' ) | |
| 385 | - ); | |
| 386 | - | |
| 387 | - if ( $message ) { | |
| 388 | - learn_press_display_message( $message ); | |
| 389 | - } | |
| 390 | - | |
| 391 | - throw new Exception( $message ); | |
| 387 | + if ( $order && $order->get_status() === LP_ORDER_PROCESSING ) { | |
| 388 | + $code_err = 'order_processing'; | |
| 389 | + throw new Exception( __( 'Your order is waiting for processing', 'learnpress' ) ); | |
| 392 | 390 | } |
| 393 | 391 | |
| 394 | 392 | if ( $this->has_purchased_course( $course_id ) ) { |
| 395 | - throw new Exception( 'Course is purchased' ); | |
| 393 | + $code_err = 'course_purchased'; | |
| 394 | + throw new Exception( __( 'Course is purchased', 'learnpress' ) ); | |
| 396 | 395 | } |
| 397 | 396 | |
| 398 | 397 | $is_blocked_course = 0 === $course->timestamp_remaining_duration(); |
| 399 | 398 | $is_enrolled_course = $this->has_enrolled_course( $course_id ); |
| 400 | - $is_finished_course = $this->has_finished_course( $course_id ); | |
| 401 | - | |
| 402 | 399 | if ( $course->allow_repurchase() ) { |
| 403 | 400 | if ( $is_enrolled_course && ! $is_blocked_course ) { |
| 401 | + $code_err = 'course_is_enrolled'; | |
| 404 | 402 | throw new Exception( 'Course is enrolled' ); |
| 405 | 403 | } |
| 406 | 404 | } else { |
| 407 | 405 | if ( $this->has_enrolled_or_finished( $course_id ) ) { |
| 408 | - throw new Exception( 'Course is enrolled' ); | |
| 406 | + $code_err = 'course_is_enrolled_or_finished'; | |
| 407 | + throw new Exception( __( 'Course is enrolled or finished', 'learnpress' ) ); | |
| 409 | 408 | } |
| 410 | 409 | } |
| 411 | - } catch ( Exception $e ) { | |
| 410 | + } catch ( Throwable $e ) { | |
| 411 | + $can_purchase = new WP_Error( $code_err, $e->getMessage() ); | |
| 412 | + } | |
| 413 | + | |
| 414 | + if ( $can_purchase instanceof WP_Error ) { | |
| 412 | 415 | $can_purchase = false; |
| 413 | 416 | } |
| 414 | 417 | |
| 415 | 418 | return apply_filters( 'learn-press/user/can-purchase-course', $can_purchase, $this->get_id(), $course_id ); |
| @@ -418,8 +421,9 @@ | ||
| 418 | 421 | /** |
| 419 | 422 | * Check condition show finish course button |
| 420 | 423 | * |
| 421 | 424 | * @param $course |
| 425 | + * | |
| 422 | 426 | * @return array |
| 423 | 427 | * @author nhamdv |
| 424 | 428 | * @editor tungnx |
| 425 | 429 | * @version 1.0.2 |
| @@ -437,17 +441,17 @@ | ||
| 437 | 441 | |
| 438 | 442 | $course_id = $course->get_id(); |
| 439 | 443 | |
| 440 | 444 | if ( $this->has_finished_course( $course_id ) ) { |
| 441 | - throw new Exception( esc_html__( 'Course is has finished.', 'learnpress' ) ); | |
| 445 | + throw new Exception( esc_html__( 'The course has finished.', 'learnpress' ) ); | |
| 442 | 446 | } |
| 443 | 447 | |
| 444 | 448 | if ( ! $this->has_enrolled_course( $course_id ) ) { |
| 445 | - throw new Exception( esc_html__( 'Course is not enroll.', 'learnpress' ) ); | |
| 449 | + throw new Exception( esc_html__( 'The course is not enrolled.', 'learnpress' ) ); | |
| 446 | 450 | } |
| 447 | 451 | |
| 448 | 452 | if ( ! $this->is_course_in_progress( $course_id ) ) { |
| 449 | - throw new Exception( esc_html__( 'Error: Course is not in-progress.', 'learnpress' ) ); | |
| 453 | + throw new Exception( esc_html__( 'Error: The course is not in progress.', 'learnpress' ) ); | |
| 450 | 454 | } |
| 451 | 455 | |
| 452 | 456 | $course_data = $this->get_course_data( $course_id ); |
| 453 | 457 | |
| @@ -470,9 +474,9 @@ | ||
| 470 | 474 | } |
| 471 | 475 | } |
| 472 | 476 | |
| 473 | 477 | if ( ! apply_filters( 'lp_can_finish_course', true ) ) { |
| 474 | - throw new Exception( esc_html__( 'Error: Filter disable finish course.', 'learnpress' ) ); | |
| 478 | + throw new Exception( esc_html__( 'Error: Filter the disabled finished courses.', 'learnpress' ) ); | |
| 475 | 479 | } |
| 476 | 480 | } catch ( Exception $e ) { |
| 477 | 481 | $return['status'] = 'false'; |
| 478 | 482 | $return['message'] = $e->getMessage(); |
| @@ -483,23 +487,24 @@ | ||
| 483 | 487 | |
| 484 | 488 | /** |
| 485 | 489 | * Start quiz for the user. |
| 486 | 490 | * |
| 487 | - * @param int $quiz_id | |
| 488 | - * @param int $course_id | |
| 491 | + * @param int $quiz_id | |
| 492 | + * @param int $course_id | |
| 489 | 493 | * @param bool $wp_error Optional. Whether to return a WP_Error on failure. Default false. |
| 490 | 494 | * |
| 491 | 495 | * @return LP_User_Item_Quiz|bool|WP_Error |
| 492 | 496 | * @throws Exception |
| 497 | + * @deprecated 4.2.9.1 | |
| 493 | 498 | */ |
| 494 | 499 | public function start_quiz( int $quiz_id, int $course_id = 0, bool $wp_error = false ) { |
| 500 | + _deprecated_function( __METHOD__, '4.2.9.1' ); | |
| 501 | + return false; | |
| 502 | + | |
| 495 | 503 | try { |
| 496 | - $item_id = learn_press_get_request( 'lp-preview' ); | |
| 497 | - | |
| 498 | - if ( $item_id ) { | |
| 499 | - learn_press_add_message( __( 'You cannot start a quiz in preview mode.', 'learnpress' ), 'error' ); | |
| 500 | - wp_safe_redirect( learn_press_get_preview_url( $item_id ) ); | |
| 501 | - exit(); | |
| 504 | + $item_is_preview = learn_press_get_request( 'lp-preview' ); | |
| 505 | + if ( $item_is_preview ) { | |
| 506 | + throw new Exception( __( 'You cannot start a quiz in preview mode.', 'learnpress' ) ); | |
| 502 | 507 | } |
| 503 | 508 | |
| 504 | 509 | // Validate course and quiz |
| 505 | 510 | $course_id = $this->_verify_course_item( $quiz_id, $course_id ); |
| @@ -504,16 +509,14 @@ | ||
| 504 | 509 | // Validate course and quiz |
| 505 | 510 | $course_id = $this->_verify_course_item( $quiz_id, $course_id ); |
| 506 | 511 | if ( ! $course_id ) { |
| 507 | 512 | throw new Exception( |
| 508 | - __( 'Course does not exist or does not contain the quiz', 'learnpress' ), | |
| 513 | + __( 'The course does not exist or does not contain a quiz.', 'learnpress' ), | |
| 509 | 514 | LP_INVALID_QUIZ_OR_COURSE |
| 510 | 515 | ); |
| 511 | 516 | } |
| 512 | 517 | |
| 513 | 518 | $course = learn_press_get_course( $course_id ); |
| 514 | - //$access_level = $this->get_course_access_level( $course_id ); | |
| 515 | - | |
| 516 | 519 | // If user has already finished the course |
| 517 | 520 | if ( $this->has_finished_course( $course_id ) ) { |
| 518 | 521 | throw new Exception( |
| 519 | 522 | __( 'You have already finished the course of this quiz', 'learnpress' ), |
| @@ -523,9 +526,9 @@ | ||
| 523 | 526 | |
| 524 | 527 | if ( ! $this->has_enrolled_course( $course_id ) || ! $this->is_course_in_progress( $course_id ) ) { |
| 525 | 528 | if ( ! $course->is_no_required_enroll() ) { |
| 526 | 529 | throw new Exception( |
| 527 | - __( 'Please enroll course before starting quiz.', 'learnpress' ), | |
| 530 | + __( 'Please enroll in the course before starting the quiz.', 'learnpress' ), | |
| 528 | 531 | LP_COURSE_IS_FINISHED |
| 529 | 532 | ); |
| 530 | 533 | } |
| 531 | 534 | } |
| @@ -532,18 +535,18 @@ | ||
| 532 | 535 | |
| 533 | 536 | // Check if user has already started or completed quiz |
| 534 | 537 | if ( $this->has_item_status( array( 'started', 'completed' ), $quiz_id, $course_id ) ) { |
| 535 | 538 | throw new Exception( |
| 536 | - __( 'User has started or completed quiz', 'learnpress' ), | |
| 539 | + __( 'The user has started or completed the quiz.', 'learnpress' ), | |
| 537 | 540 | LP_QUIZ_HAS_STARTED_OR_COMPLETED |
| 538 | 541 | ); |
| 539 | 542 | } |
| 540 | - $user = learn_press_get_current_user(); | |
| 541 | 543 | |
| 542 | - if ( $user->is_guest() ) { | |
| 544 | + $user_current = learn_press_get_current_user(); | |
| 545 | + if ( $user_current->is_guest() ) { | |
| 543 | 546 | // if course required enroll => print message "You have to login for starting quiz" |
| 544 | 547 | if ( ! $course->is_no_required_enroll() ) { |
| 545 | - throw new Exception( __( 'You have to login for starting quiz.', 'learnpress' ), LP_REQUIRE_LOGIN ); | |
| 548 | + throw new Exception( __( 'You have to log in to start the quiz.', 'learnpress' ), LP_REQUIRE_LOGIN ); | |
| 546 | 549 | } |
| 547 | 550 | } |
| 548 | 551 | |
| 549 | 552 | /** |
| @@ -551,9 +554,9 @@ | ||
| 551 | 554 | * |
| 552 | 555 | * @see learn_press_hk_before_start_quiz |
| 553 | 556 | */ |
| 554 | 557 | $can_start_quiz = apply_filters( |
| 555 | - 'learn-press/before-start-quiz', | |
| 558 | + 'learn-press/can-start-quiz', | |
| 556 | 559 | true, |
| 557 | 560 | $quiz_id, |
| 558 | 561 | $course_id, |
| 559 | 562 | $this->get_id() |
| @@ -562,9 +565,9 @@ | ||
| 562 | 565 | if ( ! $can_start_quiz ) { |
| 563 | 566 | return false; |
| 564 | 567 | } |
| 565 | 568 | |
| 566 | - $user_quiz = learn_press_user_start_quiz( $quiz_id, false, $course_id, $wp_error ); | |
| 569 | + $user_quiz = false; | |
| 567 | 570 | |
| 568 | 571 | /** |
| 569 | 572 | * Hook quiz started |
| 570 | 573 | * |
| @@ -573,9 +576,9 @@ | ||
| 573 | 576 | do_action( 'learn-press/user/quiz-started', $quiz_id, $course_id, $this->get_id() ); |
| 574 | 577 | |
| 575 | 578 | // $return = $user_quiz->get_mysql_data(); |
| 576 | 579 | $return = $user_quiz; |
| 577 | - } catch ( Exception $ex ) { | |
| 580 | + } catch ( Throwable $ex ) { | |
| 578 | 581 | $return = $wp_error ? new WP_Error( $ex->getCode(), $ex->getMessage() ) : false; |
| 579 | 582 | } |
| 580 | 583 | |
| 581 | 584 | return $return; |
| @@ -583,10 +586,10 @@ | ||
| 583 | 586 | |
| 584 | 587 | /** |
| 585 | 588 | * Finish a quiz for the user and save all data needed |
| 586 | 589 | * |
| 587 | - * @param int $quiz_id | |
| 588 | - * @param int $course_id | |
| 590 | + * @param int $quiz_id | |
| 591 | + * @param int $course_id | |
| 589 | 592 | * @param bool $wp_error |
| 590 | 593 | * |
| 591 | 594 | * @return LP_User_Item_Quiz|bool|WP_Error |
| 592 | 595 | */ |
| @@ -596,9 +599,9 @@ | ||
| 596 | 599 | try { |
| 597 | 600 | // If user has already finished the course |
| 598 | 601 | if ( $this->has_finished_course( $course_id ) ) { |
| 599 | 602 | throw new Exception( |
| 600 | - __( 'User has already finished course of this quiz', 'learnpress' ), | |
| 603 | + __( 'The user has already finished the course of this quiz.', 'learnpress' ), | |
| 601 | 604 | LP_COURSE_IS_FINISHED |
| 602 | 605 | ); |
| 603 | 606 | |
| 604 | 607 | } |
| @@ -605,9 +608,9 @@ | ||
| 605 | 608 | |
| 606 | 609 | // Check if user has already started or completed quiz |
| 607 | 610 | if ( $this->has_item_status( array( 'completed' ), $quiz_id, $course_id ) ) { |
| 608 | 611 | throw new Exception( |
| 609 | - __( 'User has completed quiz', 'learnpress' ), | |
| 612 | + __( 'The user has completed the quiz', 'learnpress' ), | |
| 610 | 613 | LP_QUIZ_HAS_STARTED_OR_COMPLETED |
| 611 | 614 | ); |
| 612 | 615 | } |
| 613 | 616 | |
| @@ -627,17 +630,18 @@ | ||
| 627 | 630 | |
| 628 | 631 | /** |
| 629 | 632 | * Retake a quiz for the user |
| 630 | 633 | * |
| 631 | - * @param int $quiz_id | |
| 632 | - * @param int $course_id | |
| 634 | + * @param int $quiz_id | |
| 635 | + * @param int $course_id | |
| 633 | 636 | * @param bool $wp_error |
| 634 | 637 | * |
| 635 | 638 | * @return bool|WP_Error|LP_User_Item_Quiz |
| 636 | 639 | * |
| 637 | 640 | * @throws Exception |
| 641 | + * @deprecated 4.2.7.2 | |
| 638 | 642 | */ |
| 639 | - public function retake_quiz( int $quiz_id, int $course_id, bool $wp_error = false ) { | |
| 643 | + /*public function retake_quiz( int $quiz_id, int $course_id, bool $wp_error = false ) { | |
| 640 | 644 | $return = false; |
| 641 | 645 | |
| 642 | 646 | try { |
| 643 | 647 | $course_id = $this->_verify_course_item( $quiz_id, $course_id ); |
| @@ -645,9 +649,9 @@ | ||
| 645 | 649 | if ( false === $course_id ) { |
| 646 | 650 | throw new Exception( |
| 647 | 651 | sprintf( |
| 648 | 652 | __( |
| 649 | - 'Course does not exist or does not contain the quiz.', | |
| 653 | + 'The course does not exist or does not contain a quiz.', | |
| 650 | 654 | 'learnpress' |
| 651 | 655 | ), |
| 652 | 656 | __CLASS__, |
| 653 | 657 | __FUNCTION__ |
| @@ -672,9 +676,9 @@ | ||
| 672 | 676 | // Check if user has already started or completed quiz |
| 673 | 677 | if ( ! $this->has_item_status( array( 'completed' ), $quiz_id, $course_id ) ) { |
| 674 | 678 | throw new Exception( |
| 675 | 679 | sprintf( |
| 676 | - __( '%1$s::%2$s - User has not completed quiz.', 'learnpress' ), | |
| 680 | + __( '%1$s::%2$s - The user has not completed the quiz.', 'learnpress' ), | |
| 677 | 681 | __CLASS__, |
| 678 | 682 | __FUNCTION__ |
| 679 | 683 | ), |
| 680 | 684 | LP_QUIZ_HAS_STARTED_OR_COMPLETED |
| @@ -685,9 +689,9 @@ | ||
| 685 | 689 | |
| 686 | 690 | if ( ! $this->has_retake_quiz( $quiz_id, $course_id ) ) { |
| 687 | 691 | throw new Exception( |
| 688 | 692 | sprintf( |
| 689 | - __( '%1$s::%2$s - Your Quiz can\'t retake.', 'learnpress' ), | |
| 693 | + __( '%1$s::%2$s - Your quiz can\'t be retaken.', 'learnpress' ), | |
| 690 | 694 | __CLASS__, |
| 691 | 695 | __FUNCTION__ |
| 692 | 696 | ), |
| 693 | 697 | LP_QUIZ_HAS_STARTED_OR_COMPLETED |
| @@ -702,18 +706,18 @@ | ||
| 702 | 706 | do_action( 'learn-press/user/retake-quiz-failure', $quiz_id, $course_id, $this->get_id() ); |
| 703 | 707 | } |
| 704 | 708 | |
| 705 | 709 | return $return; |
| 706 | - } | |
| 710 | + }*/ | |
| 707 | 711 | |
| 708 | 712 | /** |
| 709 | 713 | * Get quiz's user learning or completed |
| 710 | 714 | * |
| 711 | - * @param LP_User_Items_Filter $filter | |
| 715 | + * @param LP_User_Items_Filter|UserItemsFilter $filter | |
| 712 | 716 | * |
| 713 | 717 | * @return LP_Query_List_Table |
| 714 | 718 | */ |
| 715 | - public function get_user_quizzes( LP_User_Items_Filter $filter ): LP_Query_List_Table { | |
| 719 | + public function get_user_quizzes( $filter ): LP_Query_List_Table { | |
| 716 | 720 | $quizzes = [ |
| 717 | 721 | 'total' => 0, |
| 718 | 722 | 'items' => [], |
| 719 | 723 | 'pages' => 0, |
| @@ -789,6 +793,149 @@ | ||
| 789 | 793 | error_log( $e->getMessage() ); |
| 790 | 794 | } |
| 791 | 795 | |
| 792 | 796 | return $flag; |
| 797 | + } | |
| 798 | + | |
| 799 | + /** | |
| 800 | + * Get statistic info of student user | |
| 801 | + * | |
| 802 | + * @return array | |
| 803 | + * @since 4.1.6 | |
| 804 | + * @version 1.0.0 | |
| 805 | + */ | |
| 806 | + public function get_student_statistic(): array { | |
| 807 | + $user = $this; | |
| 808 | + $statistic = array( | |
| 809 | + 'enrolled_courses' => 0, | |
| 810 | + 'in_progress_course' => 0, | |
| 811 | + 'finished_courses' => 0, | |
| 812 | + 'passed_courses' => 0, | |
| 813 | + 'failed_courses' => 0, | |
| 814 | + ); | |
| 815 | + | |
| 816 | + try { | |
| 817 | + if ( ! $user ) { | |
| 818 | + throw new Exception( 'The user is invalid' ); | |
| 819 | + } | |
| 820 | + | |
| 821 | + $user_id = $user->get_id(); | |
| 822 | + $lp_user_items_db = LP_User_Items_DB::getInstance(); | |
| 823 | + | |
| 824 | + // Count status | |
| 825 | + $filter = new LP_User_Items_Filter(); | |
| 826 | + $filter->user_id = $user_id; | |
| 827 | + $count_status = $lp_user_items_db->count_status_by_items( $filter ); | |
| 828 | + $total_courses_enrolled = intval( $count_status->{LP_COURSE_PURCHASED} ?? 0 ) | |
| 829 | + + intval( $count_status->{LP_COURSE_ENROLLED} ?? 0 ) | |
| 830 | + + intval( $count_status->{LP_COURSE_FINISHED} ?? 0 ); | |
| 831 | + | |
| 832 | + $statistic['enrolled_courses'] = $total_courses_enrolled; | |
| 833 | + $statistic['in_progress_course'] = $count_status->{LP_COURSE_GRADUATION_IN_PROGRESS} ?? 0; | |
| 834 | + $statistic['finished_courses'] = $count_status->{LP_COURSE_FINISHED} ?? 0; | |
| 835 | + $statistic['passed_courses'] = $count_status->{LP_COURSE_GRADUATION_PASSED} ?? 0; | |
| 836 | + $statistic['failed_courses'] = $count_status->{LP_COURSE_GRADUATION_FAILED} ?? 0; | |
| 837 | + } catch ( Throwable $e ) { | |
| 838 | + error_log( __FUNCTION__ . ': ' . $e->getMessage() ); | |
| 839 | + } | |
| 840 | + | |
| 841 | + return apply_filters( 'lp/profile/student/statistic', $statistic, $this ); | |
| 842 | + } | |
| 843 | + | |
| 844 | + /** | |
| 845 | + * Get statistic info of instructor user | |
| 846 | + * | |
| 847 | + * @param array $params | |
| 848 | + * | |
| 849 | + * @return array | |
| 850 | + * @since 4.1.6 | |
| 851 | + * @version 1.0.1 | |
| 852 | + */ | |
| 853 | + public function get_instructor_statistic( array $params = [] ): array { | |
| 854 | + $statistic = array( | |
| 855 | + 'total_course' => 0, | |
| 856 | + 'published_course' => 0, | |
| 857 | + 'pending_course' => 0, | |
| 858 | + 'total_student' => 0, | |
| 859 | + 'student_completed' => 0, | |
| 860 | + 'student_in_progress' => 0, | |
| 861 | + ); | |
| 862 | + | |
| 863 | + try { | |
| 864 | + $user_id = $this->get_id(); | |
| 865 | + $lp_user_items_db = LP_User_Items_DB::getInstance(); | |
| 866 | + $lp_course_db = LP_Course_DB::getInstance(); | |
| 867 | + | |
| 868 | + if ( ! $this->can_create_course() ) { | |
| 869 | + throw new Exception( 'The user is not Instructor' ); | |
| 870 | + } | |
| 871 | + | |
| 872 | + // Count total user completed course of author | |
| 873 | + $filter_course = new LP_Course_Filter(); | |
| 874 | + $filter_course->only_fields = array( 'ID' ); | |
| 875 | + $filter_course->post_author = $user_id; | |
| 876 | + $filter_course->post_status = 'publish'; | |
| 877 | + $filter_course->return_string_query = true; | |
| 878 | + $query_courses_str = LP_Course_DB::getInstance()->get_courses( $filter_course ); | |
| 879 | + | |
| 880 | + $filter_count_users = new LP_User_Items_Filter(); | |
| 881 | + $filter_count_users->item_type = LP_COURSE_CPT; | |
| 882 | + $filter_count_users->where[] = "AND item_id IN ({$query_courses_str})"; | |
| 883 | + $count_student_has_status = $lp_user_items_db->count_status_by_items( $filter_count_users ); | |
| 884 | + // Count total user in progress course of author | |
| 885 | + | |
| 886 | + // Get total users attend course of author | |
| 887 | + $filter_count_users = $lp_user_items_db->count_user_attend_courses_of_author( $user_id ); | |
| 888 | + $count_users_attend_courses_of_author = $lp_user_items_db->get_user_courses( $filter_count_users ); | |
| 889 | + | |
| 890 | + // Get total courses publish of author | |
| 891 | + $filter_count_courses = $lp_course_db->count_courses_of_author( $user_id, [ 'publish' ] ); | |
| 892 | + $total_courses_publish_of_author = $lp_course_db->get_courses( $filter_count_courses ); | |
| 893 | + | |
| 894 | + // Get total courses of author | |
| 895 | + $filter_count_courses = $lp_course_db->count_courses_of_author( $user_id ); | |
| 896 | + $total_courses_of_author = $lp_course_db->get_courses( $filter_count_courses ); | |
| 897 | + | |
| 898 | + // Get total courses pending of author | |
| 899 | + $filter_count_courses = $lp_course_db->count_courses_of_author( $user_id, [ 'pending' ] ); | |
| 900 | + $total_courses_pending_of_author = $lp_course_db->get_courses( $filter_count_courses ); | |
| 901 | + | |
| 902 | + $statistic['total_course'] = $total_courses_of_author; | |
| 903 | + $statistic['published_course'] = $total_courses_publish_of_author; | |
| 904 | + $statistic['pending_course'] = $total_courses_pending_of_author; | |
| 905 | + $statistic['total_student'] = $count_users_attend_courses_of_author; | |
| 906 | + $statistic['student_completed'] = $count_student_has_status->{LP_COURSE_FINISHED} ?? 0; | |
| 907 | + $statistic['student_in_progress'] = $count_student_has_status->{LP_COURSE_GRADUATION_IN_PROGRESS} ?? 0; | |
| 908 | + } catch ( Throwable $e ) { | |
| 909 | + error_log( __FUNCTION__ . ': ' . $e->getMessage() ); | |
| 910 | + } | |
| 911 | + | |
| 912 | + return apply_filters( 'lp/profile/instructor/statistic', $statistic, $this ); | |
| 913 | + } | |
| 914 | + | |
| 915 | + /** | |
| 916 | + * Get url instructor. | |
| 917 | + * | |
| 918 | + * @return string | |
| 919 | + * @version 1.0.1 | |
| 920 | + * @since 4.2.3 | |
| 921 | + */ | |
| 922 | + public function get_url_instructor(): string { | |
| 923 | + $single_instructor_link = ''; | |
| 924 | + | |
| 925 | + try { | |
| 926 | + $author_id = $this->get_id(); | |
| 927 | + $userModel = UserModel::find( $author_id, true ); | |
| 928 | + if ( ! $userModel ) { | |
| 929 | + throw new Exception( 'User not found' ); | |
| 930 | + } | |
| 931 | + | |
| 932 | + $single_instructor_page_id = learn_press_get_page_id( 'single_instructor' ); | |
| 933 | + $user_slug = $userModel->get_slug_link(); | |
| 934 | + $single_instructor_link = trailingslashit( trailingslashit( get_page_link( $single_instructor_page_id ) ) . $user_slug ); | |
| 935 | + } catch ( Throwable $e ) { | |
| 936 | + LP_Debug::error_log( $e ); | |
| 937 | + } | |
| 938 | + | |
| 939 | + return $single_instructor_link; | |
| 793 | 940 | } |
| 794 | 941 | } |