Module Research Notes
Evidence gathered from the current module files before writing the user guide pages.
Research Sources Inspected
Source path
modules/Learn
Feature flags marked true
- Controllers
- Models
- Views
- Language
- Permissions
- Left Menu
- Routes
- Migrations
- Cron Jobs
- Api Endpoints
Evidence Summary
Manifest
module.json defines slug courses, version 1.0.0, category Learnings, and the module capability flags used in this guide.
Runtime surface
29 controller file(s), 73 view file(s), and 77 route mapping(s) were found.
Data surface
23 model file(s), 17 declared table(s), and 20 migration file(s) were found.
Operations surface
9 permission key(s), 1 job(s), 2 seeder(s), and 0 test file(s) were found.
Detailed File Evidence
Controllers and methods
CertificationsCourse_categoriesCourse_choicesCourse_discussionsCourse_enrollmentsCourse_enumerationsCourse_essaysCourse_examsCourse_groupsCourse_modulesCourse_portalCourse_questionsCoursesInstructor_applicationsLearn_aiLearn_api_courses- index, viewLearn_attemptsLearn_certificate_templatesLearn_certificatesLearn_gradebookLearn_me_courses- index, viewLearn_pointsLearn_settings- seo, save_seo_settingsLearn_studentSkillsetsSkillsets_job_functionSkillsets_workforceUniversityUniversity_settings
Jobs and schedules
- Sync public catalog counts (30 3 * * *) - Recomputes each tenant\
Routes sampled
| Route | Target |
|---|---|
learn/courses | Courses/index |
learn/courses/(:any) | Courses/$1 |
learn/courses/(:any)/(:any) | Courses/$1/$2 |
learn/course_categories | Course_categories/index |
learn/course_categories/(:any) | Course_categories/$1 |
learn/course_categories/(:any)/(:any) | Course_categories/$1/$2 |
learn/course_enrollments | Course_enrollments/index |
learn/course_enrollments/(:any) | Course_enrollments/$1 |
learn/course_enrollments/(:any)/(:any) | Course_enrollments/$1/$2 |
learn/course_modules | Course_modules/index |
learn/course_modules/(:any) | Course_modules/$1 |
learn/course_modules/(:any)/(:any) | Course_modules/$1/$2 |
learn/course_groups | Course_groups/index |
learn/course_groups/(:any) | Course_groups/$1 |
learn/course_groups/(:any)/(:any) | Course_groups/$1/$2 |
learn/course_groups/(:any)/(:any)/(:any) | Course_groups/$1/$2/$3 |
learn/course_exams | Course_exams/index |
learn/course_exams/(:any) | Course_exams/$1 |
learn/course_exams/(:any)/(:any) | Course_exams/$1/$2 |
learn/course_exams/(:any)/(:any)/(:any) | Course_exams/$1/$2/$3 |
| 57 additional route(s) omitted for readability. | |
README topics
- Layout
- Demo seeder
- Naming
- Migration history
Operating Implications
- Permission coverage is part of the module contract, so every workflow should be tested with a role-limited user and an administrator.
- The module has migrations, so fresh installs and tenant databases need migration validation before go-live.
- The module has a public or portal-facing surface, so privacy review and logged-out testing are required.
- The module has API documentation or routes, so response examples and query filters should stay aligned with user-facing screens.
- Scheduled jobs can change statuses, notifications, or summaries after users leave the screen; support should check cron status during troubleshooting.
- Seeders exist for sample or starter data; operators should know whether seeded records are demo-only or operational defaults.
Known Risks from the Manifest
- The legacy learn_* tables (learn_courses, learn_categories, learn_module, learn_group, learn_exams, learn_questions, learn_choices, learn_discussions, learn_students) ship in the base install schema (install/migration/schema.php). The newer tables (learn_progress, learn_attempts, learn_answers, learn_certificates, learn_university_settings) and the Phase 1 learn_choices audit-block ALTER are MODULE-OWNED migrations under modules/Learn/migrations/ (tracked in the migrations_courses table). Because Tenant_provisioner runs only core migrations, a newly provisioned tenant does NOT receive these tables/columns at provision time - they are applied by `php erpat migrate:latest`/`migrate:modules` (primary DB) and by the Tenancy Bulk/per-tenant Database Migration tools (erpat_run_module_migrations) against each tenant DB. Run a tenant migration pass after enabling Learn so the schema reaches every tenant (same constraint as the Production and Warehouse module-owned tables).
- The public /university providers directory reads DENORMALIZED columns on the main-DB clients registry - public_course_count, public_learning_meta and public_learning_categories - so a public page hit never scans each tenant DB. These are CORE migrations (application/migrations/, main DB only; NOT module-owned, per the module-files G5 boundary): 20260704062702_add_public_course_count_to_clients.php and 20260704125247_add_public_learning_meta_to_clients.php. They are maintained live by learn_sync_public_course_count() (University_settings::save, Courses::save/update_status/delete) and reconciled by the SyncPublicCatalogCountJob cron. After migrating, run `php erpat cron:run sync_public_catalog_count` to backfill; the directory cards degrade to name+count until a sync has run for each tenant.