Files
moko-platform/lib/Enterprise/PluginRegistry.php
T
Jonathan Miller 1799401db5
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
feat: add standard file headers to all 57 files missing them
- Add Copyright + FILE INFORMATION headers to 11 PHP enterprise classes
- Add FILE INFORMATION blocks to 9 PHP files with incomplete headers
- Add headers to 2 test files
- Add markdown comment headers to 27 index/README files
- Add headers to 5 root markdown files
- Add FILE INFORMATION to 4 files with existing but incomplete headers

All files now conform to moko-platform file header standard.

Authored-by: Moko Consulting

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-11 17:10:19 -05:00

283 lines
8.7 KiB
PHP

<?php
declare(strict_types=1);
/* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
*
* This file is part of a Moko Consulting project.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*
* FILE INFORMATION
* DEFGROUP: MokoStandards.Enterprise.Plugins
* INGROUP: MokoStandards.Enterprise
* REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform
* PATH: /lib/Enterprise/PluginRegistry.php
* BRIEF: Plugin registry for available project plugins
*/
namespace MokoEnterprise;
use MokoEnterprise\Plugins\JoomlaPlugin;
use MokoEnterprise\Plugins\DolibarrPlugin;
use MokoEnterprise\Plugins\GenericPlugin;
use MokoEnterprise\Plugins\DocumentationPlugin;
use MokoEnterprise\Plugins\NodeJsPlugin;
use MokoEnterprise\Plugins\PythonPlugin;
use MokoEnterprise\Plugins\TerraformPlugin;
use MokoEnterprise\Plugins\WordPressPlugin;
use MokoEnterprise\Plugins\MobilePlugin;
use MokoEnterprise\Plugins\ApiPlugin;
use MokoEnterprise\Plugins\McpServerPlugin;
/**
* Plugin Registry - Central registry for all project type plugins
*
* Manages plugin discovery, registration, and lifecycle
*
* @package MokoStandards\Enterprise
* @version 1.0.0
*/
class PluginRegistry
{
/** @var array<string, string> Map of project types to plugin class names */
private static $pluginClasses = [
'joomla' => JoomlaPlugin::class,
'dolibarr' => DolibarrPlugin::class,
'generic' => GenericPlugin::class,
'documentation' => DocumentationPlugin::class,
'nodejs' => NodeJsPlugin::class,
'python' => PythonPlugin::class,
'terraform' => TerraformPlugin::class,
'wordpress' => WordPressPlugin::class,
'mobile' => MobilePlugin::class,
'api' => ApiPlugin::class,
'mcp-server' => McpServerPlugin::class,
];
/** @var array<string, ProjectPluginInterface> Instantiated plugins */
private static $plugins = [];
/** @var AuditLogger|null Shared audit logger */
private static $logger = null;
/** @var MetricsCollector|null Shared metrics collector */
private static $metricsCollector = null;
/**
* Set shared logger for all plugins
*
* @param AuditLogger $logger Audit logger instance
* @return void
*/
public static function setLogger(AuditLogger $logger): void
{
self::$logger = $logger;
}
/**
* Set shared metrics collector for all plugins
*
* @param MetricsCollector $metricsCollector Metrics collector instance
* @return void
*/
public static function setMetricsCollector(MetricsCollector $metricsCollector): void
{
self::$metricsCollector = $metricsCollector;
}
/**
* Register a custom plugin for a project type
*
* @param string $projectType Project type identifier
* @param string $pluginClass Fully qualified plugin class name
* @return void
* @throws \InvalidArgumentException If plugin class doesn't implement ProjectPluginInterface
*/
public static function registerPlugin(string $projectType, string $pluginClass): void
{
if (!class_exists($pluginClass)) {
throw new \InvalidArgumentException("Plugin class does not exist: {$pluginClass}");
}
if (!is_subclass_of($pluginClass, ProjectPluginInterface::class)) {
throw new \InvalidArgumentException(
"Plugin class must implement ProjectPluginInterface: {$pluginClass}"
);
}
self::$pluginClasses[$projectType] = $pluginClass;
// Clear cached instance if exists
if (isset(self::$plugins[$projectType])) {
unset(self::$plugins[$projectType]);
}
}
/**
* Get plugin instance for a project type
*
* @param string $projectType Project type identifier
* @param array $config Optional plugin configuration
* @return ProjectPluginInterface|null Plugin instance or null if not found
*/
public static function getPlugin(string $projectType, array $config = []): ?ProjectPluginInterface
{
// Check if plugin is already instantiated
if (isset(self::$plugins[$projectType])) {
return self::$plugins[$projectType];
}
// Check if plugin class is registered
if (!isset(self::$pluginClasses[$projectType])) {
return null;
}
// Instantiate plugin
$pluginClass = self::$pluginClasses[$projectType];
$plugin = new $pluginClass(self::$logger, self::$metricsCollector, $config);
// Cache plugin instance
self::$plugins[$projectType] = $plugin;
return $plugin;
}
/**
* Get all registered project types
*
* @return array List of project type identifiers
*/
public static function getRegisteredTypes(): array
{
return array_keys(self::$pluginClasses);
}
/**
* Get all registered plugins
*
* @param array $config Optional plugin configuration
* @return array<string, ProjectPluginInterface> Map of project types to plugin instances
*/
public static function getAllPlugins(array $config = []): array
{
$plugins = [];
foreach (self::$pluginClasses as $projectType => $pluginClass) {
$plugins[$projectType] = self::getPlugin($projectType, $config);
}
return $plugins;
}
/**
* Check if a plugin is registered for a project type
*
* @param string $projectType Project type identifier
* @return bool True if plugin is registered
*/
public static function hasPlugin(string $projectType): bool
{
return isset(self::$pluginClasses[$projectType]);
}
/**
* Unregister a plugin
*
* @param string $projectType Project type identifier
* @return void
*/
public static function unregisterPlugin(string $projectType): void
{
unset(self::$pluginClasses[$projectType]);
unset(self::$plugins[$projectType]);
}
/**
* Clear all plugin instances (forces re-instantiation)
*
* @return void
*/
public static function clearCache(): void
{
self::$plugins = [];
}
/**
* Get plugin information
*
* @param string $projectType Project type identifier
* @return array|null Plugin info or null if not found
*/
public static function getPluginInfo(string $projectType): ?array
{
$plugin = self::getPlugin($projectType);
if ($plugin === null) {
return null;
}
return [
'project_type' => $plugin->getProjectType(),
'plugin_name' => $plugin->getPluginName(),
'plugin_version' => $plugin->getPluginVersion(),
'required_files' => $plugin->getRequiredFiles(),
'recommended_files' => $plugin->getRecommendedFiles(),
'best_practices_count' => count($plugin->getBestPractices()),
'commands_count' => count($plugin->getCommands()),
];
}
/**
* Get all plugins information
*
* @return array Map of project types to plugin information
*/
public static function getAllPluginsInfo(): array
{
$info = [];
foreach (self::getRegisteredTypes() as $projectType) {
$info[$projectType] = self::getPluginInfo($projectType);
}
return $info;
}
/**
* Find plugin by feature/capability
*
* @param string $feature Feature name (e.g., 'package_manager', 'type_checking')
* @return array List of project types supporting the feature
*/
public static function findPluginsByFeature(string $feature): array
{
$matches = [];
foreach (self::getRegisteredTypes() as $projectType) {
$plugin = self::getPlugin($projectType);
if ($plugin !== null) {
$bestPractices = $plugin->getBestPractices();
foreach ($bestPractices as $practice) {
if (stripos($practice['title'] ?? '', $feature) !== false ||
stripos($practice['description'] ?? '', $feature) !== false) {
$matches[] = $projectType;
break;
}
}
}
}
return $matches;
}
/**
* Get plugin registry statistics
*
* @return array Registry statistics
*/
public static function getStatistics(): array
{
return [
'total_plugins' => count(self::$pluginClasses),
'instantiated_plugins' => count(self::$plugins),
'registered_types' => self::getRegisteredTypes(),
'has_logger' => self::$logger !== null,
'has_metrics_collector' => self::$metricsCollector !== null,
];
}
}