' . esc_html__( 'Reports', 'accessnow-lms' ) . '

'; if ( $user_id && $course_id ) { self::render_student_detail( $user_id, $course_id ); } elseif ( $course_id ) { self::render_course_detail( $course_id ); } else { self::render_overview(); } echo ''; } private static function render_overview() { $courses = get_posts( array( 'post_type' => 'slms_course', 'posts_per_page' => -1, 'post_status' => 'publish', 'orderby' => 'title', 'order' => 'ASC', ) ); echo '

'; Csv_Export::button( 'enrollments', __( 'Export all enrollments (CSV)', 'accessnow-lms' ) ); Csv_Export::button( 'quiz_attempts', __( 'Export all quiz attempts (CSV)', 'accessnow-lms' ) ); echo '

'; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; foreach ( $courses as $course ) { $active = Enrollment::count_enrollments( array( 'course_id' => $course->ID, 'status' => 'active', ) ); $completed = Enrollment::count_enrollments( array( 'course_id' => $course->ID, 'status' => 'completed', ) ); $avg_progress = Progress::get_average_progress( $course->ID ); $detail_url = add_query_arg( array( 'page' => 'slms-reports', 'course_id' => $course->ID, ), admin_url( 'admin.php' ) ); echo ''; printf( '', esc_html( $course->post_title ) ); printf( '', esc_html( number_format_i18n( (int) $active ) ) ); printf( '', esc_html( number_format_i18n( (int) $completed ) ) ); printf( '', esc_html( (int) $avg_progress ) ); printf( '', esc_url( $detail_url ), esc_html__( 'View Details', 'accessnow-lms' ) ); echo ''; } echo '
' . esc_html__( 'Course', 'accessnow-lms' ) . '' . esc_html__( 'Enrolled', 'accessnow-lms' ) . '' . esc_html__( 'Completed', 'accessnow-lms' ) . '' . esc_html__( 'Avg Progress', 'accessnow-lms' ) . '' . esc_html__( 'Actions', 'accessnow-lms' ) . '
%s%s%s%s%%%s
'; } private static function render_course_detail( $course_id ) { $course = get_post( $course_id ); if ( ! $course ) { echo '

' . esc_html__( 'Course not found.', 'accessnow-lms' ) . '

'; return; } $back_url = add_query_arg( 'page', 'slms-reports', admin_url( 'admin.php' ) ); printf( '

← %s

', esc_url( $back_url ), esc_html__( 'Back to Overview', 'accessnow-lms' ) ); printf( '

%s

', esc_html( $course->post_title ) ); echo '

'; Csv_Export::button( 'enrollments', __( 'Export enrollments (CSV)', 'accessnow-lms' ), $course_id ); Csv_Export::button( 'quiz_attempts', __( 'Export quiz attempts (CSV)', 'accessnow-lms' ), $course_id ); echo '

'; $enrollments = Enrollment::get_course_enrollments( $course_id ); echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; foreach ( $enrollments as $e ) { $user = get_userdata( $e->user_id ); $progress = Progress::get_course_progress( $e->user_id, $course_id, $e->id ); $detail_url = add_query_arg( array( 'page' => 'slms-reports', 'course_id' => $course_id, 'user_id' => $e->user_id, 'enrollment_id' => $e->id, ), admin_url( 'admin.php' ) ); echo ''; printf( '', esc_html( $user ? $user->display_name : '#' . $e->user_id ) ); printf( '', esc_html( ucfirst( $e->status ) ) ); printf( '', esc_html( (int) $progress ) ); printf( '', esc_html( $e->enrolled_at ) ); printf( '', esc_url( $detail_url ), esc_html__( 'View', 'accessnow-lms' ) ); echo ''; } echo '
' . esc_html__( 'Student', 'accessnow-lms' ) . '' . esc_html__( 'Status', 'accessnow-lms' ) . '' . esc_html__( 'Progress', 'accessnow-lms' ) . '' . esc_html__( 'Enrolled', 'accessnow-lms' ) . '' . esc_html__( 'Details', 'accessnow-lms' ) . '
%s%s%s%%%s%s
'; } private static function render_student_detail( $user_id, $course_id ) { $user = get_userdata( $user_id ); $course = get_post( $course_id ); if ( ! $user || ! $course ) { echo '

' . esc_html__( 'Course not found.', 'accessnow-lms' ) . '

'; return; } $enrollment_id = isset( $_GET['enrollment_id'] ) ? absint( $_GET['enrollment_id'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only report filter. if ( ! $enrollment_id ) { $enrollment = Enrollment::get_enrollment( $user_id, $course_id ); $enrollment_id = $enrollment ? $enrollment->id : 0; } $back_url = add_query_arg( array( 'page' => 'slms-reports', 'course_id' => $course_id, ), admin_url( 'admin.php' ) ); printf( '

← %s

', esc_url( $back_url ), esc_html__( 'Back to Course', 'accessnow-lms' ) ); printf( '

%s — %s

', esc_html( $user->display_name ), esc_html( $course->post_title ) ); $progress = Progress::get_course_progress( $user_id, $course_id, $enrollment_id ); printf( '

%s: %s%%

', esc_html__( 'Overall Progress', 'accessnow-lms' ), esc_html( (int) $progress ) ); // Show lesson completion status $lesson_ids = Progress::get_course_lesson_ids( $course_id ); echo '

' . esc_html__( 'Lessons', 'accessnow-lms' ) . '

'; echo ''; echo ''; echo ''; echo ''; foreach ( $lesson_ids as $lid ) { $complete = Progress::is_complete( $user_id, $lid, $enrollment_id ); echo ''; printf( '', esc_html( get_the_title( $lid ) ) ); printf( '', $complete ? esc_html__( 'Complete', 'accessnow-lms' ) : esc_html__( 'Incomplete', 'accessnow-lms' ) ); echo ''; } echo '
' . esc_html__( 'Lesson', 'accessnow-lms' ) . '' . esc_html__( 'Status', 'accessnow-lms' ) . '
%s%s
'; // Show quiz attempts global $wpdb; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- plugin table, admin report. $quiz_attempts = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}slms_quiz_attempts WHERE user_id = %d AND course_id = %d AND enrollment_id = %d ORDER BY completed_at DESC", $user_id, $course_id, $enrollment_id ) ); if ( ! empty( $quiz_attempts ) ) { echo '

' . esc_html__( 'Quiz Attempts', 'accessnow-lms' ) . '

'; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; foreach ( $quiz_attempts as $a ) { echo ''; printf( '', esc_html( get_the_title( $a->quiz_id ) ) ); printf( '', esc_html( (int) $a->attempt_number ) ); printf( '', esc_html( $a->score ) ); printf( '', esc_html( Quiz_Engine::attempt_status_label( $a ) ) ); printf( '', esc_html( $a->completed_at ) ); echo ''; } echo '
' . esc_html__( 'Quiz', 'accessnow-lms' ) . '' . esc_html__( 'Attempt', 'accessnow-lms' ) . '' . esc_html__( 'Score', 'accessnow-lms' ) . '' . esc_html__( 'Status', 'accessnow-lms' ) . '' . esc_html__( 'Date', 'accessnow-lms' ) . '
%s#%s%s%%%s%s
'; } } }