← All changes
|
inc/jwt/rest-api/version1/class-lp-rest-lessons-v1-controller.php
+68
-4
4.4.0
→
4.4.9
View file →
| @@ -1,8 +1,9 @@ | ||
| 1 | 1 | <?php |
| 2 | 2 | |
| 3 | 3 | use LearnPress\Models\CourseModel; |
| 4 | 4 | use LearnPress\Models\LessonPostModel; |
| 5 | +use LearnPress\Models\UserItems\UserCourseModel; | |
| 5 | 6 | use LearnPress\Models\UserItems\UserLessonModel; |
| 6 | 7 | use LearnPress\Models\UserModel; |
| 7 | 8 | |
| 8 | 9 | class LP_Jwt_Lessons_V1_Controller extends LP_REST_Jwt_Posts_Controller { |
| @@ -81,8 +82,17 @@ | ||
| 81 | 82 | ); |
| 82 | 83 | } |
| 83 | 84 | |
| 84 | 85 | /** |
| 86 | + * Allow guests/unauthenticated users to query the list endpoint (filtered by slug). | |
| 87 | + * Per-item visibility is still enforced by check_read_permission, which only | |
| 88 | + * allows preview items for guests. | |
| 89 | + */ | |
| 90 | + public function get_items_permissions_check( $request ) { | |
| 91 | + return true; | |
| 92 | + } | |
| 93 | + | |
| 94 | + /** | |
| 85 | 95 | * Checks if a course can be read. |
| 86 | 96 | * |
| 87 | 97 | * Correctly handles courses with the inherit status. |
| 88 | 98 | * |
| @@ -109,8 +119,20 @@ | ||
| 109 | 119 | if ( ! $post_status_obj || ! $post_status_obj->public ) { |
| 110 | 120 | return false; |
| 111 | 121 | } |
| 112 | 122 | |
| 123 | + // Allow guests and unenrolled users to read items marked as preview. | |
| 124 | + $course_id = $this->get_course_by_item_id( $post_id ); | |
| 125 | + if ( $course_id ) { | |
| 126 | + $course = learn_press_get_course( $course_id ); | |
| 127 | + if ( $course ) { | |
| 128 | + $item = $course->get_item( $post_id ); | |
| 129 | + if ( $item && $item->is_preview() ) { | |
| 130 | + return true; | |
| 131 | + } | |
| 132 | + } | |
| 133 | + } | |
| 134 | + | |
| 113 | 135 | $user_id = get_current_user_id(); |
| 114 | 136 | |
| 115 | 137 | if ( ! $user_id ) { |
| 116 | 138 | return false; |
| @@ -117,11 +139,8 @@ | ||
| 117 | 139 | } |
| 118 | 140 | |
| 119 | 141 | $user = learn_press_get_user( $user_id ); |
| 120 | 142 | |
| 121 | - // Get course ID by lesson ID assigned. | |
| 122 | - $course_id = $this->get_course_by_item_id( $post_id ); | |
| 123 | - | |
| 124 | 143 | if ( empty( $course_id ) ) { |
| 125 | 144 | return false; |
| 126 | 145 | } |
| 127 | 146 | |
| @@ -229,13 +248,58 @@ | ||
| 229 | 248 | $course_id, |
| 230 | 249 | LP_COURSE_CPT, |
| 231 | 250 | true |
| 232 | 251 | ); |
| 252 | + | |
| 253 | + // Auto-create user lesson item if user is enrolled but never opened the lesson. | |
| 233 | 254 | if ( ! $userLessonModel instanceof UserLessonModel ) { |
| 234 | - throw new Exception( __( 'You have not started lesson', 'learnpress' ) ); | |
| 255 | + $userCourseModel = UserCourseModel::find( get_current_user_id(), $course_id, true ); | |
| 256 | + if ( ! $userCourseModel instanceof UserCourseModel || ! $userCourseModel->has_enrolled_or_finished() ) { | |
| 257 | + throw new Exception( __( 'You must enroll the course first.', 'learnpress' ) ); | |
| 258 | + } | |
| 259 | + | |
| 260 | + $userLessonModel = new UserLessonModel(); | |
| 261 | + $userLessonModel->user_id = get_current_user_id(); | |
| 262 | + $userLessonModel->item_id = $id; | |
| 263 | + $userLessonModel->item_type = $lessonModel->post_type; | |
| 264 | + $userLessonModel->ref_id = $course_id; | |
| 265 | + $userLessonModel->ref_type = LP_COURSE_CPT; | |
| 266 | + $userLessonModel->parent_id = $userCourseModel->get_user_item_id(); | |
| 267 | + $userLessonModel->status = LP_ITEM_STARTED; | |
| 268 | + $userLessonModel->save(); | |
| 269 | + } elseif ( empty( $userLessonModel->parent_id ) ) { | |
| 270 | + // Repair legacy rows that were created without parent_id — without it, the lesson | |
| 271 | + // won't be counted by UserCourseModel::count_items_completed(). | |
| 272 | + $userCourseModel = UserCourseModel::find( get_current_user_id(), $course_id, true ); | |
| 273 | + if ( $userCourseModel instanceof UserCourseModel ) { | |
| 274 | + $userLessonModel->parent_id = $userCourseModel->get_user_item_id(); | |
| 275 | + $userLessonModel->save(); | |
| 276 | + } | |
| 235 | 277 | } |
| 236 | 278 | |
| 237 | 279 | $userLessonModel->set_complete(); |
| 280 | + | |
| 281 | + // Recalculate course progress and persist to learnpress_user_item_results. | |
| 282 | + $userCourseModel = $userLessonModel->get_user_course_model(); | |
| 283 | + if ( $userCourseModel instanceof UserCourseModel ) { | |
| 284 | + $course_results = $userCourseModel->calculate_course_results( true ); | |
| 285 | + LP_User_Items_Result_DB::instance()->update( | |
| 286 | + $userCourseModel->get_user_item_id(), | |
| 287 | + wp_json_encode( $course_results ) | |
| 288 | + ); | |
| 289 | + | |
| 290 | + // Auto-finish the course when evaluation criteria are met. | |
| 291 | + $can_finish = $userCourseModel->can_finish(); | |
| 292 | + if ( $can_finish === true && ! is_wp_error( $can_finish ) ) { | |
| 293 | + try { | |
| 294 | + $userCourseModel->set_finish(); | |
| 295 | + } catch ( Throwable $finishError ) { | |
| 296 | + // Non-fatal — user can still click Finish manually. | |
| 297 | + error_log( __METHOD__ . ' auto-finish: ' . $finishError->getMessage() ); | |
| 298 | + } | |
| 299 | + } | |
| 300 | + } | |
| 301 | + | |
| 238 | 302 | $response->status = 'success'; |
| 239 | 303 | $response->message = esc_html__( 'Congrats! You have completed the lesson successfully', 'learnpress' ); |
| 240 | 304 | } catch ( Throwable $th ) { |
| 241 | 305 | $response->message = $th->getMessage(); |