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).
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: LDDashboardCommission, LDDashboardACFRenderer, LDDashboardActivityReporter, LdDashboardShortcodes, LDDashboardCSSGenerator, LDDashboardEmailHandler, LDDashboardCourseBuilder, LDDashboardInstructorManager, LDDashboardAssets, LDDashboardMessaging.
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 | LDDashboardReport_Registry | lddashboardregisterreports / lddashboardregistercharts |
| Tabs | LDDashboardTab_Registry | lddashboardregistered_tabs filter |
| Modules | LDDashboardModule_Registry | lddashboardregister_modules |
Template Method
LDDashboardTabBase defines the rendering algorithm in its final public function render() method. Subclasses implement the abstract steps (getaccessibleids, getfilterargs, renderitem) without changing the overall flow.
Builder (Field Builder)
LDDashboardField_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}lddashboardemails | Email log — records emails sent by instructors to students |
{prefix}lddashboardinstructorcommissionlogs | Commission transaction records per course sale |
{prefix}lddashboardtime_tracking | Per-user, per-post time-on-page tracking data |
{prefix}lddashboardinvite_user | Course invitation records with acceptance status |
{prefix}lddashboardusers_statistics | Cached aggregate stats per user (courses, students, etc.) |
{prefix}lddashboardemail_queue | DB-backed email queue with retry logic and status tracking |
{prefix}lddashboardmessages | Private messaging threads and replies |
{prefix}lddashboardenrollment_codes | Enrollment code batches with usage limits and expiry |
{prefix}lddashboardcode_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.
