Creating Custom Modules
Modules are self-contained feature extensions that boot conditionally based on enabled status and dependency availability. The module system was introduced in version 7.5.0.
LD_Dashboard_Module_Base
Section titled “LD_Dashboard_Module_Base”Located at includes/modules/class-ld-dashboard-module-base.php.
All custom modules must extend this abstract class.
Abstract Methods (required)
Section titled “Abstract Methods (required)”| Method | Return | Description |
|---|---|---|
get_id(): string |
string |
Unique module identifier (e.g., my-analytics). Must be a valid slug. |
get_name(): string |
string |
Human-readable module name for display in settings. |
get_description(): string |
string |
Short description of what the module does. |
boot(): void |
void |
Module initialization — register hooks, load files, enqueue assets. Called only when all dependencies pass. |
Dependency System
Section titled “Dependency System”Declare dependencies in the $requires property. The module will not boot if any dependency is missing.
protected $requires = array( 'plugin:woocommerce', // Check if WooCommerce class exists 'class:WooCommerce', // Check for specific class 'function:wc_get_product', // Check for function 'constant:WOOCOMMERCE_VERSION', // Check for constant);Dependency types:
| Prefix | Check | Example |
|---|---|---|
plugin: |
Class lookup for known plugins, then is_plugin_active() |
plugin:buddypress |
class: |
class_exists() |
class:BuddyPress |
function: |
function_exists() |
function:bp_is_active |
constant: |
defined() |
constant:BP_VERSION |
Known plugins with class-based checks: buddypress → BuddyPress, bp-user-todo-list → BP_User_Todo_List, learndash → SFWD_LMS, woocommerce → WooCommerce.
Initialization Flow
Section titled “Initialization Flow”The registry calls init() on each module. You cannot override init() — it is declared final.
init() is called by registry ├── is_enabled()? (checks ld_dashboard_module_settings option) │ └── false → skip (module disabled by user) ├── check_dependencies()? (iterates $requires) │ └── false → skip (missing plugin/class/function/constant) └── boot() is called └── do_action('ld_dashboard_module_loaded', $module) └── do_action('ld_dashboard_module_{id}_loaded', $module)Optional Override Methods
Section titled “Optional Override Methods”| Method | Default | Description |
|---|---|---|
is_enabled(): bool |
Reads ld_dashboard_module_settings option |
Override to use a different settings source. |
get_settings_config(): array |
Base config with id, name, description, requires, enabled | Override to add module-specific settings fields for the admin UI. |
Protected Helpers
Section titled “Protected Helpers”| Method | Description |
|---|---|
get_module_path(): string |
Returns the module’s directory path with trailing slash. |
get_module_url(): string |
Returns the module’s URL with trailing slash. |
LD_Dashboard_Module_Registry
Section titled “LD_Dashboard_Module_Registry”Located at includes/modules/class-ld-dashboard-module-registry.php.
The registry is a singleton that manages all module registration and lifecycle.
Registration
Section titled “Registration”Register modules inside the ld_dashboard_register_modules action hook, which fires during the registry’s private constructor before built-in modules boot.
add_action( 'ld_dashboard_register_modules', function( $registry ) { $registry->register( 'my-analytics', 'My_Analytics_Module' );} );You must register modules before the registry calls boot(). Registering after boot triggers _doing_it_wrong().
Global Helpers
Section titled “Global Helpers”// Get the registry instance$registry = ld_dashboard_modules();
// Check if a module is active (loaded, deps met, and booted)if ( ld_dashboard_is_module_active( 'zoom' ) ) { // Zoom is running.}
// Get a module instance$zoom = ld_dashboard_modules()->get( 'zoom' );
// Get all active modules$active = ld_dashboard_modules()->get_active_modules();
// Check if a module is registered (not necessarily active)$registered = ld_dashboard_modules()->is_registered( 'my-analytics' );Module Settings
Section titled “Module Settings”Modules can be toggled in the admin via Settings → Integrations. The enabled state is stored in the ld_dashboard_module_settings WordPress option as an associative array of module_id => bool.
// Programmatically enable/disable a moduleld_dashboard_modules()->set_module_enabled( 'my-analytics', true );
// Check if a module is enabled (not the same as active — dependency check not run)$module = ld_dashboard_modules()->get( 'my-analytics' );if ( $module && $module->is_enabled() ) { // Enabled in settings.}Complete Example: Analytics Module
Section titled “Complete Example: Analytics Module”This example creates an “Analytics” module that requires a custom analytics plugin to be active.
<?php/** * Analytics Module for LD Dashboard. * * @since 1.0.0 */class My_Analytics_Module extends LD_Dashboard_Module_Base {
/** * Module dependencies. * * @var array */ protected $requires = array( 'plugin:my-analytics-plugin', // Must be active 'class:My_Analytics', // Class must exist );
/** * Get module ID. * * @since 1.0.0 * @return string */ public function get_id(): string { return 'my-analytics'; }
/** * Get module name. * * @since 1.0.0 * @return string */ public function get_name(): string { return __( 'My Analytics', 'my-plugin' ); }
/** * Get module description. * * @since 1.0.0 * @return string */ public function get_description(): string { return __( 'Adds advanced analytics tracking to the LearnDash Dashboard.', 'my-plugin' ); }
/** * Boot the module. * * Called only when enabled and all dependencies are met. * * @since 1.0.0 * @return void */ protected function boot(): void { // Load module files. require_once $this->get_module_path() . 'class-analytics-tracker.php';
// Register hooks. add_action( 'ld_dashboard_register_reports', array( $this, 'register_reports' ) ); add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_assets' ) );
// Register REST route. add_action( 'rest_api_init', array( $this, 'register_rest_routes' ) ); }
/** * Register analytics reports with the report registry. * * @since 1.0.0 * @return void */ public function register_reports(): void { LD_Dashboard_Report_Registry::register( 'analytics-overview', 'My_Analytics_Overview_Report' ); }
/** * Enqueue module assets. * * @since 1.0.0 * @return void */ public function enqueue_assets(): void { if ( ! is_page() ) { return; }
wp_enqueue_script( 'my-analytics-module', $this->get_module_url() . 'assets/analytics.js', array( 'jquery' ), '1.0.0', true ); }
/** * Register REST routes. * * @since 1.0.0 * @return void */ public function register_rest_routes(): void { register_rest_route( 'my-plugin/v1', '/analytics', array( 'methods' => WP_REST_Server::READABLE, 'callback' => array( $this, 'rest_get_analytics' ), 'permission_callback' => function() { return current_user_can( 'manage_options' ); }, ) ); }
/** * REST callback. * * @since 1.0.0 * @param WP_REST_Request $request REST request. * @return WP_REST_Response */ public function rest_get_analytics( WP_REST_Request $request ): WP_REST_Response { $data = My_Analytics::get_summary(); return rest_ensure_response( array( 'success' => true, 'data' => $data ) ); }
/** * Provide settings configuration for the admin UI. * * @since 1.0.0 * @return array */ public function get_settings_config(): array { $config = parent::get_settings_config();
// Add module-specific fields. $config['fields'] = array( array( 'id' => 'tracking_enabled', 'label' => __( 'Enable Tracking', 'my-plugin' ), 'type' => 'checkbox', 'default' => true, ), );
return $config; }}
// Register the module via the action hook.add_action( 'ld_dashboard_register_modules', function( $registry ) { $registry->register( 'my-analytics', 'My_Analytics_Module' );} );Using the Module Elsewhere
Section titled “Using the Module Elsewhere”// Check if active before using module features.if ( ld_dashboard_is_module_active( 'my-analytics' ) ) { $module = ld_dashboard_modules()->get( 'my-analytics' ); // Use module methods.}
// React to module loading.add_action( 'ld_dashboard_module_my-analytics_loaded', function( $module ) { // Module is active — extend or decorate it.} );Built-in Modules
Section titled “Built-in Modules”| ID | Class | Dependency |
|---|---|---|
zoom |
LD_Dashboard_Zoom_Module |
None (uses bundled Zoom API class) |
buddypress |
LD_Dashboard_BP_Module |
plugin:buddypress (BuddyPress class) |
todo |
LD_Dashboard_Todo_Module |
plugin:bp-user-todo-list (BP_User_Todo_List class) |
uncanny-groups |
LD_Dashboard_Uncanny_Groups_Module |
Uncanny Groups plugin |
Module files are autoloaded from includes/modules/{id}/class-ld-dashboard-{id}-module.php.

