'string', 'name' => 'string', 'author' => 'string', 'version' => 'string', 'description' => 'string', 'category' => 'string', 'url' => 'string', 'update_url' => 'string', 'namespace' => 'string', 'class' => 'string', 'panels' => 'string', 'panel_version' => 'string', 'composer_packages' => 'string', 'status' => 'string', 'status_message' => 'string', 'load_order' => 'integer', ]; } /** * @return array */ public function getRows(): array { $plugins = []; $directories = File::directories(base_path('plugins/')); foreach ($directories as $directory) { $plugin = File::basename($directory); $path = plugin_path($plugin, 'plugin.json'); if (!file_exists($path)) { continue; } try { $data = File::json($path, JSON_THROW_ON_ERROR); $panels = null; if (array_key_exists('panels', $data)) { $panels = $data['panels']; $panels = is_array($panels) ? implode(',', $panels) : $panels; } $composerPackages = null; if (array_key_exists('composer_packages', $data)) { $composerPackages = $data['composer_packages']; $composerPackages = is_array($composerPackages) ? implode(',', $composerPackages) : $composerPackages; } $data = [ 'id' => $data['id'], 'name' => $data['name'], 'author' => $data['author'], 'version' => Arr::get($data, 'version', '1.0.0'), 'description' => Arr::get($data, 'description', null), 'category' => Arr::get($data, 'category', null), 'url' => Arr::get($data, 'url', null), 'update_url' => Arr::get($data, 'update_url', null), 'namespace' => $data['namespace'], 'class' => $data['class'], 'panels' => $panels, 'panel_version' => Arr::get($data, 'update_url', null), 'composer_packages' => $composerPackages, 'status' => Arr::get($data, 'meta.status', PluginStatus::NotInstalled->value), 'status_message' => Arr::get($data, 'meta.status_message', null), 'load_order' => Arr::integer($data, 'meta.load_order', 0), ]; $plugins[] = $data; } catch (Exception $exception) { report($exception); if (!$exception instanceof JsonException) { $plugins[] = [ 'id' => $data['id'] ?? Str::uuid(), 'name' => $data['name'] ?? 'Invalid Plugin', 'author' => $data['author'] ?? 'Unknown', 'version' => '0.0.0', 'description' => 'Plugin.json is invalid!', 'category' => 'invalid', 'url' => null, 'update_url' => null, 'namespace' => 'Error', 'class' => 'Error', 'panels' => null, 'panel_version' => null, 'composer_packages' => null, 'status' => PluginStatus::Errored->value, 'status_message' => $exception->getMessage(), 'load_order' => 0, ]; } } } return $plugins; } protected function sushiShouldCache(): bool { return false; } protected function casts(): array { return [ 'status' => PluginStatus::class, ]; } public function fullClass(): string { return '\\' . $this->namespace . '\\' . $this->class; } public function shouldLoad(): bool { return !$this->isDisabled() && $this->isInstalled() && !$this->isIncompatible(); } public function shouldLoadPanel(string $panelId): bool { return !$this->isDisabled() && $this->isInstalled() && !$this->isIncompatible() && ($this->panels === null || in_array($panelId, explode(',', $this->panels))); } public function canEnable(): bool { return $this->isDisabled() && $this->isInstalled() && $this->isCompatible(); } public function canDisable(): bool { return $this->isEnabled() && $this->isInstalled() && $this->isCompatible(); } public function isEnabled(): bool { return $this->status === PluginStatus::Enabled; } public function isDisabled(): bool { return $this->status === PluginStatus::Disabled; } public function isInstalled(): bool { return $this->status !== PluginStatus::NotInstalled; } public function hasErrored(): bool { return $this->status === PluginStatus::Errored; } public function isIncompatible(): bool { return $this->status === PluginStatus::Incompatible; } public function isCompatible(): bool { $panelVersion = config('app.version', 'canary'); return $this->panel_version === null || $panelVersion === 'canary' || version_compare($this->panel_version, $panelVersion, $this->isPanelVersionStrict() ? '=' : '>='); } public function isPanelVersionStrict(): bool { if ($this->panel_version === null) { return false; } return !str($this->panel_version)->startsWith('^'); } /** @return null|array */ private function getUpdateData(): ?array { if ($this->update_url === null) { return null; } return cache()->remember("plugins.$this->id.update", now()->addMinutes(10), function () { try { return json_decode(file_get_contents($this->update_url), true, 512, JSON_THROW_ON_ERROR); } catch (Exception $exception) { report($exception); } return null; }); } public function isUpdateAvailable(): bool { $panelVersion = config('app.version', 'canary'); if ($panelVersion === 'canary') { return false; } $updateData = $this->getUpdateData(); if ($updateData) { if (array_key_exists($panelVersion, $updateData)) { return version_compare($updateData[$panelVersion]['version'], $this->version, '>'); } if (array_key_exists('*', $updateData)) { return version_compare($updateData['*']['version'], $this->version, '>'); } } return false; } public function getDownloadUrlForUpdate(): ?string { $panelVersion = config('app.version', 'canary'); if ($panelVersion === 'canary') { return null; } $updateData = $this->getUpdateData(); if ($updateData) { if (array_key_exists($panelVersion, $updateData)) { return $updateData['panelVersion']['download_url']; } if (array_key_exists('*', $updateData)) { return $updateData['*']['download_url']; } } return null; } public function hasSettings(): bool { $class = $this->fullClass(); if (class_exists($class) && method_exists($class, 'get')) { $pluginObject = ($class)::get(); return method_exists($pluginObject, 'getSettingsForm') && method_exists($pluginObject, 'saveSettings'); } return false; } /** * @return Component[] */ public function getSettingsForm(): array { $class = $this->fullClass(); if (class_exists($class) && method_exists($class, 'get')) { $pluginObject = ($class)::get(); if (method_exists($pluginObject, 'getSettingsForm')) { return $pluginObject->getSettingsForm(); } } return []; } /** * @param array $data */ public function saveSettings(array $data): void { $class = $this->fullClass(); if (class_exists($class) && method_exists($class, 'get')) { $pluginObject = ($class)::get(); if (method_exists($pluginObject, 'saveSettings')) { $pluginObject->saveSettings($data); } } } /** * @return string[] */ public function getProviders(): array { $path = plugin_path($this->id, 'src', 'Providers'); if (File::missing($path)) { return []; } return array_map(fn ($provider) => $this->namespace . '\\Providers\\' . str($provider->getRelativePathname())->remove('.php', false), File::allFiles($path)); } /** * @return string[] */ public function getCommands(): array { $path = plugin_path($this->id, 'src', 'Console', 'Commands'); if (File::missing($path)) { return []; } return array_map(fn ($provider) => $this->namespace . '\\Console\\Commands\\' . str($provider->getRelativePathname())->remove('.php', false), File::allFiles($path)); } }