mirror of
https://github.com/RaspAP/raspap-webgui.git
synced 2024-11-21 23:20:22 +00:00
Initial commit
This commit is contained in:
parent
a86c637f04
commit
262ff6a00e
3 changed files with 249 additions and 0 deletions
31
src/RaspAP/Plugins/PluginInterface.php
Normal file
31
src/RaspAP/Plugins/PluginInterface.php
Normal file
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Plugin Interface
|
||||
*
|
||||
* @description Basic plugin interface for RaspAP
|
||||
* @author Bill Zimmerman <billzimmerman@gmail.com>
|
||||
* @license https://github.com/raspap/raspap-webgui/blob/master/LICENSE
|
||||
* @see
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace RaspAP\Plugins;
|
||||
|
||||
use RaspAP\UI\Sidebar;
|
||||
|
||||
interface PluginInterface {
|
||||
/**
|
||||
* Initialize the plugin
|
||||
* @param Sidebar $sidebar Sidebar instance for adding items
|
||||
*/
|
||||
public function initialize(Sidebar $sidebar): void;
|
||||
|
||||
/**
|
||||
* Provide template data for rendering
|
||||
* @return array
|
||||
*/
|
||||
public function getTemplateData(): array;
|
||||
}
|
||||
|
120
src/RaspAP/Plugins/PluginManager.php
Normal file
120
src/RaspAP/Plugins/PluginManager.php
Normal file
|
@ -0,0 +1,120 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Plugin Manager class
|
||||
*
|
||||
* @description Architecture to support user plugins for RaspAP
|
||||
* @author Bill Zimmerman <billzimmerman@gmail.com>
|
||||
* @license https://github.com/raspap/raspap-webgui/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace RaspAP\Plugins;
|
||||
|
||||
use RaspAP\UI\Sidebar;
|
||||
|
||||
class PluginManager {
|
||||
private static $instance = null;
|
||||
private $plugins = [];
|
||||
private $sidebar;
|
||||
|
||||
private function __construct() {
|
||||
$this->pluginPath = 'plugins';
|
||||
$this->sidebar = new Sidebar();
|
||||
$this->autoloadPlugins(); // autoload plugins on instantiation
|
||||
}
|
||||
|
||||
// Get the single instance of PluginManager
|
||||
public static function getInstance(): PluginManager {
|
||||
if (self::$instance === null) {
|
||||
self::$instance = new PluginManager();
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
// Autoload plugins found in pluginPath
|
||||
private function autoloadPlugins(): void {
|
||||
if (!is_dir($this->pluginPath)) {
|
||||
return;
|
||||
}
|
||||
$directories = array_filter(glob($this->pluginPath . '/*'), 'is_dir');
|
||||
foreach ($directories as $dir) {
|
||||
$pluginName = basename($dir);
|
||||
$pluginFile = "$dir/$pluginName.php";
|
||||
|
||||
if (file_exists($pluginFile)) {
|
||||
require_once $pluginFile;
|
||||
$className = "RaspAP\\Plugins\\$pluginName\\$pluginName"; // Fully qualified class name
|
||||
if (class_exists($className)) {
|
||||
$plugin = new $className();
|
||||
$this->registerPlugin($plugin);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Registers a plugin by its interface implementation
|
||||
private function registerPlugin(PluginInterface $plugin) {
|
||||
$plugin->initialize($this->sidebar); // pass sidebar to initialize method
|
||||
$this->plugins[] = $plugin; // store the plugin instance
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a template from inside a plugin directory
|
||||
* @param string $pluginName
|
||||
* @param string $templateName
|
||||
* @param array $__data
|
||||
*/
|
||||
public function renderTemplate(string $pluginName, string $templateName, array $__data = []): string {
|
||||
// Construct the file path for the template
|
||||
$templateFile = "{$this->pluginPath}/{$pluginName}/templates/{$templateName}.php";
|
||||
|
||||
if (!file_exists($templateFile)) {
|
||||
return "Template file {$templateFile} not found.";
|
||||
}
|
||||
|
||||
// Extract the data for use in the template
|
||||
if (!empty($__data)) {
|
||||
extract($__data);
|
||||
}
|
||||
|
||||
// Start output buffering to capture the template output
|
||||
ob_start();
|
||||
include $templateFile;
|
||||
return ob_get_clean(); // return the output
|
||||
}
|
||||
|
||||
// Returns the sidebar
|
||||
public function getSidebar(): Sidebar {
|
||||
return $this->sidebar;
|
||||
}
|
||||
|
||||
// Forwards the page to the responsible plugin
|
||||
public function handlePageAction(string $page): void {
|
||||
foreach ($this->getInstalledPlugins() as $plugin) {
|
||||
if (str_starts_with($page, "/plugin__" . $plugin . "__")) {
|
||||
require_once($this->pluginPath . "/" . $plugin . "/functions.php");
|
||||
$function = '\\' . $plugin . '\\pluginHandlePageAction';
|
||||
$function($page);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Returns all installed plugins
|
||||
public function getInstalledPlugins(): array {
|
||||
$plugins = [];
|
||||
if (file_exists($this->pluginPath)) {
|
||||
$files = scandir($this->pluginPath);
|
||||
foreach ($files as $file) {
|
||||
if ($file === "." || $file === "..") continue;
|
||||
$filePath = $this->pluginPath . '/' . $file;
|
||||
if (is_dir($filePath)) {
|
||||
$plugins[] = $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $plugins;
|
||||
}
|
||||
}
|
||||
|
98
src/RaspAP/UI/Sidebar.php
Normal file
98
src/RaspAP/UI/Sidebar.php
Normal file
|
@ -0,0 +1,98 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Sidebar UI class
|
||||
*
|
||||
* @description A sidebar class for the RaspAP UI, extendable by user plugins
|
||||
* @author Bill Zimmerman <billzimmerman@gmail.com>
|
||||
* @license https://github.com/raspap/raspap-webgui/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
namespace RaspAP\UI;
|
||||
|
||||
class Sidebar {
|
||||
private $items = [];
|
||||
|
||||
public function __construct() {
|
||||
// Load default sidebar items
|
||||
$this->addItem(_('Dashboard'), 'fa-solid fa-gauge-high', 'wlan0_info', 10);
|
||||
$this->addItem(_('Hotspot'), 'far fa-dot-circle', 'hostapd_conf', 20,
|
||||
fn() => defined('RASPI_HOTSPOT_ENABLED') && RASPI_HOTSPOT_ENABLED
|
||||
);
|
||||
$this->addItem(_('DHCP Server'), 'fas fa-exchange-alt', 'dhcpd_conf', 30,
|
||||
fn() => defined('RASPI_DHCP_ENABLED') && RASPI_DHCP_ENABLED && !$_SESSION["bridgedEnabled"]
|
||||
);
|
||||
$this->addItem(_('Ad Blocking'), 'far fa-hand-paper', 'adblock_conf', 40,
|
||||
fn() => defined('RASPI_ADBLOCK_ENABLED') && RASPI_HOTSPOT_ENABLED && !$_SESSION["bridgedEnabled"]
|
||||
);
|
||||
$this->addItem(_('Networking'), 'fas fa-network-wired', 'network_conf', 50,
|
||||
fn() => defined('RASPI_NETWORK_ENABLED') && RASPI_NETWORK_ENABLED
|
||||
);
|
||||
$this->addItem(_('WiFi client'), 'fas fa-wifi', 'wpa_conf', 60,
|
||||
fn() => defined('RASPI_WIFICLIENT_ENABLED') && RASPI_WIFICLIENT_ENABLED && !$_SESSION["bridgedEnabled"]
|
||||
);
|
||||
$this->addItem(_('OpenVPN'), 'fas fa-key', 'openvpn_conf', 70,
|
||||
fn() => defined('RASPI_OPENVPN_ENABLED') && RASPI_OPENVPN_ENABLED
|
||||
);
|
||||
$this->addItem(_('WireGuard'), 'ra-wireguard', 'wg_conf', 80,
|
||||
fn() => defined('RASPI_WIREGUARD_ENABLED') && RASPI_WIREGUARD_ENABLED
|
||||
);
|
||||
$this->addItem(_(getProviderValue($_SESSION["providerID"], "name")), 'fas fa-shield-alt', 'provider_conf', 90,
|
||||
fn() => defined('RASPI_VPN_PROVIDER_ENABLED') && RASPI_VPN_PROVIDER_ENABLED
|
||||
);
|
||||
$this->addItem(_('Authentication'), 'fas fa-user-lock', 'auth_conf', 100,
|
||||
fn() => defined('RASPI_CONFAUTH_ENABLED') && RASPI_CONFAUTH_ENABLED
|
||||
);
|
||||
$this->addItem(_('Data usage'), 'fas fa-chart-area', 'data_use', 110,
|
||||
fn() => defined('RASPI_VNSTAT_ENABLED') && RASPI_VNSTAT_ENABLED
|
||||
);
|
||||
$this->addItem(_('RestAPI'), 'fas fa-puzzle-piece', 'restapi_conf', 120,
|
||||
fn() => defined('RASPI_VNSTAT_ENABLED') && RASPI_VNSTAT_ENABLED
|
||||
);
|
||||
$this->addItem(_('System'), 'fas fa-cube', 'data_use', 130,
|
||||
fn() => defined('RASPI_SYSTEM_ENABLED') && RASPI_SYSTEM_ENABLED
|
||||
);
|
||||
$this->addItem(_('About RaspAP'), 'fas fa-info-circle', 'about', 140);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an item to the sidebar
|
||||
* @param string $label
|
||||
* @param string $iconClass
|
||||
* @param string $link
|
||||
* @param int $priority
|
||||
* @param callable $condition
|
||||
*/
|
||||
public function addItem(string $label, string $iconClass, string $link, int $priority, callable $condition = null) {
|
||||
$this->items[] = [
|
||||
'label' => $label,
|
||||
'icon' => $iconClass,
|
||||
'link' => $link,
|
||||
'priority' => $priority,
|
||||
'condition' => $condition
|
||||
];
|
||||
}
|
||||
|
||||
public function getItems(): array {
|
||||
// Sort items by priority and filter by enabled condition
|
||||
$filteredItems = array_filter($this->items, function ($item) {
|
||||
return $item['condition'] === null || call_user_func($item['condition']);
|
||||
});
|
||||
usort($filteredItems, function ($a, $b) {
|
||||
return $a['priority'] <=> $b['priority'];
|
||||
});
|
||||
return $filteredItems;
|
||||
}
|
||||
|
||||
public function render() {
|
||||
foreach ($this->getItems() as $item) {
|
||||
echo "<div class=\"sb-nav-link-icon px-2\">
|
||||
<a class=\"nav-link\" href=\"{$item['link']}\">
|
||||
<i class=\"sb-nav-link-icon {$item['icon']} fa-fw mr-2\"></i>
|
||||
<span class=\"nav-label\">{$item['label']}</span>
|
||||
</a>
|
||||
</div>";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in a new issue