Skip to content
Learnomy

Course Access and Enrollment

Enrollment is the record that a student has access to a course. Learnomy grants that access based on the course's access type (free, paid, membership, or both) and keeps one enrollment row per student, per course, per source, so a student who reaches a course through more than one path never loses access when one path ends.

What you can do

  • Let a signed-in student enrol in a free course with one click and no payment.
  • Route paid and members-only courses to checkout or the membership page instead of a plain Enroll button, so nobody reaches a course without the access they paid for.
  • Grant access by hand from the admin, either one student at a time or in bulk from a list of emails.
  • Remove a student's access to a single course, or clear all of a student's enrollments at once.
  • Require students to finish prerequisite courses before they can enrol.
  • Keep membership access and a one-time purchase side by side on the same course, because each source is its own enrollment row.
  • Have fixed-term (time-limited) enrollments expire automatically once their access window ends.

Course access and enrollment first view

How to use it

Step 1 -- set how the course is reached

The Enroll button a student sees is driven by the course's access type. Edit the course, open the Pricing & Access section, and pick a pricing model. Free courses show an instant Enroll button; paid and members-only courses show a Buy or membership CTA instead. See Pricing and Access Models for the full model list.

Step 2 -- let students enrol themselves

On the single course page (/courses/<slug>/) a student who is not yet enrolled sees the enroll card in the sidebar:

  • Free course -- an Enroll Now button that enrols them instantly and drops them into the course.
  • Paid course -- a Buy button that routes to checkout; the enrollment is created only after payment completes.
  • Members-only course -- a link to the membership page; the enrollment is created from their active membership.

You can also drop an enroll button anywhere on the site with the shortcode [learnomy_enrollment_button course_id="123" text="Enroll Now"]. It renders the right CTA for the course and shows an "Already enrolled" state when the current user already has access.

Step 3 -- grant access by hand (admin)

When you need to enrol someone yourself, open the course's overview page in wp-admin and use the Enroll a student control. Enter the student's email or username (there is no dropdown of every user, so it stays fast on large sites). This creates a manual-source enrollment. You can also enrol a student into a course from that student's detail page.

Step 4 -- enrol a list in bulk

To onboard a group, use the course's bulk-enroll control and paste or upload a list of emails. Unknown emails are provisioned as new accounts with a set-password invite. The list is processed in chunks and capped per request so a large paste never times out. See Bulk Enroll from a List.

Step 5 -- remove access

To revoke access, remove the student's enrollment from the Students screen. You can remove a single course enrollment, or clear every enrollment a student holds in one action.

Settings & options

  • Access type decides the enroll path per course (free / paid / membership / paid_or_membership). The public enroll action never trusts a source sent by the browser; the server derives it from the course's access type plus the student's verified state (a completed transaction or an active membership).
  • Prerequisites -- when a course requires prerequisite courses, enrollment is refused until the student has completed them. Configure these in the course editor; see Course Prerequisites.
  • Enrollment sources -- each enrollment carries a source: free, purchase, membership, subscription, manual, or webhook. The table is unique on (user_id, course_id, source), so a student can hold both a membership enrollment and a purchase enrollment on the same course without one overwriting the other.
  • Enrollment status -- active, completed, cancelled, expired, or pending. Fixed-term enrollments are moved to expired automatically when their access window closes.
  • External enrollment -- courses set to the closed model are enrolled from an outside system through the incoming webhook. See Incoming Enrollment Webhook.

For developers

Service (Learnomy\Services\Enrollment_Service):

  • enroll( int $user_id, int $course_id, string $source = 'free', array $options = [] ) -- the single write path; checks prerequisites, dedupes on source, returns the enrollment id or a WP_Error. Adapters call this directly with their own verified source.
  • unenroll( int $enrollment_id ) -- removes one enrollment.
  • can_access( int $user_id, int $course_id ) -- delegates to Permission_Engine::can( $user_id, 'access_course', $course_id ).
  • retake( int $user_id, int $course_id ) -- reopens a completed course when the per-course allow_retake setting is on.

Permissions and capabilities:

  • Access decisions run through Permission_Engine::can( $user_id, 'access_course', $course_id ) -- never a direct capability check.
  • The learnomy_can_access_course filter (result, user_id, course_id) lets add-ons override the access decision.
  • Self-enrollment requires the learnomy_enroll capability.

Hooks fired:

  • learnomy_student_enrolled -- ( enrollment_id, user_id, course_id, source ). Fires on every enrollment; notifications, lesson-unlock scheduling, and the outgoing webhook listen here.
  • learnomy_enrollment_expired -- ( enrollment_id, user_id, course_id ). Fired by cron when a fixed-term enrollment lapses.
  • learnomy_course_completed -- ( enrollment_id, user_id, course_id ).
  • learnomy_course_retaken -- fired when a completed course is reopened.

REST (learnomy/v1):

  • POST /courses/{course_id}/enroll -- self-enroll for the logged-in user. source and plan_id are deliberately not accepted; the server derives the source. Paid or members-only courses without proof return 402 with a checkout_url or membership_url.
  • DELETE /enrollments/{id} -- unenroll a single row.
  • DELETE /students/{user_id}/enrollments -- remove every enrollment for a user (cap manage_settings).
  • POST /admin/courses/{id}/enroll -- admin enrol by email/username (manual source).
  • POST /admin/courses/{id}/bulk-enroll -- admin CSV/paste bulk enroll, capped by learnomy_bulk_enroll_max.
  • POST /admin/students/{id}/enroll -- admin enrol a student into a course from the student detail page.

Related