# Plugin Development ## Plugin types CodePress has two kinds of plugins, determined by the `type` field in `plugin.json`: - **Content plugins** (`type: "content"`) — Appear in the sidebar and in the plugin selection on content-edit pages. Provide sidebar content via `getSidebarContent()`. - **System plugins** (`type: "system"`) — Are loaded by PluginManager but do NOT appear in the sidebar. Provide functionality via admin menu, routes and the CMSAPI. When no `type` field is present, `content` is assumed. ## Plugin structure ``` plugins/MyPlugin/ ├── MyPlugin.php # Plugin code (NOT plugin.php) ├── plugin.json # Metadata with type field ├── config.json # Optional configuration └── assets/ ├── scss/myplugin.scss # SCSS source (optional) └── css/myplugin.css # CSS (manually maintained) ``` Plugin files are named `.php` (e.g. `Navigation.php`, `HTMLBlock.php`). `PluginManager` loads `$pluginDir . '/' . $pluginName . '.php'`. ## plugin.json ```json { "name": "My Plugin", "version": "1.0.0", "author": "Your Name", "description": "Description", "type": "content" } ``` - `name` — Display name - `type` — `"content"` or `"system"` (default: `content`) ## Content plugin example ```php 'My Plugin', 'type' => 'content', ]; } public function getSidebarContent(): string { return '

Hello World

'; } } ``` ## System plugin example ```php 'My System', 'type' => 'system', ]; } public function getAdminMenu(): array { return [ ['label' => 'My System', 'route' => 'my-system', 'icon' => 'bi-gear'], ]; } public function getAdminRoutes(): array { return ['my-system']; } public function handleAdminRoute(string $route): void { echo '

My System page

'; } } ``` System plugins are shown in the admin sidebar via `PluginManager::getAdminMenuItems()` and handled via `PluginManager::handleAdminRoute()`. ## Using CMSAPI ```php getConfig(); $page = $api->getPage($path); ``` `setAPI()` is called automatically by `PluginManager` if the plugin has the method. ## Plugin CSS - Plugin CSS in `assets/css/` is manually maintained (SCSS compilation for plugins is not yet automatic) - Plugin CSS is automatically loaded after theme CSS (in `base.twig`), so themes can override plugin styling - Plugin assets are served via `cms/router.php` at URL `/plugins//assets/...` - Implement `getCssUrl()` in the plugin class to return the CSS URL ```php public function getCssUrl(): string { return '/plugins/MyPlugin/assets/css/myplugin.css'; } ``` ## Hooks and filters PluginManager auto-registers these methods as hooks/filters: - **Hooks**: `onPageLoad`, `onBeforeRender`, `onAfterRender`, `onSearch`, `onMenuBuild` - **Filters**: `onContentFilter`, `onTitleFilter`, `onMenuFilter` ```php public function onPageLoad($page) { /* ... */ } public function onContentFilter($content) { return $content; } ``` ## Essential plugins Essential plugins are defined in `getProtectedPlugins()` in `public/admin.php`. Current essential plugin: **Navigation**. These plugins cannot be deactivated, edited or deleted. Always add the `isProtectedPlugin()` check to new plugin handlers.