pluginsPath = $pluginsPath; $this->enabledPlugins = $enabledPlugins; $this->loadPlugins(); } public function setAPI($api): void { $this->api = $api; foreach ($this->plugins as $plugin) { if (method_exists($plugin, 'setAPI')) { $plugin->setAPI($api); } } } private function loadPlugins(): void { if (!is_dir($this->pluginsPath)) { return; } $pluginDirs = glob($this->pluginsPath . '/*', GLOB_ONLYDIR); foreach ($pluginDirs as $pluginDir) { $pluginName = basename($pluginDir); if (!in_array($pluginName, $this->enabledPlugins, true)) { continue; } $pluginFile = $pluginDir . '/' . $pluginName . '.php'; if (file_exists($pluginFile)) { require_once $pluginFile; $className = $pluginName; if (class_exists($className)) { $this->plugins[$pluginName] = new $className(); // Auto-register hooks from plugin methods $hookMethods = ['onPageLoad', 'onBeforeRender', 'onAfterRender', 'onSearch', 'onMenuBuild']; foreach ($hookMethods as $hook) { if (method_exists($this->plugins[$pluginName], $hook)) { $this->addAction($hook, [$this->plugins[$pluginName], $hook]); } } // Register filter methods $filterMethods = ['onContentFilter', 'onTitleFilter', 'onMenuFilter']; foreach ($filterMethods as $filter) { if (method_exists($this->plugins[$pluginName], $filter)) { $this->addFilter($filter, [$this->plugins[$pluginName], $filter]); } } } } } } public function addAction(string $hook, callable $callback, int $priority = 10): void { $this->actions[$hook][$priority][] = $callback; } public function addFilter(string $hook, callable $callback, int $priority = 10): void { $this->filters[$hook][$priority][] = $callback; } public function doAction(string $hook, ...$args): void { if (!isset($this->actions[$hook])) return; ksort($this->actions[$hook]); foreach ($this->actions[$hook] as $callbacks) { foreach ($callbacks as $callback) { $callback(...$args); } } } public function applyFilters(string $hook, $value, ...$args) { if (!isset($this->filters[$hook])) return $value; ksort($this->filters[$hook]); foreach ($this->filters[$hook] as $callbacks) { foreach ($callbacks as $callback) { $value = $callback($value, ...$args); } } return $value; } public function getPlugin(string $name): ?object { return $this->plugins[$name] ?? null; } public function getAllPlugins(): array { return $this->plugins; } public function getEnabledPlugins(): array { return $this->enabledPlugins; } public function isEnabled(string $pluginName): bool { return in_array($pluginName, $this->enabledPlugins, true); } public function isPluginViewable(object $plugin): bool { if (method_exists($plugin, 'getConfig')) { $config = $plugin->getConfig(); return !isset($config['viewable']) || $config['viewable'] !== false; } return true; } public function getSidebarContent(?array $allowedPlugins = null): string { $sidebarContent = ''; foreach ($this->plugins as $pluginName => $plugin) { if (!$this->isPluginViewable($plugin) || !method_exists($plugin, 'getSidebarContent')) { continue; } if ($allowedPlugins !== null && !in_array($pluginName, $allowedPlugins, true)) { continue; } $content = $plugin->getSidebarContent(); if (trim($content) === '') { continue; } $title = 'Plugin'; if (method_exists($plugin, 'getConfig')) { $config = $plugin->getConfig(); $title = $config['title'] ?? 'Plugin'; } $sidebarContent .= '