diff --git a/src/Cms/AppPlugins.php b/src/Cms/AppPlugins.php index d5b5f016dc..ccda723401 100644 --- a/src/Cms/AppPlugins.php +++ b/src/Cms/AppPlugins.php @@ -13,6 +13,7 @@ use Kirby\Image\Image; use Kirby\Plugin\License; use Kirby\Plugin\Plugin; +use Kirby\Plugin\Autoloader; use Kirby\Text\KirbyTag; use Kirby\Toolkit\A; use Kirby\Toolkit\Collection as ToolkitCollection; @@ -871,18 +872,34 @@ public static function plugin( string|null $root = null, string|null $version = null, Closure|string|array|null $license = null, + bool|string $autoloader = false ): Plugin|null { - if ($extends === null) { + + + if ($extends === null && $autoloader === false) { return static::$plugins[$name] ?? null; } + $root ??= $extends['root'] ?? dirname(debug_backtrace()[0]['file']); + + if ($autoloader) { + + //Allow to apply custom Autoloader + $autolader_class = is_bool($autoloader) ? Autoloader::class : $autoloader; + + $extends = A::merge($autolader_class::load( + name: $name, + root: $root + ), $extends ?? []); + } + $plugin = new Plugin( - name: $name, + name: $name, extends: $extends, - info: $info, + info: $info, license: $license, // TODO: Remove fallback to $extends in v7 - root: $root ?? $extends['root'] ?? dirname(debug_backtrace()[0]['file']), + root: $root, version: $version ); @@ -925,6 +942,11 @@ public function plugins(array|null $plugins = null): array return static::$plugins; } + public function allowedExtensionsKeys(): array + { + return array_keys($this->extensions); + } + /** * Loads all plugins from site/plugins * diff --git a/src/Plugin/Autoloader.php b/src/Plugin/Autoloader.php new file mode 100644 index 0000000000..9f6b4c6204 --- /dev/null +++ b/src/Plugin/Autoloader.php @@ -0,0 +1,290 @@ +loadClasses($classfolder); + } + + $folders = [ + 'autoload' => 'loadAutoload', + 'blueprints' => 'loadBlueprints', + 'i18n' => 'loadTranslations', + 'fields' => 'loadFields', + 'sections' => 'loadSections', + 'snippets' => 'loadSnippets', + 'templates' => 'loadTemplates' + ]; + + foreach (Dir::dirs($this->root) as $dir) { + if (array_key_exists($dir, $folders)) { + $method = $folders[$dir]; + $this->$method($this->root . '/' . $dir . '/'); + } + } + } + + /** + * Autoload autoload + * @param string $root + * @return void + */ + public function loadAutoload(string $root): void + { + foreach (Dir::files($root) as $path) { + + $key = F::name($path); + $file = $root . $path; + $this->data[$key] = Data::read($file); + }; + } + + /** + * Autoload blueprints + * @param string $root + * @return void + */ + public function loadBlueprints(string $root): void + { + foreach (Dir::index($root) as $path) { + + $file = $root . $path; + + //Skip folder and file/folder thats starts with '_' + if (F::exists($file) === false || Str::contains($path, '/_')) { + continue; + } + + //Has no Subfolder + if (($dirname = F::dirname($path)) === '.') { + $key = F::name($path); + } + + $key ??= $dirname . '/' . F::name($path); + + $this->data['blueprints'][$key] = Data::read($file); + }; + } + + /** + * Load classes + * @param string $root + * @return void + */ + public function loadClasses(string $root): void + { + + $classes = []; + + foreach (Dir::index($root) as $path) { + + $file = $root . $path; + + //Skip folder and file/folder thats starts with '_' + if (F::exists($file) === false || Str::contains($path, '/_')) { + continue; + } + + //Has no Subfolder + if (($dirname = F::dirname($path)) === '.') { + $key = F::name($path); + } + + $key ??= $dirname . '/' . F::name($path); + + $prefix = array_map('ucfirst', explode('/', $this->name)); + $classname = A::merge($prefix, explode('/', $key)); + $classes[implode('\\', $classname)] = $file; + }; + + F::loadClasses($classes); + } + + + /** + * Autoload translations + * @param string $root + * @return void + */ + public function loadTranslations(string $root): void + { + foreach (Dir::index($root) as $path) { + + $file = $root . $path; + + //Skip folder and file/folder thats starts with '_' + if (F::exists($file) === false || Str::contains($path, '/_')) { + continue; + } + + //Has no Subfolder + if (($dirname = F::dirname($path)) === '.') { + $key = F::name($path); + } + + $key ??= $dirname . '/' . F::name($path); + + $this->data['translations'][$key] = Data::read($file); + }; + } + + /** + * Autoload fields + * @param string $root + * @return void + */ + public function loadFields(string $root): void + { + foreach (Dir::index($root) as $path) { + + $file = $root . $path; + + //Skip folder and file/folder thats starts with '_' + if (F::exists($file) === false || Str::contains($path, '/_')) { + continue; + } + + //Has no Subfolder + if (($dirname = F::dirname($path)) === '.') { + $key = F::name($path); + } + + $key ??= $dirname . '/' . F::name($path); + + $this->data['fields'][$key] = Data::read($file); + }; + } + + /** + * Autoload sections + * @param string $root + * @return void + */ + public function loadSections(string $root): void + { + foreach (Dir::index($root) as $path) { + + $file = $root . $path; + + //Skip folder and file/folder thats starts with '_' + if (F::exists($file) === false || Str::contains($path, '/_')) { + continue; + } + + //Has no Subfolder + if (($dirname = F::dirname($path)) === '.') { + $key = F::name($path); + } + + $key ??= $dirname . '/' . F::name($path); + + $this->data['sections'][$key] = Data::read($file); + }; + } + + /** + * Autoload snippets + * @param string $root + * @return void + */ + public function loadSnippets(string $root): void + { + foreach (Dir::index($root) as $path) { + + $file = $root . $path; + + //Skip folder and file/folder thats starts with '_' + if (F::exists($file) === false || Str::contains($path, '/_')) { + continue; + } + + //Has no Subfolder + if (($dirname = F::dirname($path)) === '.') { + $key = F::name($path); + } + + $key ??= $dirname . '/' . F::name($path); + + $this->data['snippets'][$key] = $file; + }; + } + + /** + * Autoload templates + * @param string $root + * @return void + */ + public function loadTemplates(string $root): void + { + foreach (Dir::index($root) as $path) { + + $file = $root . $path; + + //Skip folder and file/folder thats starts with '_' + if (F::exists($file) === false || Str::contains($path, '/_')) { + continue; + } + + //Has no Subfolder + if (($dirname = F::dirname($path)) === '.') { + $key = F::name($path); + } + + $key ??= $dirname . '/' . F::name($path); + + $this->data['templates'][$key] = $file; + }; + } + + /** + * Run autoloader and return the results + * @param mixed ...$params + * @return array + */ + public static function load(...$params): array + { + $self = new self(...$params); + return $self->toArray(); + } + + /** + * Returns the autoloaded data + * @return array */ + public function toArray(): array + { + return $this->data; + } +} diff --git a/src/Plugin/Plugin.php b/src/Plugin/Plugin.php index ab3ee6e63f..ffb15f4882 100644 --- a/src/Plugin/Plugin.php +++ b/src/Plugin/Plugin.php @@ -71,6 +71,7 @@ public function __construct( $info = Data::read($this->manifest(), fail: false); $this->info = [...$info, ...$this->info]; $this->license = $license ?? $this->info['license'] ?? '-'; + } /** diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php index 0002e42587..1e5e13c0b8 100644 --- a/vendor/composer/autoload_classmap.php +++ b/vendor/composer/autoload_classmap.php @@ -80,6 +80,7 @@ 'Kirby\\Cms\\HasChildren' => $baseDir . '/src/Cms/HasChildren.php', 'Kirby\\Cms\\HasFiles' => $baseDir . '/src/Cms/HasFiles.php', 'Kirby\\Cms\\HasMethods' => $baseDir . '/src/Cms/HasMethods.php', + 'Kirby\\Cms\\HasModels' => $baseDir . '/src/Cms/HasModels.php', 'Kirby\\Cms\\HasSiblings' => $baseDir . '/src/Cms/HasSiblings.php', 'Kirby\\Cms\\Helpers' => $baseDir . '/src/Cms/Helpers.php', 'Kirby\\Cms\\Html' => $baseDir . '/src/Cms/Html.php', @@ -205,6 +206,7 @@ 'Kirby\\Form\\FieldClass' => $baseDir . '/src/Form/FieldClass.php', 'Kirby\\Form\\Field\\BlocksField' => $baseDir . '/src/Form/Field/BlocksField.php', 'Kirby\\Form\\Field\\EntriesField' => $baseDir . '/src/Form/Field/EntriesField.php', + 'Kirby\\Form\\Field\\ExceptionField' => $baseDir . '/src/Form/Field/ExceptionField.php', 'Kirby\\Form\\Field\\LayoutField' => $baseDir . '/src/Form/Field/LayoutField.php', 'Kirby\\Form\\Fields' => $baseDir . '/src/Form/Fields.php', 'Kirby\\Form\\Form' => $baseDir . '/src/Form/Form.php', @@ -314,6 +316,7 @@ 'Kirby\\Parsley\\Schema\\Plain' => $baseDir . '/src/Parsley/Schema/Plain.php', 'Kirby\\Plugin\\Asset' => $baseDir . '/src/Plugin/Asset.php', 'Kirby\\Plugin\\Assets' => $baseDir . '/src/Plugin/Assets.php', + 'Kirby\\Plugin\\Autoloader' => $baseDir . '/src/Plugin/Autoloader.php', 'Kirby\\Plugin\\License' => $baseDir . '/src/Plugin/License.php', 'Kirby\\Plugin\\LicenseStatus' => $baseDir . '/src/Plugin/LicenseStatus.php', 'Kirby\\Plugin\\Plugin' => $baseDir . '/src/Plugin/Plugin.php', diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index 12df7353c2..2edc30936b 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -201,6 +201,7 @@ class ComposerStaticInit0bf5c8a9cfa251a218fc581ac888fe35 'Kirby\\Cms\\HasChildren' => __DIR__ . '/../..' . '/src/Cms/HasChildren.php', 'Kirby\\Cms\\HasFiles' => __DIR__ . '/../..' . '/src/Cms/HasFiles.php', 'Kirby\\Cms\\HasMethods' => __DIR__ . '/../..' . '/src/Cms/HasMethods.php', + 'Kirby\\Cms\\HasModels' => __DIR__ . '/../..' . '/src/Cms/HasModels.php', 'Kirby\\Cms\\HasSiblings' => __DIR__ . '/../..' . '/src/Cms/HasSiblings.php', 'Kirby\\Cms\\Helpers' => __DIR__ . '/../..' . '/src/Cms/Helpers.php', 'Kirby\\Cms\\Html' => __DIR__ . '/../..' . '/src/Cms/Html.php', @@ -326,6 +327,7 @@ class ComposerStaticInit0bf5c8a9cfa251a218fc581ac888fe35 'Kirby\\Form\\FieldClass' => __DIR__ . '/../..' . '/src/Form/FieldClass.php', 'Kirby\\Form\\Field\\BlocksField' => __DIR__ . '/../..' . '/src/Form/Field/BlocksField.php', 'Kirby\\Form\\Field\\EntriesField' => __DIR__ . '/../..' . '/src/Form/Field/EntriesField.php', + 'Kirby\\Form\\Field\\ExceptionField' => __DIR__ . '/../..' . '/src/Form/Field/ExceptionField.php', 'Kirby\\Form\\Field\\LayoutField' => __DIR__ . '/../..' . '/src/Form/Field/LayoutField.php', 'Kirby\\Form\\Fields' => __DIR__ . '/../..' . '/src/Form/Fields.php', 'Kirby\\Form\\Form' => __DIR__ . '/../..' . '/src/Form/Form.php', @@ -435,6 +437,7 @@ class ComposerStaticInit0bf5c8a9cfa251a218fc581ac888fe35 'Kirby\\Parsley\\Schema\\Plain' => __DIR__ . '/../..' . '/src/Parsley/Schema/Plain.php', 'Kirby\\Plugin\\Asset' => __DIR__ . '/../..' . '/src/Plugin/Asset.php', 'Kirby\\Plugin\\Assets' => __DIR__ . '/../..' . '/src/Plugin/Assets.php', + 'Kirby\\Plugin\\Autoloader' => __DIR__ . '/../..' . '/src/Plugin/Autoloader.php', 'Kirby\\Plugin\\License' => __DIR__ . '/../..' . '/src/Plugin/License.php', 'Kirby\\Plugin\\LicenseStatus' => __DIR__ . '/../..' . '/src/Plugin/LicenseStatus.php', 'Kirby\\Plugin\\Plugin' => __DIR__ . '/../..' . '/src/Plugin/Plugin.php',