Allow importing eggs via url (#344)

* allow importing eggs via url

* refactor

* run pint

* turn back into one button

* fix empty check

* small cleanup

* removed container for tabs

* Update URL function

* Use sys temp

---------

Co-authored-by: notCharles <charles@pelican.dev>
This commit is contained in:
Boy132 2024-06-07 23:31:34 +02:00 committed by GitHub
parent 02d24b8a36
commit cc1ac1eba1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 149 additions and 16 deletions

View File

@ -8,6 +8,7 @@ use App\Services\Eggs\Sharing\EggImporterService;
use Exception; use Exception;
use Filament\Actions; use Filament\Actions;
use Filament\Forms; use Filament\Forms;
use Filament\Forms\Components\Tabs;
use Filament\Notifications\Notification; use Filament\Notifications\Notification;
use Filament\Resources\Pages\ListRecords; use Filament\Resources\Pages\ListRecords;
use Filament\Tables\Table; use Filament\Tables\Table;
@ -62,21 +63,58 @@ class ListEggs extends ListRecords
Actions\Action::make('import') Actions\Action::make('import')
->label('Import') ->label('Import')
->form([ ->form([
Forms\Components\FileUpload::make('egg') Tabs::make('Tabs')
->acceptedFileTypes(['application/json']) ->tabs([
->storeFiles(false) Tabs\Tab::make('From File')
->multiple(), ->icon('tabler-file-upload')
->schema([
Forms\Components\FileUpload::make('egg')
->label('Egg')
->hint('This should be the json file ( egg-minecraft.json )')
->acceptedFileTypes(['application/json'])
->storeFiles(false)
->multiple(),
]),
Tabs\Tab::make('From URL')
->icon('tabler-world-upload')
->schema([
Forms\Components\TextInput::make('url')
->label('URL')
->hint('This URL should point to a single json file')
->url(),
]),
])
->contained(false),
]) ])
->action(function (array $data): void { ->action(function (array $data): void {
/** @var TemporaryUploadedFile $eggFile */
$eggFile = $data['egg'];
/** @var EggImporterService $eggImportService */ /** @var EggImporterService $eggImportService */
$eggImportService = resolve(EggImporterService::class); $eggImportService = resolve(EggImporterService::class);
foreach ($eggFile as $file) { if (!empty($data['egg'])) {
/** @var TemporaryUploadedFile[] $eggFile */
$eggFile = $data['egg'];
foreach ($eggFile as $file) {
try {
$eggImportService->fromFile($file);
} catch (Exception $exception) {
Notification::make()
->title('Import Failed')
->danger()
->send();
report($exception);
return;
}
}
}
if (!empty($data['url'])) {
try { try {
$eggImportService->handle($file); $eggImportService->fromUrl($data['url']);
} catch (Exception $exception) { } catch (Exception $exception) {
Notification::make() Notification::make()
->title('Import Failed') ->title('Import Failed')

View File

@ -46,7 +46,7 @@ class EggShareController extends Controller
*/ */
public function import(EggImportFormRequest $request): RedirectResponse public function import(EggImportFormRequest $request): RedirectResponse
{ {
$egg = $this->importerService->handle($request->file('import_file')); $egg = $this->importerService->fromFile($request->file('import_file'));
$this->alert->success(trans('admin/eggs.notices.imported'))->flash(); $this->alert->success(trans('admin/eggs.notices.imported'))->flash();
return redirect()->route('admin.eggs.view', ['egg' => $egg->id]); return redirect()->route('admin.eggs.view', ['egg' => $egg->id]);
@ -61,7 +61,7 @@ class EggShareController extends Controller
*/ */
public function update(EggImportFormRequest $request, Egg $egg): RedirectResponse public function update(EggImportFormRequest $request, Egg $egg): RedirectResponse
{ {
$this->updateImporterService->handle($egg, $request->file('import_file')); $this->updateImporterService->fromFile($egg, $request->file('import_file'));
$this->alert->success(trans('admin/eggs.notices.updated_via_import'))->flash(); $this->alert->success(trans('admin/eggs.notices.updated_via_import'))->flash();
return redirect()->route('admin.eggs.view', ['egg' => $egg]); return redirect()->route('admin.eggs.view', ['egg' => $egg]);

View File

@ -9,6 +9,7 @@ use Illuminate\Http\UploadedFile;
use App\Models\EggVariable; use App\Models\EggVariable;
use Illuminate\Database\ConnectionInterface; use Illuminate\Database\ConnectionInterface;
use App\Services\Eggs\EggParserService; use App\Services\Eggs\EggParserService;
use Spatie\TemporaryDirectory\TemporaryDirectory;
class EggImporterService class EggImporterService
{ {
@ -21,7 +22,7 @@ class EggImporterService
* *
* @throws \App\Exceptions\Service\InvalidFileUploadException|\Throwable * @throws \App\Exceptions\Service\InvalidFileUploadException|\Throwable
*/ */
public function handle(UploadedFile $file): Egg public function fromFile(UploadedFile $file): Egg
{ {
$parsed = $this->parser->handle($file); $parsed = $this->parser->handle($file);
@ -46,4 +47,19 @@ class EggImporterService
}); });
} }
/**
* Take an url and parse it into a new egg.
*
* @throws \App\Exceptions\Service\InvalidFileUploadException|\Throwable
*/
public function fromUrl(string $url): Egg
{
$info = pathinfo($url);
$tmpDir = TemporaryDirectory::make()->deleteWhenDestroyed();
$tmpPath = $tmpDir->path($info['basename']);
file_put_contents($tmpPath, file_get_contents($url));
return $this->fromFile(new UploadedFile($tmpPath, $info['basename'], 'application/json'));
}
} }

View File

@ -8,6 +8,7 @@ use Illuminate\Support\Collection;
use App\Models\EggVariable; use App\Models\EggVariable;
use Illuminate\Database\ConnectionInterface; use Illuminate\Database\ConnectionInterface;
use App\Services\Eggs\EggParserService; use App\Services\Eggs\EggParserService;
use Spatie\TemporaryDirectory\TemporaryDirectory;
class EggUpdateImporterService class EggUpdateImporterService
{ {
@ -23,7 +24,7 @@ class EggUpdateImporterService
* *
* @throws \App\Exceptions\Service\InvalidFileUploadException|\Throwable * @throws \App\Exceptions\Service\InvalidFileUploadException|\Throwable
*/ */
public function handle(Egg $egg, UploadedFile $file): Egg public function fromFile(Egg $egg, UploadedFile $file): Egg
{ {
$parsed = $this->parser->handle($file); $parsed = $this->parser->handle($file);
@ -47,4 +48,20 @@ class EggUpdateImporterService
return $egg->refresh(); return $egg->refresh();
}); });
} }
/**
* Update an existing Egg using an url.
*
* @throws \App\Exceptions\Service\InvalidFileUploadException|\Throwable
*/
public function fromUrl(Egg $egg, string $url): Egg
{
$info = pathinfo($url);
$tmpDir = TemporaryDirectory::make()->deleteWhenDestroyed();
$tmpPath = $tmpDir->path($info['basename']);
file_put_contents($tmpPath, file_get_contents($url));
return $this->fromFile($egg, new UploadedFile($tmpPath, $info['basename'], 'application/json'));
}
} }

View File

@ -33,6 +33,7 @@
"s1lentium/iptools": "~1.2.0", "s1lentium/iptools": "~1.2.0",
"spatie/laravel-fractal": "^6.2", "spatie/laravel-fractal": "^6.2",
"spatie/laravel-query-builder": "^5.8.1", "spatie/laravel-query-builder": "^5.8.1",
"spatie/temporary-directory": "^2.2",
"symfony/http-client": "^7.1", "symfony/http-client": "^7.1",
"symfony/mailgun-mailer": "^7.1", "symfony/mailgun-mailer": "^7.1",
"symfony/postmark-mailer": "^7.0.7", "symfony/postmark-mailer": "^7.0.7",

65
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "8feeafbeb16044bd6716510a73393fc0", "content-hash": "bf44faee3aae2b1d4c1b57893c1aba98",
"packages": [ "packages": [
{ {
"name": "abdelhamiderrahmouni/filament-monaco-editor", "name": "abdelhamiderrahmouni/filament-monaco-editor",
@ -6990,6 +6990,67 @@
], ],
"time": "2024-05-10T08:19:35+00:00" "time": "2024-05-10T08:19:35+00:00"
}, },
{
"name": "spatie/temporary-directory",
"version": "2.2.1",
"source": {
"type": "git",
"url": "https://github.com/spatie/temporary-directory.git",
"reference": "76949fa18f8e1a7f663fd2eaa1d00e0bcea0752a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/spatie/temporary-directory/zipball/76949fa18f8e1a7f663fd2eaa1d00e0bcea0752a",
"reference": "76949fa18f8e1a7f663fd2eaa1d00e0bcea0752a",
"shasum": ""
},
"require": {
"php": "^8.0"
},
"require-dev": {
"phpunit/phpunit": "^9.5"
},
"type": "library",
"autoload": {
"psr-4": {
"Spatie\\TemporaryDirectory\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Alex Vanderbist",
"email": "alex@spatie.be",
"homepage": "https://spatie.be",
"role": "Developer"
}
],
"description": "Easily create, use and destroy temporary directories",
"homepage": "https://github.com/spatie/temporary-directory",
"keywords": [
"php",
"spatie",
"temporary-directory"
],
"support": {
"issues": "https://github.com/spatie/temporary-directory/issues",
"source": "https://github.com/spatie/temporary-directory/tree/2.2.1"
},
"funding": [
{
"url": "https://spatie.be/open-source/support-us",
"type": "custom"
},
{
"url": "https://github.com/spatie",
"type": "github"
}
],
"time": "2023-12-25T11:46:58+00:00"
},
{ {
"name": "symfony/clock", "name": "symfony/clock",
"version": "v7.0.7", "version": "v7.0.7",
@ -13096,5 +13157,5 @@
"ext-zip": "*" "ext-zip": "*"
}, },
"platform-dev": [], "platform-dev": [],
"plugin-api-version": "2.6.0" "plugin-api-version": "2.3.0"
} }

View File

@ -75,10 +75,10 @@ class EggSeeder extends Seeder
->first(); ->first();
if ($egg instanceof Egg) { if ($egg instanceof Egg) {
$this->updateImporterService->handle($egg, $file); $this->updateImporterService->fromFile($egg, $file);
$this->command->info('Updated ' . $decoded['name']); $this->command->info('Updated ' . $decoded['name']);
} else { } else {
$this->importerService->handle($file); $this->importerService->fromFile($file);
$this->command->comment('Created ' . $decoded['name']); $this->command->comment('Created ' . $decoded['name']);
} }
} }