Problem/Motivation
hook_lms_initialize_lesson (#3550125) only fires when a LessonStatus is first created. It does not fire on subsequent visits to the same lesson.
For modules that let teachers dynamically check/uncheck lessons (e.g., unlock Lesson 3 on Monday, lock it again on Wednesday), this means a student who already visited a lesson can still access it even after the teacher revoked access.
Steps to reproduce
Proposed resolution
Add a new hook_lms_lesson_access invoked on every lesson request. The hook receives the $lesson_status and modules can throw a TrainingException to deny access with a custom message and redirect, the same way as hook_lms_initialize_lesson.
The hook should be invoked in 3 places in TrainingManager:
getRequestedLessonStatus() — same lesson path (after load/initialize, before return)
getRequestedLessonStatus() — different lesson path (after load/initialize, before save)
getNextLessonStatus() — before returning the loaded/initialized status
In all cases, TrainingException is already caught by CourseControllerTrait::handleError().
Remaining tasks
User interface changes
API changes
<?php
function hook_lms_lesson_access(\Drupal\lms\Entity\LessonStatusInterface $lesson_status): void {
// Throw TrainingException to deny access.
}
Comments