From 45cd5a412ce2ec61f9a3ba061ed23d9c27e9a975 Mon Sep 17 00:00:00 2001 From: Darko Gjorgjijoski Date: Fri, 21 Aug 2026 14:16:22 +0200 Subject: [PATCH] chore(modules): remove the admin controller and resource retaining legacy attribution --- .../Controllers/Admin/ModulesController.php | 114 ------------- .../Modules/Http/Resources/ModuleResource.php | 152 ------------------ 2 files changed, 266 deletions(-) delete mode 100644 app/Platform/Modules/Http/Controllers/Admin/ModulesController.php delete mode 100644 app/Platform/Modules/Http/Resources/ModuleResource.php diff --git a/app/Platform/Modules/Http/Controllers/Admin/ModulesController.php b/app/Platform/Modules/Http/Controllers/Admin/ModulesController.php deleted file mode 100644 index f8bbb147..00000000 --- a/app/Platform/Modules/Http/Controllers/Admin/ModulesController.php +++ /dev/null @@ -1,114 +0,0 @@ -authorize('manage modules'); - - $response = $client->catalog(); - $body = $response->json(); - $modules = is_array($body) ? ($body['modules'] ?? $body['data'] ?? null) : null; - - if (! $response->successful() || ! is_array($modules)) { - return response()->json(['error' => 'marketplace_unavailable'], 503); - } - - return ModuleResource::collection(collect($modules)); - } - - public function show(string $module, MarketplaceClient $client) - { - $this->authorize('manage modules'); - - $response = $client->module($module); - $body = $response->json(); - - if ($response->status() === 404) { - return response()->json(['error' => 'not_found'], 404); - } - - if (! $response->successful() || ! is_array($body) || ! is_array($body['module'] ?? null)) { - return response()->json(['error' => 'marketplace_unavailable'], 503); - } - - return (new ModuleResource($body['module'])) - ->additional(['meta' => [ - 'modules' => ModuleResource::collection( - collect($body['meta']['modules'] ?? []) - ), - ]]); - } - - public function enable(string $module): JsonResponse - { - $this->authorize('manage modules'); - - $module = ModelsModule::query() - ->where('name', $module) - ->where('installed', true) - ->firstOrFail(); - $installedModule = Module::find($module->name); - - if ($installedModule === null) { - $this->markRuntimeMissing($module); - - return response()->json([ - 'success' => false, - 'error' => 'module_runtime_missing', - ], 409); - } - - $installedModule->enable(); - $module->refresh(); - - event(new ModuleEnabledEvent($module)); - - return new JsonResponse(['success' => true]); - } - - public function disable(string $module, DatabaseActivator $activator): JsonResponse - { - $this->authorize('manage modules'); - - $module = ModelsModule::query() - ->where('name', $module) - ->where('installed', true) - ->firstOrFail(); - - $activator->setActiveByName($module->name, false); - - if (Module::find($module->name) === null) { - $this->markRuntimeMissing($module); - } else { - $module->refresh(); - } - - ModuleDisabledEvent::dispatch($module); - - return response()->json(['success' => true]); - } - - private function markRuntimeMissing(ModelsModule $module): void - { - $module->update([ - 'installed' => false, - 'enabled' => false, - 'state' => 'failed', - 'last_error' => 'module_runtime_missing', - 'last_failed_at' => now(), - ]); - } -} diff --git a/app/Platform/Modules/Http/Resources/ModuleResource.php b/app/Platform/Modules/Http/Resources/ModuleResource.php deleted file mode 100644 index ea1ac4a6..00000000 --- a/app/Platform/Modules/Http/Resources/ModuleResource.php +++ /dev/null @@ -1,152 +0,0 @@ -resource, 'module_name'); - $installedModule = is_string($moduleName) - ? ModelsModule::where('name', $moduleName)->first() - : null; - $release = data_get($this->resource, 'release'); - $latestVersion = data_get($this->resource, 'latest_module_version') ?? data_get($release, 'version'); - $compatibility = data_get($this->resource, 'compatibility') ?? data_get($release, 'compatibility'); - $access = data_get($this->resource, 'access', 'free'); - - return [ - 'id' => data_get($this->resource, 'id'), - 'average_rating' => data_get($this->resource, 'average_rating'), - 'cover' => data_get($this->resource, 'cover'), - 'slug' => data_get($this->resource, 'slug'), - 'module_name' => $moduleName, - 'access_tier' => data_get($this->resource, 'access_tier') ?? ($access === 'paid' ? 'premium' : 'public'), - 'access' => $access, - 'entitlement' => data_get($this->resource, 'entitlement'), - 'compatibility' => $compatibility, - 'compatible' => data_get($this->resource, 'compatible'), - 'release_state' => data_get($this->resource, 'release_state') ?? data_get($release, 'state') ?? 'published', - 'yanked_reason' => data_get($this->resource, 'yanked_reason') ?? data_get($release, 'yanked_reason'), - 'channel' => data_get($this->resource, 'channel') ?? data_get($release, 'channel') ?? 'stable', - 'faq' => data_get($this->resource, 'faq'), - 'highlights' => data_get($this->resource, 'highlights'), - 'installed_module_version' => $this->getInstalledModuleVersion($installedModule), - 'installed_module_version_updated_at' => $this->getInstalledModuleUpdatedAt($installedModule), - 'latest_module_version' => $latestVersion, - 'latest_module_version_updated_at' => data_get($this->resource, 'latest_module_version_updated_at') ?? data_get($release, 'published_at'), - 'latest_min_invoiceshelf_version' => data_get($this->resource, 'latest_min_invoiceshelf_version'), - 'latest_module_checksum_sha256' => data_get($this->resource, 'latest_module_checksum_sha256') ?? data_get($release, 'artifact.sha256'), - 'is_dev' => (bool) data_get($this->resource, 'is_dev', false), - 'license' => data_get($this->resource, 'license', 'AGPL-3.0-only'), - 'long_description' => data_get($this->resource, 'long_description'), - 'monthly_price' => data_get($this->resource, 'monthly_price'), - 'name' => data_get($this->resource, 'name'), - 'purchased' => data_get($this->resource, 'purchased') ?? ($access === 'free' || (bool) data_get($this->resource, 'entitlement.active', false)), - 'purchase_url' => data_get($this->resource, 'purchase_url'), - 'reviews' => data_get($this->resource, 'reviews', []), - 'screenshots' => data_get($this->resource, 'screenshots'), - 'short_description' => data_get($this->resource, 'short_description'), - 'type' => data_get($this->resource, 'type'), - 'yearly_price' => data_get($this->resource, 'yearly_price'), - 'author_name' => data_get($this->resource, 'author_name') ?? data_get($this->resource, 'author.name'), - 'author_avatar' => data_get($this->resource, 'author_avatar') ?? data_get($this->resource, 'author.avatar'), - 'installed' => $this->moduleInstalled($installedModule), - 'enabled' => $this->moduleEnabled($installedModule), - 'supports_data_cleanup' => $this->supportsDataCleanup($installedModule), - 'update_available' => $this->updateAvailable($installedModule, $latestVersion), - 'video_link' => data_get($this->resource, 'video_link') ?? data_get($this->resource, 'video.url'), - 'video_thumbnail' => data_get($this->resource, 'video_thumbnail') ?? data_get($this->resource, 'video.thumbnail'), - 'links' => data_get($this->resource, 'links'), - ]; - } - - public function getInstalledModuleVersion(?ModelsModule $installedModule): ?string - { - if ($installedModule && $installedModule->installed) { - return $installedModule->version; - } - - return null; - } - - public function getInstalledModuleUpdatedAt(?ModelsModule $installedModule): ?string - { - if ($installedModule && $installedModule->installed) { - return $installedModule->updated_at?->toIso8601String(); - } - - return null; - } - - public function moduleInstalled(?ModelsModule $installedModule): bool - { - return (bool) ($installedModule?->installed); - } - - public function moduleEnabled(?ModelsModule $installedModule): bool - { - return (bool) ($installedModule?->installed && $installedModule?->enabled); - } - - public function updateAvailable(?ModelsModule $installedModule, mixed $latestVersion): bool - { - if (! $installedModule || ! $installedModule->installed) { - return false; - } - - if (! is_string($latestVersion)) { - return false; - } - - return version_compare($installedModule->version, $latestVersion, '<'); - } - - public function supportsDataCleanup(?ModelsModule $installedModule): bool - { - if (! $installedModule?->installed) { - return false; - } - - $path = base_path('Modules/'.$installedModule->name.'/module.json'); - $metadata = File::isFile($path) ? json_decode((string) File::get($path), true) : null; - $uninstall = is_array($metadata) ? ($metadata['uninstall'] ?? null) : null; - $cleanup = is_array($uninstall) ? ($uninstall['data_cleanup'] ?? null) : null; - $contract = 'InvoiceShelf\\Modules\\Contracts\\DataCleanup'; - - if (! (is_array($metadata) - && ($metadata['schema_version'] ?? null) === 2 - && ($metadata['migration_policy'] ?? null) === 'reversible' - && is_array($uninstall) - && array_keys($uninstall) === ['data_cleanup'] - && is_string($cleanup) - && interface_exists($contract))) { - return false; - } - - try { - $reflection = new \ReflectionClass($cleanup); - - return ! $reflection->isAbstract() - && $reflection->isInstantiable() - && is_a($cleanup, $contract, true) - && $reflection->hasMethod('cleanup') - && $reflection->getMethod('cleanup')->isPublic() - && ! $reflection->getMethod('cleanup')->isStatic(); - } catch (\Throwable) { - return false; - } - } -}