From f182f799f64117e9e0f3f993f44607439fcbdd72 Mon Sep 17 00:00:00 2001 From: Pig Fang Date: Tue, 13 Aug 2019 23:06:28 +0800 Subject: [PATCH] Refactor plugin system (part 9) --- app/Services/Plugin.php | 121 ++------------ app/Services/PluginManager.php | 281 +-------------------------------- app/helpers.php | 18 +-- 3 files changed, 29 insertions(+), 391 deletions(-) diff --git a/app/Services/Plugin.php b/app/Services/Plugin.php index b3b17238..69ba61a3 100644 --- a/app/Services/Plugin.php +++ b/app/Services/Plugin.php @@ -7,12 +7,6 @@ namespace App\Services; use Illuminate\Support\Arr; use Illuminate\Support\Str; -/** - * @property string $name - * @property string $description - * @property string $title - * @property array $author - */ class Plugin { /** @@ -22,40 +16,12 @@ class Plugin */ protected $path; - /** - * The directory name where the plugin installed. - * - * @var string - */ - protected $dirname; - /** * package.json of the package. * * @var array */ - protected $packageInfo; - - /** - * Whether the plugin is installed. - * - * @var bool - */ - protected $installed = true; - - /** - * The installed version of the plugin. - * - * @var string - */ - protected $version; - - /** - * The namespace used by the plugin. - * - * @var string - */ - protected $namespace; + protected $manifest; /** * Whether the plugin is enabled. @@ -64,71 +30,40 @@ class Plugin */ protected $enabled = false; - public function __construct(string $path, array $packageInfo) + public function __construct(string $path, array $manifest) { $this->path = $path; - $this->packageInfo = $packageInfo; + $this->manifest = $manifest; } public function __get(string $name) { - return $this->packageInfoAttribute(Str::snake($name, '-')); + return $this->getManifestAttr(Str::snake($name, '-')); } public function __isset(string $name) { - return isset($this->{$name}) || $this->packageInfoAttribute(snake_case($name, '-')); - } - - public function packageInfoAttribute(string $name) - { - return Arr::get($this->packageInfo, $name); + return isset($this->{$name}) || $this->getManifestAttr(Str::snake($name, '-')); } public function getManifest() { - return $this->packageInfo; + return $this->manifest; + } + + public function getManifestAttr(string $name, $default = null) + { + return Arr::get($this->manifest, $name, $default); } public function assets(string $relativeUri): string { $baseUrl = config('plugins.url') ?: url('plugins'); - return "$baseUrl/{$this->getDirname()}/assets/$relativeUri?v=".$this->version; + return "$baseUrl/{$this->name}/assets/$relativeUri?v=".$this->version; } - public function setInstalled(bool $installed): self - { - $this->installed = $installed; - - return $this; - } - - public function getDirname(): string - { - return $this->dirname; - } - - public function setDirname(string $dirname): self - { - $this->dirname = $dirname; - - return $this; - } - - public function getNamespace(): string - { - return $this->namespace; - } - - public function setNameSpace(string $namespace): self - { - $this->namespace = $namespace; - - return $this; - } - - public function getViewPathByFileName(string $filename): string + public function getViewPath(string $filename): string { return $this->path."/views/$filename"; } @@ -136,39 +71,15 @@ class Plugin public function getConfigView() { return $this->hasConfigView() - ? view()->file($this->getViewPathByFileName(Arr::get($this->packageInfo, 'config', 'config.blade.php'))) + ? view()->file($this->getViewPath(Arr::get($this->manifest, 'config', 'config.blade.php'))) : null; } public function hasConfigView(): bool { - $filename = Arr::get($this->packageInfo, 'config', 'config.blade.php'); + $filename = Arr::get($this->manifest, 'config', 'config.blade.php'); - return $filename && file_exists($this->getViewPathByFileName($filename)); - } - - public function setVersion(string $version): self - { - $this->version = $version; - - return $this; - } - - public function getVersion(): string - { - return $this->version; - } - - public function setRequirements(array $require): self - { - $this->require = $require; - - return $this; - } - - public function getRequirements(): array - { - return (array) $this->require; + return $filename && file_exists($this->getViewPath($filename)); } public function setEnabled(bool $enabled): self diff --git a/app/Services/PluginManager.php b/app/Services/PluginManager.php index 5a7df0ec..b867c474 100644 --- a/app/Services/PluginManager.php +++ b/app/Services/PluginManager.php @@ -244,97 +244,6 @@ class PluginManager } /** - * @return Collection - */ - public function getPlugins() - { - if (is_null($this->plugins)) { - $plugins = new Collection(); - $enabled = $this->getFullEnabled(); - - $installed = []; - - $cwd = getcwd(); - chdir(base_path()); - - try { - $resource = opendir($this->getPluginsDir()); - } catch (\Exception $e) { - throw new PrettyPageException(trans('errors.plugins.directory', ['msg' => $e->getMessage()]), 500); - } - - // traverse plugins dir - while ($filename = @readdir($resource)) { - if ($filename == '.' || $filename == '..') { - continue; - } - - $path = $this->getPluginsDir().DIRECTORY_SEPARATOR.$filename; - - if (is_dir($path)) { - $packageJsonPath = $path.DIRECTORY_SEPARATOR.'package.json'; - - if (file_exists($packageJsonPath)) { - // load packages installed - $installed[$filename] = json_decode($this->filesystem->get($packageJsonPath), true); - } - } - } - closedir($resource); - - foreach ($installed as $dirname => $package) { - - // Instantiates an Plugin object using the package path and package.json file. - $plugin = new Plugin($this->getPluginsDir().DIRECTORY_SEPARATOR.$dirname, $package); - - // Each default all plugins are installed if they are registered in composer. - $plugin->setDirname($dirname); - $plugin->setInstalled(true); - $plugin->setNameSpace(Arr::get($package, 'namespace')); - $plugin->setVersion(Arr::get($package, 'version')); - $plugin->setEnabled($this->isEnabled($plugin->name)); - - if ($plugins->has($plugin->name)) { - throw new PrettyPageException(trans('errors.plugins.duplicate', [ - 'dir1' => $plugin->getDirname(), - 'dir2' => $plugins->get($plugin->name)->getDirname(), - ]), 5); - } - - $plugins->put($plugin->name, $plugin); - - if ( - $enabled->has($plugin->name) && - Comparator::notEqualTo($plugin->getVersion(), $enabled->get($plugin->name)) - ) { - $this->copyPluginAssets($plugin); - } - } - - $this->plugins = $plugins->sortBy(function ($plugin, $name) { - return $plugin->name; - }); - - chdir($cwd); - } - - return $this->plugins; - } - - /** - * Loads an Plugin with all information. - * - * @param string $name - * @return Plugin|null - */ - public function getPlugin($name) - { - return $this->getPlugins()->get($name); - } - - /** - * Enables the plugin. - * * @param string $name */ public function enable($name) @@ -351,8 +260,6 @@ class PluginManager } /** - * Disables an plugin. - * * @param string $name */ public function disable($name) @@ -377,8 +284,6 @@ class PluginManager } /** - * Uninstalls an plugin. - * * @param string $name */ public function delete($name) @@ -397,86 +302,13 @@ class PluginManager } /** - * Get only enabled plugins. - * * @return Collection */ public function getEnabledPlugins() { - return $this->getPlugins()->only($this->getEnabled()); - } - - /** - * Loads all bootstrap.php files of the enabled plugins. - * - * @return Collection - */ - public function getEnabledBootstrappers() - { - $bootstrappers = new Collection; - - foreach ($this->getEnabledPlugins() as $plugin) { - if ($this->filesystem->exists($file = $plugin->getPath().'/bootstrap.php')) { - $bootstrappers->push($file); - } - } - - return $bootstrappers; - } - - /** - * Loads composer autoloader for the enabled plugins if exists. - * - * @return Collection - */ - public function getEnabledComposerAutoloaders() - { - $autoloaders = new Collection; - - foreach ($this->getEnabledPlugins() as $plugin) { - if ($this->filesystem->exists($file = $plugin->getPath().'/vendor/autoload.php')) { - $autoloaders->push($file); - } - } - - return $autoloaders; - } - - /** - * The id's of the enabled plugins. - * - * @return array - */ - public function getEnabled() - { - $enabled = collect(json_decode($this->option->get('plugins_enabled'), true)); - - return $enabled->map(function ($item) { - if (is_string($item)) { - return $item; - } else { - return $item['name']; - } - })->values()->toArray(); - } - - /** - * Return enabled plugins with version information. - * - * @return Collection - */ - public function getFullEnabled() - { - $enabled = collect(json_decode($this->option->get('plugins_enabled'), true)); - $ret = collect(); - - $enabled->each(function ($item) use ($ret) { - if (is_array($item)) { - $ret->put($item['name'], $item['version']); - } + return $this->all()->filter(function ($plugin) { + return $plugin->isEnabled(); }); - - return $ret; } /** @@ -485,19 +317,8 @@ class PluginManager protected function saveEnabled() { $this->option->set('plugins_enabled', $this->enabled->map(function ($info, $name) { - // - })->toJson()); - } - - /** - * Whether the plugin is enabled. - * - * @param string $pluginName - * @return bool - */ - public function isEnabled($pluginName) - { - return in_array($pluginName, $this->getEnabled()); + return array_merge(compact('name'), $info); + })->values()->toJson()); } /** @@ -529,78 +350,6 @@ class PluginManager }); } - /** - * Get the unsatisfied requirements of plugin. - * - * @param string|Plugin|array $plugin - * @return array - */ - public function getUnsatisfiedRequirements($plugin) - { - if (is_array($plugin)) { - $requirements = $plugin; - } else { - if (! $plugin instanceof Plugin) { - $plugin = $this->getPlugin($plugin); - } - - if (! $plugin) { - throw new \InvalidArgumentException('Plugin with given name does not exist.'); - } - - $requirements = $plugin->getRequirements(); - } - - $unsatisfied = []; - - foreach ($requirements as $name => $versionConstraint) { - // Version requirement for the main application - if ($name == 'blessing-skin-server') { - if (! Semver::satisfies(config('app.version'), $versionConstraint)) { - $unsatisfied['blessing-skin-server'] = [ - 'version' => config('app.version'), - 'constraint' => $versionConstraint, - ]; - } - - continue; - } - - $requiredPlugin = $this->getPlugin($name); - - if (! $requiredPlugin || ! $requiredPlugin->isEnabled()) { - $unsatisfied[$name] = [ - 'version' => null, - 'constraint' => $versionConstraint, - ]; - - continue; - } - - if (! Semver::satisfies($requiredPlugin->getVersion(), $versionConstraint)) { - $unsatisfied[$name] = [ - 'version' => $requiredPlugin->getVersion(), - 'constraint' => $versionConstraint, - ]; - - continue; - } - } - - return $unsatisfied; - } - - /** - * Whether the plugin's requirements are satisfied. - * - * @param string|Plugin|array $plugin - * @return bool - */ - public function isRequirementsSatisfied($plugin) - { - return empty($this->getUnsatisfiedRequirements($plugin)); - } - /** * The plugins path. * @@ -610,26 +359,4 @@ class PluginManager { return config('plugins.directory') ? realpath(config('plugins.directory')) : base_path('plugins'); } - - /** - * Copy plugin assets. - * - * @param Plugin $plugin - * - * @return bool - */ - public function copyPluginAssets($plugin) - { - $dir = public_path('plugins/'.$plugin->name); - Storage::deleteDirectory($dir); - - $this->filesystem->copyDirectory( - $this->getPluginsDir().DIRECTORY_SEPARATOR.$plugin->name.DIRECTORY_SEPARATOR.'assets', - $dir.'/assets' - ); - $this->filesystem->copyDirectory( - $this->getPluginsDir().DIRECTORY_SEPARATOR.$plugin->name.DIRECTORY_SEPARATOR.'lang', - $dir.'/lang' - ); - } } diff --git a/app/helpers.php b/app/helpers.php index a53f972b..e029c050 100644 --- a/app/helpers.php +++ b/app/helpers.php @@ -124,21 +124,21 @@ if (! function_exists('bs_menu')) { $menu[$type] = array_map(function ($item) { if (Arr::get($item, 'id') === 'plugin-configs') { - $availablePluginConfigs = []; - - foreach (app('plugins')->getEnabledPlugins() as $plugin) { - if ($plugin->hasConfigView()) { - $availablePluginConfigs[] = [ + $pluginConfigs = app('plugins')->getEnabledPlugins() + ->filter(function ($plugin) { + return $plugin->hasConfigView(); + }) + ->map(function ($plugin) { + return [ 'title' => trans($plugin->title), 'link' => 'admin/plugins/config/'.$plugin->name, 'icon' => 'fa-circle', ]; - } - } + }); // Don't display this menu item when no plugin config is available - if (count($availablePluginConfigs) > 0) { - $item['children'] = array_merge($item['children'], $availablePluginConfigs); + if ($pluginConfigs->isNotEmpty()) { + $item['children'] = array_merge($item['children'], $pluginConfigs->values()->all()); return $item; }