Founding offer — 25% off applied automatically at checkout. Ends 1 November 2026 or after our first 30 orders. See pricing →
← Back to Course Cadence Changelog Skip to document content

Integration with Dantian Training Hub

This document explains what happens when Dantian Course Cadence and its sibling plugin Dantian Training Hub are installed on the same WordPress site. It is written for site administrators; the final section is a reference for developers.

The integration is optional and additive. Course Cadence works fully on its own, and nothing needs configuring to use the two plugins together. In practice the plugins share one thing — the class (cohort) tables used in standalone mode — and Course Cadence offers integration points that another plugin can use to fold its weekly guidance into a combined digest.

At a glance

Site setup Course Cadence takes courses from Where classes are managed Weekly guidance emails
Course Cadence only, Tutor LMS or LifterLMS active The LMS Not used Sent by Course Cadence
Course Cadence only, no LMS Native classes Course Cadence → Classes Sent by Course Cadence
Course Cadence + Training Hub, Tutor LMS or LifterLMS active The LMS Not used by Course Cadence Sent by Course Cadence (Training Hub sends its own emails separately)
Course Cadence + Training Hub, no LMS Native classes (shared with Training Hub) Training Hub → Classes — Course Cadence hides its own Classes page Sent by Course Cadence (Training Hub sends its own emails separately)

“Training Hub active” means the Training Hub plugin is activated. A Training Hub that is installed but deactivated does not hide Course Cadence’s Classes page.

Shared class tables

When no LMS is active, Course Cadence runs in standalone mode and stores classes in two database tables shared with Training Hub (shown with the default wp_ prefix):

Table Holds
wp_dthub_classes One row per class: label, code, year, status, notes
wp_dthub_class_members One row per person per role in a class, with the date they were added

Both plugins create these tables with the same structure and read and write the same rows:

  • Install in any order. Install Course Cadence first and Training Hub later, or the other way round. Whichever plugin runs first creates the tables; the other simply uses them. No migration is ever needed.
  • One set of classes. A class created in Training Hub appears in Course Cadence’s course picker straight away (if it is active), and vice versa. Members added in either plugin are members in both.
  • Course Cadence creates the tables on every site, even when an LMS is active, so a later switch to standalone mode needs no extra step.
  • Changes to the structure are additive only. Neither plugin renames, removes or narrows a column. Both record the shared structure version in the same option (dthub_classes_db_version, currently 1.0.0).
  • Safety check. If the shared tables are ever changed in a way Course Cadence does not recognise, it shows “The shared class schema (dthub_classes) appears incompatible. Class writes are paused to prevent data corruption. Please check that Dantian Training Hub and this plugin are both up to date.” and stops writing to the class tables until both plugins are updated. Reading continues normally.

Where classes are managed

  • Training Hub not active: Course Cadence → Classes (see Native classes).
  • Training Hub active: Course Cadence removes its Classes menu item and its class-management endpoints. Manage classes and members under Training Hub → Classes, using Training Hub’s own permissions. Course Cadence does not show a notice about this; the Classes item simply disappears from the Course Cadence menu, and the “Welcome to Course Cadence” checklist no longer includes the “Add a class” step.

Trainers and instructors are the same people

Course Cadence calls the teaching role Trainer; Training Hub calls it instructor. Both are stored the same way, so a trainer in one plugin is an instructor in the other.

Stored role (shared table) Course Cadence shows Training Hub shows
student Student Student
instructor Trainer Instructor

Class status

Course Cadence lets you set a class to Active or Inactive; Training Hub uses active and archived. Course Cadence only lists and emails active classes, so a class archived in Training Hub disappears from Course Cadence too.

Legacy table names

Very early pre-release builds of both plugins named these tables {prefix}tam_classes and {prefix}tam_class_members. Each plugin renames old tables to the current dthub_ names in place the first time it loads after updating, keeping all data. Nothing needs doing by hand.

Uninstalling with both plugins installed

The shared tables belong to both plugins, so the two uninstall routines treat them differently:

  • Course Cadence removes its data on deletion only if Settings → System → Remove All Data on Uninstall is on. Even then it keeps the shared class tables if Training Hub is installed (active or not), because Training Hub may still be using them. If Training Hub is not installed, the shared tables and their version option are removed with everything else.
  • Training Hub removes the shared class tables whenever its own Delete all plugin data on uninstall setting is on — it does not check whether Course Cadence is still installed.

Before deleting Training Hub on a standalone Course Cadence site, turn off Training Hub’s “Delete all plugin data on uninstall” setting (or take a database backup). Otherwise every class and class membership Course Cadence relies on is deleted. If that has already happened, restore the two tables from backup; deactivating and reactivating Course Cadence recreates them empty, but the classes and their members are gone.

More on uninstalling: Privacy, data and uninstall.

Weekly emails and the Training Hub digest

Training Hub has an optional weekly student digest (Enable Weekly Digest) that can absorb its upcoming-session and clinic-reminder emails. It does not include Course Cadence guidance: Training Hub 1.0.0 does not use the integration points described below and has no setting for Course Cadence content.

So when both plugins are active, each sends its own emails — students receive Course Cadence’s weekly guidance email as well as anything Training Hub sends. Nothing is suppressed automatically. If you want to stagger them, choose a different dispatch day or time under Course Cadence → Settings → Schedule.

Moving from Course Cadence classes to Training Hub

If a site starts with Course Cadence’s native classes and later adds Training Hub, there is nothing to migrate. As soon as Training Hub is active, its Classes screen shows the same classes and members, and Course Cadence keeps using them as its courses — timelines, prompts and email history are unaffected because the class records have not changed.

Example: a college adding Training Hub

A massage therapy college has run Course Cadence in standalone mode for a year with six classes. It installs Training Hub to manage tutorials and attendance. After activation, Course Cadence → Classes disappears and Training Hub → Classes lists the same six classes with the same students; the trainers appear as instructors. Course Cadence’s Monday guidance emails continue unchanged. The site administrator turns off Training Hub’s “Delete all plugin data on uninstall” so the shared classes can never be removed by accident, and reviews when Training Hub’s own student emails go out, moving Course Cadence’s dispatch time under Settings → Schedule if needed so students are not sent two emails at once.


Developer reference: integration hooks

Course Cadence exposes three hooks so another plugin (Training Hub or your own code) can read a student’s weekly guidance and take over its delivery. They are all prefixed dantian_course_cadence_ and documented in src/php/helpers/hooks-reference.php. As noted above, Training Hub 1.0.0 does not currently use them.

Filter: dantian_course_cadence_student_weekly_sections

Ask Course Cadence for one student’s guidance for a given week, without sending anything.

$sections = apply_filters(
    'dantian_course_cadence_student_weekly_sections',
    [],
    $student_id,  // int  — WordPress user ID
    $week_start,  // string — Y-m-d, Monday of the target week
    $week_end     // string — Y-m-d, Sunday of the target week (accepted, not currently used)
);

Course Cadence answers with one section per enrolled course that has guidance that week:

[
    [
        'course_id'       => 17,
        'course_title'    => 'Anatomy 101',
        'week_number'     => 5,
        'audience'        => 'student',
        'html'            => '<h3>Anatomy 101 — Week 5</h3><ul>…</ul>',
        'plain'           => 'Anatomy 101 — Week 5 …',
        'view_online_url' => 'https://example.com/guidance/?dcc_course_id=17&dcc_week=5',
    ],
]

How sections are chosen:

  • the student’s courses come from the active provider (LMS or native classes);
  • the course needs a timeline active at midday on $week_start;
  • courses whose email delivery is paused, or whose $week_start falls inside a break period, are skipped;
  • only prompts with the Student or Both audience are included;
  • view_online_url is built from the Student Guidance Page URL setting and is an empty string when that setting is blank;
  • the week number is calculated from the timeline’s start date. For Rolling timelines this filter does not use each student’s own enrolment date, so the week returned may not match what that student’s standalone email would contain.

Filter: dantian_course_cadence_suppress_dispatch

Called immediately before Course Cadence sends an email. Return true to stop that send.

add_filter(
    'dantian_course_cadence_suppress_dispatch',
    function ( bool $suppress, array $context ): bool {
        if ( $suppress ) {
            return true; // another listener already claimed it
        }
        if ( 'admin_digest' === $context['dispatch_type'] ) {
            return false; // leave operational email alone
        }
        // Return true only when your plugin has delivered (or will deliver)
        // this student's guidance for $context['week_start']–$context['week_end'].
        return my_plugin_has_delivered_guidance( $context['student_id'], $context['week_start'] );
    },
    10,
    2
);

$context contains:

Key Value
dispatch_type weekly (one course), consolidated (several courses in one email), catchup (automatic catch-up), pending_catchup (catch-up sent by an administrator), or admin_digest
student_id WordPress user ID (0 for admin_digest)
course_id The course, or 0 for consolidated, a consolidated catch-up, and admin_digest
week_start, week_end Y-m-d. For weekly, consolidated and admin-digest sends: the Monday and Sunday of the dispatch week. For catch-ups: both are today’s date.
audience student, trainer or admin

Behaviour when suppressed:

  • Weekly / consolidated: the send is skipped and not recorded as sent, so the recipient is not marked as having received that week.
  • Catch-ups (catchup, pending_catchup): the send is skipped but recorded as sent, because the consumer has taken responsibility for delivery.
  • Admin digest: skipped.

Action: dantian_course_cadence_dispatch_suppressed_by

Fired by Course Cadence every time a send is suppressed, with $who = 'unknown':

do_action( 'dantian_course_cadence_dispatch_suppressed_by', 'unknown', $context );

For weekly, consolidated and admin-digest sends $context is the same array passed to the suppress filter; for catch-ups it is an empty array. Course Cadence always fires this action itself, so a consumer does not need to fire it — doing so would record the suppression twice.

dantian_course_cadence_lms_provider lets a site force tutorlms, lifterlms or native. See LMS integration and native classes.

Was this helpful?