From c71a4b06ef7bdaa3ab8f2707349e3c82998a2da0 Mon Sep 17 00:00:00 2001 From: Hugo Sales Date: Sat, 21 Aug 2021 22:30:24 +0100 Subject: [PATCH] [CONFIG] Make it possible to write module configuration in a config.{php,yml,yaml,xml} file and set each value as properties in the module object --- src/Core/GNUsocial.php | 27 +++++++++++++++++++++-- src/Core/ModuleManager.php | 39 ++++++++++++++++++++++++++++++++++ src/Core/Modules/Component.php | 3 ++- src/Core/Modules/Module.php | 19 +++++++++++------ src/Core/Modules/Plugin.php | 10 +-------- src/Util/Common.php | 4 +++- 6 files changed, 83 insertions(+), 19 deletions(-) diff --git a/src/Core/GNUsocial.php b/src/Core/GNUsocial.php index 6674b3acf2..38fbba46aa 100644 --- a/src/Core/GNUsocial.php +++ b/src/Core/GNUsocial.php @@ -224,6 +224,10 @@ class GNUsocial implements EventSubscriberInterface /** * Load configuration files + * + * Happens at "compile time" + * + * @codeCoverageIgnore */ public static function configureContainer(ContainerBuilder $container, LoaderInterface $loader): void { @@ -241,8 +245,27 @@ class GNUsocial implements EventSubscriberInterface $loader->load(INSTALLDIR . '/social' . Kernel::CONFIG_EXTS, 'glob'); $container->setParameter('gnusocial_defaults', $container->getParameter('gnusocial')); - $configs = array_replace_recursive($container->getParameter('gnusocial'), $locals['gnusocial']); - $container->setParameter('gnusocial', $configs); + // Load module config + $parameters = ModuleManager::configureContainer($container, $loader); + + // Merge parameter $from with values already set in $to + $merge_config = function ($from, $to = null) use ($container, $locals) { + $to = $to ?? $from; + $wrapper = $container->hasParameter($to) ? $container->getParameter($to) : []; + $content = [$from => $container->getParameter($from)]; + $container->getParameterBag()->remove($from); + $locals = isset($locals[$from]) ? [$from => $locals[$from]] : []; + $configs = array_replace_recursive($wrapper, $content, $locals); + $container->setParameter($to, $configs); + }; + + // Override and merge any of the previous settings from the locals + if (is_array($locals)) { + $merge_config('gnusocial'); + foreach ($parameters as $mod => $type) { + $merge_config($mod, $type); + } + } } /** diff --git a/src/Core/ModuleManager.php b/src/Core/ModuleManager.php index 4da968f0f6..7ac2c01281 100644 --- a/src/Core/ModuleManager.php +++ b/src/Core/ModuleManager.php @@ -33,12 +33,14 @@ namespace App\Core; +use App\Kernel; use App\Util\Formatting; use AppendIterator; use FilesystemIterator; use Functional as F; use RecursiveDirectoryIterator; use RecursiveIteratorIterator; +use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; @@ -166,10 +168,47 @@ class ModuleManager $obj = require CACHE_FILE; + foreach ($obj->modules as $module) { + $module->loadConfig(); + } + foreach ($obj->events as $event => $callables) { foreach ($callables as $callable) { Event::addHandler($event, $callable); } } } + + /** + * Load Module settings and setup Twig template load paths + * + * Happens at "compile time" + * + * @codeCoverageIgnore + */ + public static function configureContainer(ContainerBuilder $container, LoaderInterface $loader): array + { + $template_modules = array_merge(glob(INSTALLDIR . '/components/*/templates'), glob(INSTALLDIR . '/plugins/*/templates')); + // Regular template location + $templates = ['%kernel.project_dir%/templates' => 'default_path', '%kernel.project_dir%/public' => 'public_path']; + // Path => alias + foreach ($template_modules as $mod) { + $templates[$mod] = null; + } + $container->loadFromExtension('twig', ['paths' => $templates]); + + $modules = array_merge(glob(INSTALLDIR . '/components/*'), glob(INSTALLDIR . '/plugins/*')); + $parameters = []; + foreach ($modules as $mod) { + $path = "{$mod}/config" . Kernel::CONFIG_EXTS; + $loader->load($path, 'glob'); // Is supposed to, but doesn't return anything that would let us identify if loading worked + foreach (explode(',', substr(Kernel::CONFIG_EXTS, 2, -1)) as $ext) { + if (file_exists("{$mod}/config.{$ext}")) { + $parameters[basename(strtolower($mod))] = basename(dirname(strtolower($mod))); + break; + } + } + } + return $parameters; + } } diff --git a/src/Core/Modules/Component.php b/src/Core/Modules/Component.php index e0824297eb..b01fa319a0 100644 --- a/src/Core/Modules/Component.php +++ b/src/Core/Modules/Component.php @@ -4,4 +4,5 @@ namespace App\Core\Modules; abstract class Component extends Module { -} \ No newline at end of file + const MODULE_TYPE = 'component'; +} diff --git a/src/Core/Modules/Module.php b/src/Core/Modules/Module.php index 5ff6d1fed6..0146c80eb5 100644 --- a/src/Core/Modules/Module.php +++ b/src/Core/Modules/Module.php @@ -27,18 +27,25 @@ use App\Util\Common; abstract class Module { /** - * TODO Handle configuration - * - * @codeCoverageIgnore + * Load values from the config and set them as properties on each module object */ - public function __construct() + public function loadConfig() { // Load Module settings - foreach (Common::config(static::class) as $aname => $avalue) { - $this->{$aname} = $avalue; + foreach (Common::config(static::MODULE_TYPE . 's') as $module => $values) { + if ($module == $this->name()) { + foreach ($values as $property => $value) { + $this->{$property} = $value; + } + } } } + public static function name() + { + return mb_strtolower(explode('\\', static::class)[2]); + } + /** * Serialize the class to store in the cache * diff --git a/src/Core/Modules/Plugin.php b/src/Core/Modules/Plugin.php index c0174d05c8..38af6b5d39 100644 --- a/src/Core/Modules/Plugin.php +++ b/src/Core/Modules/Plugin.php @@ -11,15 +11,7 @@ use App\Core\Event; */ abstract class Plugin extends Module { - public function __construct() - { - parent::__construct(); - } - - public function name() - { - return mb_substr(static::class, 0, -6); - } + const MODULE_TYPE = 'plugin'; public function version() { diff --git a/src/Util/Common.php b/src/Util/Common.php index a09a41b855..3d1d46e64d 100644 --- a/src/Util/Common.php +++ b/src/Util/Common.php @@ -49,7 +49,9 @@ abstract class Common private static ?array $config = null; public static function setupConfig(ContainerBagInterface $config) { - self::$config = $config->get('gnusocial'); + $components = $config->has('components') ? $config->get('components') : []; + $plugins = $config->has('plugins') ? $config->get('plugins') : []; + self::$config = array_merge($config->get('gnusocial'), ['components' => $components], ['plugins' => $plugins]); self::$defaults = $config->get('gnusocial_defaults'); }