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.
LDDashboardModule_Base
Located at includes/modules/class-ld-dashboard-module-base.php.
All custom modules must extend this abstract class.
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
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<em>plugin</em>active() | plugin:buddypress |
class: | class_exists() | class:BuddyPress |
function: | function_exists() | function:bp<em>is</em>active |
constant: | defined() | constant:BP_VERSION |
Known plugins with class-based checks: buddypress → BuddyPress, bp-user-todo-list → BP<em>User</em>Todo<em>List, learndash → SFWD</em>LMS, woocommerce → WooCommerce.
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
| Method | Default | Description |
|---|---|---|
is_enabled(): bool | Reads ld<em>dashboard</em>module_settings option | Override to use a different settings source. |
get<em>settings</em>config(): array | Base config with id, name, description, requires, enabled | Override to add module-specific settings fields for the admin UI. |
Protected Helpers
| Method | Description |
|---|---|
get<em>module</em>path(): string | Returns the module’s directory path with trailing slash. |
get<em>module</em>url(): string | Returns the module’s URL with trailing slash. |
LDDashboardModule_Registry
Located at includes/modules/class-ld-dashboard-module-registry.php.
The registry is a singleton that manages all module registration and lifecycle.
Registration
Register modules inside the ld<em>dashboard</em>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 <em>doing</em>it_wrong().
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
Modules can be toggled in the admin via Settings → Integrations. The enabled state is stored in the ld<em>dashboard</em>module<em>settings WordPress option as an associative array of module</em>id => bool.
// Programmatically enable/disable a module
ld_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
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
// 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
| ID | Class | Dependency |
|---|---|---|
zoom | LD<em>Dashboard</em>Zoom_Module | None (uses bundled Zoom API class) |
buddypress | LD<em>Dashboard</em>BP_Module | plugin:buddypress (BuddyPress class) |
todo | LD<em>Dashboard</em>Todo_Module | plugin:bp-user-todo-list (BP<em>User</em>Todo_List class) |
uncanny-groups | LD<em>Dashboard</em>Uncanny<em>Groups</em>Module | Uncanny Groups plugin |
Module files are autoloaded from includes/modules/{id}/class-ld-dashboard-{id}-module.php.
