The content model
What POM LMS stores, and how courses, lessons and students relate to each other.
Two post types
| Post type | Key | Notes |
|---|---|---|
| Course | course |
No archive; supports title, editor, thumbnail and comments |
| Lesson | lesson |
Listed under the Courses menu; additionally supports page attributes for ordering |
Both are ordinary posts. Everything WordPress does with posts — authors, statuses, revisions of the editor content, taxonomies registered against them by the theme — applies.
Courses have no archive, so there is no automatic /courses/ listing and no archive template to override. A catalogue page is something the site builds.
The relationship
A lesson names its course. The course names its sections.
Course
├── Sections (defined on the course, as a repeater)
└── Lessons (each naming its course and one of those sections)
Consequences that matter when you build on it:
- Lessons are attached from the lesson side. The course does not hold a list of its lessons; you find them by querying lessons that name the course.
- A lesson belongs to exactly one course. To use the same material in two courses, duplicate the lesson.
- A lesson with no course cannot render. The lesson template returns not found, because there are no access rules to apply.
- A lesson naming a section that no longer exists is still attached to the course — it is counted in progress and absent from the outline.
Ordering
Lessons are ordered within a section by the WordPress menu order field, exposed in the editor as the page-attributes order.
Query lessons with orderby => menu_order to reproduce the outline's order.
Access data
Access configuration lives on the course, with optional overrides on the lesson:
| Concern | Where |
|---|---|
| Login requirement | Course |
| Permission rule | Course, overridable per lesson |
| Paid flag and attached products | Course |
| Preview flag | Lesson |
| No-access text | Course, overridable per lesson |
Read them through the access helpers rather than directly. The helpers encode the precedence, and the precedence is the part that must not be reimplemented. See The access control contract.
Progress data
Completion is stored per student, per course: which lessons that student has completed in that course.
Read it with pom_lms_get_course_completion(), and change it with pom_lms_check_lesson(). See Completion helpers.
Progress is keyed by course, so moving a lesson to another course leaves the old record behind and starts the lesson uncompleted in its new home.
What is not stored
Worth knowing before you plan a feature on top:
- No enrollment record. There is no list of students in a course. Access is computed on every request from roles, rules and orders.
- No timestamps. Nothing records when a student started, finished, or last opened a lesson.
- No scores, attempts or submissions.
- No certificates.
If your integration needs any of those, it needs its own storage.