%PDF- %PDF-
| Direktori : /www/varak.net/dmarc.varak.net/classes/Plugins/ |
| Current File : /www/varak.net/dmarc.varak.net/classes/Plugins/PluginManager.php |
<?php
/**
* dmarc-srg - A php parser, viewer and summary report generator for incoming DMARC reports.
* Copyright (C) 2025 Aleksey Andreev (liuch)
*
* Available at:
* https://github.com/liuch/dmarc-srg
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, either version 3 of the License.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* =========================
*
* This file contains the class PluginManager
*
* @category API
* @package DmarcSrg
* @author Aleksey Andreev (liuch)
* @license https://www.gnu.org/licenses/gpl-3.0.html GNU/GPLv3
*/
namespace Liuch\DmarcSrg\Plugins;
use Liuch\DmarcSrg\Exception\SoftException;
use Liuch\DmarcSrg\Exception\RuntimeException;
/**
* Class for managing the plugin system
*/
class PluginManager
{
private static $instance = null;
private $plugins = [];
/**
* Sends an event to plugin that are subscribed to it
*
* @param string $group Event group
* @param string $name Event name
* @param array $data Array of data to be passed to each plugin
*
* @return void
*/
public static function dispatchEvent(string $group, string $name, array &$data): void
{
$plist = self::instance()->loadPlugins($group);
$data['event'] = $name;
$plugin = null;
try {
foreach ($plist as &$it) {
$handler = $it['handlers'][$name] ?? null;
if ($handler) {
$plugin = $it['plugin'];
$plugin->$handler($data);
}
}
unset($it);
} catch (SoftException $e) {
if ($plugin) {
$e = new SoftException('[' . $plugin->name() . '] ' . $e->getMessage(), $e->getCode());
}
throw $e;
}
}
/**
* Searches and loads plugins for the specified type, if necessary.
*
* Splitting plug-ins into groups is necessary to save resources,
* so that only necessary plug-ins are loaded.
*
* @param string $group Event group
*
* @return array Array of plugins of the specified group sorted by name
*/
private function loadPlugins(string $group): array
{
if (isset($this->plugins[$group])) {
return $this->plugins[$group];
}
$group_path = ROOT_PATH . 'plugins/' . $group;
if (!is_dir($group_path) || !is_readable($group_path)) {
return [];
}
$res = [];
try {
foreach (new \FilesystemIterator($group_path) as $plugin_fi) {
if ($plugin_fi->isDir() && $plugin_fi->isReadable()) {
$plugin_name = $plugin_fi->getFilename();
$plugin_path = $plugin_fi->getPathname() . "/{$plugin_name}.php";
if (is_file($plugin_path) && is_readable($plugin_path)) {
include_once($plugin_path);
$plugin_ns_name = __NAMESPACE__ . '\\' . $plugin_name;
$plugin = new $plugin_ns_name();
if ($plugin instanceof PluginInterface) {
$res[] = [
'plugin' => $plugin,
'name' => $plugin_name,
'handlers' => $plugin->subscribedEvents()
];
}
}
}
}
} catch (\Exception $e) {
throw new RuntimeException('Plugin loading error', -1, $e);
}
usort($res, function ($a, $b) {
return strcmp($a['name'], $b['name']);
});
$this->plugins[$group] = $res;
return $res;
}
/**
* Returns an instance of the class
*
* @return self
*/
private static function instance()
{
if (!self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
}