Make Reports Overview students and courses tabs read HPPS progress tables - #8171
Make Reports Overview students and courses tabs read HPPS progress tables#8171donnapep wants to merge 19 commits into
Conversation
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
docs/plans/sen83.md was staged before this task started and got swept into the previous commit. Remove it from git tracking; the working-artifact file stays on disk, untracked, as intended. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Rides the existing grade join with GROUP BY user_id so per-row average grade can be primed once per page, instead of one query per user. Implemented in both the tables-based and comments-based services, with tests pinning parity between them (auto-passed lessons without a real quiz attempt are excluded in both). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Extend prime_row_aggregates() in the students overview list table to also fetch per-user grade totals via Grading_Stats_Service_Interface, and have get_row_data() read from that primed cache instead of running per-row Sensei_Utils::sensei_check_for_activity / Sensei_Grading::get_user_graded_lessons_sum calls. Deprecate the now-unused sensei_analysis_user_lesson_grades filter. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Ports count_statuses_by_post, get_lesson_completion_counts, and get_courses_average_days_to_completion into both the comments-based and tables-based Progress_Aggregation_Service implementations. These generalize the private per-course queries currently in Sensei_Reports_Overview_Service_Courses to work with prepared placeholders instead of raw ID interpolation, powering the Courses overview aggregates. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace the raw comments-table queries in Sensei_Reports_Overview_Service_Courses with calls to Progress_Query_Service_Factory's aggregation service, so students count, lesson completions, and average days to completion read from HPPS progress tables when tables storage is active. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Branch the students report's last-activity join on the active progress storage mode. In tables mode it derives last_activity_date from sensei_lms_progress, mirroring the quiz-effective-status join used by Tables_Based_Progress_Aggregation_Service::count_lesson_statuses_with_quiz() so passed/graded lessons (whose granular status lives on the quiz progress row) are counted correctly. Comments mode is unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Course-scoped counterpart to get_grade_totals_by_user, needed so the reports overview courses table can prime its per-row average grade in one query per page instead of one query per course row. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replaces the per-row sensei_check_for_activity() + get_course_users_grades_sum() calls with a single get_grade_totals_by_course() call primed once per page, matching the pattern already used for the students table. Deprecates the now-unused sensei_analysis_course_percentage filter. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Extract the per-course average progress calculation out of get_total_average_progress() into a new public get_average_progress_per_course() method, so the courses list table can prime per-row progress from primed table-aware data instead of running per-row comment queries. get_total_average_progress() now sums the per-course values, keeping its return value unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace the courses list table's remaining per-row comment queries (completions, feeding both the completions and completion_rate columns, and average_progress) with cache lookups primed for the current page via count_statuses_by_post() and the new get_average_progress_per_course() service method. This makes both columns storage-aware in HPPS mode, same as the other columns on this table. Also deprecates the now-unused sensei_analysis_course_completions filter. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR updates the Reports → Overview Students and Courses tabs to read progress/grade metrics from the active progress storage backend (comments vs HPPS tables), and reduces query volume by priming per-page aggregates rather than recalculating per row.
Changes:
- Prime per-page aggregates for Students/Courses list tables (course status counts, grade totals, completions, average progress) and reuse them for row rendering + CSV export.
- Extend the internal aggregation/grading stats services with grouped “totals” APIs (by user, by post, lesson completion counts, courses avg days-to-completion).
- Update unit tests to seed fixtures through the appropriate repositories and validate tables-mode behavior (last activity, sorting, per-row aggregates).
Reviewed changes
Copilot reviewed 20 out of 20 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/unit-tests/reports/overview/services/test-class-sensei-reports-overview-service-courses.php | Adds HPPS-aware fixtures and new coverage for per-course average progress calculations. |
| tests/unit-tests/reports/overview/list-table/test-class-sensei-reports-overview-list-table-students.php | Adds tests asserting primed per-row course counts and grade totals behavior. |
| tests/unit-tests/reports/overview/list-table/test-class-sensei-reports-overview-list-table-courses.php | Adds tests asserting primed per-row grade totals, completions, and average progress behavior. |
| tests/unit-tests/reports/overview/data-provider/test-class-sensei-reports-overview-data-provider-students.php | Adds tables-mode coverage for last activity sourcing and sorting; aligns repository mode during tests. |
| tests/unit-tests/internal/services/test-class-tables-based-progress-aggregation-service.php | Expands coverage for newly added aggregation methods and table-mode parity behaviors. |
| tests/unit-tests/internal/services/test-class-tables-based-grading-stats-service.php | Adds coverage for new grade totals grouped APIs in tables mode. |
| tests/unit-tests/internal/services/test-class-comments-based-progress-aggregation-service.php | Adds coverage for newly added aggregation methods in comments mode. |
| tests/unit-tests/internal/services/test-class-comments-based-grading-stats-service.php | Adds coverage for new grade totals grouped APIs in comments mode. |
| includes/reports/overview/services/class-sensei-reports-overview-service-courses.php | Refactors average progress + days-to-completion to use backend-appropriate aggregation services. |
| includes/reports/overview/list-table/class-sensei-reports-overview-list-table-students.php | Primes per-page user aggregates (course counts, grade totals) and deprecates now-unused per-row filters. |
| includes/reports/overview/list-table/class-sensei-reports-overview-list-table-courses.php | Primes per-page course aggregates (grade totals, completions, average progress) and removes per-row queries/filters. |
| includes/reports/overview/list-table/class-sensei-reports-overview-list-table-abstract.php | Adds an extension point to prime caches before CSV row generation. |
| includes/reports/overview/data-provider/class-sensei-reports-overview-data-provider-students.php | Adds tables-mode last activity join logic for correct sorting/filtering when using HPPS tables. |
| includes/internal/services/class-tables-based-progress-aggregation-service.php | Adds grouped aggregation APIs (by user/post, lesson completions, courses avg days-to-completion). |
| includes/internal/services/class-tables-based-grading-stats-service.php | Adds grouped grade totals APIs (by user/course) for tables mode. |
| includes/internal/services/class-progress-aggregation-service-interface.php | Extends the interface to include the new aggregation methods. |
| includes/internal/services/class-grading-stats-service-interface.php | Extends the interface to include the new grade totals methods. |
| includes/internal/services/class-comments-based-progress-aggregation-service.php | Implements the new aggregation APIs for comments mode. |
| includes/internal/services/class-comments-based-grading-stats-service.php | Implements the new grade totals APIs for comments mode. |
| changelog/prime-students-reports-course-counts | Changelog entry for students per-row course counts using HPPS. |
| changelog/fix-reports-overview-students-last-activity-hpps | Changelog entry for students last activity using HPPS. |
| changelog/fix-reports-overview-students-average-grade-hpps | Changelog entry for students average grade using HPPS. |
| changelog/fix-reports-overview-courses-completions-progress-hpps | Changelog entry for courses completions/progress using HPPS. |
| changelog/fix-reports-overview-courses-average-grade-hpps | Changelog entry for courses average grade using HPPS. |
| changelog/fix-reports-overview-courses-aggregates-hpps | Changelog entry for courses aggregates using HPPS. |
Suppressed comments (2)
includes/reports/overview/list-table/class-sensei-reports-overview-list-table-courses.php:332
$average_progress_by_courseomits courses that have no enrolled students or no lessons, but the row renderer defaults missing entries to0%. That changes the previous behavior (N/A) and can mislead by implying zero progress rather than “not applicable”. PreserveN/Awhen the course has no computable average, while still showing0%for real computed zeroes.
$average_course_progress = $this->average_progress_by_course[ (int) $item->ID ] ?? 0;
$average_course_progress = esc_html( sprintf( '%d%%', round( $average_course_progress ) ) );
includes/reports/overview/list-table/class-sensei-reports-overview-list-table-students.php:62
- The PR description’s “Deprecated Code” list omits
sensei_analysis_user_lesson_grades, but this list table now explicitly deprecates that hook as well. Please update the PR description (and any release notes) so consumers aren’t surprised by the additional deprecated filter.
if ( has_filter( 'sensei_analysis_user_courses_started' ) ) {
_deprecated_hook( 'sensei_analysis_user_courses_started', '$$next-version$$' );
}
if ( has_filter( 'sensei_analysis_user_courses_ended' ) ) {
_deprecated_hook( 'sensei_analysis_user_courses_ended', '$$next-version$$' );
}
if ( has_filter( 'sensei_analysis_user_lesson_grades' ) ) {
_deprecated_hook( 'sensei_analysis_user_lesson_grades', '$$next-version$$' );
}
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A course with no enrolled students or no lessons has no computable average progress. Restore the previous N/A display for those courses instead of showing 0%, which wrongly implied zero progress. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Match the ordering in class-sensei-reports-overview-list-table-lessons.php. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Split into 8 stacked, individually-testable PRs (one field each). Reviewing/merging these in order supersedes this PR:
Each is stacked on the previous (#8203 → trunk). Keeping this PR open as the tracking umbrella. |
|
PR #8224 ( That hook only fires inside
On tables + WPML secondary language, those IDs are translations while progress is stored under originals → completions/grades/progress come back 0 / N/A. Before merging any of these: translate the incoming IDs to original language inside the table service, reusing the existing per-ID filters ( |
SEN-83
Proposed Changes
Sensei can store student progress in two ways: the older comment-based storage, or the newer High-Performance Progress Storage (HPPS) tables. On HPPS sites, progress is also mirrored into the comment storage (synchronization is required in that mode), so the Reports screen's Students and Courses tabs — which still read several of their numbers from the comment storage — show correct numbers today.
The problem is that these tabs only stay correct as long as that synchronization is on and never drifts. This change makes both tabs read directly from whichever storage the site actually uses, so they're correct on their own and no longer depend on synchronized comment data. The numbers you see are unchanged in every case; as a bonus, each row's values are now looked up once per page instead of once per row, so the tabs run far fewer database queries.
Now reading from whichever storage the site is set to use:
Known limitation: the Courses tab's per-row Days to Completion value comes from a separate progress service that has a pre-existing HPPS issue, tracked separately. It's out of scope here.
Testing Instructions
Do this first on a site using the default (comment-based) storage, then repeat on HPPS to confirm the numbers match.
Deprecated Code
These per-row filters no longer run, because the values now come from a single batched query per page. They have no replacement:
sensei_analysis_user_courses_startedsensei_analysis_user_courses_endedsensei_analysis_user_lesson_gradessensei_analysis_course_percentagesensei_analysis_course_completions