Plugin Architecture
Overview
LearnDash Dashboard is a WordPress plugin that extends LearnDash LMS with a frontend dashboard panel. It provides role-specific interfaces for administrators, instructors, group leaders, and students.
Key stats: 28 frontend tabs, 49 AJAX handlers, 17 REST endpoints, 16 admin pages, 9 database tables, 7 cron jobs, 38+ classes.
Requirements: LearnDash LMS (sfwd-lms), ACF PRO.
Directory Structure
ld-dashboard/
├── ld-dashboard.php # Plugin entry point
├── admin/
│ ├── class-ld-dashboard-admin.php
│ ├── fields/ # ACF field registration (Field Builder)
│ └── partials/ # Admin settings templates
├── includes/
│ ├── class-ld-dashboard.php # Core loader
│ ├── class-ld-dashboard-functions.php
│ ├── emails/ # Email template system
│ ├── modules/ # Feature modules (Zoom, BuddyPress, To-Do)
│ ├── reports/ # Reports + charts architecture
│ ├── save-handlers/ # Form save handlers
│ └── tabs/ # Instructor tab renderers
├── public/
│ ├── class-ld-dashboard-public.php
│ ├── css/ # Frontend CSS modules
│ ├── js/ # Frontend JS modules
│ └── reports/ # User statistics REST endpoint
├── shortcodes/ # Legacy shortcode implementations
├── templates/
│ └── emails/ # Email HTML templates
└── widgets/ # WordPress widgets
Design Patterns
Singleton
Used for classes that should have only one instance throughout the request lifecycle.
// Access a singleton
$commission = LD_Dashboard_Commission::instance();
$shortcodes = Ld_Dashboard_Shortcodes::instance();
$email = LD_Dashboard_Email_Template::instance();
Singleton classes: LD<em>Dashboard</em>Commission, LD<em>Dashboard</em>ACF<em>Renderer, LD</em>Dashboard<em>Activity</em>Reporter, Ld<em>Dashboard</em>Shortcodes, LD<em>Dashboard</em>CSS<em>Generator, LD</em>Dashboard<em>Email</em>Handler, LD<em>Dashboard</em>Course<em>Builder, LD</em>Dashboard<em>Instructor</em>Manager, LD<em>Dashboard</em>Assets, LD<em>Dashboard</em>Messaging.
Registry
Central registries manage discovery, instantiation, and REST API routing for reports, charts, tabs, and modules. Each registry is a singleton.
| Registry | Class | Registration Hook |
|---|---|---|
| Reports + Charts | LD<em>Dashboard</em>Report_Registry | ld<em>dashboard</em>register<em>reports / ld</em>dashboard<em>register</em>charts |
| Tabs | LD<em>Dashboard</em>Tab_Registry | ld<em>dashboard</em>registered_tabs filter |
| Modules | LD<em>Dashboard</em>Module_Registry | ld<em>dashboard</em>register_modules |
Template Method
LD<em>Dashboard</em>Tab<em>Base defines the rendering algorithm in its final public function render() method. Subclasses implement the abstract steps (get</em>accessible<em>ids, get</em>filter<em>args, render</em>item) without changing the overall flow.
Builder (Field Builder)
LD<em>Dashboard</em>Field_Builder uses a fluent API to register ACF field groups:
$builder = new LD_Dashboard_Field_Builder( 'lesson' );
$builder
->add_title_field( $label )
->add_status_field( $label, $statuses )
->add_content_field( $label )
->register( 'lesson-field-group', $title, $location );
Static Utility Classes
Stateless helper classes accessed via static methods:
LD_Dashboard_Helper::is_instructor( $user_id );
LD_Dashboard_Course_Helper::get_instructor_courses( $user_id );
LD_Dashboard_Query_Helper::get_activity_table_name();
Class Hierarchy
LD_Dashboard_Report_Base (abstract)
└── LD_Dashboard_Chart_Base (abstract)
├── LD_Dashboard_Chart_Course_Completion
├── LD_Dashboard_Chart_Top_Courses
├── LD_Dashboard_Chart_Instructor_Earnings
└── LD_Dashboard_Chart_Time_Spent
└── LD_Dashboard_Report_Quiz_Results
└── LD_Dashboard_Report_Essay_Submissions
└── LD_Dashboard_Report_Assignment_Status
└── LD_Dashboard_Report_Course_Progress
LD_Dashboard_Module_Base (abstract)
├── LD_Dashboard_Zoom_Module
├── LD_Dashboard_BP_Module
├── LD_Dashboard_Todo_Module
└── LD_Dashboard_Uncanny_Groups_Module
LD_Dashboard_Tab_Base (abstract)
├── LD_Dashboard_Tab_Lesson
├── LD_Dashboard_Tab_Topic
├── LD_Dashboard_Tab_Quiz
├── LD_Dashboard_Tab_Question
├── LD_Dashboard_Tab_Assignment
├── LD_Dashboard_Tab_Announcement
└── LD_Dashboard_Tab_Certificate
LD_Dashboard_Save_Handler_Base (abstract)
├── LD_Dashboard_Save_Handler_Course
├── LD_Dashboard_Save_Handler_Lesson
├── LD_Dashboard_Save_Handler_Topic
├── LD_Dashboard_Save_Handler_Quiz
├── LD_Dashboard_Save_Handler_Question
├── LD_Dashboard_Save_Handler_Certificate
├── LD_Dashboard_Save_Handler_Announcement
└── LD_Dashboard_Save_Handler_Group
Key Entry Points
The plugin boots from ld-dashboard.php which instantiates Ld_Dashboard (the core loader).
ld-dashboard.php
└── Ld_Dashboard (includes/class-ld-dashboard.php)
├── loads Admin class → LD_Dashboard_Admin
├── loads Public class → Ld_Dashboard_Public
├── loads Report Registry → LD_Dashboard_Report_Registry
├── loads Module Registry → LD_Dashboard_Module_Registry
├── loads Tab Registry → LD_Dashboard_Tab_Registry
├── loads Messaging → LD_Dashboard_Messaging
└── loads REST endpoints → LD_Dashboard_User_Statistics
Hook Lifecycle
plugins_loaded
└── Plugin class instantiated
└── All includes required
└── Module registry boots (dependency checks)
init (priority 20)
└── Report Registry initializes
├── do_action('ld_dashboard_register_reports', $registry)
└── do_action('ld_dashboard_register_charts', $registry)
rest_api_init
└── Report Registry registers REST routes
└── Messaging registers REST routes
└── User Statistics registers REST route
wp_enqueue_scripts
└── LD_Dashboard_Assets enqueues CSS/JS modules
Database Tables
The plugin creates 9 custom tables on activation via dbDelta(). All tables use the WordPress table prefix.
| Table | Purpose |
|---|---|
{prefix}ld<em>dashboard</em>emails | Email log — records emails sent by instructors to students |
{prefix}ld<em>dashboard</em>instructor<em>commission</em>logs | Commission transaction records per course sale |
{prefix}ld<em>dashboard</em>time_tracking | Per-user, per-post time-on-page tracking data |
{prefix}ld<em>dashboard</em>invite_user | Course invitation records with acceptance status |
{prefix}ld<em>dashboard</em>users_statistics | Cached aggregate stats per user (courses, students, etc.) |
{prefix}ld<em>dashboard</em>email_queue | DB-backed email queue with retry logic and status tracking |
{prefix}ld<em>dashboard</em>messages | Private messaging threads and replies |
{prefix}ld<em>dashboard</em>enrollment_codes | Enrollment code batches with usage limits and expiry |
{prefix}ld<em>dashboard</em>code_redemptions | Records of code redemptions per user |
Tables are created or updated safely on every plugin activation using dbDelta(), which is safe to re-run on existing tables.
