From a02c5dd810f954d8cae060718110a5d1614bb4d8 Mon Sep 17 00:00:00 2001 From: jasonzli-DEV Date: Sat, 13 Jun 2026 23:44:19 -0400 Subject: [PATCH] add importing extensions and fix removing --- .../Extensions/Pages/ListExtensions.php | 37 ++++++++++--------- app/Services/Extensions/ExtensionManager.php | 23 ++++++++++++ 2 files changed, 42 insertions(+), 18 deletions(-) diff --git a/app/Filament/Resources/Extensions/Pages/ListExtensions.php b/app/Filament/Resources/Extensions/Pages/ListExtensions.php index 6f9d4cc9b..52cd2506c 100644 --- a/app/Filament/Resources/Extensions/Pages/ListExtensions.php +++ b/app/Filament/Resources/Extensions/Pages/ListExtensions.php @@ -21,7 +21,6 @@ protected function getHeaderActions(): array Action::make('uploadInstall') ->label(trans('admin/extensions.actions.upload')) ->icon('heroicon-o-arrow-up-tray') - ->disabled() // TODO: not finished yet, so disable for now ->form([ FileUpload::make('file') ->label(trans('admin/extensions.columns.file')) @@ -30,7 +29,8 @@ protected function getHeaderActions(): array ->storeFiles(false), ]) ->action(function (array $data): void { - $path = $this->resolveUploadPath(Arr::get($data, 'file')); + $uploaded = Arr::get($data, 'file'); + $path = $this->resolveUploadPath($uploaded); if ($path === null) { Notification::make() @@ -41,8 +41,11 @@ protected function getHeaderActions(): array return; } - // check if .rext - if (strtolower(pathinfo($path, PATHINFO_EXTENSION)) !== 'rext') { + $clientName = $uploaded instanceof TemporaryUploadedFile + ? $uploaded->getClientOriginalName() + : basename($path); + + if (strtolower(pathinfo($clientName, PATHINFO_EXTENSION)) !== 'rext') { Notification::make() ->title(trans('admin/extensions.alerts.invalid_file_type')) ->danger() @@ -52,35 +55,33 @@ protected function getHeaderActions(): array } // validation - try { - $zip = new \ZipArchive(); - - if ($zip->open($path) !== true) { - throw new \Exception('Invalid extension archive.'); - } - - if ($zip->locateName('extension.json') === false) { - $zip->close(); - throw new \Exception('Invalid .rext package: extension.json missing.'); - } + $needsCopy = strtolower(pathinfo($path, PATHINFO_EXTENSION)) !== 'rext'; + $archivePath = $path; - $zip->close(); + if ($needsCopy) { + $archivePath = sys_get_temp_dir() . DIRECTORY_SEPARATOR . uniqid('rext_', true) . '.rext'; + copy($path, $archivePath); + } + try { /** @var ExtensionManager $manager */ $manager = app(ExtensionManager::class); - $extension = $manager->installFromArchive($path, basename($path)); + $extension = $manager->installFromArchive($archivePath, $clientName); Notification::make() ->title(trans('admin/extensions.alerts.install_success', ['name' => $extension->name, 'version' => $extension->version])) ->success() ->send(); - } catch (\Throwable $exception) { Notification::make() ->title(trans('admin/extensions.alerts.install_failed')) ->body($exception->getMessage()) ->danger() ->send(); + } finally { + if ($needsCopy && is_file($archivePath)) { + @unlink($archivePath); + } } }), ]; diff --git a/app/Services/Extensions/ExtensionManager.php b/app/Services/Extensions/ExtensionManager.php index 261a3a403..7ea9226c3 100644 --- a/app/Services/Extensions/ExtensionManager.php +++ b/app/Services/Extensions/ExtensionManager.php @@ -98,6 +98,7 @@ public function installFromArchive(string $archivePath, ?string $archiveFilename $record->api_version = $resolvedApiVersion; $record->target_version = Arr::get($manifest, 'target_version'); $record->manifest = $manifest; + $record->enabled = true; $record->installed_at ??= now(); $record->extension_updated_at = now(); $record->save(); @@ -137,6 +138,8 @@ public function remove(string $identifier): void /** @var Extension $extension */ $extension = Extension::query()->where('identifier', $identifier)->firstOrFail(); + $this->removeOrphanedFilamentPages($identifier); + if (File::exists($extension->install_path)) { File::deleteDirectory($extension->install_path); } @@ -149,6 +152,26 @@ public function remove(string $identifier): void $extension->delete(); } + private function removeOrphanedFilamentPages(string $identifier): void + { + $pagesPath = app_path('Filament/Pages'); + if (! File::isDirectory($pagesPath)) { + return; + } + + $needle = 'extensions/' . $identifier . '/'; + + foreach (File::files($pagesPath) as $file) { + if ($file->getExtension() !== 'php') { + continue; + } + + if (str_contains((string) File::get($file->getPathname()), $needle)) { + File::delete($file->getPathname()); + } + } + } + /** * @return Collection */