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.