Queries and URL helpers

Finding courses and lessons, and linking to them.

There is no query API

POM LMS does not provide functions for listing courses or fetching a course's lessons. Courses and lessons are ordinary posts, so you query them with WP_Query and get_posts() like anything else.

This article documents the shapes that produce correct results.

Listing courses

$courses = get_posts( [
    'post_type'      => 'course',
    'posts_per_page' => -1,
    'fields'         => 'ids',
] );

Courses have no archive, so there is no archive query to hook into and no archive template. Any catalogue is a query you write.

Always filter the result by access before showing content:

$accessible = array_filter( $courses, 'pom_lms_user_can_access_course' );

Titles and thumbnails can reasonably be shown for courses a visitor cannot open — that is a catalogue. Content cannot.

A course's lessons

Lessons name their course, not the other way round. Query lessons by the attached-course field:

$lessons = get_posts( [
    'post_type'      => 'lesson',
    'posts_per_page' => -1,
    'meta_key'       => 'pom_lms_lesson_course',
    'meta_value'     => $course_id,
    'orderby'        => 'menu_order',
    'order'          => 'ASC',
] );

orderby => menu_order reproduces the order editors set with the page-attributes order field, which is the order the course outline uses.

This returns every lesson attached to the course, including lessons with no section — which do not appear in the outline but are counted in progress. If you are reproducing the outline, group by section and expect some lessons to fall outside it.

Sections

Sections are defined on the course, as a repeater of named sections; each lesson names the section it belongs to.

Read them from the course's stored fields:

$course_metas = pom_lms_get_post_metas( $course_id );

Sections are content, not a taxonomy. There is no section archive, no section URL and no term to query by.

Post statuses

Only published lessons appear in the outline. When querying, keep the default status handling — a query that includes drafts will show editors' unfinished work to students.

URLs

Courses and lessons are posts, so get_permalink() is the correct way to link to them.

echo esc_url( get_permalink( $lesson_id ) );

Never build a course or lesson URL by concatenating a base and a slug. The base segments are configurable, and lesson URLs additionally change shape when the child structure is enabled — the URL from get_permalink() follows both, and a hand-built one does not.

The account area

Resolve the My courses URL through WooCommerce's account URL functions and the configured endpoint slug, rather than hard-coding a path. The slug is a setting, and sites change it.

Courses and lessons are queryable post types, so they can appear in site search depending on your theme's configuration.

Lesson results are usually a mistake: a lesson title out of context means nothing, and a blocked lesson in results advertises content the visitor cannot open. If your theme lets you choose searchable types, include courses and exclude lessons.

Performance

The lesson query above runs a meta lookup. On a course page rendering an outline, run it once and reuse the result rather than querying per section.

For access, remember that paid courses cost an order lookup each. A page listing a large catalogue with per-course access checks is the one place this plugin can get slow.