Add 3 subplugins and amended pre-existing Step: coursedelete#297
Add 3 subplugins and amended pre-existing Step: coursedelete#297ccaewan wants to merge 9 commits intolearnweb:mainfrom
Conversation
Comment out plugin dependencies for future reference.
Updated context retrieval to handle missing courses gracefully.
Updated documentation for get_processes_by_workflow method to clarify orphaned process handling and fixed typos.
Added new upgrade steps for version 2026012004 and 2026012005, including cleanup of orphaned process records.
fix to prevent error message when proceeding or rolling back deleted course
|
@ccaewan very quick scan
|
Initially commented out to prevent error during instance upgrade
Response to 1 + 3The changes to deletecourse could be useful for the LC plugin in general as they offer a fix for the preexisting subplugin, so I'll keep them within the PR. The issue was similar to #294 except the deletion was not manual in my case but was via the LC deletecourse step. As for the 3 new subplugins I agree with the rebase. The best course of action will be to eventually move them to separate repos (once the recent #293 changes have been approved), considering the UCL niche of the subplugins. Response to 2I designed uclcontextfreeze taking https://ucldata.atlassian.net/browse/CTP-4885 into consideration - so the step has a hard dependency on block_lifecycle to action the archival of courses. I wasn't aware that this wasn't being used on live extend already. Should block_lifecycle be installed on live Extend to facilitate this? or should the context freeze logic be implemented directly into the archival step? |
|
Moved the 3 plugins to individual repos: Step: Triggers:
Will rebase onto #293 once it has been merged onto main or 405_stable |
🔀 Purpose of this PR:
📝 Description:
Course Delete Fix
What bug does it address?
When the
deletecoursestep deleted a course, an orphanedtool_lifecycle_processrecord was occasionally left behind pointing to the now-deleted course. On subsequent cron runs the LC would throw a fataldml_missing_record_exception(course ID not found) error, breaking the entire lifecycle workflow and preventing any further processing or manual intervention via the UI.Why is this change necessary?
The fatal exception blocked the workflow completely and could not be resolved without direct DB access. The never-accessed course exclusion meant courses eligible for deletion were silently skipped indefinitely.
Expected behaviour after the change:
get_processes_by_workflow()and moved to thetool_lifecycle_proc_errortable rather than crashing the workflowprocess::from_record()usesIGNORE_MISSINGwhen loading the course context, so it never throws on a deleted courseerrors.phpUI handles deleted course records gracefully when proceeding or rolling back, preventing a crash when actioning error recordsdeletecoursestep self-cleans its own orphaned process record if it encounters an already-deleted courseNew subplugins
The archival workflow:
I created a configurable trigger subplugin (coursefreeze) to target courses with (default values) last acc > 1yr and creation date > 2yrs.
Step subplugin (uclcontextfreeze) then calls the manager/service method used by the context freeze task to successfully archive (make read-only) the triggered courses directly from Lifecycle.
The deletion workflow:
The deletion workflow will use the pre existing deletecourse step in the lifecycle.
📋 Checklist
phpunitand/orbehattests that cover my changes or additions.var_dump()orvar_exportor any other debugging statements that should not appear on the productive branch.db/upgrade.phpand updated theversion.php.📋 Files changed
classes/local/entity/process.php— useIGNORE_MISSINGincontext_course::instance()classes/local/manager/process_manager.php— orphan detection inget_processes_by_workflow()errors.php— safeget_course()calls with try/catch for deleted coursesdb/upgrade.php— cleanup step for orphaned process records (version2026012005)version.php— bumped to2026012005steps/deletecourse/lib.php— self-cleaning guard for already-deleted coursesFiles added
trigger/coursedelete/lib.php— a configurable trigger to target archived courses that have Last access > x and creation date > xtrigger/coursefreeze/lib.php— a configurable trigger to target courses that have Last access > x and creation date > xstep/coursefreeze/lib.php— calls a uclcontextfreeze manager to archive coursesNotes for reviewers
Testing
🔍 Related Issues
🧾 Additional Information
The root of the deletion error was that
delete_course()removes the course record but does not guarantee atomic cleanup oftool_lifecycle_processentries, particularly if a previous cron run was interrupted. The fix applies defence in depth across three layers (entity, manager, step) so the system self-heals regardless of which code path encounters the orphaned record first.