Files
CodePress/guide/en/codepress-developer/plugin-development.md
T
E.Noorlander 20adea7544 v2.6.0: Content backup/git versioning, plugin type system, docs update
New features:
- ContentBackup class with ZIP backup/restore and git versioning
- Admin backup & restore page (content-backup.twig) with git init/commit/log/restore
- Plugin type system: system (blue) vs content (green) with visual badges
- PluginAPIInterface + AdminPluginAPI for plugin architecture
- Essential plugin flag (cannot edit/deactivate/delete)

Improvements:
- Consolidated enabled_plugins config (removed plugins.enabled)
- Removed Analytics/Logging toggles from admin config page
- Fixed Dashboard plugin Twig comments rendered as text
- Updated 20 guide files (NL+EN): configuratie, plugins, plugin-development,
  core-classes, theme-json, layouts, scss-styling, admin-beheerder, nieuw-thema, architectuur
- Improved accessibility test script (grep -E, min/max checks)

Cleanup:
- Removed unused classes: ARIAComponents, AccessibilityManager, ContentSecurityPolicy, etc.
- Removed vendor packages: mustache/mustache, php-mqtt/client
- Removed old templates: logs.twig, statistics.twig (now plugins)
- Moved language files to language/ directory

Tests:
- Pentest: 30/30 passed, 0 vulnerabilities
- WCAG 2.1 AA: 25/25 passed, 100% compliance
2026-08-15 19:21:04 +02:00

3.4 KiB

Plugin Development

Plugin structure

plugins/MyPlugin/
├── MyPlugin.php         # Main plugin class (name = folder name)
├── plugin.json          # Plugin metadata
├── config.json          # Optional configuration
└── assets/              # Optional CSS/JS
    ├── css/
    └── scss/

plugin.json

{
  "name": "My Plugin",
  "version": "1.0.0",
  "author": "Your Name",
  "description": "Description",
  "type": "content",
  "essential": false,
  "hasConfig": false
}

Fields

Field Value Description
name string Display name in admin
version string Version number
author string Author
description string Short description
type "system" or "content" System (blue badge) or content (green badge)
essential boolean Essential plugins cannot be edited/deleted
hasConfig boolean Shows a Config button in admin

Plugin class example

<?php

class MyPlugin
{
    private ?PluginAPIInterface $api = null;

    public function setAPI(PluginAPIInterface $api): void
    {
        $this->api = $api;
    }

    public function getConfig(): array
    {
        return [
            'title' => 'My Plugin',
            'type' => 'content',
            'viewable' => true,
        ];
    }

    public function getSidebarContent(): string
    {
        $title = $this->api ? $this->api->getCurrentPageTitle() : '';
        return '<p>Current page: ' . htmlspecialchars($title) . '</p>';
    }
}

The plugin class is automatically loaded by PluginManager when the plugin is listed in enabled_plugins in config.json.

Using the API

The API is injected via setAPI(), not via a static method. In the front-end context this is a CMSAPI instance, in the admin context an AdminPluginAPI instance. Both implement PluginAPIInterface.

// Front-end API (CMSAPI)
$this->api->getCurrentPageTitle();
$this->api->getMenu();
$this->api->getConfig('site_title');
$this->api->getCurrentLanguage();
$this->api->isHomepage();
$this->api->createUrl('about-us');

// Admin API (AdminPluginAPI)
$this->api->getConfig('analytics.enabled');
$this->api->getContentDir();
$this->api->getEnabledPlugins();

Hooks

Plugins can implement the following methods for automatic hook registration:

Actions (no return value):

  • onPageLoad - On page load
  • onBeforeRender - Before rendering
  • onAfterRender - After rendering
  • onSearch - On search
  • onMenuBuild - On menu build

Filters (return modified value):

  • onContentFilter - Filter content
  • onTitleFilter - Filter title
  • onMenuFilter - Filter menu

Admin integration

Plugins can add custom admin pages via getAdminMenu() and handleAdminRoute():

public function getAdminMenu(): array
{
    return [
        [
            'plugin' => 'MyPlugin',
            'route' => 'my-plugin',
            'label' => 'My Plugin',
            'icon' => 'bi-puzzle',
            'section' => 'general',  // or 'system'
        ],
    ];
}

public function handleAdminRoute(string $action): ?string
{
    return '<h2>My Plugin admin page</h2>';
}

Only plugins listed in enabled_plugins are shown in the admin sidebar.

Adding CSS

Plugins can provide a CSS URL via getCssUrl():

public function getCssUrl(): string
{
    return '/plugins/MyPlugin/assets/css/style.css';
}