PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.4.10
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.4.10
4.4.10 4.4.9.1 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 All 142 releases
← All changes | inc/jwt/rest-api/version1/class-lp-rest-quiz-v1-controller.php +94 -4 4.4.8 → 4.4.10 View file →
@@ -112,8 +112,17 @@
112 112 );
113 113 }
114 114
115 115 /**
116 + * Allow guests/unauthenticated users to query the list endpoint (filtered by slug).
117 + * Per-item visibility is still enforced by check_read_permission, which only
118 + * allows preview items for guests.
119 + */
120 + public function get_items_permissions_check( $request ) {
121 + return true;
122 + }
123 +
124 + /**
116 125 * Checks if a course can be read.
117 126 *
118 127 * Correctly handles courses with the inherit status.
119 128 *
@@ -140,8 +149,20 @@
140 149 if ( ! $post_status_obj || ! $post_status_obj->public ) {
141 150 return false;
142 151 }
143 152
153 + // Allow guests and unenrolled users to read items marked as preview.
154 + $course_id = $this->get_course_by_item_id( $post_id );
155 + if ( $course_id ) {
156 + $course = learn_press_get_course( $course_id );
157 + if ( $course ) {
158 + $item = $course->get_item( $post_id );
159 + if ( $item && $item->is_preview() ) {
160 + return true;
161 + }
162 + }
163 + }
164 +
144 165 $user_id = get_current_user_id();
145 166
146 167 if ( ! $user_id ) {
147 168 return false;
@@ -148,11 +169,8 @@
148 169 }
149 170
150 171 $user = learn_press_get_user( $user_id );
151 172
152 - // Get course ID by lesson ID assigned.
153 - $course_id = $this->get_course_by_item_id( $post_id );
154 -
155 173 if ( empty( $course_id ) ) {
156 174 return false;
157 175 }
158 176
@@ -471,14 +489,18 @@
471 489 }
472 490
473 491 $duration = $quiz->get_duration();
474 492
493 + // Plugin's get_pagination() returns 0 when value <= 1 (treats 1 as "no pagination").
494 + // Override here so admins can set 1 question per page for step-by-step quizzes.
495 + $pagination_raw = absint( get_post_meta( $quiz->get_id(), '_lp_pagination', true ) );
496 +
475 497 $array = array(
476 498 'passing_grade' => $quiz->get_passing_grade(),
477 499 'negative_marking' => $quiz->get_negative_marking(),
478 500 'instant_check' => $quiz->get_instant_check(),
479 501 'retake_count' => (float) $quiz->get_retake_count(),
480 - 'questions_per_page' => $quiz->get_pagination(),
502 + 'questions_per_page' => $pagination_raw > 0 ? $pagination_raw : 0,
481 503 'page_numbers' => get_post_meta( $quiz->get_id(), '_lp_pagination_numbers', true ) === 'yes',
482 504 'review_questions' => $quiz->get_review_questions(),
483 505 'support_options' => learn_press_get_question_support_answer_options(),
484 506 'duration' => $duration ? $duration->get() : false,
@@ -494,8 +516,76 @@
494 516 'answered' => $answered,
495 517 'show_correct_review' => $show_correct_review,
496 518 )
497 519 );
520 +
521 + // Post-process FIB questions: the actual question content (with [fib] shortcodes)
522 + // is stored in lp_question_answers.title — NOT post_content. Read it from there,
523 + // strip `fill=` answers, replace shortcodes with {{FIB_<id>}} placeholders for
524 + // the client. On reveal, attach `fib_answers` with per-blank correctness.
525 + foreach ( $questions as &$q ) {
526 + if ( ! isset( $q['type'] ) || $q['type'] !== 'fill_in_blanks' ) {
527 + continue;
528 + }
529 +
530 + $question_obj = $q['object'] ?? null;
531 + if ( ! $question_obj || ! method_exists( $question_obj, 'get_data' ) ) {
532 + continue;
533 + }
534 +
535 + $question_id = $q['id'] ?? 0;
536 + $answer_options = $question_obj->get_data( 'answer_options' );
537 + if ( empty( $answer_options ) || ! is_array( $answer_options ) ) {
538 + continue;
539 + }
540 +
541 + $first_answer = reset( $answer_options );
542 + $raw_content = $first_answer['title'] ?? '';
543 + $answer_id = $first_answer['question_answer_id'] ?? 0;
544 + $user_answer = $answered[ $question_id ]['answered'] ?? '';
545 + $revealed = $show_check || $status === 'completed';
546 +
547 + $q['content'] = apply_filters(
548 + 'learn-press/question/fib/regex-content',
549 + $raw_content,
550 + $answer_id,
551 + $revealed,
552 + $user_answer
553 + );
554 +
555 + // FIB has no answer "options" in radio/checkbox sense; clear them.
556 + $q['options'] = array();
557 +
558 + if ( $revealed && method_exists( $question_obj, 'get_answer_data' ) ) {
559 + $q['fib_answers'] = $question_obj->get_answer_data(
560 + $raw_content,
561 + $answer_id,
562 + $user_answer
563 + );
564 + }
565 + }
566 + unset( $q );
567 +
568 + // Plugin's `learn_press_rest_prepare_user_questions()` only emits `explanation`
569 + // when the user explicitly triggered instant_check on a question (it reads
570 + // `$args['status']` which is never set in the defaults). For completed quizzes
571 + // fill in explanations here so clients can render them on the review screen.
572 + if ( $status === 'completed' ) {
573 + foreach ( $questions as &$q ) {
574 + if ( ! empty( $q['explanation'] ) ) {
575 + continue;
576 + }
577 + $question_obj = $q['object'] ?? null;
578 + if ( $question_obj && method_exists( $question_obj, 'get_explanation' ) ) {
579 + $explanation = $question_obj->get_explanation();
580 + if ( $explanation ) {
581 + $q['explanation'] = $explanation;
582 + $q['has_explanation'] = true;
583 + }
584 + }
585 + }
586 + unset( $q );
587 + }
498 588
499 589 $output['questions'] = $questions;
500 590 }
501 591