From 58f0d5f07f240debcf8aaec9c2eaf96fd0ca7123 Mon Sep 17 00:00:00 2001 From: thomascombe Date: Thu, 9 Dec 2021 11:42:13 +0100 Subject: [PATCH 1/9] Remove useless factory --- database/factories/ModelFactory.php | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 100644 database/factories/ModelFactory.php diff --git a/database/factories/ModelFactory.php b/database/factories/ModelFactory.php deleted file mode 100644 index 811153a..0000000 --- a/database/factories/ModelFactory.php +++ /dev/null @@ -1,19 +0,0 @@ - Date: Thu, 9 Dec 2021 11:42:44 +0100 Subject: [PATCH 2/9] Add action type to export model --- database/migrations/create_backpack_async_export_table.php.stub | 1 + src/Models/Export.php | 2 ++ 2 files changed, 3 insertions(+) diff --git a/database/migrations/create_backpack_async_export_table.php.stub b/database/migrations/create_backpack_async_export_table.php.stub index dfd6c93..7ff1f98 100644 --- a/database/migrations/create_backpack_async_export_table.php.stub +++ b/database/migrations/create_backpack_async_export_table.php.stub @@ -12,6 +12,7 @@ class CreateBackpackAsyncExportTable extends Migration $table->bigIncrements('id'); $table->unsignedBigInteger('user_id'); + $table->string('action_type'); $table->string('export_type'); $table->string('filename'); $table->string('disk'); diff --git a/src/Models/Export.php b/src/Models/Export.php index 8efc636..47bc949 100644 --- a/src/Models/Export.php +++ b/src/Models/Export.php @@ -17,6 +17,7 @@ class Export extends Model implements ExportInterface use SoftDeletes; public const COLUMN_USER_ID = 'user_id'; + public const COLUMN_ACTION_TYPE = 'action_type'; public const COLUMN_EXPORT_TYPE = 'export_type'; public const COLUMN_FILENAME = 'filename'; public const COLUMN_DISK = 'disk'; @@ -26,6 +27,7 @@ class Export extends Model implements ExportInterface protected $fillable = [ self::COLUMN_USER_ID, + self::COLUMN_ACTION_TYPE, self::COLUMN_EXPORT_TYPE, self::COLUMN_FILENAME, self::COLUMN_DISK, From 2ad3adc93ee763ea6ecab6f7440acbfb49d1a9d6 Mon Sep 17 00:00:00 2001 From: thomascombe Date: Thu, 9 Dec 2021 11:47:14 +0100 Subject: [PATCH 3/9] Allow to import file in async mode --- config/backpack-async-export.php | 11 +- resources/lang/en/admin.php | 13 ++ resources/lang/en/import.php | 25 ++++ resources/views/buttons/export.blade.php | 2 +- resources/views/buttons/import.blade.php | 5 + resources/views/pages/import.blade.php | 63 +++++++++ routes/backpack/export.php | 7 +- src/Enums/ActionType.php | 19 +++ .../Admin/ExportCrudController.php | 4 +- .../Admin/ImportCrudController.php | 44 ++++++ .../Admin/Interfaces/ImportableCrud.php | 12 ++ .../Admin/Traits/HasExportButton.php | 4 +- .../Admin/Traits/HasImportButton.php | 127 ++++++++++++++++++ src/Http/Requests/ImportRequest.php | 25 ++++ src/Jobs/ImportJob.php | 72 ++++++++++ src/Models/Export.php | 2 +- 16 files changed, 428 insertions(+), 7 deletions(-) create mode 100644 resources/lang/en/admin.php create mode 100644 resources/lang/en/import.php create mode 100644 resources/views/buttons/import.blade.php create mode 100644 resources/views/pages/import.blade.php create mode 100644 src/Enums/ActionType.php create mode 100644 src/Http/Controllers/Admin/ImportCrudController.php create mode 100644 src/Http/Controllers/Admin/Interfaces/ImportableCrud.php create mode 100644 src/Http/Controllers/Admin/Traits/HasImportButton.php create mode 100644 src/Http/Requests/ImportRequest.php create mode 100644 src/Jobs/ImportJob.php diff --git a/config/backpack-async-export.php b/config/backpack-async-export.php index 76df39d..f56b35b 100644 --- a/config/backpack-async-export.php +++ b/config/backpack-async-export.php @@ -1,6 +1,14 @@ [ + 'export' => true, + 'import' => true, + ], /************** * MODEL *************** @@ -11,7 +19,8 @@ * Routing *************** */ - 'admin_route' => 'export', + 'admin_export_route' => 'export', + 'admin_import_route' => 'import', /************** * Filesystem *************** diff --git a/resources/lang/en/admin.php b/resources/lang/en/admin.php new file mode 100644 index 0000000..6a124da --- /dev/null +++ b/resources/lang/en/admin.php @@ -0,0 +1,13 @@ + [ + 'file' => 'File', + ], + 'button' => [ + 'import' => 'Import', + ], + 'operation' => [ + 'import' => 'Import', + ], +]; diff --git a/resources/lang/en/import.php b/resources/lang/en/import.php new file mode 100644 index 0000000..bddc045 --- /dev/null +++ b/resources/lang/en/import.php @@ -0,0 +1,25 @@ + [ + 'singular' => 'import', + 'plurial' => 'imports', + ], + 'columns' => [ + 'user_id' => 'User', + 'export_type' => 'Type', + 'filename' => 'Filename', + 'status' => 'Status', + 'error' => 'Error', + 'completed_at' => 'Completed at', + ], + 'buttons' => [ + 'import' => 'Import', + ], + 'notifications' => [ + 'queued' => 'Import launched! Results will be available when ready on "Import" tab', + ], + 'errors' => [ + 'global-import' => 'Error during import', + ], +]; diff --git a/resources/views/buttons/export.blade.php b/resources/views/buttons/export.blade.php index 2d113d4..1431002 100644 --- a/resources/views/buttons/export.blade.php +++ b/resources/views/buttons/export.blade.php @@ -1,6 +1,6 @@ @if ($crud->hasAccess('list')) @php($exports = $crud->get('exports', ['default' => null])) @foreach($exports as $export => $exportsName) - {{ __('backpack-async-export::export.buttons.exports') }}@if (!empty($exportsName)) ({{ $exportsName }})@endif + {{ __('backpack-async-export::export.buttons.exports') }}@if (!empty($exportsName)) ({{ $exportsName }})@endif @endforeach @endif diff --git a/resources/views/buttons/import.blade.php b/resources/views/buttons/import.blade.php new file mode 100644 index 0000000..3229ec7 --- /dev/null +++ b/resources/views/buttons/import.blade.php @@ -0,0 +1,5 @@ +@if ($crud->hasAccess('list')) + @php($route = $crud->get('import_route')) + + {{ __('backpack-async-export::import.buttons.import') }} +@endif diff --git a/resources/views/pages/import.blade.php b/resources/views/pages/import.blade.php new file mode 100644 index 0000000..e634967 --- /dev/null +++ b/resources/views/pages/import.blade.php @@ -0,0 +1,63 @@ +@extends('backpack::layouts.top_left') + +@section('header') +
+

+ {!! $crud->getHeading() ?? $crud->entity_name_plural !!} + {!! $crud->getSubheading() ?? trans('backpack-async-export::admin.operation.import') . ' ' . $crud->entity_name !!}. +

+ @include('backpack::inc.breadcrumbs') +
+@endsection + +@section('content') + @if ($crud->hasAccess('list')) + + + {{ trans('backpack::crud.back_to_all') }} + {{ $crud->entity_name_plural }} + + @endif + +
+
+ + + @include('crud::inc.grouped_errors') + +
+ @csrf + +
+
+ + @if(view()->exists('backpack-async-export::vendor.backpack.crud.form_content')) + @include('backpack-async-export::vendor.backpack.crud.form_content', ['fields' => $fields, 'action' => 'edit']) + @elseif(view()->exists('vendor.backpack.crud.form_content')) + @include('vendor.backpack.crud.form_content', ['fields' => $fields, 'action' => 'edit']) + @else + @include('crud::form_content', ['fields' => $fields, 'action' => 'edit']) + @endif + +
+ +
+
+ +
+ + + + {{ trans('backpack::crud.cancel') }} + +
+
+
+
+
+@endsection diff --git a/routes/backpack/export.php b/routes/backpack/export.php index 8e1bb98..1e11936 100644 --- a/routes/backpack/export.php +++ b/routes/backpack/export.php @@ -4,5 +4,10 @@ 'prefix' => config('backpack.base.route_prefix', 'admin'), 'middleware' => ['web', backpack_middleware()], ], function () { - Route::crud(config('backpack-async-export.admin_route'), 'ExportCrudController'); + if (config('backpack-async-export.feature_enabled.export')) { + Route::crud(config('backpack-async-export.admin_export_route'), 'ExportCrudController'); + } + if (config('backpack-async-export.feature_enabled.import')) { + Route::crud(config('backpack-async-export.admin_import_route'), 'ImportCrudController'); + } }); diff --git a/src/Enums/ActionType.php b/src/Enums/ActionType.php new file mode 100644 index 0000000..efa3735 --- /dev/null +++ b/src/Enums/ActionType.php @@ -0,0 +1,19 @@ +getConstants(); + } +} diff --git a/src/Http/Controllers/Admin/ExportCrudController.php b/src/Http/Controllers/Admin/ExportCrudController.php index 391252e..959d9a2 100644 --- a/src/Http/Controllers/Admin/ExportCrudController.php +++ b/src/Http/Controllers/Admin/ExportCrudController.php @@ -10,6 +10,7 @@ use Illuminate\Support\Facades\File; use Illuminate\Support\Facades\Route; use Symfony\Component\HttpFoundation\StreamedResponse; +use Thomascombe\BackpackAsyncExport\Enums\ActionType; use Thomascombe\BackpackAsyncExport\Models\Export; /** @@ -24,11 +25,12 @@ class ExportCrudController extends CrudController public function setup() { CRUD::setModel(config('backpack-async-export.export_model')); - CRUD::setRoute(sprintf('%s/%s', config('backpack.base.route_prefix'), config('backpack-async-export.admin_route'))); + CRUD::setRoute(sprintf('%s/%s', config('backpack.base.route_prefix'), config('backpack-async-export.admin_export_route'))); CRUD::setEntityNameStrings( __('backpack-async-export::export.name.singular'), __('backpack-async-export::export.name.plurial') ); + $this->crud->query->where('action_type', ActionType::Export); $this->addCrudButtons(); } diff --git a/src/Http/Controllers/Admin/ImportCrudController.php b/src/Http/Controllers/Admin/ImportCrudController.php new file mode 100644 index 0000000..757b747 --- /dev/null +++ b/src/Http/Controllers/Admin/ImportCrudController.php @@ -0,0 +1,44 @@ +crud->query->where('action_type', ActionType::Import); + } + + protected function setupListOperation() + { + CRUD::column('user_id')->label(__('backpack-async-export::import.columns.user_id')); + CRUD::column('export_type_name')->label(__('backpack-async-export::import.columns.export_type')); + CRUD::column('filename')->label(__('backpack-async-export::import.columns.filename')); + CRUD::column('status')->label(__('backpack-async-export::import.columns.status')); + CRUD::column('error')->label(__('backpack-async-export::import.columns.error')); + CRUD::column('completed_at')->label(__('backpack-async-export::import.columns.completed_at')); + } +} diff --git a/src/Http/Controllers/Admin/Interfaces/ImportableCrud.php b/src/Http/Controllers/Admin/Interfaces/ImportableCrud.php new file mode 100644 index 0000000..8edc225 --- /dev/null +++ b/src/Http/Controllers/Admin/Interfaces/ImportableCrud.php @@ -0,0 +1,12 @@ +checkInterfaceImplementation(); - Route::get($segment . '/' . config('backpack-async-export.admin_route'), [ + Route::get($segment . '/' . config('backpack-async-export.admin_export_route'), [ 'as' => $routeName . '.export', 'uses' => $controller . '@export', 'operation' => 'export', @@ -71,7 +71,7 @@ public function export(): RedirectResponse ExportJob::dispatch($exportModel, ...$parameters); \Alert::info(__('backpack-async-export::export.notifications.queued'))->flash(); - return response()->redirectToRoute(config('backpack-async-export.admin_route') . '.index'); + return response()->redirectToRoute(config('backpack-async-export.admin_export_route') . '.index'); } /** diff --git a/src/Http/Controllers/Admin/Traits/HasImportButton.php b/src/Http/Controllers/Admin/Traits/HasImportButton.php new file mode 100644 index 0000000..f4f913c --- /dev/null +++ b/src/Http/Controllers/Admin/Traits/HasImportButton.php @@ -0,0 +1,127 @@ +checkInterfaceImplementation(); + + $this->crud->setting('import_route', url(route('user.import'))); + $this->crud->addButton('top', 'export', 'view', 'backpack-async-export::buttons/import', 'end'); + } + + /** + * @throws \Exception + */ + protected function setupImportRoutes($segment, $routeName, $controller) + { + $this->checkInterfaceImplementation(); + + Route::get($segment . '/' . config('backpack-async-export.admin_import_route'), [ + 'as' => $routeName . '.import', + 'uses' => $controller . '@import', + 'operation' => 'import', + ]); + Route::post($segment . '/' . config('backpack-async-export.admin_import_route'), [ + 'as' => $routeName . '.import-submit', + 'uses' => $controller . '@importSubmit', + 'operation' => 'import-submit', + ]); + } + + /** + * @throws \Exception + */ + public function import(): View + { + $this->checkInterfaceImplementation(); + + $this->data['crud'] = $this->crud; + $this->data['title'] = $this->crud->getTitle(); + $this->data['fields'] = [ + [ + 'name' => 'file', + 'label' => trans('backpack-async-export::admin.column.file'), + 'type' => 'upload', + 'upload' => true, + // 'hint' => $hint, + // 'attributes' => [ + // 'accept' => $accept, + // ], + ] + ]; + + return view('backpack-async-export::pages.import', $this->data); + } + + /** + * @throws \Exception + */ + public function importSubmit(ImportRequest $request): RedirectResponse + { + $this->checkInterfaceImplementation(); + + /** @var Export $exportModel */ + $exportModel = $this->{$this->getImportMethodName()}(); + $parameters = $this->{$this->getImportParametersMethodName()}(); + + /** @var UploadedFile $file */ + $file = $request->files->get($request::PARAM_FILE); + $filename = sprintf('%s/%s', $exportModel->{Export::COLUMN_FILENAME}, $file->getClientOriginalName()); + Storage::disk($exportModel->{Export::COLUMN_DISK}) + ->put( + $filename, + $file->getContent() + ); + $exportModel->{Export::COLUMN_FILENAME} = $filename; + $exportModel->save(); + ImportJob::dispatch($exportModel, ...$parameters); + \Alert::info(__('backpack-async-export::import.notifications.queued'))->flash(); + + return response()->redirectToRoute(config('backpack-async-export.admin_import_route') . '.index'); + } + + /** + * @throws \Exception + */ + protected function checkInterfaceImplementation(): void + { + if (!$this instanceof ImportableCrud) { + throw new \Exception(sprintf('%s need to implement %s', self::class, ImportableCrud::class)); + } + } + + protected function getImportMethodName(): string + { + return 'getImport'; + } + + protected function getImportParametersMethodName(): string + { + return 'getImportParameters'; + } +} diff --git a/src/Http/Requests/ImportRequest.php b/src/Http/Requests/ImportRequest.php new file mode 100644 index 0000000..787c586 --- /dev/null +++ b/src/Http/Requests/ImportRequest.php @@ -0,0 +1,25 @@ + [ + 'required', + 'file', + ], + ]; + } + + public function authorize(): bool + { + return backpack_auth()->check(); + } +} diff --git a/src/Jobs/ImportJob.php b/src/Jobs/ImportJob.php new file mode 100644 index 0000000..e5a2d80 --- /dev/null +++ b/src/Jobs/ImportJob.php @@ -0,0 +1,72 @@ +export = $export; + $this->exportParameters = $exportParameters; + } + + public function handle() + { + if ($this->export->action_type !== ActionType::Import) { + $message = sprintf('Import of type "%s" try to be import', $this->export->action_type); + $this->export->update([ + Export::COLUMN_STATUS => ExportStatus::Error, + Export::COLUMN_ERROR => $message, + ]); + Log::error($message); + return; + } + + $this->export->update([ + Export::COLUMN_STATUS => ExportStatus::Processing, + ]); + + try { + ini_set('memory_limit', config('backpack-async-export.export_memory_limit')); + $exportClass = $this->export->{Export::COLUMN_EXPORT_TYPE}; + + Excel::import( + new $exportClass(...$this->exportParameters), + $this->export->{Export::COLUMN_FILENAME}, + config('backpack-async-export.disk') + ); + + $this->export->{Export::COLUMN_STATUS} = ExportStatus::Successful; + $this->export->save(); + $this->export->update([ + Export::COLUMN_STATUS => ExportStatus::Successful, + Export::COLUMN_COMPLETED_AT => now(), + ]); + } catch (\Exception | \Throwable $exception) { + $this->export->update([ + Export::COLUMN_STATUS => ExportStatus::Error, + Export::COLUMN_ERROR => $exception->getMessage(), + ]); + Log::error(__('backpack-async-export::import.errors.global-export'), ['exception' => $exception]); + } + } +} diff --git a/src/Models/Export.php b/src/Models/Export.php index 47bc949..a818e1c 100644 --- a/src/Models/Export.php +++ b/src/Models/Export.php @@ -86,7 +86,7 @@ public function getDownloadButton(): string { if ($this->isReady) { $url = route( - config('backpack-async-export.admin_route') . '.download', + config('backpack-async-export.admin_export_route') . '.download', [ 'export' => $this->id, ] From 28f9ac65e45e2b0376e9bf9cd311f98f4fbe5f12 Mon Sep 17 00:00:00 2001 From: thomascombe Date: Thu, 9 Dec 2021 14:44:06 +0100 Subject: [PATCH 4/9] Allow to filter by mimetype --- .../Admin/Traits/HasImportButton.php | 76 +++++++++++++++---- src/Jobs/ImportJob.php | 4 + 2 files changed, 65 insertions(+), 15 deletions(-) diff --git a/src/Http/Controllers/Admin/Traits/HasImportButton.php b/src/Http/Controllers/Admin/Traits/HasImportButton.php index f4f913c..818addc 100644 --- a/src/Http/Controllers/Admin/Traits/HasImportButton.php +++ b/src/Http/Controllers/Admin/Traits/HasImportButton.php @@ -7,7 +7,9 @@ use Illuminate\Http\UploadedFile; use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Storage; +use Illuminate\Support\Facades\Validator; use Illuminate\View\View; +use Prologue\Alerts\Facades\Alert; use Thomascombe\BackpackAsyncExport\Http\Controllers\Admin\Interfaces\ImportableCrud; use Thomascombe\BackpackAsyncExport\Http\Requests\ImportRequest; use Thomascombe\BackpackAsyncExport\Jobs\ImportJob; @@ -22,7 +24,6 @@ */ trait HasImportButton { - /** * @throws \Exception */ @@ -62,16 +63,21 @@ public function import(): View $this->data['crud'] = $this->crud; $this->data['title'] = $this->crud->getTitle(); + $parameters = $this->{$this->getImportParametersMethodName()}(); + $this->data['fields'] = [ [ 'name' => 'file', 'label' => trans('backpack-async-export::admin.column.file'), 'type' => 'upload', 'upload' => true, - // 'hint' => $hint, - // 'attributes' => [ - // 'accept' => $accept, - // ], + 'hint' => $parameters['private']['hint'] ?? null, + 'attributes' => [ + 'accept' => implode( + ',', + isset($parameters['private']) ? $parameters['private']['mimetypes'] : [] + ), + ], ] ]; @@ -89,22 +95,48 @@ public function importSubmit(ImportRequest $request): RedirectResponse $exportModel = $this->{$this->getImportMethodName()}(); $parameters = $this->{$this->getImportParametersMethodName()}(); - /** @var UploadedFile $file */ - $file = $request->files->get($request::PARAM_FILE); - $filename = sprintf('%s/%s', $exportModel->{Export::COLUMN_FILENAME}, $file->getClientOriginalName()); - Storage::disk($exportModel->{Export::COLUMN_DISK}) - ->put( - $filename, - $file->getContent() - ); - $exportModel->{Export::COLUMN_FILENAME} = $filename; - $exportModel->save(); + list($mimetypeState, $validator) = $this->checkFileMimetype($request, $parameters); + if (!$mimetypeState) { + return redirect() + ->back() + ->withErrors($validator) + ->withInput(); + } + + $this->saveUploadFile($request, $exportModel); + ImportJob::dispatch($exportModel, ...$parameters); \Alert::info(__('backpack-async-export::import.notifications.queued'))->flash(); return response()->redirectToRoute(config('backpack-async-export.admin_import_route') . '.index'); } + private function checkFileMimetype(ImportRequest $request): array + { + $parameters = $this->{$this->getImportParametersMethodName()}(); + $mimetypes = isset($parameters['private']) ? $parameters['private']['mimetypes'] : []; + + if (!empty($mimetypes)) { + $validator = Validator::make($request->all(), [ + $request::PARAM_FILE => [ + 'required', + 'file', + sprintf('mimetypes:%s', implode(',', $mimetypes)), + ], + ]); + + if ($validator->fails()) { + Alert::error($validator->errors()->get('file'))->flash(); + + return [false, $validator]; + } + + return [true, $validator]; + } + + return [true]; + } + /** * @throws \Exception */ @@ -124,4 +156,18 @@ protected function getImportParametersMethodName(): string { return 'getImportParameters'; } + + private function saveUploadFile(ImportRequest $request, Export $exportModel): void + { + /** @var UploadedFile $file */ + $file = $request->files->get($request::PARAM_FILE); + $filename = sprintf('%s/%s', $exportModel->{Export::COLUMN_FILENAME}, $file->getClientOriginalName()); + Storage::disk($exportModel->{Export::COLUMN_DISK}) + ->put( + $filename, + $file->getContent() + ); + $exportModel->{Export::COLUMN_FILENAME} = $filename; + $exportModel->save(); + } } diff --git a/src/Jobs/ImportJob.php b/src/Jobs/ImportJob.php index e5a2d80..e5874ee 100644 --- a/src/Jobs/ImportJob.php +++ b/src/Jobs/ImportJob.php @@ -8,6 +8,7 @@ use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; use Illuminate\Support\Facades\Log; +use Illuminate\Support\Facades\Storage; use Maatwebsite\Excel\Facades\Excel; use Thomascombe\BackpackAsyncExport\Enums\ActionType; use Thomascombe\BackpackAsyncExport\Enums\ExportStatus; @@ -49,6 +50,7 @@ public function handle() ini_set('memory_limit', config('backpack-async-export.export_memory_limit')); $exportClass = $this->export->{Export::COLUMN_EXPORT_TYPE}; + unset($this->exportParameters['private']); Excel::import( new $exportClass(...$this->exportParameters), $this->export->{Export::COLUMN_FILENAME}, @@ -67,6 +69,8 @@ public function handle() Export::COLUMN_ERROR => $exception->getMessage(), ]); Log::error(__('backpack-async-export::import.errors.global-export'), ['exception' => $exception]); + } finally { + Storage::disk($this->export->{Export::COLUMN_DISK})->delete($this->export->{Export::COLUMN_FILENAME}); } } } From 71906f6f0918544110a90237fd485fe6ba944277 Mon Sep 17 00:00:00 2001 From: thomascombe Date: Thu, 9 Dec 2021 14:51:30 +0100 Subject: [PATCH 5/9] Allow to commit sub vendor dir --- .gitignore | 2 +- .../backpack/crud/form_content.blade.php | 161 ++++++++++++++++++ 2 files changed, 162 insertions(+), 1 deletion(-) create mode 100644 resources/views/vendor/backpack/crud/form_content.blade.php diff --git a/.gitignore b/.gitignore index 3bde4cb..1b2c307 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,4 @@ coverage phpunit.xml psalm.xml testbench.yaml -vendor +./vendor diff --git a/resources/views/vendor/backpack/crud/form_content.blade.php b/resources/views/vendor/backpack/crud/form_content.blade.php new file mode 100644 index 0000000..3b4f2c5 --- /dev/null +++ b/resources/views/vendor/backpack/crud/form_content.blade.php @@ -0,0 +1,161 @@ +route) }}> +{{-- See if we're using tabs --}} +@if ($crud->tabsEnabled() && count($crud->getTabs())) + @include('crud::inc.show_tabbed_fields') + +@else +
+
+ @include('crud::inc.show_fields', ['fields' => $fields]) +
+
+@endif + + +{{-- Define blade stacks so css and js can be pushed from the fields to these sections. --}} + +@section('after_styles') + + + + + + @stack('crud_fields_styles') +@endsection + +@section('after_scripts') + + + + + + @stack('crud_fields_scripts') + + +@endsection From 1a7d868f2bcd26377c6fe26d74216d7f538221aa Mon Sep 17 00:00:00 2001 From: thomascombe Date: Thu, 9 Dec 2021 15:36:38 +0100 Subject: [PATCH 6/9] fix psalm --- src/Http/Requests/ImportRequest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Http/Requests/ImportRequest.php b/src/Http/Requests/ImportRequest.php index 787c586..3ea1c2d 100644 --- a/src/Http/Requests/ImportRequest.php +++ b/src/Http/Requests/ImportRequest.php @@ -3,6 +3,7 @@ namespace Thomascombe\BackpackAsyncExport\Http\Requests; use Illuminate\Foundation\Http\FormRequest; +use Illuminate\Support\Facades\Auth; class ImportRequest extends FormRequest { @@ -20,6 +21,6 @@ public function rules(): array public function authorize(): bool { - return backpack_auth()->check(); + return Auth::guard(backpack_guard_name())->check(); } } From ac865122b72db90b67382e7836911ae0b7d6f6f6 Mon Sep 17 00:00:00 2001 From: thomascombe Date: Thu, 9 Dec 2021 15:53:21 +0100 Subject: [PATCH 7/9] fix psalm --- src/Http/Requests/ImportRequest.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Http/Requests/ImportRequest.php b/src/Http/Requests/ImportRequest.php index 3ea1c2d..0c10e8f 100644 --- a/src/Http/Requests/ImportRequest.php +++ b/src/Http/Requests/ImportRequest.php @@ -3,7 +3,6 @@ namespace Thomascombe\BackpackAsyncExport\Http\Requests; use Illuminate\Foundation\Http\FormRequest; -use Illuminate\Support\Facades\Auth; class ImportRequest extends FormRequest { @@ -21,6 +20,9 @@ public function rules(): array public function authorize(): bool { - return Auth::guard(backpack_guard_name())->check(); + /** + * @psalm-suppress UndefinedFunction + */ + return \backpack_auth()->check(); } } From 2f76cde9d03ef8e9adda4c2165698c3513bcdcb6 Mon Sep 17 00:00:00 2001 From: thomascombe Date: Thu, 9 Dec 2021 18:15:45 +0100 Subject: [PATCH 8/9] Rename export to import-export --- README.md | 106 +++++++++++++++--- ...t.php => backpack-async-import-export.php} | 2 +- ...kpack_async_import_exports_table.php.stub} | 6 +- resources/views/buttons/export.blade.php | 2 +- routes/backpack/export.php | 13 --- routes/backpack/import-export.php | 13 +++ src/BackpackAsyncExportServiceProvider.php | 6 +- .../Admin/ExportCrudController.php | 10 +- .../Admin/ImportCrudController.php | 4 +- .../Admin/Interfaces/ExportableCrud.php | 4 +- .../Admin/Interfaces/ImportableCrud.php | 4 +- .../Admin/Traits/HasExportButton.php | 4 +- .../Admin/Traits/HasImportButton.php | 18 +-- src/Jobs/ExportJob.php | 26 ++--- src/Jobs/ImportJob.php | 32 +++--- src/Models/{Export.php => ImportExport.php} | 17 +-- ...nterface.php => ImportExportInterface.php} | 2 +- 17 files changed, 171 insertions(+), 98 deletions(-) rename config/{backpack-async-export.php => backpack-async-import-export.php} (85%) rename database/migrations/{create_backpack_async_export_table.php.stub => create_backpack_async_import_exports_table.php.stub} (80%) delete mode 100644 routes/backpack/export.php create mode 100644 routes/backpack/import-export.php rename src/Models/{Export.php => ImportExport.php} (84%) rename src/Models/Interfaces/{ExportInterface.php => ImportExportInterface.php} (69%) diff --git a/README.md b/README.md index a01cb89..0231dc7 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ [![PHPCS check](https://github.com/thomascombe/backpack-async-export/actions/workflows/phpcs.yml/badge.svg)](https://github.com/thomascombe/backpack-async-export/actions/workflows/phpcs.yml) [![Total Downloads](https://img.shields.io/packagist/dt/thomascombe/backpack-async-export.svg?style=flat-square)](https://packagist.org/packages/thomascombe/backpack-async-export) -This is a package to manage async export in [Backpack](https://backpackforlaravel.com/) for Laravel +This is a package to manage async export and import in [Backpack](https://backpackforlaravel.com/) for Laravel

Demo of Laravel Backpack Async Export

@@ -34,15 +34,20 @@ This is the contents of the published config file: ```php return [ + 'feature_enabled' => [ + 'export' => true, + 'import' => true, + ], 'user_model' => 'App\Models\User', - 'export_model' => \Thomascombe\BackpackAsyncExport\Models\Export::class, - 'admin_route' => 'export', + 'import_export_model' => \Thomascombe\BackpackAsyncExport\Models\ImportExport::class, + 'admin_export_route' => 'export', + 'admin_import_route' => 'import', 'export_memory_limit' => '2048M', 'disk' => 'local', ]; ``` -## Usage +## Usage for export ### Add export item in menu ```bash @@ -82,17 +87,18 @@ public function setup() ``` ### Add method to your CRUD controller + ```php use Thomascombe\BackpackAsyncExport\Enums\ExportStatus; -use Thomascombe\BackpackAsyncExport\Models\Export; +use Thomascombe\BackpackAsyncExport\Models\ImportExport; -public function getExport(): Export +public function getExport(): ImportExport { - return Export::create([ - Export::COLUMN_USER_ID => backpack_user()->id, - Export::COLUMN_STATUS => ExportStatus::Created, - Export::COLUMN_FILENAME => sprintf('export/users_%s.xlsx', now()->toIso8601String()), - Export::COLUMN_EXPORT_TYPE => UserExport::class, + return ImportExport::create([ + ImportExport::COLUMN_USER_ID => backpack_user()->id, + ImportExport::COLUMN_STATUS => ExportStatus::Created, + ImportExport::COLUMN_FILENAME => sprintf('export/users_%s.xlsx', now()->toIso8601String()), + ImportExport::COLUMN_EXPORT_TYPE => UserExport::class, ]); } @@ -102,14 +108,80 @@ public function getExportParameters(): array } ``` +## Usage for import + +### Add import item in menu +```bash +php artisan backpack:add-sidebar-content "" +``` + +### Create you import class +```bash +php artisan make:import UserImport --model=App\Models\User +``` +For all details, have a look at [Laravel Excel Package](https://laravel-excel.com/) + +### Create your controller +```bash +php artisan backpack:crud {Name}CrudController +``` + +### Your controller need to implement interface +```php +use Thomascombe\BackpackAsyncExport\Http\Controllers\Admin\Interfaces\ImportableCrud; + +class {Name}CrudController extends CrudController implements ImportableCrud {} +``` + +### Use awesome trait +```php +use Thomascombe\BackpackAsyncExport\Http\Controllers\Admin\Traits\HasImportButton; +``` + +### Call method to add buttons +```php +public function setup() +{ + // ... + $this->addImportButtons(); +} +``` + +### Add method to your CRUD controller + +```php +use Thomascombe\BackpackAsyncExport\Enums\ExportStatus; +use Thomascombe\BackpackAsyncExport\Models\ImportExport; + +public function getImport(): ImportExport +{ + return ImportExport::create([ + ImportExport::COLUMN_USER_ID => backpack_user()->id, + ImportExport::COLUMN_STATUS => ExportStatus::Created, + ImportExport::COLUMN_FILENAME => sprintf('export/users_%s.xlsx', now()->toIso8601String()), + ImportExport::COLUMN_EXPORT_TYPE => UserExport::class, + ]); +} + +public function getImportParameters(): array +{ + return [ + 'private' => [ + 'hint' => 'CSV file required', + 'mimetypes' => ['text/csv', 'application/csv'], + ], + ]; +} +``` + ## Need more? -### Override Export model -You can override `Export` model using config : `export_model`. -Your model class **need** to implement `\Thomascombe\BackpackAsyncExport\Models\Export`. +### Override ImportExport model +You can override `ImportExport` model using config : `import_export_model`. +Your model class **need** to implement `\Thomascombe\BackpackAsyncExport\Models\ImportExport`. ```php -class Export extends \Thomascombe\BackpackAsyncExport\Models\Export +class ImportExport extends \Thomascombe\BackpackAsyncExport\Models\ImportExport { } ``` @@ -153,9 +225,9 @@ public function getAvailableExports(): array For each new export you have to add news methods: ```php -public function getExport*All*(): Export +public function getExport*All*(): ImportExport { - return Export::create(...); + return ImportExport::create(...); } public function getExport*All*Parameters(): array diff --git a/config/backpack-async-export.php b/config/backpack-async-import-export.php similarity index 85% rename from config/backpack-async-export.php rename to config/backpack-async-import-export.php index f56b35b..a49e402 100644 --- a/config/backpack-async-export.php +++ b/config/backpack-async-import-export.php @@ -14,7 +14,7 @@ *************** */ 'user_model' => 'App\Models\User', - 'export_model' => \Thomascombe\BackpackAsyncExport\Models\Export::class, + 'import_export_model' => \Thomascombe\BackpackAsyncExport\Models\ImportExport::class, /************** * Routing *************** diff --git a/database/migrations/create_backpack_async_export_table.php.stub b/database/migrations/create_backpack_async_import_exports_table.php.stub similarity index 80% rename from database/migrations/create_backpack_async_export_table.php.stub rename to database/migrations/create_backpack_async_import_exports_table.php.stub index 7ff1f98..3cb16e2 100644 --- a/database/migrations/create_backpack_async_export_table.php.stub +++ b/database/migrations/create_backpack_async_import_exports_table.php.stub @@ -4,11 +4,11 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -class CreateBackpackAsyncExportTable extends Migration +class CreateBackpackAsyncImportExportsTable extends Migration { public function up() { - Schema::create('exports', function (Blueprint $table) { + Schema::create('import_exports', function (Blueprint $table) { $table->bigIncrements('id'); $table->unsignedBigInteger('user_id'); @@ -23,7 +23,7 @@ class CreateBackpackAsyncExportTable extends Migration $table->timestamps(); $table->softDeletes(); - $table->foreign('user_id', 'exports_ibfk_1') + $table->foreign('user_id', 'import_exports_ibfk_1') ->references('id') ->on('users'); }); diff --git a/resources/views/buttons/export.blade.php b/resources/views/buttons/export.blade.php index 1431002..39a6828 100644 --- a/resources/views/buttons/export.blade.php +++ b/resources/views/buttons/export.blade.php @@ -1,6 +1,6 @@ @if ($crud->hasAccess('list')) @php($exports = $crud->get('exports', ['default' => null])) @foreach($exports as $export => $exportsName) - {{ __('backpack-async-export::export.buttons.exports') }}@if (!empty($exportsName)) ({{ $exportsName }})@endif + {{ __('backpack-async-export::export.buttons.exports') }}@if (!empty($exportsName)) ({{ $exportsName }})@endif @endforeach @endif diff --git a/routes/backpack/export.php b/routes/backpack/export.php deleted file mode 100644 index 1e11936..0000000 --- a/routes/backpack/export.php +++ /dev/null @@ -1,13 +0,0 @@ - 'Thomascombe\BackpackAsyncExport\Http\Controllers\Admin', - 'prefix' => config('backpack.base.route_prefix', 'admin'), - 'middleware' => ['web', backpack_middleware()], -], function () { - if (config('backpack-async-export.feature_enabled.export')) { - Route::crud(config('backpack-async-export.admin_export_route'), 'ExportCrudController'); - } - if (config('backpack-async-export.feature_enabled.import')) { - Route::crud(config('backpack-async-export.admin_import_route'), 'ImportCrudController'); - } -}); diff --git a/routes/backpack/import-export.php b/routes/backpack/import-export.php new file mode 100644 index 0000000..59a17c9 --- /dev/null +++ b/routes/backpack/import-export.php @@ -0,0 +1,13 @@ + 'Thomascombe\BackpackAsyncExport\Http\Controllers\Admin', + 'prefix' => config('backpack.base.route_prefix', 'admin'), + 'middleware' => ['web', backpack_middleware()], +], function () { + if (config('backpack-async-import-export.feature_enabled.export')) { + Route::crud(config('backpack-async-import-export.admin_export_route'), 'ExportCrudController'); + } + if (config('backpack-async-import-export.feature_enabled.import')) { + Route::crud(config('backpack-async-import-export.admin_import_route'), 'ImportCrudController'); + } +}); diff --git a/src/BackpackAsyncExportServiceProvider.php b/src/BackpackAsyncExportServiceProvider.php index e8735ba..fabb091 100644 --- a/src/BackpackAsyncExportServiceProvider.php +++ b/src/BackpackAsyncExportServiceProvider.php @@ -16,10 +16,10 @@ public function configurePackage(Package $package): void */ $package ->name('backpack-async-export') - ->hasConfigFile() + ->hasConfigFile('backpack-async-import-export') ->hasViews() - ->hasMigrations(['create_backpack_async_export_table']) - ->hasRoutes('backpack/export') + ->hasMigrations(['create_backpack_async_import_exports_table']) + ->hasRoutes('backpack/import-export') ->hasTranslations(); } } diff --git a/src/Http/Controllers/Admin/ExportCrudController.php b/src/Http/Controllers/Admin/ExportCrudController.php index 959d9a2..60fe6a7 100644 --- a/src/Http/Controllers/Admin/ExportCrudController.php +++ b/src/Http/Controllers/Admin/ExportCrudController.php @@ -11,7 +11,7 @@ use Illuminate\Support\Facades\Route; use Symfony\Component\HttpFoundation\StreamedResponse; use Thomascombe\BackpackAsyncExport\Enums\ActionType; -use Thomascombe\BackpackAsyncExport\Models\Export; +use Thomascombe\BackpackAsyncExport\Models\ImportExport; /** * Class ExportCrudController @@ -24,8 +24,8 @@ class ExportCrudController extends CrudController public function setup() { - CRUD::setModel(config('backpack-async-export.export_model')); - CRUD::setRoute(sprintf('%s/%s', config('backpack.base.route_prefix'), config('backpack-async-export.admin_export_route'))); + CRUD::setModel(config('backpack-async-import-export.import_export_model')); + CRUD::setRoute(sprintf('%s/%s', config('backpack.base.route_prefix'), config('backpack-async-import-export.admin_export_route'))); CRUD::setEntityNameStrings( __('backpack-async-export::export.name.singular'), __('backpack-async-export::export.name.plurial') @@ -53,7 +53,7 @@ protected function setupListOperation() CRUD::column('completed_at')->label(__('backpack-async-export::export.columns.completed_at')); } - public function download(Export $export): StreamedResponse + public function download(ImportExport $export): StreamedResponse { if (! $export->isReady) { abort(Response::HTTP_NOT_FOUND); @@ -61,7 +61,7 @@ public function download(Export $export): StreamedResponse $fileContent = file_get_contents($export->storagePath); $mimetype = File::mimeType($export->storagePath); - $fileNameExplode = explode('/', $export->{Export::COLUMN_FILENAME}); + $fileNameExplode = explode('/', $export->{ImportExport::COLUMN_FILENAME}); return response()->streamDownload( function () use ($fileContent): void { diff --git a/src/Http/Controllers/Admin/ImportCrudController.php b/src/Http/Controllers/Admin/ImportCrudController.php index 757b747..ecce68c 100644 --- a/src/Http/Controllers/Admin/ImportCrudController.php +++ b/src/Http/Controllers/Admin/ImportCrudController.php @@ -19,11 +19,11 @@ class ImportCrudController extends CrudController public function setup() { - CRUD::setModel(config('backpack-async-export.export_model')); + CRUD::setModel(config('backpack-async-import-export.import_export_model')); CRUD::setRoute(sprintf( '%s/%s', config('backpack.base.route_prefix'), - config('backpack-async-export.admin_import_route') + config('backpack-async-import-export.admin_import_route') )); CRUD::setEntityNameStrings( __('backpack-async-export::import.name.singular'), diff --git a/src/Http/Controllers/Admin/Interfaces/ExportableCrud.php b/src/Http/Controllers/Admin/Interfaces/ExportableCrud.php index 0c63736..d5bec1f 100644 --- a/src/Http/Controllers/Admin/Interfaces/ExportableCrud.php +++ b/src/Http/Controllers/Admin/Interfaces/ExportableCrud.php @@ -2,11 +2,11 @@ namespace Thomascombe\BackpackAsyncExport\Http\Controllers\Admin\Interfaces; -use Thomascombe\BackpackAsyncExport\Models\Export; +use Thomascombe\BackpackAsyncExport\Models\ImportExport; interface ExportableCrud { - public function getExport(): Export; + public function getExport(): ImportExport; public function getExportParameters(): array; } diff --git a/src/Http/Controllers/Admin/Interfaces/ImportableCrud.php b/src/Http/Controllers/Admin/Interfaces/ImportableCrud.php index 8edc225..3b13f8c 100644 --- a/src/Http/Controllers/Admin/Interfaces/ImportableCrud.php +++ b/src/Http/Controllers/Admin/Interfaces/ImportableCrud.php @@ -2,11 +2,11 @@ namespace Thomascombe\BackpackAsyncExport\Http\Controllers\Admin\Interfaces; -use Thomascombe\BackpackAsyncExport\Models\Export; +use Thomascombe\BackpackAsyncExport\Models\ImportExport; interface ImportableCrud { - public function getImport(): Export; + public function getImport(): ImportExport; public function getImportParameters(): array; } diff --git a/src/Http/Controllers/Admin/Traits/HasExportButton.php b/src/Http/Controllers/Admin/Traits/HasExportButton.php index ebaf51a..8d5e6f9 100644 --- a/src/Http/Controllers/Admin/Traits/HasExportButton.php +++ b/src/Http/Controllers/Admin/Traits/HasExportButton.php @@ -45,7 +45,7 @@ protected function setupExportRoutes($segment, $routeName, $controller) { $this->checkInterfaceImplementation(); - Route::get($segment . '/' . config('backpack-async-export.admin_export_route'), [ + Route::get($segment . '/' . config('backpack-async-import-export.admin_export_route'), [ 'as' => $routeName . '.export', 'uses' => $controller . '@export', 'operation' => 'export', @@ -71,7 +71,7 @@ public function export(): RedirectResponse ExportJob::dispatch($exportModel, ...$parameters); \Alert::info(__('backpack-async-export::export.notifications.queued'))->flash(); - return response()->redirectToRoute(config('backpack-async-export.admin_export_route') . '.index'); + return response()->redirectToRoute(config('backpack-async-import-export.admin_export_route') . '.index'); } /** diff --git a/src/Http/Controllers/Admin/Traits/HasImportButton.php b/src/Http/Controllers/Admin/Traits/HasImportButton.php index 818addc..0437779 100644 --- a/src/Http/Controllers/Admin/Traits/HasImportButton.php +++ b/src/Http/Controllers/Admin/Traits/HasImportButton.php @@ -13,7 +13,7 @@ use Thomascombe\BackpackAsyncExport\Http\Controllers\Admin\Interfaces\ImportableCrud; use Thomascombe\BackpackAsyncExport\Http\Requests\ImportRequest; use Thomascombe\BackpackAsyncExport\Jobs\ImportJob; -use Thomascombe\BackpackAsyncExport\Models\Export; +use Thomascombe\BackpackAsyncExport\Models\ImportExport; /** * Trait HasImportButton @@ -42,12 +42,12 @@ protected function setupImportRoutes($segment, $routeName, $controller) { $this->checkInterfaceImplementation(); - Route::get($segment . '/' . config('backpack-async-export.admin_import_route'), [ + Route::get($segment . '/' . config('backpack-async-import-export.admin_import_route'), [ 'as' => $routeName . '.import', 'uses' => $controller . '@import', 'operation' => 'import', ]); - Route::post($segment . '/' . config('backpack-async-export.admin_import_route'), [ + Route::post($segment . '/' . config('backpack-async-import-export.admin_import_route'), [ 'as' => $routeName . '.import-submit', 'uses' => $controller . '@importSubmit', 'operation' => 'import-submit', @@ -91,7 +91,7 @@ public function importSubmit(ImportRequest $request): RedirectResponse { $this->checkInterfaceImplementation(); - /** @var Export $exportModel */ + /** @var ImportExport $exportModel */ $exportModel = $this->{$this->getImportMethodName()}(); $parameters = $this->{$this->getImportParametersMethodName()}(); @@ -108,7 +108,7 @@ public function importSubmit(ImportRequest $request): RedirectResponse ImportJob::dispatch($exportModel, ...$parameters); \Alert::info(__('backpack-async-export::import.notifications.queued'))->flash(); - return response()->redirectToRoute(config('backpack-async-export.admin_import_route') . '.index'); + return response()->redirectToRoute(config('backpack-async-import-export.admin_import_route') . '.index'); } private function checkFileMimetype(ImportRequest $request): array @@ -157,17 +157,17 @@ protected function getImportParametersMethodName(): string return 'getImportParameters'; } - private function saveUploadFile(ImportRequest $request, Export $exportModel): void + private function saveUploadFile(ImportRequest $request, ImportExport $exportModel): void { /** @var UploadedFile $file */ $file = $request->files->get($request::PARAM_FILE); - $filename = sprintf('%s/%s', $exportModel->{Export::COLUMN_FILENAME}, $file->getClientOriginalName()); - Storage::disk($exportModel->{Export::COLUMN_DISK}) + $filename = sprintf('%s/%s', $exportModel->{ImportExport::COLUMN_FILENAME}, $file->getClientOriginalName()); + Storage::disk($exportModel->{ImportExport::COLUMN_DISK}) ->put( $filename, $file->getContent() ); - $exportModel->{Export::COLUMN_FILENAME} = $filename; + $exportModel->{ImportExport::COLUMN_FILENAME} = $filename; $exportModel->save(); } } diff --git a/src/Jobs/ExportJob.php b/src/Jobs/ExportJob.php index 7b4108d..d84d3a2 100644 --- a/src/Jobs/ExportJob.php +++ b/src/Jobs/ExportJob.php @@ -10,7 +10,7 @@ use Illuminate\Support\Facades\Log; use Maatwebsite\Excel\Facades\Excel; use Thomascombe\BackpackAsyncExport\Enums\ExportStatus; -use Thomascombe\BackpackAsyncExport\Models\Export; +use Thomascombe\BackpackAsyncExport\Models\ImportExport; class ExportJob implements ShouldQueue { @@ -19,10 +19,10 @@ class ExportJob implements ShouldQueue use Queueable; use SerializesModels; - private Export $export; + private ImportExport $export; private array $exportParameters; - public function __construct(Export $export, ...$exportParameters) + public function __construct(ImportExport $export, ...$exportParameters) { $this->export = $export; $this->exportParameters = $exportParameters; @@ -31,29 +31,29 @@ public function __construct(Export $export, ...$exportParameters) public function handle() { $this->export->update([ - Export::COLUMN_STATUS => ExportStatus::Processing, + ImportExport::COLUMN_STATUS => ExportStatus::Processing, ]); try { - ini_set('memory_limit', config('backpack-async-export.export_memory_limit')); - $exportClass = $this->export->{Export::COLUMN_EXPORT_TYPE}; + ini_set('memory_limit', config('backpack-async-import-export.export_memory_limit')); + $exportClass = $this->export->{ImportExport::COLUMN_EXPORT_TYPE}; Excel::store( new $exportClass(...$this->exportParameters), - $this->export->{Export::COLUMN_FILENAME}, - config('backpack-async-export.disk') + $this->export->{ImportExport::COLUMN_FILENAME}, + config('backpack-async-import-export.disk') ); - $this->export->{Export::COLUMN_STATUS} = ExportStatus::Successful; + $this->export->{ImportExport::COLUMN_STATUS} = ExportStatus::Successful; $this->export->save(); $this->export->update([ - Export::COLUMN_STATUS => ExportStatus::Successful, - Export::COLUMN_COMPLETED_AT => now(), + ImportExport::COLUMN_STATUS => ExportStatus::Successful, + ImportExport::COLUMN_COMPLETED_AT => now(), ]); } catch (\Exception | \Throwable $exception) { $this->export->update([ - Export::COLUMN_STATUS => ExportStatus::Error, - Export::COLUMN_ERROR => $exception->getMessage(), + ImportExport::COLUMN_STATUS => ExportStatus::Error, + ImportExport::COLUMN_ERROR => $exception->getMessage(), ]); Log::error(__('backpack-async-export::export.errors.global-export'), ['exception' => $exception]); } diff --git a/src/Jobs/ImportJob.php b/src/Jobs/ImportJob.php index e5874ee..6dbd670 100644 --- a/src/Jobs/ImportJob.php +++ b/src/Jobs/ImportJob.php @@ -12,7 +12,7 @@ use Maatwebsite\Excel\Facades\Excel; use Thomascombe\BackpackAsyncExport\Enums\ActionType; use Thomascombe\BackpackAsyncExport\Enums\ExportStatus; -use Thomascombe\BackpackAsyncExport\Models\Export; +use Thomascombe\BackpackAsyncExport\Models\ImportExport; class ImportJob implements ShouldQueue { @@ -21,10 +21,10 @@ class ImportJob implements ShouldQueue use Queueable; use SerializesModels; - private Export $export; + private ImportExport $export; private array $exportParameters; - public function __construct(Export $export, ...$exportParameters) + public function __construct(ImportExport $export, ...$exportParameters) { $this->export = $export; $this->exportParameters = $exportParameters; @@ -35,42 +35,42 @@ public function handle() if ($this->export->action_type !== ActionType::Import) { $message = sprintf('Import of type "%s" try to be import', $this->export->action_type); $this->export->update([ - Export::COLUMN_STATUS => ExportStatus::Error, - Export::COLUMN_ERROR => $message, + ImportExport::COLUMN_STATUS => ExportStatus::Error, + ImportExport::COLUMN_ERROR => $message, ]); Log::error($message); return; } $this->export->update([ - Export::COLUMN_STATUS => ExportStatus::Processing, + ImportExport::COLUMN_STATUS => ExportStatus::Processing, ]); try { - ini_set('memory_limit', config('backpack-async-export.export_memory_limit')); - $exportClass = $this->export->{Export::COLUMN_EXPORT_TYPE}; + ini_set('memory_limit', config('backpack-async-import-export.export_memory_limit')); + $exportClass = $this->export->{ImportExport::COLUMN_EXPORT_TYPE}; unset($this->exportParameters['private']); Excel::import( new $exportClass(...$this->exportParameters), - $this->export->{Export::COLUMN_FILENAME}, - config('backpack-async-export.disk') + $this->export->{ImportExport::COLUMN_FILENAME}, + config('backpack-async-import-export.disk') ); - $this->export->{Export::COLUMN_STATUS} = ExportStatus::Successful; + $this->export->{ImportExport::COLUMN_STATUS} = ExportStatus::Successful; $this->export->save(); $this->export->update([ - Export::COLUMN_STATUS => ExportStatus::Successful, - Export::COLUMN_COMPLETED_AT => now(), + ImportExport::COLUMN_STATUS => ExportStatus::Successful, + ImportExport::COLUMN_COMPLETED_AT => now(), ]); } catch (\Exception | \Throwable $exception) { $this->export->update([ - Export::COLUMN_STATUS => ExportStatus::Error, - Export::COLUMN_ERROR => $exception->getMessage(), + ImportExport::COLUMN_STATUS => ExportStatus::Error, + ImportExport::COLUMN_ERROR => $exception->getMessage(), ]); Log::error(__('backpack-async-export::import.errors.global-export'), ['exception' => $exception]); } finally { - Storage::disk($this->export->{Export::COLUMN_DISK})->delete($this->export->{Export::COLUMN_FILENAME}); + Storage::disk($this->export->{ImportExport::COLUMN_DISK})->delete($this->export->{ImportExport::COLUMN_FILENAME}); } } } diff --git a/src/Models/Export.php b/src/Models/ImportExport.php similarity index 84% rename from src/Models/Export.php rename to src/Models/ImportExport.php index a818e1c..2f6f3f7 100644 --- a/src/Models/Export.php +++ b/src/Models/ImportExport.php @@ -9,9 +9,10 @@ use Illuminate\Support\Facades\Storage; use Thomascombe\BackpackAsyncExport\Enums\ExportStatus; use Thomascombe\BackpackAsyncExport\Exports\ExportWithName; -use Thomascombe\BackpackAsyncExport\Models\Interfaces\ExportInterface; +use Thomascombe\BackpackAsyncExport\Models\Interfaces\ImportExportInterface; -class Export extends Model implements ExportInterface +class +ImportExport extends Model implements ImportExportInterface { use CrudTrait; use SoftDeletes; @@ -46,15 +47,15 @@ class Export extends Model implements ExportInterface public function user(): BelongsTo { - return $this->belongsTo(config('backpack-async-export.user_model')); + return $this->belongsTo(config('backpack-async-import-export.user_model')); } protected static function boot() { parent::boot(); - Export::saving(function (Export $export) { + ImportExport::saving(function (ImportExport $export) { if (empty($export->attributes[self::COLUMN_DISK])) { - $export->attributes[self::COLUMN_DISK] = config('backpack-async-export.disk', 'local'); + $export->attributes[self::COLUMN_DISK] = config('backpack-async-import-export.disk', 'local'); } }); } @@ -71,7 +72,7 @@ public function getExportTypeNameAttribute(): string public function getDiskAttribute(): string { - return $this->attributes[self::COLUMN_DISK] ?? config('backpack-async-export.disk', 'local'); + return $this->attributes[self::COLUMN_DISK] ?? config('backpack-async-import-export.disk', 'local'); } public function getStoragePathAttribute(): string @@ -86,7 +87,7 @@ public function getDownloadButton(): string { if ($this->isReady) { $url = route( - config('backpack-async-export.admin_export_route') . '.download', + config('backpack-async-import-export.admin_export_route') . '.download', [ 'export' => $this->id, ] @@ -107,7 +108,7 @@ public function getDownloadButton(): string public function getIsReadyAttribute(): bool { - return ExportStatus::Successful === $this->{Export::COLUMN_STATUS} + return ExportStatus::Successful === $this->{ImportExport::COLUMN_STATUS} && Storage::disk($this->disk)->exists($this->{self::COLUMN_FILENAME}); } } diff --git a/src/Models/Interfaces/ExportInterface.php b/src/Models/Interfaces/ImportExportInterface.php similarity index 69% rename from src/Models/Interfaces/ExportInterface.php rename to src/Models/Interfaces/ImportExportInterface.php index 7ae2c16..ba15d46 100644 --- a/src/Models/Interfaces/ExportInterface.php +++ b/src/Models/Interfaces/ImportExportInterface.php @@ -2,6 +2,6 @@ namespace Thomascombe\BackpackAsyncExport\Models\Interfaces; -interface ExportInterface +interface ImportExportInterface { } From 65283574f3f284253ab32ca2c38d10e16de88f17 Mon Sep 17 00:00:00 2001 From: thomascombe Date: Fri, 11 Feb 2022 09:17:26 +0100 Subject: [PATCH 9/9] Allow Laravel 9 and Backpack 5 --- composer.json | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index feaba78..9790afe 100644 --- a/composer.json +++ b/composer.json @@ -19,8 +19,8 @@ ], "require": { "php": "^7.4|^8.0", - "backpack/crud": "4.1.*", - "illuminate/contracts": "^6.0|^7.0|^8.0", + "backpack/crud": "4.1.*|~5.0", + "illuminate/contracts": "^6.0|^7.0|^8.0|^9.0", "maatwebsite/excel": "^3.1", "thomascombe/laravel-package-tools": "^1.7" }, @@ -49,7 +49,10 @@ "test-coverage": "vendor/bin/phpunit --coverage-html coverage" }, "config": { - "sort-packages": true + "sort-packages": true, + "allow-plugins": { + "composer/package-versions-deprecated": true + } }, "extra": { "laravel": {