diff --git a/src/Cms/AppPlugins.php b/src/Cms/AppPlugins.php index 9d761ce057..3b5e69dc3a 100644 --- a/src/Cms/AppPlugins.php +++ b/src/Cms/AppPlugins.php @@ -802,19 +802,26 @@ public function nativeComponent(string $component) return $this->core->components()[$component] ?? false; } - /** - * Kirby plugin factory and getter - * - * @param string $name - * @param array|null $extends If null is passed it will be used as getter. Otherwise as factory. - * @return \Kirby\Cms\Plugin|null - * @throws \Kirby\Exception\DuplicateException - */ - public static function plugin(string $name, array $extends = null) - { - if ($extends === null) { - return static::$plugins[$name] ?? null; - } + /** + * Kirby plugin factory + * + * @param array|null $extends If null is passed it will be take it from the folders. Otherwise as factory. + * @throws \Kirby\Exception\DuplicateException + */ + public static function plugin( + string $name, + array $extends = null, + array $info = [], + string|null $root = null, + string|null $version = null + ): Plugin|null { + + if ( + $extends === null && + $plugin = static::$plugins[$name] ?? null + ) { + return $plugin; + } // get the correct root for the plugin $extends['root'] = $extends['root'] ?? dirname(debug_backtrace()[0]['file']); diff --git a/src/Cms/Plugin.php b/src/Cms/Plugin.php index 84d6cfe872..e059878838 100644 --- a/src/Cms/Plugin.php +++ b/src/Cms/Plugin.php @@ -5,6 +5,10 @@ use Exception; use Kirby\Data\Data; use Kirby\Exception\InvalidArgumentException; +use Kirby\Filesystem\Dir; +use Kirby\Filesystem\F; +use Kirby\Toolkit\A; +use Kirby\Toolkit\Str; use Kirby\Toolkit\V; /** @@ -41,12 +45,13 @@ public function __call(string $key, array $arguments = null) * @param string $name * @param array $extends */ - public function __construct(string $name, array $extends = []) + public function __construct(string $name, ?array $extends = null, $info = [], $root = null, $version = null) { $this->setName($name); - $this->extends = $extends; - $this->root = $extends['root'] ?? dirname(debug_backtrace()[0]['file']); - $this->info = empty($extends['info']) === false && is_array($extends['info']) ? $extends['info'] : null; + $this->root = $root ?? $extends['root'] ?? dirname(debug_backtrace()[0]['file']); + $this->extends = $extends ?? $this->autoload(); + $this->info = + $imfo ?? empty($extends['info']) === false && is_array($extends['info']) ? $extends['info'] : null; unset($this->extends['root'], $this->extends['info']); } @@ -218,4 +223,124 @@ public function toArray(): array 'version' => $this->version() ]; } + + + /** + * Autoload the configuration from the current plugins folder. + * + * 'Kirby::plugin("your/plugin", Plugin::autoload());' + * + * @param string|array|null $folder string or array of folder to autoload. null = autoloading snippets, blueprint, templates, I18n and options. + */ + public function autoload( + string|array|null $folder = null, + array $items = [] + ):array { + + //Load all + if ($folder === null) { + + return A::merge( + $this->loadFiles('config'), + $this->autoload([ + 'snippets', + 'templates', + 'blueprints' + ]), + ['translation' => $this->loadTranslations( + 'I18n', + F::safeName($this->name) + )] + + ); + + } + + if (is_array($folder)) { + + foreach ($folder as $item) { + $items = $this->autoload($item, $items); + } + return $items; + } + + $items[$folder] = $this->loadFiles( + $folder, + fn($file) => $file, + true + ); + + return $items; + + } + + /** + * Autoload the translations of the current plugins folder. + */ + public function loadTranslations( + string $folder = 'I18n', + ?string $prefix = null + ): array { + return $this->loadFiles( + $folder, + function ($file) use ($prefix) { + + if (F::extension($file, 'json')) { + $data = Data::read($file); + } + + $data ??= require_once $file; + + if ($prefix === null) { + return $data; + } + + $translations = []; + + foreach ($data as $key => $value) { + $translations["{$prefix}.{$key}"] = $value; + } + + return $translations; + + } + + ); + } + + /** + * Reads the files of the current plugins folder. + */ + public function loadFiles( + string $folder, + callable $callback = null, + bool $recursive = false + ): array { + + $callback ??= fn($value) => require_once $value; + $folder = $this->root() . "/{$folder}"; + + if ( + Str::startsWith(basename($folder), '_') || + Dir::exists($folder) === false + ) { + return []; + } + + return A::reduce( + Dir::index($folder, $recursive), + function($items, $item) use ($callback, $folder) { + + $key = Str::before($item, '.'); + $filename = A::last(explode('/', $item)); + + if ($key && Str::startsWith($filename, '_') == false ) { + $items[$key] = $callback("{$folder}/{$item}"); + } + + return $items; + + } + ); + } }