This concept mod is inspired by the Wedge plugin system. It adds plugin support to SMF.
Plugins are standalone modifications that do not need to be installed or removed through the Package Manager. They don't make changes to SMF files and run entirely on hooks.
The entry point of each plugin is plugin.php with an anonymous class inside. Also in the directory of each plugin should be a file plugin-info.xml, which contains the key data of the plugin:
* name
* description
* plugin version
* author name
* link to the author's website (optional)
* email of the author (optional)
* the license used
* link to the plugin site
Plugins are turned on and off at the touch of a button. To install, simply place the plugin folder with the correct structure in the Plugins directory.
The list of currently active plugins is stored in the global variable $plugins in the Settings.php file. To disable a problem plugin, just remove its name from the $plugins variable, or rename the plugin folder, or rename the plugin.php file of the plugin.
example_plugin/
images/
example.png
index.php
languages/
english.php
index.php
russian.php
sources/
index.php
plugin.php
templates/
index.php
Example.template.php
scripts/
index.php
example.js
styles/
index.php
example.css
index.php
license.txt
plugin-info.xml
<?xml version="1.0" standalone="yes" ?>
<plugin id="Author:Example">
<name>Example</name>
<description>
<english>Description...</english>
<russian>Описание...</russian>
</description>
<version>0.1</version>
<author email="noreply@site.com" url="https://author-site.com">Author</author>
<license url="https://license-site.com">License name</license>
<website>https://plugin-site.com</website>
<settings>
<setting name="key1" type="text" default="" />
<setting name="key2" type="large_text" default="" />
<setting name="key3" type="check" default="1" />
<setting name="key4" type="int" default="1" />
</settings>
</plugin>
Plugins that require creation of tables in the database for their work must contain a node <database>file_name.php</database>
in plugin-info.xml. In the specified file, you can place a script to create the necessary tables when the plugin is enabled, if they have not yet been created.
<?php
/**
* @package Example
* @link https://plugin-site.com
* @author Author https://author-site.com
* @copyright 2024 Author
* @license https://opensource.org/licenses/MIT The MIT License
*/
use Bugo\PluginLoader\Plugin;
if (!defined('SMF'))
die('No direct access...');
return class extends Plugin
{
public const NAME = 'example';
#[Hook('integrate_load_theme', self::class . '::loadTheme#', __FILE__)]
public function loadTheme(): void
{
// Your code
// Use language strings
// $this->loadLanguage();
// var_dump($this->txt['key'])
// Use template
// $this->loadTemplate('Example'); // will be loaded /templates/Example.template.php
// Use other source file of the same plugin
// $this->loadSource('other); // will be loaded /sources/other.php
// Use CSS file
// $this->loadCSS('test'); // will be loaded /styles/test.css
// Use JS file
// $this->loadJS('test'); // will be loaded /scripts/test.js
// Use plugin settings
// var_dump($this->getSettings());
}
#[Hook('integrate_menu_buttons', self::class . '::menuButtons#', __FILE__)]
public function menuButtons($buttons): void
{
// var_dump($buttons);
}
};
As you can see, all hooks required by the plugin are defined using the Hook
attribute.
<?php
return [
'key1' => 'Text 1',
'key2' => 'Text 2',
];
The following methods are provided to work within plugin classes:
loadLanguage($lang_name)
- plugging PHP language file$lang_name
from subdirectorylanguages
of the current plugin (by default$lang_name = $context['user']['language']
)loadTemplate($template_name)
- plugging PHP template file$template_name
from subdirectorytemplates
of the current pluginloadCSS($css_name)
- plugging CSS file$css_name
from subdirectorystyles
of the current pluginloadJS($js_name)
- plugging JS-file$js_name
from subdirectoryscripts
of the current pluginloadSource($source_name)
- plugging PHP file$source_name
from subdirectorysources
of the current plugingetUrl($sub_directory = '')
- returns URL to the directory of the current plugin, including$sub_directory
(if specified)