8.6 KiB
module.php: module descriptor
module.php returns a PHP array without HTML output or side effects.
The system reads the descriptor and registers the module in common registries.
Example control panel module
<?php
use App\Adminx\Notes\DashboardWidget;
use App\Adminx\Notes\Controller;
defined('BASEPATH') || die('Direct access to this location is not allowed.');
return array(
'code' => 'notes',
'name' => 'Заметки',
'version' => '1.0.0',
'description' => 'Личные заметки администратора.',
'author' => 'AVE.cms',
'lifecycle' => array(
'managed' => true,
'uninstall' => array('migrations/uninstall.sql'),
),
'requires' => array('users'),
'permissions' => array(
'key' => 'notes',
'items' => array(
array('code' => 'view_notes', 'group_code' => 'navigation',
'name' => 'Заметки: просмотр', 'sort_order' => 10),
array('code' => 'manage_notes', 'group_code' => 'content',
'name' => 'Заметки: управление', 'sort_order' => 20),
),
'icon' => 'ti ti-notes',
'priority' => 46,
),
'routes' => array(
array('GET', '/notes', array(Controller::class, 'index')),
array('POST', '/notes', array(Controller::class, 'store')),
),
'migrations' => array(
array('id' => '001_create_notes', 'file' => 'migrations/001_create_notes.sql'),
),
'assets' => array(
'styles' => array(
array('url' => ADMINX_BASE . '/modules/Notes/assets/notes.css', 'priority' => 46),
),
'scripts' => array(
array('url' => ADMINX_BASE . '/modules/Notes/assets/notes.js', 'priority' => 46),
),
),
'admin_extension' => array(
'url' => '/notes',
'icon' => 'ti ti-notes',
'feature' => 'Личные заметки',
'menu' => array(array(
'code' => 'modules_notes', 'label' => 'Заметки', 'url' => '/notes',
'icon' => 'ti ti-notes', 'permission' => 'view_notes',
'group' => 'Система', 'parent' => 'modules', 'sort_order' => 9,
'match' => array('/notes'),
)),
'dashboard' => array(
'template' => '@notes/dashboard.twig',
'provider' => array(DashboardWidget::class, 'data'),
'permission' => 'view_notes',
'sort_order' => 24,
),
),
);
Existing panel modules can hold routes, assets, permissions and
navigation at the top level. In a composite package there are contextual services,
routes and hooks are divided into admin and public.
Identification
| Key | Destination |
|---|---|
code |
Mandatory stable module code. |
name |
Human readable name. |
version |
Code version and migrations. |
description, author |
Module page metadata. |
Do not change code after release: it is referenced by status, migrations,
settings, rights, dependencies and sources of field types.
Lifecycle and dependencies
'lifecycle' => array(
'managed' => true,
'install' => array(Installer::class, 'install'),
'update' => array(Installer::class, 'update'),
'uninstall' => array(Installer::class, 'uninstall'),
),
'requires' => array('commerce'),
'package' => array('removable' => true),
managedincludes explicit install and activity states.install,update,uninstallaccept callable; instead of uninstall-callable You can pass a list of SQL or PHP migration files.adopt_existingonly applies to controlled transfers already existing legacy module and is prohibited for the new ZIP.requireslists required modules installed and enabled.package.removableallows physical removal of the uninstalled module: a separate administrative directory or a composite package ofmodules/<code>. This flag is not set for system kernel partitions.
Details: operations and migrations.
General connections
| Key | Destination |
|---|---|
namespaces |
Additional pairs Namespace → relative directory. |
config |
Module configuration. |
settings |
Guided settings diagram. |
services, helpers, files |
PHP files that can be included at any runtime. |
view_globals |
Common Twig values. |
migrations |
Versioned SQL schema files and PHP data conversion files. |
hook_definitions |
Description of new module expansion points. |
hooks |
General event subscriptions. |
field_types |
Provided field type classes. |
General connections are also available when the installed module is turned off, if needed to read existing data. Don't post routes and UI here that should disappear when turned off.
Admin and public
'admin' => array(
'services' => array('services.php'),
'routes' => array(
array('GET', '/example', array(AdminController::class, 'index')),
),
'hooks' => array(
array(
'name' => 'content.document.saved',
'handler' => array(AdminSubscriber::class, 'afterSave'),
'priority' => 20,
),
),
'assets' => array(/* styles и scripts */),
),
'public' => array(
'services' => array('services.php'),
'routes' => array(
array('GET', '/example/{id}', array(PublicController::class, 'show')),
),
'hooks' => array(/* публичные обработчики */),
),
The admin section is loaded only in the control panel, the public section is loaded only on the public website. When the module is turned off, both sections are skipped.
Public tags and visual inspector
The public tag is registered in services.php. Optional key inspect
tells the protected public debugger what to name the element and where to go
to configure it:
ModuleTagRegistry::register(
'gallery-widget',
'#\\[mod_gallery:([1-9][0-9]*)\\]#i',
array(Tags::class, 'render'),
20,
array(
'cacheable' => false,
'inspect' => array(
'module' => 'galleries',
'title' => 'Галереи',
'edit_url' => 'modules/galleries',
),
)
);
module- stable package code;title- a human-readable name;edit_url— path inside the control panel without the name of its physical folder;edit_urlcan be omitted if the tag does not have its own editor.
The full URL builds AdminLocation, so renaming the panel directory does not
breaks the transition. Do not pass element contents to inspect, custom
data or secrets.
Rights and routes
permissions describes the rights group and elements. Routes must additionally
check the right in the controller: having a menu item is not a protection.
'permissions' => array(
'key' => 'notes',
'items' => array(
array('code' => 'view_notes', 'group_code' => 'navigation',
'name' => 'Заметки: просмотр', 'sort_order' => 10),
array('code' => 'manage_notes', 'group_code' => 'content',
'name' => 'Заметки: управление', 'sort_order' => 20),
),
'icon' => 'ti ti-notes',
'priority' => 46,
),
'routes' => array(
array('GET', '/notes', array(Controller::class, 'index')),
array('POST', '/notes', array(Controller::class, 'store')),
),
Keep static rights, menus and routes in module.php. Separate provider
or routes.php is needed only for calculated or reused logic.
Hooks and custom events
'hook_definitions' => array(
array(
'name' => 'reviews.review.approved',
'kind' => 'action',
'domain' => 'reviews',
'description' => 'Отзыв прошёл модерацию',
'context' => ReviewEvent::class,
'mutable' => false,
),
),
'hooks' => array(
array(
'name' => 'content.document.saved',
'handler' => array(Subscriber::class, 'onDocumentSaved'),
'priority' => 20,
),
),
The full contract is in the Hooks and Events section.
Field types
'field_types' => array(
array('class' => RatingField::class, 'creatable' => true),
),
creatable = false leaves a handler for existing data, but hides
type when creating a new field. Type development is described in section
Document fields.
Contributions to the panel interface
admin_extension can provide a menu, header action, dashboard widget and
notifications. For each contribution, provider/template, right and order are specified.
Detailed diagrams and examples: UI Contributions.