Upgrade Plugin to Module
1. Implement Module Interfaces
Add IModule to your plugin class, plus any scope interface you need (ISystemSpaceModule, IWorkSpaceModule, IUserSpaceModule).
2. Migrate Initialization Logic
Replace onInit() scope-specific logic with the matching lifecycle method. Keep onInit() only for logic that must always run (e.g. facade setup).
Before:
public function onInit()
{
parent::onInit();
$this->_booksFacade = $this->_getBooksFacadeInstance();
}
After:
public function onInit()
{
parent::onInit();
$this->_booksFacade = $this->_getBooksFacadeInstance();
}
public function onLoadSystemSpaceModule(): void
{
// module-specific initialization here
}
parent::onInit() is not needed inside the scope lifecycle method — only module-specific work belongs there.
3. SQL Migration
Register the module and clean up the old plugin navigation:
-- Register module
INSERT INTO modules (caption, ident, plugin, required, description, hooks, is_active, is_workspace)
VALUES ('Test Module', 'test_module', 'TestModule', NULL, 'Test description.', NULL, true, true);
-- Remove old navigation
DELETE FROM festi_menus WHERE url = '/test_plugin_menu/';
DELETE FROM festi_url_rules WHERE plugin = 'TestModule';
-- Activate in all target workspaces
INSERT INTO modules2workspaces (id_module, id_workspace, is_active)
SELECT (SELECT id FROM modules WHERE ident = 'test_module'), id, TRUE
FROM schools
WHERE type = 'general';
Add module options to module_options if needed — see docs/ModuleOptions.md.
4. Replace Menu Registration
Remove the old static menu entry and implement IModuleMenuFetcher instead — see docs/CreatingModule.md for the full example.
5. Access the Module
After the migration the module is accessible both ways:
// As a module
/** @var TestModulePlugin $plugin */
$plugin = ModulesManager::getInstance()->getModule('TestModule');
assert($plugin instanceof TestModulePlugin);
// As a plugin (works as long as onInit() is still present)
$this->plugin->testModule->method();
Core::getInstance()->getPluginInstance(TestModulePlugin::class)->method();