DashboardSectionProvider plugins¶
How to contribute a section to /admin/reports/wow.
When to use this¶
- Your submodule has status your operators should see (row counts, last-sync time, queue depth, something warning-worthy).
- You want administrators to trigger one-click actions (sync, resync, wipe, reset state) from the dashboard.
The interface¶
Drupal\wow\DashboardSectionProviderInterface
Plugins return value objects, never HTML:
DashboardSection— the top-level block with a title and rows.DashboardRow— one line inside a section: severity (OK / warning / error), label, value, optional actions.DashboardAction— a dropdown item on a row: ID, label, optionaldestructive: TRUEflag to force a confirmation form.
DashboardRenderer owns all markup. A theme refresh to the dashboard doesn't ripple out to every plugin.
The attribute¶
use Drupal\wow\Attribute\DashboardSectionProvider;
#[DashboardSectionProvider(
id: 'wow_my_thing',
label: new TranslatableMarkup('My thing'),
)]
class MyThingStatus extends DashboardSectionProviderBase { /* ... */ }
Plugins live in modules/<module>/src/Plugin/DashboardSectionProvider/.
Two base classes¶
TaxonomyDashboardProviderBase¶
For taxonomy-backed reference-data modules. You implement five metadata getters and the base class handles:
- term counts
- last-sync timestamp (
wow.last_modified.<entity>_index.<region>) - the standard "Sync now" action
- skipping the wipe action (taxonomy wipes would break entity_reference integrity)
Reference: modules/wow_playable_class/src/Plugin/DashboardSectionProvider/PlayableClassStatus.php.
DashboardSectionProviderBase¶
The generic base. Use when your module has its own content entities, queue state, or non-standard actions to surface. Reference implementations:
modules/wow_achievement/src/Plugin/DashboardSectionProvider/AchievementStatus.php— queue depth, category counts, batch syncmodules/wow_character/src/Plugin/DashboardSectionProvider/CharacterStatus.php— stored count, force-resync, wipesrc/Plugin/DashboardSectionProvider/BattleNetStatus.php— API connection health, credential status
Implementing actions¶
Actions are IDs in your DashboardAction objects; when clicked, Drupal routes to your plugin's executeAction():
public function executeAction(string $actionId, array $parameters = []): ?BatchBuilder {
return match ($actionId) {
'sync_now' => $this->buildSyncBatch($this->defaultRegion()),
'force_resync' => $this->buildSyncBatch($this->defaultRegion(), resetState: TRUE),
'wipe' => $this->buildWipeBatch(),
default => parent::executeAction($actionId, $parameters),
};
}
Return a BatchBuilder — the dashboard controller runs it as a Drupal batch with progress. Return NULL for actions that complete immediately (e.g. state reset).
Destructive actions (destructive: TRUE) route through DashboardActionConfirmForm before executing, so the operator sees a "Are you sure?" step.
Testing expectations¶
Kernel tests for dashboard plugins are straightforward — see PlayableClassStatusTest or AchievementStatusTest:
- Install the module + schemas.
- Seed some state (stored rows, a state key).
- Invoke the plugin's
getSection()directly and assert severity, label, value, action presence.
Tests don't need to render markup — assert against the value objects.
Common pitfalls¶
- Hardcoded region fallback: always fall back to
'eu'(matchesconfig/install/wow.settings.yml). Don't use'us'— it diverges from what other modules assume. - Writing HTML in the plugin: don't. Return value objects. If you need custom markup, work with the core maintainers on expanding
DashboardRenderer— not in-plugin markup. - Coupling to another module's services: a dashboard plugin inside
wow_mountshould only usewow_mount's own services + core. Cross-module dependencies in dashboard plugins tend to indicate a deeper architecture problem.