diff --git a/app/Config/Autoload.php b/app/Config/Autoload.php index e4aad938..201e63ef 100644 --- a/app/Config/Autoload.php +++ b/app/Config/Autoload.php @@ -96,7 +96,7 @@ class Autoload extends AutoloadConfig * * @var list */ - public $files = [APPPATH . 'Libraries/ViewComponents/Helpers/view_components_helper.php']; + public $files = []; /** * ------------------------------------------------------------------- @@ -110,34 +110,4 @@ class Autoload extends AutoloadConfig * @var list */ public $helpers = ['auth', 'setting', 'icons', 'plugins']; - - public function __construct() - { - // load plugins namespaces - $pluginsPaths = glob(PLUGINS_PATH . '*/*', GLOB_ONLYDIR | GLOB_NOSORT); - - if (! $pluginsPaths) { - $pluginsPaths = []; - } - - foreach ($pluginsPaths as $pluginPath) { - $vendor = basename(dirname($pluginPath)); - $package = basename($pluginPath); - - // validate plugin pattern - if (preg_match('~' . PLUGINS_KEY_PATTERN . '~', $vendor . '/' . $package) === false) { - continue; - } - - $pluginNamespace = 'Plugins\\' . str_replace( - ' ', - '', - ucwords(str_replace(['-', '_', '.'], ' ', $vendor . '\\' . $package)) - ); - - $this->psr4[$pluginNamespace] = $pluginPath; - } - - parent::__construct(); - } } diff --git a/modules/Plugins/Config/Plugins.php b/modules/Plugins/Config/Plugins.php index 08cbb8e7..cea88693 100644 --- a/modules/Plugins/Config/Plugins.php +++ b/modules/Plugins/Config/Plugins.php @@ -8,6 +8,8 @@ use CodeIgniter\Config\BaseConfig; class Plugins extends BaseConfig { + public string $folder = PLUGINS_PATH; + /** * @var list */ diff --git a/modules/Plugins/Config/Services.php b/modules/Plugins/Config/Services.php index 84dcd1c8..44b8b2ca 100644 --- a/modules/Plugins/Config/Services.php +++ b/modules/Plugins/Config/Services.php @@ -15,6 +15,8 @@ class Services extends BaseService return self::getSharedInstance('plugins'); } - return new Plugins(); + $config = config('Plugins'); + + return new Plugins($config); } } diff --git a/modules/Plugins/Core/BasePlugin.php b/modules/Plugins/Core/BasePlugin.php index 985c095f..a07976c5 100644 --- a/modules/Plugins/Core/BasePlugin.php +++ b/modules/Plugins/Core/BasePlugin.php @@ -101,6 +101,11 @@ abstract class BasePlugin implements PluginInterface return $this->status; } + final public function getDirectory(): string + { + return $this->directory; + } + /** * @return array */ diff --git a/modules/Plugins/Core/Plugins.php b/modules/Plugins/Core/Plugins.php index 90dd6295..198cfdbc 100644 --- a/modules/Plugins/Core/Plugins.php +++ b/modules/Plugins/Core/Plugins.php @@ -8,6 +8,7 @@ use App\Entities\Episode; use App\Entities\Podcast; use App\Libraries\SimpleRSSElement; use Config\Database; +use Modules\Plugins\Config\Plugins as PluginsConfig; /** * @method void rssBeforeChannel(Podcast $podcast) @@ -63,8 +64,9 @@ class Plugins protected static int $activeCount = 0; - public function __construct() - { + public function __construct( + protected PluginsConfig $config + ) { helper('plugins'); $this->registerPlugins(); @@ -91,6 +93,14 @@ class Plugins return array_slice(static::$plugins, (($page - 1) * $perPage), $perPage); } + /** + * @return array + */ + public function getAllPlugins(): array + { + return static::$plugins; + } + /** * @return array */ @@ -240,8 +250,8 @@ class Plugins return false; } - // delete plugin folder from PLUGINS_PATH - $pluginFolder = PLUGINS_PATH . $plugin->getKey(); + // delete plugin folder + $pluginFolder = $this->config->folder . $plugin->getKey(); $rmdirResult = $this->rrmdir($pluginFolder); $transResult = $db->transCommit(); @@ -252,13 +262,12 @@ class Plugins protected function registerPlugins(): void { // search for plugins in plugins folder - $pluginsDirectories = glob(PLUGINS_PATH . '*/*', GLOB_ONLYDIR); + $pluginsDirectories = glob($this->config->folder . '*/*', GLOB_ONLYDIR); if ($pluginsDirectories === false || $pluginsDirectories === []) { return; } - $locator = service('locator'); foreach ($pluginsDirectories as $pluginDirectory) { $vendor = basename(dirname($pluginDirectory)); $package = basename($pluginDirectory); @@ -267,13 +276,17 @@ class Plugins continue; } - $pluginFile = $pluginDirectory . DIRECTORY_SEPARATOR . 'Plugin.php'; + $className = str_replace( + ' ', + '', + ucwords(str_replace(['-', '_', '.'], ' ', $vendor . ' ' . $package)) . 'Plugin' + ); - $className = $locator->findQualifiedNameFromPath($pluginFile); - - if ($className === false) { - continue; - } + spl_autoload_register(static function ($class) use (&$className, &$pluginDirectory): void { + if ($class === $className) { + include $pluginDirectory . DIRECTORY_SEPARATOR . 'Plugin.php'; + } + }, true); $plugin = new $className($vendor, $package, $pluginDirectory); if (! $plugin instanceof BasePlugin) { diff --git a/modules/Plugins/Helpers/plugins_helper.php b/modules/Plugins/Helpers/plugins_helper.php index 6af0beba..7ab2ab1b 100644 --- a/modules/Plugins/Helpers/plugins_helper.php +++ b/modules/Plugins/Helpers/plugins_helper.php @@ -49,3 +49,35 @@ if (! function_exists('set_plugin_option')) { ->set($key, $value, $context); } } + +if (! function_exists('load_plugins_translations')) { + /** + * @return array + */ + function load_plugins_translations(string $locale): array + { + $allPlugins = plugins() + ->getAllPlugins(); + + $translations = []; + foreach ($allPlugins as $plugin) { + $file = $plugin->getDirectory() . DIRECTORY_SEPARATOR . 'i18n' . DIRECTORY_SEPARATOR . $locale . '.json'; + + $jsonContents = @file_get_contents($file); + + if (! $jsonContents) { + continue; + } + + $contents = json_decode($jsonContents, true); + + if (! $contents) { + continue; + } + + $translations[$plugin->getKey()] = $contents; + } + + return $translations; + } +} diff --git a/modules/Plugins/Language/br/Plugin.php b/modules/Plugins/Language/br/Plugin.php new file mode 100644 index 00000000..36a992fa --- /dev/null +++ b/modules/Plugins/Language/br/Plugin.php @@ -0,0 +1,8 @@ +options as $option) { $optionsArray[] = [ - 'label' => $option->label, 'value' => $option->value, - 'hint' => (string) $option->hint, + 'label' => esc($this->getTranslated($i18nKey . '.' . $option->value . '.label', $option->label)), + 'hint' => esc($this->getTranslated($i18nKey . '.' . $option->value . '.hint', (string) $option->hint)), ]; } return $optionsArray; } + + public function getTranslated(string $i18nKey, string $default): string + { + $key = 'Plugin.' . $i18nKey; + + /** @var string $i18nField */ + $i18nField = lang($key); + + if ($default === '' || $i18nField === $key) { + return $default; + } + + return $i18nField; + } } diff --git a/modules/Plugins/Manifest/ManifestObject.php b/modules/Plugins/Manifest/ManifestObject.php index c6a58b98..4ae097a9 100644 --- a/modules/Plugins/Manifest/ManifestObject.php +++ b/modules/Plugins/Manifest/ManifestObject.php @@ -90,11 +90,20 @@ abstract class ManifestObject if (is_array($cast)) { if (is_array($value)) { foreach ($value as $valueKey => $valueElement) { - $value[$valueKey] = new $cast[0]($this->pluginKey, $valueElement); + if (is_subclass_of($cast[0], self::class)) { + $value[$valueKey] = new $cast[0]($this->pluginKey); + $value[$valueKey]->loadData($valueElement); + } else { + $value[$valueKey] = new $cast[0]($valueElement); + } } } + } elseif (is_subclass_of($cast, self::class)) { + $valueElement = $value; + $value = new $cast($this->pluginKey); + $value->loadData($valueElement ?? []); } else { - $value = new $cast($this->pluginKey, $value ?? []); + $value = new $cast($value ?? []); } } diff --git a/themes/cp_admin/plugins/_settings_form.php b/themes/cp_admin/plugins/_settings_form.php index c7797ad3..14c4bb21 100644 --- a/themes/cp_admin/plugins/_settings_form.php +++ b/themes/cp_admin/plugins/_settings_form.php @@ -5,24 +5,24 @@ type): case 'checkbox': ?> label ?> + >getTranslated(sprintf('%s.settings.%s.%s.label', $plugin->getKey(), $type, $field->key), $field->label)) ?> label ?> + >getTranslated(sprintf('%s.settings.%s.%s.label', $plugin->getKey(), $type, $field->key), $field->label)) ?> @@ -31,10 +31,10 @@ @@ -43,10 +43,10 @@ @@ -56,9 +56,9 @@ as="Input" type="email" name="key ?>" - label="label) ?>" - hint="hint) ?>" - helper="helper) ?>" + label="getTranslated(sprintf('%s.settings.%s.%s.label', $plugin->getKey(), $type, $field->key), $field->label)) ?>" + hint="getTranslated(sprintf('%s.settings.%s.%s.hint', $plugin->getKey(), $type, $field->key), $field->hint)) ?>" + helper="getTranslated(sprintf('%s.settings.%s.%s.helper', $plugin->getKey(), $type, $field->key), $field->helper)) ?>" isRequired="optional ? 'false' : 'true' ?>" value="getKey(), $field->key, $context) ?>" /> @@ -69,9 +69,9 @@ type="url" placeholder="https://…" name="key ?>" - label="label) ?>" - hint="hint) ?>" - helper="helper) ?>" + label="getTranslated(sprintf('%s.settings.%s.%s.label', $plugin->getKey(), $type, $field->key), $field->label)) ?>" + hint="getTranslated(sprintf('%s.settings.%s.%s.hint', $plugin->getKey(), $type, $field->key), $field->hint)) ?>" + helper="getTranslated(sprintf('%s.settings.%s.%s.helper', $plugin->getKey(), $type, $field->key), $field->helper)) ?>" isRequired="optional ? 'false' : 'true' ?>" value="getKey(), $field->key, $context) ?>" /> @@ -81,9 +81,9 @@ as="Input" type="number" name="key ?>" - label="label) ?>" - hint="hint) ?>" - helper="helper) ?>" + label="getTranslated(sprintf('%s.settings.%s.%s.label', $plugin->getKey(), $type, $field->key), $field->label)) ?>" + hint="getTranslated(sprintf('%s.settings.%s.%s.hint', $plugin->getKey(), $type, $field->key), $field->hint)) ?>" + helper="getTranslated(sprintf('%s.settings.%s.%s.helper', $plugin->getKey(), $type, $field->key), $field->helper)) ?>" isRequired="optional ? 'false' : 'true' ?>" value="getKey(), $field->key, $context) ?>" /> @@ -92,9 +92,9 @@ @@ -103,21 +103,21 @@ - + case 'datetime': + $hasDatetime = true ?> @@ -126,9 +126,9 @@ diff --git a/themes/cp_admin/plugins/settings.php b/themes/cp_admin/plugins/settings.php index 10d0e16e..587fd772 100644 --- a/themes/cp_admin/plugins/settings.php +++ b/themes/cp_admin/plugins/settings.php @@ -34,6 +34,7 @@ if (isset($episode)) { 'plugin' => $plugin, 'action' => route_to(sprintf('plugins-settings-%s-action', $type), ...$params), 'fields' => $fields, + 'type' => $type, 'context' => $context, ]) ?> endSection() ?>