Skip to content

Migrate learner management start date to progress repositories#7933

Open
donnapep wants to merge 17 commits into
trunkfrom
add/hpps-learner-start-date-pr
Open

Migrate learner management start date to progress repositories#7933
donnapep wants to merge 17 commits into
trunkfrom
add/hpps-learner-start-date-pr

Conversation

@donnapep

@donnapep donnapep commented Apr 1, 2026

Copy link
Copy Markdown
Member

Summary

  • Adds set_started_at() to course and lesson progress model interfaces/abstracts (follows existing set_updated_at() pattern)
  • Migrates the Students AJAX handler (edit_date_started) from get/update_comment_meta to progress repository get()/set_started_at()/save()
  • Migrates the Students list table start date display from get_comment_meta to repository lookup

Related

  • Sensei Pro companion PR: Automattic/sensei-pro#2695 — migrates course-expiration date editing off the deprecated sensei_learners_learner_updated filter onto the new sensei_students_row_updated hook. Release in lockstep (Pro bumps its minimum Sensei to 4.26.2).

Test plan

HPPS disabled (comments storage)

  • Go to Sensei LMS → Settings → Experimental Features
  • Uncheck "High-Performance Progress Storage" and save
  • Navigate to Sensei LMS → Students (the top-level menu item)
  • In the students list, find a student enrolled in a course and click the course name in their row
  • Verify the Date Started column displays correctly
  • Click the date to edit it, change it, and save — verify the new date persists after page reload
  • Click the Lessons tab, then Manage students on a lesson
  • Verify the lesson's Date Started column displays correctly
  • Click the date to edit it, change it, and save — verify the new date persists after page reload

HPPS enabled (tables storage)

  • Go to Sensei LMS → Settings → Experimental Features
  • Check "High-Performance Progress Storage"
  • Select "High-Performance progress storage (experimental)" for the repository option and save
  • Navigate to Sensei LMS → Students, find a student and click the course name in their row
  • Verify the Date Started column displays correctly
  • Click the date to edit it, change it, and save — verify the new date persists after page reload
  • Click the Lessons tab, then Manage students on a lesson
  • Verify the lesson's Date Started column displays correctly
  • Click the date to edit it, change it, and save — verify the new date persists after page reload

Sync check

  • If sync is enabled: after editing a date in tables mode, switch back to comments mode (uncheck HPPS) and verify the edited date carried over

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings April 1, 2026 18:44

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR migrates Learner Management “start date” read/edit functionality away from direct comment meta access and into the internal student progress repositories, adding a set_started_at() API to course/lesson progress models to support that change across storage backends (comments vs HPPS tables).

Changes:

  • Add set_started_at() to course + lesson progress interfaces/abstracts (mirroring the existing set_updated_at() pattern) and add unit tests for it.
  • Update the Learner Management AJAX handler (edit_date_started) to update started_at via the appropriate progress repository and persist via save().
  • Update the Learners list table “start date” display to read from the progress repository rather than get_comment_meta().

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
tests/unit-tests/internal/student-progress/lesson-progress/models/test-class-tables-based-lesson-progress.php Adds unit coverage for set_started_at() on tables-based lesson progress.
tests/unit-tests/internal/student-progress/lesson-progress/models/test-class-comments-based-lesson-progress.php Adds unit coverage for set_started_at() on comments-based lesson progress.
tests/unit-tests/internal/student-progress/course-progress/models/test-class-tables-based-course-progress.php Adds unit coverage for set_started_at() on tables-based course progress.
tests/unit-tests/internal/student-progress/course-progress/models/test-class-comments-based-course-progress.php Adds unit coverage for set_started_at() on comments-based course progress.
includes/internal/student-progress/lesson-progress/models/class-lesson-progress-interface.php Introduces set_started_at() to the lesson progress model contract.
includes/internal/student-progress/lesson-progress/models/class-lesson-progress-abstract.php Implements set_started_at() in the shared lesson progress base class.
includes/internal/student-progress/course-progress/models/class-course-progress-interface.php Introduces set_started_at() to the course progress model contract.
includes/internal/student-progress/course-progress/models/class-course-progress-abstract.php Implements set_started_at() in the shared course progress base class.
includes/admin/class-sensei-learners-main.php Reads started_at via progress repositories for display in Learner Management rows.
includes/admin/class-sensei-learner-management.php Writes started_at via progress repositories in the edit_date_started AJAX endpoint.
changelog/add-hpps-learner-management-start-date Changelog entry for the migration to repository-based start date handling.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread includes/admin/class-sensei-learner-management.php Outdated
Comment thread includes/admin/class-sensei-learner-management.php Outdated
Comment thread includes/admin/class-sensei-learner-management.php Outdated
Comment thread includes/admin/class-sensei-learner-management.php
Comment thread includes/admin/class-sensei-learners-main.php Outdated
@donnapep donnapep force-pushed the add/hpps-learner-start-date-pr branch from c9d3191 to fe5abad Compare April 1, 2026 19:06
@donnapep donnapep added this to the 4.26.0 milestone Apr 1, 2026
@donnapep donnapep self-assigned this Apr 1, 2026
@donnapep donnapep added the HPPS label Apr 1, 2026
donnapep and others added 4 commits April 1, 2026 15:20
Add set_started_at() to course and lesson progress model interfaces and
abstract classes. Migrate edit_date_started() in learner management and
the start date display in learners-main to use progress repositories
instead of direct comment meta access. Update the
sensei_learners_learner_updated filter to pass user_id instead of
comment_id.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Convert date to UTC before set_started_at() for tables-based storage
- Compute $updated from old vs new started_at comparison
- Preserve hook backward compat: keep deprecated comment_id param (0), add user_id as 4th
- Use absint() instead of sanitize_key() for user_id
- Use wp_date() with wp_timezone() for start date display
- Fix equals sign alignment in learners-main

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Split course/lesson repo branches to avoid union type on save()
- Guard $post_id against false before passing to repo get()
- Cast wp_date() return to string to satisfy esc_attr() type

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@donnapep donnapep force-pushed the add/hpps-learner-start-date-pr branch from 04aadef to fc51a1f Compare April 1, 2026 19:22
…ment

The filter's $comment_id parameter is a storage implementation detail
that no longer applies across both storage backends.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@donnapep donnapep modified the milestones: 4.26.0, 4.26.1 Jun 8, 2026
@donnapep donnapep added this to the 4.26.2 milestone Jun 18, 2026
@github-actions

github-actions Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

WordPress Playground Preview

The changes in this pull request can previewed and tested using a WordPress Playground instance.

Open WordPress Playground Preview

donnapep and others added 9 commits June 19, 2026 10:17
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Convert exit() to wp_die() in edit_date_started so the AJAX handler is
catchable in tests, and move set_started_at()/save() after the no-op
guard to avoid a redundant write when the date is unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Revert untested guard clauses to exit() so Psalm keeps type narrowing
(wp_die() is not stubbed as noreturn), keeping wp_die() only on the
tested no-op and success paths, and suppress the correlated-union
warning on the repository save.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@donnapep donnapep requested a review from Copilot June 19, 2026 18:23

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.

Comment thread tests/unit-tests/admin/test-class-sensei-learner-management.php Outdated
Comment thread tests/unit-tests/admin/test-class-sensei-learner-management.php Outdated
Comment thread includes/admin/class-sensei-learner-management.php
donnapep and others added 2 commits June 19, 2026 15:13
…row_updated

Add sensei_students_row_updated, passing user_id and post_type so listeners
work under both comments and tables storage, and honor its return value.
Keep firing the deprecated sensei_learners_learner_updated for back compat,
pointing it at the new hook.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… docs

- Use absint( wp_unslash() ) for post_id instead of sanitize_key()
- Assert saved start date via wp_date() in site timezone so the test is
  stable under HPPS/tables storage and non-UTC timezones
- Correct the invoke helper docblock: only the tested paths wp_die();
  validation paths use exit

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@donnapep donnapep added the Deprecation This change introduces a deprecation. label Jun 19, 2026
@donnapep

Copy link
Copy Markdown
Member Author

@merkushin Got this PR ready before I head out for some AFK. This one pairs with https://github.com/Automattic/sensei-pro/pull/2695. I've given you read-only access to Sensei Pro. 🙌🏻

@merkushin

Copy link
Copy Markdown
Contributor

@donnapep Haha, I got the invitation, but not a notification about this mention 😅 (Perhaps I choked my notifications from GitHub too much.) And I encountered the comment because I was investigating where sensei_students_row_updated was added :)
I'm skimming them briefly now, but will check more thoroughly on the weekend.

@merkushin merkushin left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good and works as described in the test instructions.

I noticed a coulple of potential visual bugs, not related to the PR.

Image

The bubble is missing the blue background. In fact, it was more trickier — it sometimes appeared, sometimes disappeared on hovering the main menu, etc.

Initially, I blamed the assets, but I checked assets were built, and generally styles looked good.

Image

The spacing on the left looks weird.
Again, I hope it was just the issue of my setup…

$post_id = absint( wp_unslash( $_POST['data']['post_id'] ) );
} else {
exit( '' );
exit;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Every time I see these exits, I'm crying 🥲

Comment on lines +526 to +528
$repository = 'course' === $post_type
? Sensei()->course_progress_repository_factory->create()
: Sensei()->lesson_progress_repository_factory->create();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A tiny possible improvement here could be to hide this logic behind a factory method like:

$repository = Sensei()->create_progress_repository( $post_type );

Comment on lines +541 to +543
$progress_repository = 'course' === $post_type
? Sensei()->course_progress_repository_factory->create()
: Sensei()->lesson_progress_repository_factory->create();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No surprise, that factory method could be used here as well.
Perhaps, there are (or will be) even more places for it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Deprecation This change introduces a deprecation. HPPS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants