From 9727f83f8eb48ec644abbc0822ccfe85a209b846 Mon Sep 17 00:00:00 2001 From: Pedro X Date: Mon, 16 Jan 2023 22:37:58 +0000 Subject: [PATCH 01/16] add media library --- .../Admin/ProductCrudController.php | 70 ++++++ app/Models/Product.php | 222 +++++++++++++++++- composer.json | 3 +- config/filesystems.php | 11 + ...017_12_19_081247_create_products_table.php | 2 + .../2023_01_16_123511_create_media_table.php | 37 +++ 6 files changed, 342 insertions(+), 3 deletions(-) create mode 100644 database/migrations/2023_01_16_123511_create_media_table.php diff --git a/app/Http/Controllers/Admin/ProductCrudController.php b/app/Http/Controllers/Admin/ProductCrudController.php index 07bad913e..d8b2f64d2 100644 --- a/app/Http/Controllers/Admin/ProductCrudController.php +++ b/app/Http/Controllers/Admin/ProductCrudController.php @@ -206,6 +206,76 @@ protected function setupCreateOperation() ], ]); + CRUD::addField([ + 'name' => 'main_image', + 'label' => 'Main Image', + 'type' => 'image', + 'disk' => 'products', + 'tab' => 'Product Media', + 'wrapper' => [ + 'class' => 'form-group col-md-3', + ], + ]); + + CRUD::addField([ + 'name' => 'secondary_image', + 'label' => 'Secondary Image', + 'type' => 'image', + 'disk' => 'products', + 'tab' => 'Product Media', + 'wrapper' => [ + 'class' => 'form-group col-md-3', + ], + ]); + + CRUD::addField([ + 'name' => 'specifications', + 'type' => 'upload_multiple', + 'disk' => 'products', + 'upload' => true, + 'tab' => 'Product Media', + 'wrapper' => [ + 'class' => 'form-group col-md-3', + ], + ]); + + CRUD::addField([ + 'name' => 'image_drm', + 'label' => 'Image DRM', + 'type' => 'upload', + 'disk' => 'products', + 'tab' => 'Product Media', + 'upload' => true, + 'wrapper' => [ + 'class' => 'form-group col-md-3', + ], + ]); + + CRUD::addField([ + 'name' => 'gallery', + 'type' => 'repeatable', + 'tab' => 'Product Media', + 'subfields' => [ + [ + 'name' => 'image_title', + 'type' => 'text', + 'wrapper' => [ + 'class' => 'form-group col-md-6', + ], + ], + [ + 'name' => 'image', + 'type' => 'image', + 'disk' => 'products', + 'wrapper' => [ + 'class' => 'form-group col-md-6', + ], + ], + ] + ]); + + + $this->crud->setOperationSetting('contentClass', 'col-md-12'); } diff --git a/app/Models/Product.php b/app/Models/Product.php index 8a2cf75ef..7077bda0b 100644 --- a/app/Models/Product.php +++ b/app/Models/Product.php @@ -7,12 +7,15 @@ use Backpack\CRUD\app\Models\Traits\SpatieTranslatable\HasTranslations; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; +use Spatie\MediaLibrary\HasMedia; +use Spatie\MediaLibrary\InteractsWithMedia; -class Product extends Model +class Product extends Model implements HasMedia { use CrudTrait; use HasTranslations; use HasFactory; + use InteractsWithMedia; /* |-------------------------------------------------------------------------- @@ -24,7 +27,7 @@ class Product extends Model protected $primaryKey = 'id'; public $timestamps = true; // protected $guarded = ['id']; - protected $fillable = ['name', 'description', 'details', 'features', 'price', 'category_id', 'extras', 'status', 'condition']; + protected $fillable = ['name', 'description', 'details', 'features', 'price', 'category_id', 'extras', 'status', 'condition', 'main_image', 'secondary_image', 'specifications', 'image_drm', 'gallery']; // protected $hidden = []; // protected $dates = []; public $translatable = ['name', 'description', 'details', 'features', 'extras']; @@ -34,12 +37,227 @@ class Product extends Model 'status' => ProductStatus::class, ]; + public static function boot() { + parent::boot(); + // since we don't have this fields in the model, we remove them before saving. + static::saving(function ($model) { + + unset($model->attributes['secondary_image']); + unset($model->attributes['specifications']); + + unset($model->attributeCastCache['image_drm']); + unset($model->attributes['image_drm']); + }); + } + /* |-------------------------------------------------------------------------- | FUNCTIONS |-------------------------------------------------------------------------- */ + public function secondaryImage(): \Illuminate\Database\Eloquent\Casts\Attribute + { + return \Illuminate\Database\Eloquent\Casts\Attribute::make( + get: function ($value, $attributes) { + $image = $this->getFirstMedia('product_images', function($media) { return $media->name === 'secondary_image'; }); + return $image ? $image->getUrl() : null; + }, + set: function ($value) { + $previousImage = $this->getFirstMedia('product_images', function ($media) { + return $media->name === 'secondary_image'; + }); + + if ($value) { + if ($previousImage && \Str::startsWith($value, 'data:image')) { + $previousImage->delete(); + } + if (\Str::startsWith($value, 'data:image')) { + $extension = '.'.\Str::after(mime_content_type($value), '/'); + $this + ->addMediaFromBase64($value) + ->usingName('secondary_image') + ->usingFileName('secondary_image'.$extension) + ->toMediaCollection('product_images', 'products'); + } + return; + } + + if ($previousImage) { + $previousImage->delete(); + } + } + ); + } + public function mainImage(): \Illuminate\Database\Eloquent\Casts\Attribute + { + return \Illuminate\Database\Eloquent\Casts\Attribute::make( + get: function () { + $image = $this->getFirstMedia('product_images', function($media) { return $media->name === 'main_image'; }); + return $image ? $image->getUrl() : null; + }, + set: function ($value) { + $previousImage = $this->getFirstMedia('product_images', function ($media) { + return $media->name === 'main_image'; + }); + + if ($value) { + + if ($previousImage && \Str::startsWith($value, 'data:image')) { + $previousImage->delete(); + } + if (\Str::startsWith($value, 'data:image')) { + $extension = '.'.\Str::after(mime_content_type($value), '/'); + $uploadedMedia = $this + ->addMediaFromBase64($value) + ->usingName('main_image') + ->usingFileName('main_image'.$extension) + ->toMediaCollection('product_images', 'products'); + } + return $uploadedMedia->id ?? $previousImage->id; + } + + if ($previousImage) { + $previousImage->delete(); + } + + } + ); + } + + public function specifications(): \Illuminate\Database\Eloquent\Casts\Attribute + { + return \Illuminate\Database\Eloquent\Casts\Attribute::make( + get: function () { + return $this + ->getMedia('product_documents', function($media) { return $media->name === 'specification_document'; }) + ->map(function($media) { + + return \Str::after($media->getUrl(), \Storage::disk('products')->url('')); + + }) + ->toArray(); + }, + set: function ($value) { + $filesToDelete = request()->get('clear_specifications'); + + $previousImages = $this->getMedia('product_documents', function ($media) { + return $media->name === 'specification_document'; + }); + + if ($filesToDelete) { + foreach ($previousImages as $previousImage) { + $storageBasePath = \Storage::disk('products')->url(''); + if (in_array(\Str::after($previousImage->getUrl(), $storageBasePath), $filesToDelete)) { + $previousImage->delete(); + } + } + } + + foreach ($value ?? [] as $file) { + if (is_file($file)) { + $this + ->addMedia($file) + ->usingName('specification_document') + ->toMediaCollection('product_documents', 'products'); + } + } + } + ); + } + + public function imageDrm(): \Illuminate\Database\Eloquent\Casts\Attribute + { + return \Illuminate\Database\Eloquent\Casts\Attribute::make( + get: function () { + $drm = $this->getFirstMedia('product_documents', function($media) { return $media->name === 'image_drm'; }); + return !empty($drm) ? $drm->getUrl() : null; + }, + set: function ($value) { + + $previousDocument = $this->getFirstMedia('product_documents', function($media) { return $media->name === 'image_drm'; }); + + if ($previousDocument && (!$value || is_file($value))) { + $previousDocument->delete(); + } + + if (is_file($value)) { + $this + ->addMedia($value) + ->usingName('image_drm') + ->toMediaCollection('product_documents', 'products'); + } + }, + ); + } + + public function gallery(): \Illuminate\Database\Eloquent\Casts\Attribute + { + return \Illuminate\Database\Eloquent\Casts\Attribute::make( + get: function ($value) { + $galleryImages = $this + ->getMedia('product_images', function($media) { return $media->name === 'gallery_image'; }) + ->transform(function($media, $key) { + $origin = substr(\Storage::disk('products')->url('/'), 0, -1); + return ['image' => str_replace($origin, '', $media->getUrl()), 'repeatableRow' => $media->getCustomProperty('repeatableRow')]; + })->sortBy('repeatableRow')->keyBy('repeatableRow')->toArray(); + + $value = json_decode($value, true) ?? []; + return array_merge_recursive_distinct($value, $galleryImages); + + }, + set: function ($value) { + + $galleryImages = $this->getMedia('product_images', function($media) { return $media->name === 'gallery_image'; }); + + $sentImages = collect($value) + ->pluck('image') + ->map(function($image) { + if(!\Str::startsWith($image, 'data:image')) { + return \Str::afterLast(\Str::beforeLast($image, '/'), '/').'/'.\Str::afterLast($image, '/'); + } + return $image; + }) + ->toArray(); + + foreach ($sentImages as $row => $image) { + if (is_string($image)) { + if (\Str::startsWith($image, 'data:image')) { + $extension = '.'.\Str::after(mime_content_type($image), '/'); + $this + ->addMediaFromBase64($image) + ->usingName('gallery_image') + ->usingFileName(\Str::random().$extension) + ->withCustomProperties(['repeatableRow' => $row]) + ->preservingOriginal() + ->toMediaCollection('product_images', 'products'); + + unset($value[$row]['image']); + continue; + } + $currentImageGallery = $galleryImages->where('id', \Str::before($image, '/'))->where('file_name', \Str::after($image, '/'))->first(); + if ($currentImageGallery) { + if ($currentImageGallery->getCustomProperty('repeatableRow') !== $row) { + $currentImageGallery->setCustomProperty('repeatableRow', $row); + $currentImageGallery->save(); + } + unset($value[$row]['image']); + } + } + } + + foreach($galleryImages as $media) { + $mediaIdentifier = $media->id.'/'.$media->file_name; + if(!in_array($mediaIdentifier, $sentImages)) { + $media->delete(); + } + } + + return json_encode($value); + }, + ); + } + /* |-------------------------------------------------------------------------- | RELATIONS diff --git a/composer.json b/composer.json index b1791fd74..81004e0ee 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,8 @@ "mews/purifier": "^3.3", "backpack/filemanager": "^2.0", "backpack/backupmanager": "^3.0", - "backpack/editable-columns": "^2.0" + "backpack/editable-columns": "^2.0", + "spatie/laravel-medialibrary": "^10.7" }, "require-dev": { "fakerphp/faker": "~1.4", diff --git a/config/filesystems.php b/config/filesystems.php index 0e5cf8131..b8c7eaf55 100644 --- a/config/filesystems.php +++ b/config/filesystems.php @@ -65,6 +65,13 @@ 'root' => public_path('uploads'), ], + 'products' => [ // used for demonstration purposes on Products controler + 'driver' => 'local', + 'root' => storage_path('app/public/products'), + 'url' => '/products', + 'visibility' => 'public' + ], + 'backups' => [ // used for Backpack/BackupManager 'driver' => 'local', 'root' => storage_path('backups'), // that's where your backups are stored by default: storage/backups @@ -84,5 +91,9 @@ ], ], + 'links' => [ + public_path('storage') => storage_path('app/public'), + public_path('products') => storage_path('app/public/products'), + ], ]; diff --git a/database/migrations/2017_12_19_081247_create_products_table.php b/database/migrations/2017_12_19_081247_create_products_table.php index 94fec805a..55191de3d 100644 --- a/database/migrations/2017_12_19_081247_create_products_table.php +++ b/database/migrations/2017_12_19_081247_create_products_table.php @@ -20,6 +20,8 @@ public function up() $table->json('features')->nullable(); $table->integer('price'); $table->integer('category_id'); + $table->text('main_image')->nullable(); + $table->json('gallery')->nullable(); $table->json('extras')->nullable(); $table->timestamps(); }); diff --git a/database/migrations/2023_01_16_123511_create_media_table.php b/database/migrations/2023_01_16_123511_create_media_table.php new file mode 100644 index 000000000..9981f7ee0 --- /dev/null +++ b/database/migrations/2023_01_16_123511_create_media_table.php @@ -0,0 +1,37 @@ +bigIncrements('id'); + + $table->morphs('model'); + $table->uuid('uuid')->nullable()->unique(); + $table->string('collection_name'); + $table->string('name'); + $table->string('file_name'); + $table->string('mime_type')->nullable(); + $table->string('disk'); + $table->string('conversions_disk')->nullable(); + $table->unsignedBigInteger('size'); + $table->json('manipulations'); + $table->json('custom_properties'); + $table->json('generated_conversions'); + $table->json('responsive_images'); + $table->unsignedInteger('order_column')->nullable()->index(); + + $table->nullableTimestamps(); + }); + } + + public function down(): void + { + Schema::dropIfExists('media'); + } +}; From 7f28b5016f598e29f16e0f81129c4c3fd0b83d3c Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Mon, 16 Jan 2023 22:38:14 +0000 Subject: [PATCH 02/16] Apply fixes from StyleCI --- .../Admin/ProductCrudController.php | 52 +++++++------- app/Models/Product.php | 72 ++++++++++--------- config/filesystems.php | 10 +-- .../2023_01_16_123511_create_media_table.php | 3 +- 4 files changed, 68 insertions(+), 69 deletions(-) diff --git a/app/Http/Controllers/Admin/ProductCrudController.php b/app/Http/Controllers/Admin/ProductCrudController.php index d8b2f64d2..22484c575 100644 --- a/app/Http/Controllers/Admin/ProductCrudController.php +++ b/app/Http/Controllers/Admin/ProductCrudController.php @@ -229,52 +229,50 @@ protected function setupCreateOperation() ]); CRUD::addField([ - 'name' => 'specifications', - 'type' => 'upload_multiple', - 'disk' => 'products', - 'upload' => true, - 'tab' => 'Product Media', + 'name' => 'specifications', + 'type' => 'upload_multiple', + 'disk' => 'products', + 'upload' => true, + 'tab' => 'Product Media', 'wrapper' => [ 'class' => 'form-group col-md-3', ], ]); CRUD::addField([ - 'name' => 'image_drm', - 'label' => 'Image DRM', - 'type' => 'upload', - 'disk' => 'products', - 'tab' => 'Product Media', - 'upload' => true, - 'wrapper' => [ - 'class' => 'form-group col-md-3', - ], - ]); - + 'name' => 'image_drm', + 'label' => 'Image DRM', + 'type' => 'upload', + 'disk' => 'products', + 'tab' => 'Product Media', + 'upload' => true, + 'wrapper' => [ + 'class' => 'form-group col-md-3', + ], + ]); + CRUD::addField([ - 'name' => 'gallery', - 'type' => 'repeatable', - 'tab' => 'Product Media', + 'name' => 'gallery', + 'type' => 'repeatable', + 'tab' => 'Product Media', 'subfields' => [ [ - 'name' => 'image_title', - 'type' => 'text', + 'name' => 'image_title', + 'type' => 'text', 'wrapper' => [ 'class' => 'form-group col-md-6', ], ], [ - 'name' => 'image', - 'type' => 'image', - 'disk' => 'products', + 'name' => 'image', + 'type' => 'image', + 'disk' => 'products', 'wrapper' => [ 'class' => 'form-group col-md-6', ], ], - ] + ], ]); - - $this->crud->setOperationSetting('contentClass', 'col-md-12'); } diff --git a/app/Models/Product.php b/app/Models/Product.php index 7077bda0b..698eb7efa 100644 --- a/app/Models/Product.php +++ b/app/Models/Product.php @@ -37,16 +37,16 @@ class Product extends Model implements HasMedia 'status' => ProductStatus::class, ]; - public static function boot() { + public static function boot() + { parent::boot(); // since we don't have this fields in the model, we remove them before saving. static::saving(function ($model) { - unset($model->attributes['secondary_image']); unset($model->attributes['specifications']); unset($model->attributeCastCache['image_drm']); - unset($model->attributes['image_drm']); + unset($model->attributes['image_drm']); }); } @@ -60,9 +60,10 @@ public function secondaryImage(): \Illuminate\Database\Eloquent\Casts\Attribute { return \Illuminate\Database\Eloquent\Casts\Attribute::make( get: function ($value, $attributes) { - $image = $this->getFirstMedia('product_images', function($media) { return $media->name === 'secondary_image'; }); + $image = $this->getFirstMedia('product_images', function ($media) { return $media->name === 'secondary_image'; }); + return $image ? $image->getUrl() : null; - }, + }, set: function ($value) { $previousImage = $this->getFirstMedia('product_images', function ($media) { return $media->name === 'secondary_image'; @@ -80,6 +81,7 @@ public function secondaryImage(): \Illuminate\Database\Eloquent\Casts\Attribute ->usingFileName('secondary_image'.$extension) ->toMediaCollection('product_images', 'products'); } + return; } @@ -89,20 +91,21 @@ public function secondaryImage(): \Illuminate\Database\Eloquent\Casts\Attribute } ); } + public function mainImage(): \Illuminate\Database\Eloquent\Casts\Attribute { return \Illuminate\Database\Eloquent\Casts\Attribute::make( get: function () { - $image = $this->getFirstMedia('product_images', function($media) { return $media->name === 'main_image'; }); + $image = $this->getFirstMedia('product_images', function ($media) { return $media->name === 'main_image'; }); + return $image ? $image->getUrl() : null; - }, + }, set: function ($value) { $previousImage = $this->getFirstMedia('product_images', function ($media) { return $media->name === 'main_image'; }); if ($value) { - if ($previousImage && \Str::startsWith($value, 'data:image')) { $previousImage->delete(); } @@ -114,13 +117,13 @@ public function mainImage(): \Illuminate\Database\Eloquent\Casts\Attribute ->usingFileName('main_image'.$extension) ->toMediaCollection('product_images', 'products'); } + return $uploadedMedia->id ?? $previousImage->id; } if ($previousImage) { $previousImage->delete(); } - } ); } @@ -130,17 +133,15 @@ public function specifications(): \Illuminate\Database\Eloquent\Casts\Attribute return \Illuminate\Database\Eloquent\Casts\Attribute::make( get: function () { return $this - ->getMedia('product_documents', function($media) { return $media->name === 'specification_document'; }) - ->map(function($media) { - + ->getMedia('product_documents', function ($media) { return $media->name === 'specification_document'; }) + ->map(function ($media) { return \Str::after($media->getUrl(), \Storage::disk('products')->url('')); - }) ->toArray(); }, set: function ($value) { $filesToDelete = request()->get('clear_specifications'); - + $previousImages = $this->getMedia('product_documents', function ($media) { return $media->name === 'specification_document'; }); @@ -170,19 +171,19 @@ public function imageDrm(): \Illuminate\Database\Eloquent\Casts\Attribute { return \Illuminate\Database\Eloquent\Casts\Attribute::make( get: function () { - $drm = $this->getFirstMedia('product_documents', function($media) { return $media->name === 'image_drm'; }); + $drm = $this->getFirstMedia('product_documents', function ($media) { return $media->name === 'image_drm'; }); + return !empty($drm) ? $drm->getUrl() : null; }, set: function ($value) { - - $previousDocument = $this->getFirstMedia('product_documents', function($media) { return $media->name === 'image_drm'; }); - + $previousDocument = $this->getFirstMedia('product_documents', function ($media) { return $media->name === 'image_drm'; }); + if ($previousDocument && (!$value || is_file($value))) { $previousDocument->delete(); } if (is_file($value)) { - $this + $this ->addMedia($value) ->usingName('image_drm') ->toMediaCollection('product_documents', 'products'); @@ -196,30 +197,31 @@ public function gallery(): \Illuminate\Database\Eloquent\Casts\Attribute return \Illuminate\Database\Eloquent\Casts\Attribute::make( get: function ($value) { $galleryImages = $this - ->getMedia('product_images', function($media) { return $media->name === 'gallery_image'; }) - ->transform(function($media, $key) { + ->getMedia('product_images', function ($media) { return $media->name === 'gallery_image'; }) + ->transform(function ($media, $key) { $origin = substr(\Storage::disk('products')->url('/'), 0, -1); - return ['image' => str_replace($origin, '', $media->getUrl()), 'repeatableRow' => $media->getCustomProperty('repeatableRow')]; + + return ['image' => str_replace($origin, '', $media->getUrl()), 'repeatableRow' => $media->getCustomProperty('repeatableRow')]; })->sortBy('repeatableRow')->keyBy('repeatableRow')->toArray(); - + $value = json_decode($value, true) ?? []; + return array_merge_recursive_distinct($value, $galleryImages); - }, set: function ($value) { - - $galleryImages = $this->getMedia('product_images', function($media) { return $media->name === 'gallery_image'; }); + $galleryImages = $this->getMedia('product_images', function ($media) { return $media->name === 'gallery_image'; }); $sentImages = collect($value) ->pluck('image') - ->map(function($image) { - if(!\Str::startsWith($image, 'data:image')) { + ->map(function ($image) { + if (!\Str::startsWith($image, 'data:image')) { return \Str::afterLast(\Str::beforeLast($image, '/'), '/').'/'.\Str::afterLast($image, '/'); } + return $image; }) ->toArray(); - + foreach ($sentImages as $row => $image) { if (is_string($image)) { if (\Str::startsWith($image, 'data:image')) { @@ -238,21 +240,21 @@ public function gallery(): \Illuminate\Database\Eloquent\Casts\Attribute $currentImageGallery = $galleryImages->where('id', \Str::before($image, '/'))->where('file_name', \Str::after($image, '/'))->first(); if ($currentImageGallery) { if ($currentImageGallery->getCustomProperty('repeatableRow') !== $row) { - $currentImageGallery->setCustomProperty('repeatableRow', $row); + $currentImageGallery->setCustomProperty('repeatableRow', $row); $currentImageGallery->save(); } unset($value[$row]['image']); } } } - - foreach($galleryImages as $media) { + + foreach ($galleryImages as $media) { $mediaIdentifier = $media->id.'/'.$media->file_name; - if(!in_array($mediaIdentifier, $sentImages)) { + if (!in_array($mediaIdentifier, $sentImages)) { $media->delete(); - } + } } - + return json_encode($value); }, ); diff --git a/config/filesystems.php b/config/filesystems.php index b8c7eaf55..8164a343a 100644 --- a/config/filesystems.php +++ b/config/filesystems.php @@ -66,10 +66,10 @@ ], 'products' => [ // used for demonstration purposes on Products controler - 'driver' => 'local', - 'root' => storage_path('app/public/products'), - 'url' => '/products', - 'visibility' => 'public' + 'driver' => 'local', + 'root' => storage_path('app/public/products'), + 'url' => '/products', + 'visibility' => 'public', ], 'backups' => [ // used for Backpack/BackupManager @@ -92,7 +92,7 @@ ], 'links' => [ - public_path('storage') => storage_path('app/public'), + public_path('storage') => storage_path('app/public'), public_path('products') => storage_path('app/public/products'), ], diff --git a/database/migrations/2023_01_16_123511_create_media_table.php b/database/migrations/2023_01_16_123511_create_media_table.php index 9981f7ee0..fe4ffe152 100644 --- a/database/migrations/2023_01_16_123511_create_media_table.php +++ b/database/migrations/2023_01_16_123511_create_media_table.php @@ -4,8 +4,7 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -return new class extends Migration -{ +return new class() extends Migration { public function up(): void { Schema::create('media', function (Blueprint $table) { From 28d0911fa77a93078e644a508ac5d5631f532dc9 Mon Sep 17 00:00:00 2001 From: Pedro X Date: Wed, 22 Feb 2023 20:24:33 +0000 Subject: [PATCH 03/16] add media library example --- .../Admin/ProductCrudController.php | 121 +++++---- app/Models/Product.php | 225 +---------------- composer.json | 10 +- config/media-library.php | 237 ++++++++++++++++++ ...017_12_19_081247_create_products_table.php | 1 - ... 2023_02_22_191429_create_media_table.php} | 5 +- 6 files changed, 313 insertions(+), 286 deletions(-) create mode 100644 config/media-library.php rename database/migrations/{2023_01_16_123511_create_media_table.php => 2023_02_22_191429_create_media_table.php} (92%) diff --git a/app/Http/Controllers/Admin/ProductCrudController.php b/app/Http/Controllers/Admin/ProductCrudController.php index 22484c575..20e907d6d 100644 --- a/app/Http/Controllers/Admin/ProductCrudController.php +++ b/app/Http/Controllers/Admin/ProductCrudController.php @@ -206,73 +206,70 @@ protected function setupCreateOperation() ], ]); - CRUD::addField([ - 'name' => 'main_image', - 'label' => 'Main Image', - 'type' => 'image', - 'disk' => 'products', - 'tab' => 'Product Media', - 'wrapper' => [ - 'class' => 'form-group col-md-3', - ], - ]); + CRUD::field('main_image') + ->label('Main Image') + ->type('image') + ->tab('Product Media') + ->wrapper(['class' => 'form-group col-md-4']) + ->withMedia(); - CRUD::addField([ - 'name' => 'secondary_image', - 'label' => 'Secondary Image', - 'type' => 'image', - 'disk' => 'products', - 'tab' => 'Product Media', - 'wrapper' => [ - 'class' => 'form-group col-md-3', - ], - ]); + CRUD::field('privacy_policy') + ->label('Privacy policy document') + ->type('upload') + ->tab('Product Media') + ->upload(true) + ->wrapper(['class' => 'form-group col-md-4']) + ->withMedia(); - CRUD::addField([ - 'name' => 'specifications', - 'type' => 'upload_multiple', - 'disk' => 'products', - 'upload' => true, - 'tab' => 'Product Media', - 'wrapper' => [ - 'class' => 'form-group col-md-3', - ], - ]); + CRUD::field('product_specifications') + ->label('Specifications') + ->type('upload_multiple') + ->tab('Product Media') + ->upload(true) + ->wrapper(['class' => 'form-group col-md-4']) + ->withMedia(); - CRUD::addField([ - 'name' => 'image_drm', - 'label' => 'Image DRM', - 'type' => 'upload', - 'disk' => 'products', - 'tab' => 'Product Media', - 'upload' => true, - 'wrapper' => [ - 'class' => 'form-group col-md-3', - ], - ]); - - CRUD::addField([ - 'name' => 'gallery', - 'type' => 'repeatable', - 'tab' => 'Product Media', - 'subfields' => [ - [ - 'name' => 'image_title', - 'type' => 'text', - 'wrapper' => [ - 'class' => 'form-group col-md-6', + CRUD::field('gallery') + ->type('repeatable') + ->tab('Product Media') + ->subfields([ + [ + 'name' => 'image_title', + 'type' => 'text', + 'wrapper' => [ + 'class' => 'form-group col-md-6', + ], ], - ], - [ - 'name' => 'image', - 'type' => 'image', - 'disk' => 'products', - 'wrapper' => [ - 'class' => 'form-group col-md-6', + [ + 'name' => 'gallery_image', + 'label' => 'image', + 'type' => 'image', + 'wrapper' => [ + 'class' => 'form-group col-md-6', + ], + 'withMedia' => true, ], - ], - ], - ]); + [ + 'name' => 'gallery_image_drm', + 'label' => 'Image DRM', + 'type' => 'upload', + 'wrapper' => [ + 'class' => 'form-group col-md-6', + ], + 'withMedia' => true, + ], + [ + 'name' => 'gallery_image_specifications', + 'label' => 'Image Specifications', + 'type' => 'upload_multiple', + 'wrapper' => [ + 'class' => 'form-group col-md-6', + ], + 'withMedia' => true, + ], + + ]) + ->withMedia(); $this->crud->setOperationSetting('contentClass', 'col-md-12'); } diff --git a/app/Models/Product.php b/app/Models/Product.php index 698eb7efa..2c93d8a4c 100644 --- a/app/Models/Product.php +++ b/app/Models/Product.php @@ -24,242 +24,31 @@ class Product extends Model implements HasMedia */ protected $table = 'products'; + protected $primaryKey = 'id'; + public $timestamps = true; + // protected $guarded = ['id']; - protected $fillable = ['name', 'description', 'details', 'features', 'price', 'category_id', 'extras', 'status', 'condition', 'main_image', 'secondary_image', 'specifications', 'image_drm', 'gallery']; + protected $fillable = ['name', 'description', 'details', 'features', 'price', 'category_id', 'extras', 'status', 'condition', 'gallery']; + // protected $hidden = []; // protected $dates = []; public $translatable = ['name', 'description', 'details', 'features', 'extras']; + public $casts = [ 'features' => 'object', 'extra_features' => 'object', 'status' => ProductStatus::class, + 'gallery' => 'json' ]; - public static function boot() - { - parent::boot(); - // since we don't have this fields in the model, we remove them before saving. - static::saving(function ($model) { - unset($model->attributes['secondary_image']); - unset($model->attributes['specifications']); - - unset($model->attributeCastCache['image_drm']); - unset($model->attributes['image_drm']); - }); - } - /* |-------------------------------------------------------------------------- | FUNCTIONS |-------------------------------------------------------------------------- */ - public function secondaryImage(): \Illuminate\Database\Eloquent\Casts\Attribute - { - return \Illuminate\Database\Eloquent\Casts\Attribute::make( - get: function ($value, $attributes) { - $image = $this->getFirstMedia('product_images', function ($media) { return $media->name === 'secondary_image'; }); - - return $image ? $image->getUrl() : null; - }, - set: function ($value) { - $previousImage = $this->getFirstMedia('product_images', function ($media) { - return $media->name === 'secondary_image'; - }); - - if ($value) { - if ($previousImage && \Str::startsWith($value, 'data:image')) { - $previousImage->delete(); - } - if (\Str::startsWith($value, 'data:image')) { - $extension = '.'.\Str::after(mime_content_type($value), '/'); - $this - ->addMediaFromBase64($value) - ->usingName('secondary_image') - ->usingFileName('secondary_image'.$extension) - ->toMediaCollection('product_images', 'products'); - } - - return; - } - - if ($previousImage) { - $previousImage->delete(); - } - } - ); - } - - public function mainImage(): \Illuminate\Database\Eloquent\Casts\Attribute - { - return \Illuminate\Database\Eloquent\Casts\Attribute::make( - get: function () { - $image = $this->getFirstMedia('product_images', function ($media) { return $media->name === 'main_image'; }); - - return $image ? $image->getUrl() : null; - }, - set: function ($value) { - $previousImage = $this->getFirstMedia('product_images', function ($media) { - return $media->name === 'main_image'; - }); - - if ($value) { - if ($previousImage && \Str::startsWith($value, 'data:image')) { - $previousImage->delete(); - } - if (\Str::startsWith($value, 'data:image')) { - $extension = '.'.\Str::after(mime_content_type($value), '/'); - $uploadedMedia = $this - ->addMediaFromBase64($value) - ->usingName('main_image') - ->usingFileName('main_image'.$extension) - ->toMediaCollection('product_images', 'products'); - } - - return $uploadedMedia->id ?? $previousImage->id; - } - - if ($previousImage) { - $previousImage->delete(); - } - } - ); - } - - public function specifications(): \Illuminate\Database\Eloquent\Casts\Attribute - { - return \Illuminate\Database\Eloquent\Casts\Attribute::make( - get: function () { - return $this - ->getMedia('product_documents', function ($media) { return $media->name === 'specification_document'; }) - ->map(function ($media) { - return \Str::after($media->getUrl(), \Storage::disk('products')->url('')); - }) - ->toArray(); - }, - set: function ($value) { - $filesToDelete = request()->get('clear_specifications'); - - $previousImages = $this->getMedia('product_documents', function ($media) { - return $media->name === 'specification_document'; - }); - - if ($filesToDelete) { - foreach ($previousImages as $previousImage) { - $storageBasePath = \Storage::disk('products')->url(''); - if (in_array(\Str::after($previousImage->getUrl(), $storageBasePath), $filesToDelete)) { - $previousImage->delete(); - } - } - } - - foreach ($value ?? [] as $file) { - if (is_file($file)) { - $this - ->addMedia($file) - ->usingName('specification_document') - ->toMediaCollection('product_documents', 'products'); - } - } - } - ); - } - - public function imageDrm(): \Illuminate\Database\Eloquent\Casts\Attribute - { - return \Illuminate\Database\Eloquent\Casts\Attribute::make( - get: function () { - $drm = $this->getFirstMedia('product_documents', function ($media) { return $media->name === 'image_drm'; }); - - return !empty($drm) ? $drm->getUrl() : null; - }, - set: function ($value) { - $previousDocument = $this->getFirstMedia('product_documents', function ($media) { return $media->name === 'image_drm'; }); - - if ($previousDocument && (!$value || is_file($value))) { - $previousDocument->delete(); - } - - if (is_file($value)) { - $this - ->addMedia($value) - ->usingName('image_drm') - ->toMediaCollection('product_documents', 'products'); - } - }, - ); - } - - public function gallery(): \Illuminate\Database\Eloquent\Casts\Attribute - { - return \Illuminate\Database\Eloquent\Casts\Attribute::make( - get: function ($value) { - $galleryImages = $this - ->getMedia('product_images', function ($media) { return $media->name === 'gallery_image'; }) - ->transform(function ($media, $key) { - $origin = substr(\Storage::disk('products')->url('/'), 0, -1); - - return ['image' => str_replace($origin, '', $media->getUrl()), 'repeatableRow' => $media->getCustomProperty('repeatableRow')]; - })->sortBy('repeatableRow')->keyBy('repeatableRow')->toArray(); - - $value = json_decode($value, true) ?? []; - - return array_merge_recursive_distinct($value, $galleryImages); - }, - set: function ($value) { - $galleryImages = $this->getMedia('product_images', function ($media) { return $media->name === 'gallery_image'; }); - - $sentImages = collect($value) - ->pluck('image') - ->map(function ($image) { - if (!\Str::startsWith($image, 'data:image')) { - return \Str::afterLast(\Str::beforeLast($image, '/'), '/').'/'.\Str::afterLast($image, '/'); - } - - return $image; - }) - ->toArray(); - - foreach ($sentImages as $row => $image) { - if (is_string($image)) { - if (\Str::startsWith($image, 'data:image')) { - $extension = '.'.\Str::after(mime_content_type($image), '/'); - $this - ->addMediaFromBase64($image) - ->usingName('gallery_image') - ->usingFileName(\Str::random().$extension) - ->withCustomProperties(['repeatableRow' => $row]) - ->preservingOriginal() - ->toMediaCollection('product_images', 'products'); - - unset($value[$row]['image']); - continue; - } - $currentImageGallery = $galleryImages->where('id', \Str::before($image, '/'))->where('file_name', \Str::after($image, '/'))->first(); - if ($currentImageGallery) { - if ($currentImageGallery->getCustomProperty('repeatableRow') !== $row) { - $currentImageGallery->setCustomProperty('repeatableRow', $row); - $currentImageGallery->save(); - } - unset($value[$row]['image']); - } - } - } - - foreach ($galleryImages as $media) { - $mediaIdentifier = $media->id.'/'.$media->file_name; - if (!in_array($mediaIdentifier, $sentImages)) { - $media->delete(); - } - } - - return json_encode($value); - }, - ); - } - /* |-------------------------------------------------------------------------- | RELATIONS diff --git a/composer.json b/composer.json index 81004e0ee..436beebc2 100644 --- a/composer.json +++ b/composer.json @@ -25,7 +25,8 @@ "backpack/filemanager": "^2.0", "backpack/backupmanager": "^3.0", "backpack/editable-columns": "^2.0", - "spatie/laravel-medialibrary": "^10.7" + "spatie/laravel-medialibrary": "^10.7", + "backpack/media-library-uploads": "dev-master" }, "require-dev": { "fakerphp/faker": "~1.4", @@ -41,6 +42,10 @@ { "type": "composer", "url": "https://repo.backpackforlaravel.com/" + }, + { + "type": "vcs", + "url": "https://github.com/Laravel-Backpack/media-library-uploads/" } ], "autoload": { @@ -73,8 +78,7 @@ "Illuminate\\Foundation\\ComposerScripts::postInstall" ], "post-update-cmd": [ - "Illuminate\\Foundation\\ComposerScripts::postUpdate", - "php artisan vendor:publish --provider=\"Backpack\\CRUD\\BackpackServiceProvider\" --tag=public --force" + "Illuminate\\Foundation\\ComposerScripts::postUpdate" ], "post-autoload-dump": [ "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump", diff --git a/config/media-library.php b/config/media-library.php new file mode 100644 index 000000000..37d0ccf5f --- /dev/null +++ b/config/media-library.php @@ -0,0 +1,237 @@ + env('MEDIA_DISK', 'products'), + + /* + * The maximum file size of an item in bytes. + * Adding a larger file will result in an exception. + */ + 'max_file_size' => 1024 * 1024 * 10, // 10MB + + /* + * This queue connection will be used to generate derived and responsive images. + * Leave empty to use the default queue connection. + */ + 'queue_connection_name' => env('QUEUE_CONNECTION', 'sync'), + + /* + * This queue will be used to generate derived and responsive images. + * Leave empty to use the default queue. + */ + 'queue_name' => '', + + /* + * By default all conversions will be performed on a queue. + */ + 'queue_conversions_by_default' => env('QUEUE_CONVERSIONS_BY_DEFAULT', true), + + /* + * The fully qualified class name of the media model. + */ + 'media_model' => Spatie\MediaLibrary\MediaCollections\Models\Media::class, + + /* + * The fully qualified class name of the model used for temporary uploads. + * + * This model is only used in Media Library Pro (https://medialibrary.pro) + */ + 'temporary_upload_model' => Spatie\MediaLibraryPro\Models\TemporaryUpload::class, + + /* + * When enabled, Media Library Pro will only process temporary uploads that were uploaded + * in the same session. You can opt to disable this for stateless usage of + * the pro components. + */ + 'enable_temporary_uploads_session_affinity' => true, + + /* + * When enabled, Media Library pro will generate thumbnails for uploaded file. + */ + 'generate_thumbnails_for_temporary_uploads' => true, + + /* + * This is the class that is responsible for naming generated files. + */ + 'file_namer' => Spatie\MediaLibrary\Support\FileNamer\DefaultFileNamer::class, + + /* + * The class that contains the strategy for determining a media file's path. + */ + 'path_generator' => Spatie\MediaLibrary\Support\PathGenerator\DefaultPathGenerator::class, + + /* + * Here you can specify which path generator should be used for the given class. + */ + 'custom_path_generators' => [ + // Model::class => PathGenerator::class + // or + // 'model_morph_alias' => PathGenerator::class + ], + + /* + * When urls to files get generated, this class will be called. Use the default + * if your files are stored locally above the site root or on s3. + */ + 'url_generator' => Spatie\MediaLibrary\Support\UrlGenerator\DefaultUrlGenerator::class, + + /* + * Moves media on updating to keep path consistent. Enable it only with a custom + * PathGenerator that uses, for example, the media UUID. + */ + 'moves_media_on_update' => false, + + /* + * Whether to activate versioning when urls to files get generated. + * When activated, this attaches a ?v=xx query string to the URL. + */ + 'version_urls' => false, + + /* + * The media library will try to optimize all converted images by removing + * metadata and applying a little bit of compression. These are + * the optimizers that will be used by default. + */ + 'image_optimizers' => [ + Spatie\ImageOptimizer\Optimizers\Jpegoptim::class => [ + '-m85', // set maximum quality to 85% + '--force', // ensure that progressive generation is always done also if a little bigger + '--strip-all', // this strips out all text information such as comments and EXIF data + '--all-progressive', // this will make sure the resulting image is a progressive one + ], + Spatie\ImageOptimizer\Optimizers\Pngquant::class => [ + '--force', // required parameter for this package + ], + Spatie\ImageOptimizer\Optimizers\Optipng::class => [ + '-i0', // this will result in a non-interlaced, progressive scanned image + '-o2', // this set the optimization level to two (multiple IDAT compression trials) + '-quiet', // required parameter for this package + ], + Spatie\ImageOptimizer\Optimizers\Svgo::class => [ + '--disable=cleanupIDs', // disabling because it is known to cause troubles + ], + Spatie\ImageOptimizer\Optimizers\Gifsicle::class => [ + '-b', // required parameter for this package + '-O3', // this produces the slowest but best results + ], + Spatie\ImageOptimizer\Optimizers\Cwebp::class => [ + '-m 6', // for the slowest compression method in order to get the best compression. + '-pass 10', // for maximizing the amount of analysis pass. + '-mt', // multithreading for some speed improvements. + '-q 90', //quality factor that brings the least noticeable changes. + ], + ], + + /* + * These generators will be used to create an image of media files. + */ + 'image_generators' => [ + Spatie\MediaLibrary\Conversions\ImageGenerators\Image::class, + Spatie\MediaLibrary\Conversions\ImageGenerators\Webp::class, + Spatie\MediaLibrary\Conversions\ImageGenerators\Pdf::class, + Spatie\MediaLibrary\Conversions\ImageGenerators\Svg::class, + Spatie\MediaLibrary\Conversions\ImageGenerators\Video::class, + ], + + /* + * The path where to store temporary files while performing image conversions. + * If set to null, storage_path('media-library/temp') will be used. + */ + 'temporary_directory_path' => null, + + /* + * The engine that should perform the image conversions. + * Should be either `gd` or `imagick`. + */ + 'image_driver' => env('IMAGE_DRIVER', 'gd'), + + /* + * FFMPEG & FFProbe binaries paths, only used if you try to generate video + * thumbnails and have installed the php-ffmpeg/php-ffmpeg composer + * dependency. + */ + 'ffmpeg_path' => env('FFMPEG_PATH', '/usr/bin/ffmpeg'), + 'ffprobe_path' => env('FFPROBE_PATH', '/usr/bin/ffprobe'), + + /* + * Here you can override the class names of the jobs used by this package. Make sure + * your custom jobs extend the ones provided by the package. + */ + 'jobs' => [ + 'perform_conversions' => Spatie\MediaLibrary\Conversions\Jobs\PerformConversionsJob::class, + 'generate_responsive_images' => Spatie\MediaLibrary\ResponsiveImages\Jobs\GenerateResponsiveImagesJob::class, + ], + + /* + * When using the addMediaFromUrl method you may want to replace the default downloader. + * This is particularly useful when the url of the image is behind a firewall and + * need to add additional flags, possibly using curl. + */ + 'media_downloader' => Spatie\MediaLibrary\Downloaders\DefaultDownloader::class, + + 'remote' => [ + /* + * Any extra headers that should be included when uploading media to + * a remote disk. Even though supported headers may vary between + * different drivers, a sensible default has been provided. + * + * Supported by S3: CacheControl, Expires, StorageClass, + * ServerSideEncryption, Metadata, ACL, ContentEncoding + */ + 'extra_headers' => [ + 'CacheControl' => 'max-age=604800', + ], + ], + + 'responsive_images' => [ + /* + * This class is responsible for calculating the target widths of the responsive + * images. By default we optimize for filesize and create variations that each are 30% + * smaller than the previous one. More info in the documentation. + * + * https://docs.spatie.be/laravel-medialibrary/v9/advanced-usage/generating-responsive-images + */ + 'width_calculator' => Spatie\MediaLibrary\ResponsiveImages\WidthCalculator\FileSizeOptimizedWidthCalculator::class, + + /* + * By default rendering media to a responsive image will add some javascript and a tiny placeholder. + * This ensures that the browser can already determine the correct layout. + */ + 'use_tiny_placeholders' => true, + + /* + * This class will generate the tiny placeholder used for progressive image loading. By default + * the media library will use a tiny blurred jpg image. + */ + 'tiny_placeholder_generator' => Spatie\MediaLibrary\ResponsiveImages\TinyPlaceholderGenerator\Blurred::class, + ], + + /* + * When enabling this option, a route will be registered that will enable + * the Media Library Pro Vue and React components to move uploaded files + * in a S3 bucket to their right place. + */ + 'enable_vapor_uploads' => env('ENABLE_MEDIA_LIBRARY_VAPOR_UPLOADS', false), + + /* + * When converting Media instances to response the media library will add + * a `loading` attribute to the `img` tag. Here you can set the default + * value of that attribute. + * + * Possible values: 'lazy', 'eager', 'auto' or null if you don't want to set any loading instruction. + * + * More info: https://css-tricks.com/native-lazy-loading/ + */ + 'default_loading_attribute_value' => null, + + /* + * You can specify a prefix for that is used for storing all media. + * If you set this to `/my-subdir`, all your media will be stored in a `/my-subdir` directory. + */ + 'prefix' => env('MEDIA_PREFIX', ''), +]; diff --git a/database/migrations/2017_12_19_081247_create_products_table.php b/database/migrations/2017_12_19_081247_create_products_table.php index 55191de3d..96f73ba4f 100644 --- a/database/migrations/2017_12_19_081247_create_products_table.php +++ b/database/migrations/2017_12_19_081247_create_products_table.php @@ -20,7 +20,6 @@ public function up() $table->json('features')->nullable(); $table->integer('price'); $table->integer('category_id'); - $table->text('main_image')->nullable(); $table->json('gallery')->nullable(); $table->json('extras')->nullable(); $table->timestamps(); diff --git a/database/migrations/2023_01_16_123511_create_media_table.php b/database/migrations/2023_02_22_191429_create_media_table.php similarity index 92% rename from database/migrations/2023_01_16_123511_create_media_table.php rename to database/migrations/2023_02_22_191429_create_media_table.php index fe4ffe152..adb2df917 100644 --- a/database/migrations/2023_01_16_123511_create_media_table.php +++ b/database/migrations/2023_02_22_191429_create_media_table.php @@ -4,11 +4,12 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -return new class() extends Migration { +return new class extends Migration +{ public function up(): void { Schema::create('media', function (Blueprint $table) { - $table->bigIncrements('id'); + $table->id(); $table->morphs('model'); $table->uuid('uuid')->nullable()->unique(); From c13f0dd6d82503b794aeba0d9094228cb8cb4ac8 Mon Sep 17 00:00:00 2001 From: Pedro X Date: Wed, 22 Feb 2023 20:25:42 +0000 Subject: [PATCH 04/16] add command back to demo --- composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 436beebc2..948cdeb34 100644 --- a/composer.json +++ b/composer.json @@ -78,7 +78,8 @@ "Illuminate\\Foundation\\ComposerScripts::postInstall" ], "post-update-cmd": [ - "Illuminate\\Foundation\\ComposerScripts::postUpdate" + "Illuminate\\Foundation\\ComposerScripts::postUpdate", + "php artisan vendor:publish --provider=\"Backpack\\CRUD\\BackpackServiceProvider\" --tag=public --force" ], "post-autoload-dump": [ "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump", From 2ee8146dbd17953350cc6ed88db4628454c37db7 Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Wed, 22 Feb 2023 20:25:55 +0000 Subject: [PATCH 05/16] Apply fixes from StyleCI --- app/Models/Product.php | 2 +- database/migrations/2023_02_22_191429_create_media_table.php | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/app/Models/Product.php b/app/Models/Product.php index 2c93d8a4c..7c3440c3d 100644 --- a/app/Models/Product.php +++ b/app/Models/Product.php @@ -40,7 +40,7 @@ class Product extends Model implements HasMedia 'features' => 'object', 'extra_features' => 'object', 'status' => ProductStatus::class, - 'gallery' => 'json' + 'gallery' => 'json', ]; /* diff --git a/database/migrations/2023_02_22_191429_create_media_table.php b/database/migrations/2023_02_22_191429_create_media_table.php index adb2df917..ea4bd59d6 100644 --- a/database/migrations/2023_02_22_191429_create_media_table.php +++ b/database/migrations/2023_02_22_191429_create_media_table.php @@ -4,8 +4,7 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -return new class extends Migration -{ +return new class() extends Migration { public function up(): void { Schema::create('media', function (Blueprint $table) { From 8b3c5ac6a9826477b280343575e80795c3fbfe23 Mon Sep 17 00:00:00 2001 From: Pedro X Date: Tue, 7 Mar 2023 12:11:24 +0000 Subject: [PATCH 06/16] wip --- .../Admin/ProductCrudController.php | 92 ++++++++++--------- app/Models/Product.php | 3 +- ...017_12_19_081247_create_products_table.php | 3 + 3 files changed, 55 insertions(+), 43 deletions(-) diff --git a/app/Http/Controllers/Admin/ProductCrudController.php b/app/Http/Controllers/Admin/ProductCrudController.php index 20e907d6d..50a5d4095 100644 --- a/app/Http/Controllers/Admin/ProductCrudController.php +++ b/app/Http/Controllers/Admin/ProductCrudController.php @@ -211,65 +211,73 @@ protected function setupCreateOperation() ->type('image') ->tab('Product Media') ->wrapper(['class' => 'form-group col-md-4']) - ->withMedia(); + ->withUploads([ + 'disk' => 'products', + ]); CRUD::field('privacy_policy') ->label('Privacy policy document') ->type('upload') ->tab('Product Media') - ->upload(true) ->wrapper(['class' => 'form-group col-md-4']) - ->withMedia(); + ->withUploads(); - CRUD::field('product_specifications') + CRUD::field('specifications') ->label('Specifications') ->type('upload_multiple') ->tab('Product Media') - ->upload(true) ->wrapper(['class' => 'form-group col-md-4']) - ->withMedia(); + ->withUploads([ + 'disk' => 'products', + ]); CRUD::field('gallery') - ->type('repeatable') - ->tab('Product Media') - ->subfields([ - [ - 'name' => 'image_title', - 'type' => 'text', - 'wrapper' => [ - 'class' => 'form-group col-md-6', - ], - ], - [ - 'name' => 'gallery_image', - 'label' => 'image', - 'type' => 'image', - 'wrapper' => [ - 'class' => 'form-group col-md-6', - ], - 'withMedia' => true, + ->type('repeatable') + ->tab('Product Media') + ->subfields([ + [ + 'name' => 'image_title', + 'type' => 'text', + 'wrapper' => [ + 'class' => 'form-group col-md-6', ], - [ - 'name' => 'gallery_image_drm', - 'label' => 'Image DRM', - 'type' => 'upload', - 'wrapper' => [ - 'class' => 'form-group col-md-6', - ], - 'withMedia' => true, + ], + [ + 'name' => 'gallery_image', + 'label' => 'image', + 'type' => 'image', + 'wrapper' => [ + 'class' => 'form-group col-md-6', ], - [ - 'name' => 'gallery_image_specifications', - 'label' => 'Image Specifications', - 'type' => 'upload_multiple', - 'wrapper' => [ - 'class' => 'form-group col-md-6', - ], - 'withMedia' => true, + 'withUploads' => [ + 'disk' => 'products', ], + ], - ]) - ->withMedia(); + [ + 'name' => 'gallery_image_drm', + 'label' => 'Image DRM', + 'type' => 'upload', + 'wrapper' => [ + 'class' => 'form-group col-md-6', + ], + 'withUploads' => [ + 'disk' => 'products', + ], + ], + [ + 'name' => 'gallery_image_specifications', + 'label' => 'Image Specifications', + 'type' => 'upload_multiple', + 'wrapper' => [ + 'class' => 'form-group col-md-6', + ], + 'withUploads' => [ + 'disk' => 'products', + ], + ], + ]) + ->withUploads(); $this->crud->setOperationSetting('contentClass', 'col-md-12'); } diff --git a/app/Models/Product.php b/app/Models/Product.php index 7c3440c3d..70a122fb7 100644 --- a/app/Models/Product.php +++ b/app/Models/Product.php @@ -30,7 +30,7 @@ class Product extends Model implements HasMedia public $timestamps = true; // protected $guarded = ['id']; - protected $fillable = ['name', 'description', 'details', 'features', 'price', 'category_id', 'extras', 'status', 'condition', 'gallery']; + protected $fillable = ['name', 'description', 'details', 'features', 'price', 'category_id', 'extras', 'status', 'condition', 'gallery', 'main_image', 'privacy_policy', 'specifications']; // protected $hidden = []; // protected $dates = []; @@ -41,6 +41,7 @@ class Product extends Model implements HasMedia 'extra_features' => 'object', 'status' => ProductStatus::class, 'gallery' => 'json', + 'specifications' => 'array' ]; /* diff --git a/database/migrations/2017_12_19_081247_create_products_table.php b/database/migrations/2017_12_19_081247_create_products_table.php index 96f73ba4f..54d30a1e1 100644 --- a/database/migrations/2017_12_19_081247_create_products_table.php +++ b/database/migrations/2017_12_19_081247_create_products_table.php @@ -22,6 +22,9 @@ public function up() $table->integer('category_id'); $table->json('gallery')->nullable(); $table->json('extras')->nullable(); + $table->string('main_image')->nullable(); + $table->string('privacy_policy')->nullable(); + $table->text('specifications')->nullable(); $table->timestamps(); }); } From 6a5f285593e7180f9e78a9046521e2f815d2a6ce Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Tue, 7 Mar 2023 12:11:42 +0000 Subject: [PATCH 07/16] Apply fixes from StyleCI --- app/Models/Product.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Models/Product.php b/app/Models/Product.php index 70a122fb7..86ad11e6c 100644 --- a/app/Models/Product.php +++ b/app/Models/Product.php @@ -41,7 +41,7 @@ class Product extends Model implements HasMedia 'extra_features' => 'object', 'status' => ProductStatus::class, 'gallery' => 'json', - 'specifications' => 'array' + 'specifications' => 'array', ]; /* From cc2d8c5e4f2183505f115beb59331a384e9d078a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 May 2023 09:14:32 +0000 Subject: [PATCH 08/16] Bump backpack/backupmanager from 3.0.9 to 4.0.2 Bumps [backpack/backupmanager](https://github.com/Laravel-Backpack/BackupManager) from 3.0.9 to 4.0.2. - [Release notes](https://github.com/Laravel-Backpack/BackupManager/releases) - [Changelog](https://github.com/Laravel-Backpack/BackupManager/blob/master/CHANGELOG.md) - [Commits](https://github.com/Laravel-Backpack/BackupManager/compare/v3.0.9...v4.0.2) --- updated-dependencies: - dependency-name: backpack/backupmanager dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- composer.json | 2 +- composer.lock | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/composer.json b/composer.json index a311ce8f8..f8ffde8f0 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,7 @@ "consoletvs/charts": "6.*", "laravel/legacy-factories": "^1.0", "backpack/filemanager": "^2.0", - "backpack/backupmanager": "^3.0", + "backpack/backupmanager": "^4.0", "backpack/editable-columns": "^2.0", "backpack/pro": "^1.6", "backpack/newscrud": "^4.0", diff --git a/composer.lock b/composer.lock index 541d6d2c7..4ff5076c3 100644 --- a/composer.lock +++ b/composer.lock @@ -4,29 +4,29 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "637807c5289bd51de9d9527e88af7410", + "content-hash": "9c46e747ca3a3c780e351aef23a75439", "packages": [ { "name": "backpack/backupmanager", - "version": "v3.0.9", + "version": "v4.0.2", "source": { "type": "git", "url": "https://github.com/Laravel-Backpack/BackupManager.git", - "reference": "a461313d706ca16ed04dfdc25cb09058f9bb503b" + "reference": "240ff3fbdd0db86ce01c83eaf610b2c7d009351e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Laravel-Backpack/BackupManager/zipball/a461313d706ca16ed04dfdc25cb09058f9bb503b", - "reference": "a461313d706ca16ed04dfdc25cb09058f9bb503b", + "url": "https://api.github.com/repos/Laravel-Backpack/BackupManager/zipball/240ff3fbdd0db86ce01c83eaf610b2c7d009351e", + "reference": "240ff3fbdd0db86ce01c83eaf610b2c7d009351e", "shasum": "" }, "require": { - "backpack/crud": "^4.0|^5.0", - "spatie/laravel-backup": "^8.0|^7.0|^6.1" + "backpack/crud": "^5.0", + "spatie/laravel-backup": "^8.0" }, "require-dev": { "phpunit/phpunit": "^9.0||^7.0", - "scrutinizer/ocular": "~1.1" + "scrutinizer/ocular": "~1.7|~1.1" }, "type": "library", "extra": { @@ -69,9 +69,9 @@ ], "support": { "issues": "https://github.com/Laravel-Backpack/BackupManager/issues", - "source": "https://github.com/Laravel-Backpack/BackupManager/tree/v3.0.9" + "source": "https://github.com/Laravel-Backpack/BackupManager/tree/v4.0.2" }, - "time": "2022-04-05T06:00:17+00:00" + "time": "2023-04-11T03:47:23+00:00" }, { "name": "backpack/crud", From ec0b719ecd5984866ee6625631b539e89683ae88 Mon Sep 17 00:00:00 2001 From: Cristian Tabacitu Date: Wed, 31 May 2023 15:10:02 +0300 Subject: [PATCH 09/16] use the latest syntax for backpack/medialibrary-uploaders package --- .../Admin/ProductCrudController.php | 23 +- composer.json | 6 +- composer.lock | 1023 ++++++++++++----- public/products | 1 + 4 files changed, 774 insertions(+), 279 deletions(-) create mode 120000 public/products diff --git a/app/Http/Controllers/Admin/ProductCrudController.php b/app/Http/Controllers/Admin/ProductCrudController.php index 50a5d4095..b41a933ac 100644 --- a/app/Http/Controllers/Admin/ProductCrudController.php +++ b/app/Http/Controllers/Admin/ProductCrudController.php @@ -209,31 +209,31 @@ protected function setupCreateOperation() CRUD::field('main_image') ->label('Main Image') ->type('image') - ->tab('Product Media') + ->tab('Media') ->wrapper(['class' => 'form-group col-md-4']) - ->withUploads([ + ->withMedia([ 'disk' => 'products', ]); CRUD::field('privacy_policy') ->label('Privacy policy document') ->type('upload') - ->tab('Product Media') + ->tab('Media') ->wrapper(['class' => 'form-group col-md-4']) - ->withUploads(); + ->withMedia(); CRUD::field('specifications') ->label('Specifications') ->type('upload_multiple') - ->tab('Product Media') + ->tab('Media') ->wrapper(['class' => 'form-group col-md-4']) - ->withUploads([ + ->withMedia([ 'disk' => 'products', ]); CRUD::field('gallery') ->type('repeatable') - ->tab('Product Media') + ->tab('Media') ->subfields([ [ 'name' => 'image_title', @@ -249,7 +249,7 @@ protected function setupCreateOperation() 'wrapper' => [ 'class' => 'form-group col-md-6', ], - 'withUploads' => [ + 'withMedia' => [ 'disk' => 'products', ], ], @@ -261,7 +261,7 @@ protected function setupCreateOperation() 'wrapper' => [ 'class' => 'form-group col-md-6', ], - 'withUploads' => [ + 'withMedia' => [ 'disk' => 'products', ], ], @@ -272,12 +272,11 @@ protected function setupCreateOperation() 'wrapper' => [ 'class' => 'form-group col-md-6', ], - 'withUploads' => [ + 'withMedia' => [ 'disk' => 'products', ], ], - ]) - ->withUploads(); + ]); $this->crud->setOperationSetting('contentClass', 'col-md-12'); } diff --git a/composer.json b/composer.json index e1cc91b2f..a0207255f 100644 --- a/composer.json +++ b/composer.json @@ -30,7 +30,7 @@ "backpack/backupmanager": "^4.0", "backpack/editable-columns": "^2.0", "spatie/laravel-medialibrary": "^10.7", - "backpack/media-library-uploads": "dev-master" + "backpack/medialibrary-uploaders": "dev-main" }, "require-dev": { "fakerphp/faker": "~1.4", @@ -58,9 +58,9 @@ "type": "composer", "url": "https://repo.backpackforlaravel.com/" }, - { + "backpack/medialibrary-uploaders": { "type": "vcs", - "url": "https://github.com/Laravel-Backpack/media-library-uploads/" + "url": "https://github.com/Laravel-Backpack/medialibrary-uploaders/" } }, "autoload": { diff --git a/composer.lock b/composer.lock index e99b65432..503a6a802 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "f3dd30ed559b2d03d0e5405b30bca612", + "content-hash": "1e29875e930e1897188dbcb4bf4441a2", "packages": [ { "name": "backpack/backupmanager", @@ -147,12 +147,12 @@ "source": { "type": "git", "url": "https://github.com/Laravel-Backpack/CRUD.git", - "reference": "5b08de0ff3c2115da0a11b377d0366ccc88d65b4" + "reference": "ccfeea938c2e225f9dc7839a02b0770323e55e4f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Laravel-Backpack/CRUD/zipball/5b08de0ff3c2115da0a11b377d0366ccc88d65b4", - "reference": "5b08de0ff3c2115da0a11b377d0366ccc88d65b4", + "url": "https://api.github.com/repos/Laravel-Backpack/CRUD/zipball/ccfeea938c2e225f9dc7839a02b0770323e55e4f", + "reference": "ccfeea938c2e225f9dc7839a02b0770323e55e4f", "shasum": "" }, "require": { @@ -234,7 +234,7 @@ "issues": "https://github.com/Laravel-Backpack/CRUD/issues", "source": "https://github.com/Laravel-Backpack/CRUD/tree/v6" }, - "time": "2023-05-19T10:45:45+00:00" + "time": "2023-05-30T13:40:20+00:00" }, { "name": "backpack/editable-columns", @@ -429,6 +429,73 @@ }, "time": "2023-04-05T08:11:51+00:00" }, + { + "name": "backpack/medialibrary-uploaders", + "version": "dev-main", + "source": { + "type": "git", + "url": "git@github.com:Laravel-Backpack/medialibrary-uploaders.git", + "reference": "df57a623b8d55daf6cd0ad08d4b63be561471fda" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Laravel-Backpack/medialibrary-uploaders/zipball/df57a623b8d55daf6cd0ad08d4b63be561471fda", + "reference": "df57a623b8d55daf6cd0ad08d4b63be561471fda", + "shasum": "" + }, + "require": { + "backpack/crud": "^6.0|6.x-dev ", + "illuminate/support": "^10.0", + "spatie/laravel-medialibrary": "^10.7" + }, + "require-dev": { + "orchestra/testbench": "~6", + "phpunit/phpunit": "~9.0" + }, + "default-branch": true, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Backpack\\MediaLibraryUploaders\\AddonServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Backpack\\MediaLibraryUploaders\\": "src/" + } + }, + "scripts": { + "test": [ + "vendor/bin/phpunit --testdox" + ] + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Tabacitu", + "email": "hello@backpackforlaravel.com", + "homepage": "https://backpackforlaravel.com" + } + ], + "description": "Helper functions to save files with spatie media library", + "homepage": "https://github.com/backpack/medialibrary-uploaders", + "keywords": [ + "Backpack", + "Backpack Addon", + "Backpack for Laravel", + "Laravel", + "spatie medialibrary uploaders" + ], + "support": { + "source": "https://github.com/Laravel-Backpack/medialibrary-uploaders/tree/main", + "issues": "https://github.com/Laravel-Backpack/medialibrary-uploaders/issues" + }, + "time": "2023-05-17T09:24:37+00:00" + }, { "name": "backpack/menucrud", "version": "v3.0.1", @@ -634,17 +701,17 @@ "source": { "type": "git", "url": "https://github.com/Laravel-Backpack/PermissionManager.git", - "reference": "8440126ef649b686fe008215f0b36d7921a1759d" + "reference": "e092031c7ee13328bf6ae06452647e2be11f09e9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Laravel-Backpack/PermissionManager/zipball/8440126ef649b686fe008215f0b36d7921a1759d", - "reference": "8440126ef649b686fe008215f0b36d7921a1759d", + "url": "https://api.github.com/repos/Laravel-Backpack/PermissionManager/zipball/e092031c7ee13328bf6ae06452647e2be11f09e9", + "reference": "e092031c7ee13328bf6ae06452647e2be11f09e9", "shasum": "" }, "require": { "backpack/crud": "^5.0", - "spatie/laravel-permission": "^6.0||^5.0||^4.0||^3.0" + "spatie/laravel-permission": "^5.0||^4.0||^3.0" }, "require-dev": { "phpunit/phpunit": "^9.0||^7.0", @@ -703,7 +770,7 @@ "issues": "https://github.com/Laravel-Backpack/PermissionManager/issues", "source": "https://github.com/Laravel-Backpack/PermissionManager/tree/6.0.16" }, - "time": "2023-02-20T15:40:44+00:00" + "time": "2023-05-25T10:51:39+00:00" }, { "name": "backpack/pro", @@ -711,13 +778,13 @@ "source": { "type": "git", "url": "git@github.com:Laravel-Backpack/PRO.git", - "reference": "6270099531c4eadf71a50c2498e1485eb8f5956b" + "reference": "f62fdd912057014476caaa52f54618353f4ef1ec" }, "dist": { "type": "zip", - "url": "https://repo.backpackforlaravel.com/dist/backpack/pro/backpack-pro-6270099531c4eadf71a50c2498e1485eb8f5956b-zip-8609e2.zip", - "reference": "6270099531c4eadf71a50c2498e1485eb8f5956b", - "shasum": "993ccd62c020dbb1d09cc46df8e98bb07132801c" + "url": "https://repo.backpackforlaravel.com/dist/backpack/pro/backpack-pro-f62fdd912057014476caaa52f54618353f4ef1ec-zip-e12fd1.zip", + "reference": "f62fdd912057014476caaa52f54618353f4ef1ec", + "shasum": "98362044e4daf604d7d05889f47d49830321dfec" }, "require": { "backpack/crud": "^6.0|v6.x-dev|^5.4.9" @@ -772,7 +839,7 @@ "source": "https://github.com/Laravel-Backpack/PRO/tree/v6", "issues": "https://github.com/Laravel-Backpack/PRO/issues" }, - "time": "2023-05-17T15:30:50+00:00" + "time": "2023-05-26T15:21:04+00:00" }, { "name": "backpack/revise-operation", @@ -1068,12 +1135,12 @@ "source": { "type": "git", "url": "https://github.com/Laravel-Backpack/theme-tabler.git", - "reference": "c59ff580a0c3f6c7e30bb366f2d0733aa3c5a6bd" + "reference": "c1ce5a259b53359c82f5d7381813372093629c65" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Laravel-Backpack/theme-tabler/zipball/c59ff580a0c3f6c7e30bb366f2d0733aa3c5a6bd", - "reference": "c59ff580a0c3f6c7e30bb366f2d0733aa3c5a6bd", + "url": "https://api.github.com/repos/Laravel-Backpack/theme-tabler/zipball/c1ce5a259b53359c82f5d7381813372093629c65", + "reference": "c1ce5a259b53359c82f5d7381813372093629c65", "shasum": "" }, "require": { @@ -1144,7 +1211,7 @@ "source": "https://github.com/Laravel-Backpack/theme-tabler/tree/main", "issues": "https://github.com/Laravel-Backpack/theme-tabler/issues" }, - "time": "2023-05-19T10:46:29+00:00" + "time": "2023-05-31T05:54:09+00:00" }, { "name": "balping/json-raw-encoder", @@ -1925,16 +1992,16 @@ }, { "name": "doctrine/deprecations", - "version": "v1.0.0", + "version": "v1.1.0", "source": { "type": "git", "url": "https://github.com/doctrine/deprecations.git", - "reference": "0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de" + "reference": "8cffffb2218e01f3b370bf763e00e81697725259" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/deprecations/zipball/0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de", - "reference": "0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/8cffffb2218e01f3b370bf763e00e81697725259", + "reference": "8cffffb2218e01f3b370bf763e00e81697725259", "shasum": "" }, "require": { @@ -1962,9 +2029,9 @@ "homepage": "https://www.doctrine-project.org/", "support": { "issues": "https://github.com/doctrine/deprecations/issues", - "source": "https://github.com/doctrine/deprecations/tree/v1.0.0" + "source": "https://github.com/doctrine/deprecations/tree/v1.1.0" }, - "time": "2022-05-02T15:47:09+00:00" + "time": "2023-05-29T18:55:17+00:00" }, { "name": "doctrine/event-manager", @@ -2549,21 +2616,21 @@ }, { "name": "guzzlehttp/guzzle", - "version": "7.6.1", + "version": "7.7.0", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "8444a2bacf1960bc6a2b62ed86b8e72e11eebe51" + "reference": "fb7566caccf22d74d1ab270de3551f72a58399f5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/8444a2bacf1960bc6a2b62ed86b8e72e11eebe51", - "reference": "8444a2bacf1960bc6a2b62ed86b8e72e11eebe51", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/fb7566caccf22d74d1ab270de3551f72a58399f5", + "reference": "fb7566caccf22d74d1ab270de3551f72a58399f5", "shasum": "" }, "require": { "ext-json": "*", - "guzzlehttp/promises": "^1.5", + "guzzlehttp/promises": "^1.5.3 || ^2.0", "guzzlehttp/psr7": "^1.9.1 || ^2.4.5", "php": "^7.2.5 || ^8.0", "psr/http-client": "^1.0", @@ -2575,7 +2642,8 @@ "require-dev": { "bamarni/composer-bin-plugin": "^1.8.1", "ext-curl": "*", - "php-http/client-integration-tests": "^3.0", + "php-http/client-integration-tests": "dev-master#2c025848417c1135031fdf9c728ee53d0a7ceaee as 3.0.999", + "php-http/message-factory": "^1.1", "phpunit/phpunit": "^8.5.29 || ^9.5.23", "psr/log": "^1.1 || ^2.0 || ^3.0" }, @@ -2654,7 +2722,7 @@ ], "support": { "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/7.6.1" + "source": "https://github.com/guzzle/guzzle/tree/7.7.0" }, "funding": [ { @@ -2670,38 +2738,37 @@ "type": "tidelift" } ], - "time": "2023-05-15T20:43:01+00:00" + "time": "2023-05-21T14:04:53+00:00" }, { "name": "guzzlehttp/promises", - "version": "1.5.2", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "b94b2807d85443f9719887892882d0329d1e2598" + "reference": "3a494dc7dc1d7d12e511890177ae2d0e6c107da6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/b94b2807d85443f9719887892882d0329d1e2598", - "reference": "b94b2807d85443f9719887892882d0329d1e2598", + "url": "https://api.github.com/repos/guzzle/promises/zipball/3a494dc7dc1d7d12e511890177ae2d0e6c107da6", + "reference": "3a494dc7dc1d7d12e511890177ae2d0e6c107da6", "shasum": "" }, "require": { - "php": ">=5.5" + "php": "^7.2.5 || ^8.0" }, "require-dev": { - "symfony/phpunit-bridge": "^4.4 || ^5.1" + "bamarni/composer-bin-plugin": "^1.8.1", + "phpunit/phpunit": "^8.5.29 || ^9.5.23" }, "type": "library", "extra": { - "branch-alias": { - "dev-master": "1.5-dev" + "bamarni-bin": { + "bin-links": true, + "forward-command": false } }, "autoload": { - "files": [ - "src/functions_include.php" - ], "psr-4": { "GuzzleHttp\\Promise\\": "src/" } @@ -2738,7 +2805,7 @@ ], "support": { "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/1.5.2" + "source": "https://github.com/guzzle/promises/tree/2.0.0" }, "funding": [ { @@ -2754,7 +2821,7 @@ "type": "tidelift" } ], - "time": "2022-08-28T14:55:35+00:00" + "time": "2023-05-21T13:50:22+00:00" }, { "name": "guzzlehttp/psr7", @@ -3042,16 +3109,16 @@ }, { "name": "laravel/framework", - "version": "v10.11.0", + "version": "v10.13.0", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "21a5b6d9b669f32c10cc8ba776511b5f62599fea" + "reference": "7322723585103082758d74917db62980684845cb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/21a5b6d9b669f32c10cc8ba776511b5f62599fea", - "reference": "21a5b6d9b669f32c10cc8ba776511b5f62599fea", + "url": "https://api.github.com/repos/laravel/framework/zipball/7322723585103082758d74917db62980684845cb", + "reference": "7322723585103082758d74917db62980684845cb", "shasum": "" }, "require": { @@ -3238,7 +3305,7 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2023-05-16T13:59:23+00:00" + "time": "2023-05-30T14:46:25+00:00" }, { "name": "laravel/legacy-factories", @@ -3760,6 +3827,71 @@ ], "time": "2023-05-02T20:02:14+00:00" }, + { + "name": "league/glide", + "version": "2.2.4", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/glide.git", + "reference": "d31132bf5651d5abeef345ff523cd9cf2575b971" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/glide/zipball/d31132bf5651d5abeef345ff523cd9cf2575b971", + "reference": "d31132bf5651d5abeef345ff523cd9cf2575b971", + "shasum": "" + }, + "require": { + "intervention/image": "^2.7", + "league/flysystem": "^2.0|^3.0", + "php": "^7.2|^8.0", + "psr/http-message": "^1.0|^2.0" + }, + "require-dev": { + "mockery/mockery": "^1.3.3", + "phpunit/php-token-stream": "^3.1|^4.0", + "phpunit/phpunit": "^8.5|^9.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\Glide\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jonathan Reinink", + "email": "jonathan@reinink.ca", + "homepage": "http://reinink.ca" + }, + { + "name": "Titouan Galopin", + "email": "galopintitouan@gmail.com", + "homepage": "https://titouangalopin.com" + } + ], + "description": "Wonderfully easy on-demand image manipulation library with an HTTP based API.", + "homepage": "http://glide.thephpleague.com", + "keywords": [ + "ImageMagick", + "editing", + "gd", + "image", + "imagick", + "league", + "manipulation", + "processing" + ], + "support": { + "issues": "https://github.com/thephpleague/glide/issues", + "source": "https://github.com/thephpleague/glide/tree/2.2.4" + }, + "time": "2023-04-18T18:42:22+00:00" + }, { "name": "league/mime-type-detection", "version": "1.11.0", @@ -3816,6 +3948,87 @@ ], "time": "2022-04-17T13:12:02+00:00" }, + { + "name": "maennchen/zipstream-php", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/maennchen/ZipStream-PHP.git", + "reference": "b46726e666b5d2ad32959ae9492ee1034e798162" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/b46726e666b5d2ad32959ae9492ee1034e798162", + "reference": "b46726e666b5d2ad32959ae9492ee1034e798162", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "ext-zlib": "*", + "php-64bit": "^8.1" + }, + "require-dev": { + "ext-zip": "*", + "friendsofphp/php-cs-fixer": "^3.16", + "guzzlehttp/guzzle": "^7.5", + "mikey179/vfsstream": "^1.6", + "php-coveralls/php-coveralls": "^2.5", + "phpunit/phpunit": "^10.0", + "vimeo/psalm": "^5.0" + }, + "suggest": { + "guzzlehttp/psr7": "^2.4", + "psr/http-message": "^2.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "ZipStream\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paul Duncan", + "email": "pabs@pablotron.org" + }, + { + "name": "Jonatan Männchen", + "email": "jonatan@maennchen.ch" + }, + { + "name": "Jesse Donat", + "email": "donatj@gmail.com" + }, + { + "name": "András Kolesár", + "email": "kolesar@kolesar.hu" + } + ], + "description": "ZipStream is a library for dynamically streaming dynamic zip files from PHP without writing to the disk at all on the server.", + "keywords": [ + "stream", + "zip" + ], + "support": { + "issues": "https://github.com/maennchen/ZipStream-PHP/issues", + "source": "https://github.com/maennchen/ZipStream-PHP/tree/3.0.2" + }, + "funding": [ + { + "url": "https://github.com/maennchen", + "type": "github" + }, + { + "url": "https://opencollective.com/zipstream", + "type": "open_collective" + } + ], + "time": "2023-04-19T19:51:03+00:00" + }, { "name": "mews/purifier", "version": "3.4.0", @@ -3997,16 +4210,16 @@ }, { "name": "nesbot/carbon", - "version": "2.66.0", + "version": "2.67.0", "source": { "type": "git", "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "496712849902241f04902033b0441b269effe001" + "reference": "c1001b3bc75039b07f38a79db5237c4c529e04c8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/496712849902241f04902033b0441b269effe001", - "reference": "496712849902241f04902033b0441b269effe001", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/c1001b3bc75039b07f38a79db5237c4c529e04c8", + "reference": "c1001b3bc75039b07f38a79db5237c4c529e04c8", "shasum": "" }, "require": { @@ -4095,7 +4308,7 @@ "type": "tidelift" } ], - "time": "2023-01-29T18:53:47+00:00" + "time": "2023-05-25T22:09:47+00:00" }, { "name": "nette/schema", @@ -4248,16 +4461,16 @@ }, { "name": "nikic/php-parser", - "version": "v4.15.4", + "version": "v4.15.5", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "6bb5176bc4af8bcb7d926f88718db9b96a2d4290" + "reference": "11e2663a5bc9db5d714eedb4277ee300403b4a9e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/6bb5176bc4af8bcb7d926f88718db9b96a2d4290", - "reference": "6bb5176bc4af8bcb7d926f88718db9b96a2d4290", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/11e2663a5bc9db5d714eedb4277ee300403b4a9e", + "reference": "11e2663a5bc9db5d714eedb4277ee300403b4a9e", "shasum": "" }, "require": { @@ -4298,9 +4511,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.4" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.5" }, - "time": "2023-03-05T19:49:14+00:00" + "time": "2023-05-19T20:20:00+00:00" }, { "name": "nunomaduro/termwind", @@ -4947,16 +5160,16 @@ }, { "name": "psy/psysh", - "version": "v0.11.17", + "version": "v0.11.18", "source": { "type": "git", "url": "https://github.com/bobthecow/psysh.git", - "reference": "3dc5d4018dabd80bceb8fe1e3191ba8460569f0a" + "reference": "4f00ee9e236fa6a48f4560d1300b9c961a70a7ec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bobthecow/psysh/zipball/3dc5d4018dabd80bceb8fe1e3191ba8460569f0a", - "reference": "3dc5d4018dabd80bceb8fe1e3191ba8460569f0a", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/4f00ee9e236fa6a48f4560d1300b9c961a70a7ec", + "reference": "4f00ee9e236fa6a48f4560d1300b9c961a70a7ec", "shasum": "" }, "require": { @@ -5017,9 +5230,9 @@ ], "support": { "issues": "https://github.com/bobthecow/psysh/issues", - "source": "https://github.com/bobthecow/psysh/tree/v0.11.17" + "source": "https://github.com/bobthecow/psysh/tree/v0.11.18" }, - "time": "2023-05-05T20:02:42+00:00" + "time": "2023-05-23T02:31:11+00:00" }, { "name": "ralouphie/getallheaders", @@ -5442,16 +5655,16 @@ }, { "name": "spatie/ignition", - "version": "1.7.0", + "version": "1.8.0", "source": { "type": "git", "url": "https://github.com/spatie/ignition.git", - "reference": "f747d83c6d7cb6229b462f3ddbb3a82dc0db0f78" + "reference": "ad13a6792992411e05d3d3b293e26bdf9f9a7321" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/ignition/zipball/f747d83c6d7cb6229b462f3ddbb3a82dc0db0f78", - "reference": "f747d83c6d7cb6229b462f3ddbb3a82dc0db0f78", + "url": "https://api.github.com/repos/spatie/ignition/zipball/ad13a6792992411e05d3d3b293e26bdf9f9a7321", + "reference": "ad13a6792992411e05d3d3b293e26bdf9f9a7321", "shasum": "" }, "require": { @@ -5521,7 +5734,131 @@ "type": "github" } ], - "time": "2023-05-04T13:20:26+00:00" + "time": "2023-05-25T10:19:32+00:00" + }, + { + "name": "spatie/image", + "version": "2.2.6", + "source": { + "type": "git", + "url": "https://github.com/spatie/image.git", + "reference": "f72ca52acd77ca03b7843a0f86e2411ce90aecfc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/image/zipball/f72ca52acd77ca03b7843a0f86e2411ce90aecfc", + "reference": "f72ca52acd77ca03b7843a0f86e2411ce90aecfc", + "shasum": "" + }, + "require": { + "ext-exif": "*", + "ext-json": "*", + "ext-mbstring": "*", + "league/glide": "^2.2.2", + "php": "^8.0", + "spatie/image-optimizer": "^1.1", + "spatie/temporary-directory": "^1.0|^2.0", + "symfony/process": "^3.0|^4.0|^5.0|^6.0" + }, + "require-dev": { + "pestphp/pest": "^1.22", + "phpunit/phpunit": "^9.5", + "symfony/var-dumper": "^4.0|^5.0|^6.0", + "vimeo/psalm": "^4.6" + }, + "type": "library", + "autoload": { + "psr-4": { + "Spatie\\Image\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Freek Van der Herten", + "email": "freek@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" + } + ], + "description": "Manipulate images with an expressive API", + "homepage": "https://github.com/spatie/image", + "keywords": [ + "image", + "spatie" + ], + "support": { + "source": "https://github.com/spatie/image/tree/2.2.6" + }, + "funding": [ + { + "url": "https://spatie.be/open-source/support-us", + "type": "custom" + }, + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2023-05-06T10:20:33+00:00" + }, + { + "name": "spatie/image-optimizer", + "version": "1.6.4", + "source": { + "type": "git", + "url": "https://github.com/spatie/image-optimizer.git", + "reference": "d997e01ba980b2769ddca2f00badd3b80c2a2512" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/image-optimizer/zipball/d997e01ba980b2769ddca2f00badd3b80c2a2512", + "reference": "d997e01ba980b2769ddca2f00badd3b80c2a2512", + "shasum": "" + }, + "require": { + "ext-fileinfo": "*", + "php": "^7.3|^8.0", + "psr/log": "^1.0 | ^2.0 | ^3.0", + "symfony/process": "^4.2|^5.0|^6.0" + }, + "require-dev": { + "pestphp/pest": "^1.21", + "phpunit/phpunit": "^8.5.21|^9.4.4", + "symfony/var-dumper": "^4.2|^5.0|^6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Spatie\\ImageOptimizer\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Freek Van der Herten", + "email": "freek@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" + } + ], + "description": "Easily optimize images using PHP", + "homepage": "https://github.com/spatie/image-optimizer", + "keywords": [ + "image-optimizer", + "spatie" + ], + "support": { + "issues": "https://github.com/spatie/image-optimizer/issues", + "source": "https://github.com/spatie/image-optimizer/tree/1.6.4" + }, + "time": "2023-03-10T08:43:19+00:00" }, { "name": "spatie/laravel-backup", @@ -5624,16 +5961,16 @@ }, { "name": "spatie/laravel-ignition", - "version": "2.1.2", + "version": "2.1.3", "source": { "type": "git", "url": "https://github.com/spatie/laravel-ignition.git", - "reference": "2f99fa6b732a6049e78ed34e4608ce589605ae54" + "reference": "35711943d4725aa80f8033e4f1cb3a6775530b25" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/2f99fa6b732a6049e78ed34e4608ce589605ae54", - "reference": "2f99fa6b732a6049e78ed34e4608ce589605ae54", + "url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/35711943d4725aa80f8033e4f1cb3a6775530b25", + "reference": "35711943d4725aa80f8033e4f1cb3a6775530b25", "shasum": "" }, "require": { @@ -5712,7 +6049,116 @@ "type": "github" } ], - "time": "2023-05-09T07:19:31+00:00" + "time": "2023-05-25T11:30:27+00:00" + }, + { + "name": "spatie/laravel-medialibrary", + "version": "10.9.3", + "source": { + "type": "git", + "url": "https://github.com/spatie/laravel-medialibrary.git", + "reference": "c7eae00741a571f5049f1f1c4090683de8df420c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/laravel-medialibrary/zipball/c7eae00741a571f5049f1f1c4090683de8df420c", + "reference": "c7eae00741a571f5049f1f1c4090683de8df420c", + "shasum": "" + }, + "require": { + "ext-exif": "*", + "ext-fileinfo": "*", + "ext-json": "*", + "illuminate/bus": "^9.18|^10.0", + "illuminate/conditionable": "^9.18|^10.0", + "illuminate/console": "^9.18|^10.0", + "illuminate/database": "^9.18|^10.0", + "illuminate/pipeline": "^9.18|^10.0", + "illuminate/support": "^9.18|^10.0", + "intervention/image": "^2.7", + "maennchen/zipstream-php": "^2.0|^3.0", + "php": "^8.0", + "spatie/image": "^2.2.2", + "spatie/temporary-directory": "^2.0", + "symfony/console": "^6.0" + }, + "conflict": { + "php-ffmpeg/php-ffmpeg": "<0.6.1" + }, + "require-dev": { + "aws/aws-sdk-php": "^3.133.11", + "doctrine/dbal": "^2.13", + "ext-imagick": "*", + "ext-pdo_sqlite": "*", + "ext-zip": "*", + "guzzlehttp/guzzle": "^7.4", + "league/flysystem-aws-s3-v3": "^3.0", + "mockery/mockery": "^1.4", + "nunomaduro/larastan": "^2.0", + "orchestra/testbench": "^7.0|^8.0", + "pestphp/pest": "^1.21", + "phpstan/extension-installer": "^1.1", + "spatie/laravel-ray": "^1.28", + "spatie/pdf-to-image": "^2.1", + "spatie/phpunit-snapshot-assertions": "^4.2" + }, + "suggest": { + "league/flysystem-aws-s3-v3": "Required to use AWS S3 file storage", + "php-ffmpeg/php-ffmpeg": "Required for generating video thumbnails", + "spatie/pdf-to-image": "Required for generating thumbsnails of PDFs and SVGs" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Spatie\\MediaLibrary\\MediaLibraryServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Spatie\\MediaLibrary\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Freek Van der Herten", + "email": "freek@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" + } + ], + "description": "Associate files with Eloquent models", + "homepage": "https://github.com/spatie/laravel-medialibrary", + "keywords": [ + "cms", + "conversion", + "downloads", + "images", + "laravel", + "laravel-medialibrary", + "media", + "spatie" + ], + "support": { + "issues": "https://github.com/spatie/laravel-medialibrary/issues", + "source": "https://github.com/spatie/laravel-medialibrary/tree/10.9.3" + }, + "funding": [ + { + "url": "https://spatie.be/open-source/support-us", + "type": "custom" + }, + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2023-05-22T12:59:16+00:00" }, { "name": "spatie/laravel-package-tools", @@ -6143,23 +6589,23 @@ }, { "name": "symfony/console", - "version": "v6.2.10", + "version": "v6.3.0", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "12288d9f4500f84a4d02254d4aa968b15488476f" + "reference": "8788808b07cf0bdd6e4b7fdd23d8ddb1470c83b7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/12288d9f4500f84a4d02254d4aa968b15488476f", - "reference": "12288d9f4500f84a4d02254d4aa968b15488476f", + "url": "https://api.github.com/repos/symfony/console/zipball/8788808b07cf0bdd6e4b7fdd23d8ddb1470c83b7", + "reference": "8788808b07cf0bdd6e4b7fdd23d8ddb1470c83b7", "shasum": "" }, "require": { "php": ">=8.1", - "symfony/deprecation-contracts": "^2.1|^3", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0", - "symfony/service-contracts": "^1.1|^2|^3", + "symfony/service-contracts": "^2.5|^3", "symfony/string": "^5.4|^6.0" }, "conflict": { @@ -6181,12 +6627,6 @@ "symfony/process": "^5.4|^6.0", "symfony/var-dumper": "^5.4|^6.0" }, - "suggest": { - "psr/log": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/lock": "", - "symfony/process": "" - }, "type": "library", "autoload": { "psr-4": { @@ -6219,7 +6659,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.2.10" + "source": "https://github.com/symfony/console/tree/v6.3.0" }, "funding": [ { @@ -6235,7 +6675,7 @@ "type": "tidelift" } ], - "time": "2023-04-28T13:37:43+00:00" + "time": "2023-05-29T12:49:39+00:00" }, { "name": "symfony/css-selector", @@ -6295,16 +6735,16 @@ }, { "name": "symfony/deprecation-contracts", - "version": "v3.2.1", + "version": "v3.3.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "e2d1534420bd723d0ef5aec58a22c5fe60ce6f5e" + "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e2d1534420bd723d0ef5aec58a22c5fe60ce6f5e", - "reference": "e2d1534420bd723d0ef5aec58a22c5fe60ce6f5e", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/7c3aff79d10325257a001fcf92d991f24fc967cf", + "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf", "shasum": "" }, "require": { @@ -6313,7 +6753,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "3.3-dev" + "dev-main": "3.4-dev" }, "thanks": { "name": "symfony/contracts", @@ -6342,7 +6782,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.2.1" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.3.0" }, "funding": [ { @@ -6358,20 +6798,20 @@ "type": "tidelift" } ], - "time": "2023-03-01T10:25:55+00:00" + "time": "2023-05-23T14:45:45+00:00" }, { "name": "symfony/error-handler", - "version": "v6.2.10", + "version": "v6.3.0", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "8b7e9f124640cb0611624a9383176c3e5f7d8cfb" + "reference": "99d2d814a6351461af350ead4d963bd67451236f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/8b7e9f124640cb0611624a9383176c3e5f7d8cfb", - "reference": "8b7e9f124640cb0611624a9383176c3e5f7d8cfb", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/99d2d814a6351461af350ead4d963bd67451236f", + "reference": "99d2d814a6351461af350ead4d963bd67451236f", "shasum": "" }, "require": { @@ -6379,8 +6819,11 @@ "psr/log": "^1|^2|^3", "symfony/var-dumper": "^5.4|^6.0" }, + "conflict": { + "symfony/deprecation-contracts": "<2.5" + }, "require-dev": { - "symfony/deprecation-contracts": "^2.1|^3", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/http-kernel": "^5.4|^6.0", "symfony/serializer": "^5.4|^6.0" }, @@ -6413,7 +6856,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v6.2.10" + "source": "https://github.com/symfony/error-handler/tree/v6.3.0" }, "funding": [ { @@ -6429,28 +6872,29 @@ "type": "tidelift" } ], - "time": "2023-04-18T13:46:08+00:00" + "time": "2023-05-10T12:03:13+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v6.2.8", + "version": "v6.3.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "04046f35fd7d72f9646e721fc2ecb8f9c67d3339" + "reference": "3af8ac1a3f98f6dbc55e10ae59c9e44bfc38dfaa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/04046f35fd7d72f9646e721fc2ecb8f9c67d3339", - "reference": "04046f35fd7d72f9646e721fc2ecb8f9c67d3339", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/3af8ac1a3f98f6dbc55e10ae59c9e44bfc38dfaa", + "reference": "3af8ac1a3f98f6dbc55e10ae59c9e44bfc38dfaa", "shasum": "" }, "require": { "php": ">=8.1", - "symfony/event-dispatcher-contracts": "^2|^3" + "symfony/event-dispatcher-contracts": "^2.5|^3" }, "conflict": { - "symfony/dependency-injection": "<5.4" + "symfony/dependency-injection": "<5.4", + "symfony/service-contracts": "<2.5" }, "provide": { "psr/event-dispatcher-implementation": "1.0", @@ -6463,13 +6907,9 @@ "symfony/error-handler": "^5.4|^6.0", "symfony/expression-language": "^5.4|^6.0", "symfony/http-foundation": "^5.4|^6.0", - "symfony/service-contracts": "^1.1|^2|^3", + "symfony/service-contracts": "^2.5|^3", "symfony/stopwatch": "^5.4|^6.0" }, - "suggest": { - "symfony/dependency-injection": "", - "symfony/http-kernel": "" - }, "type": "library", "autoload": { "psr-4": { @@ -6496,7 +6936,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v6.2.8" + "source": "https://github.com/symfony/event-dispatcher/tree/v6.3.0" }, "funding": [ { @@ -6512,33 +6952,30 @@ "type": "tidelift" } ], - "time": "2023-03-20T16:06:02+00:00" + "time": "2023-04-21T14:41:17+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v3.2.1", + "version": "v3.3.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "0ad3b6f1e4e2da5690fefe075cd53a238646d8dd" + "reference": "a76aed96a42d2b521153fb382d418e30d18b59df" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/0ad3b6f1e4e2da5690fefe075cd53a238646d8dd", - "reference": "0ad3b6f1e4e2da5690fefe075cd53a238646d8dd", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/a76aed96a42d2b521153fb382d418e30d18b59df", + "reference": "a76aed96a42d2b521153fb382d418e30d18b59df", "shasum": "" }, "require": { "php": ">=8.1", "psr/event-dispatcher": "^1" }, - "suggest": { - "symfony/event-dispatcher-implementation": "" - }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.3-dev" + "dev-main": "3.4-dev" }, "thanks": { "name": "symfony/contracts", @@ -6575,7 +7012,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.2.1" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.3.0" }, "funding": [ { @@ -6591,20 +7028,20 @@ "type": "tidelift" } ], - "time": "2023-03-01T10:32:47+00:00" + "time": "2023-05-23T14:45:45+00:00" }, { "name": "symfony/finder", - "version": "v6.2.7", + "version": "v6.3.0", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "20808dc6631aecafbe67c186af5dcb370be3a0eb" + "reference": "d9b01ba073c44cef617c7907ce2419f8d00d75e2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/20808dc6631aecafbe67c186af5dcb370be3a0eb", - "reference": "20808dc6631aecafbe67c186af5dcb370be3a0eb", + "url": "https://api.github.com/repos/symfony/finder/zipball/d9b01ba073c44cef617c7907ce2419f8d00d75e2", + "reference": "d9b01ba073c44cef617c7907ce2419f8d00d75e2", "shasum": "" }, "require": { @@ -6639,7 +7076,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v6.2.7" + "source": "https://github.com/symfony/finder/tree/v6.3.0" }, "funding": [ { @@ -6655,32 +7092,34 @@ "type": "tidelift" } ], - "time": "2023-02-16T09:57:23+00:00" + "time": "2023-04-02T01:25:41+00:00" }, { "name": "symfony/http-foundation", - "version": "v6.2.10", + "version": "v6.3.0", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "49adbb92bcb4e3c2943719d2756271e8b9602acc" + "reference": "718a97ed430d34e5c568ea2c44eab708c6efbefb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/49adbb92bcb4e3c2943719d2756271e8b9602acc", - "reference": "49adbb92bcb4e3c2943719d2756271e8b9602acc", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/718a97ed430d34e5c568ea2c44eab708c6efbefb", + "reference": "718a97ed430d34e5c568ea2c44eab708c6efbefb", "shasum": "" }, "require": { "php": ">=8.1", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-mbstring": "~1.1" + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "~1.1", + "symfony/polyfill-php83": "^1.27" }, "conflict": { "symfony/cache": "<6.2" }, "require-dev": { - "predis/predis": "~1.0", + "doctrine/dbal": "^2.13.1|^3.0", + "predis/predis": "^1.1|^2.0", "symfony/cache": "^5.4|^6.0", "symfony/dependency-injection": "^5.4|^6.0", "symfony/expression-language": "^5.4|^6.0", @@ -6688,9 +7127,6 @@ "symfony/mime": "^5.4|^6.0", "symfony/rate-limiter": "^5.2|^6.0" }, - "suggest": { - "symfony/mime": "To use the file extension guesser" - }, "type": "library", "autoload": { "psr-4": { @@ -6717,7 +7153,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v6.2.10" + "source": "https://github.com/symfony/http-foundation/tree/v6.3.0" }, "funding": [ { @@ -6733,29 +7169,29 @@ "type": "tidelift" } ], - "time": "2023-04-18T13:46:08+00:00" + "time": "2023-05-19T12:46:45+00:00" }, { "name": "symfony/http-kernel", - "version": "v6.2.10", + "version": "v6.3.0", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "81064a65a5496f17d2b6984f6519406f98864215" + "reference": "241973f3dd900620b1ca052fe409144f11aea748" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/81064a65a5496f17d2b6984f6519406f98864215", - "reference": "81064a65a5496f17d2b6984f6519406f98864215", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/241973f3dd900620b1ca052fe409144f11aea748", + "reference": "241973f3dd900620b1ca052fe409144f11aea748", "shasum": "" }, "require": { "php": ">=8.1", "psr/log": "^1|^2|^3", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/error-handler": "^6.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/error-handler": "^6.3", "symfony/event-dispatcher": "^5.4|^6.0", - "symfony/http-foundation": "^5.4.21|^6.2.7", + "symfony/http-foundation": "^6.2.7", "symfony/polyfill-ctype": "^1.8" }, "conflict": { @@ -6763,15 +7199,18 @@ "symfony/cache": "<5.4", "symfony/config": "<6.1", "symfony/console": "<5.4", - "symfony/dependency-injection": "<6.2", + "symfony/dependency-injection": "<6.3", "symfony/doctrine-bridge": "<5.4", "symfony/form": "<5.4", "symfony/http-client": "<5.4", + "symfony/http-client-contracts": "<2.5", "symfony/mailer": "<5.4", "symfony/messenger": "<5.4", "symfony/translation": "<5.4", + "symfony/translation-contracts": "<2.5", "symfony/twig-bridge": "<5.4", "symfony/validator": "<5.4", + "symfony/var-dumper": "<6.3", "twig/twig": "<2.13" }, "provide": { @@ -6780,28 +7219,27 @@ "require-dev": { "psr/cache": "^1.0|^2.0|^3.0", "symfony/browser-kit": "^5.4|^6.0", + "symfony/clock": "^6.2", "symfony/config": "^6.1", "symfony/console": "^5.4|^6.0", "symfony/css-selector": "^5.4|^6.0", - "symfony/dependency-injection": "^6.2", + "symfony/dependency-injection": "^6.3", "symfony/dom-crawler": "^5.4|^6.0", "symfony/expression-language": "^5.4|^6.0", "symfony/finder": "^5.4|^6.0", - "symfony/http-client-contracts": "^1.1|^2|^3", + "symfony/http-client-contracts": "^2.5|^3", "symfony/process": "^5.4|^6.0", + "symfony/property-access": "^5.4.5|^6.0.5", "symfony/routing": "^5.4|^6.0", + "symfony/serializer": "^6.3", "symfony/stopwatch": "^5.4|^6.0", "symfony/translation": "^5.4|^6.0", - "symfony/translation-contracts": "^1.1|^2|^3", + "symfony/translation-contracts": "^2.5|^3", "symfony/uid": "^5.4|^6.0", + "symfony/validator": "^6.3", + "symfony/var-exporter": "^6.2", "twig/twig": "^2.13|^3.0.4" }, - "suggest": { - "symfony/browser-kit": "", - "symfony/config": "", - "symfony/console": "", - "symfony/dependency-injection": "" - }, "type": "library", "autoload": { "psr-4": { @@ -6828,7 +7266,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v6.2.10" + "source": "https://github.com/symfony/http-kernel/tree/v6.3.0" }, "funding": [ { @@ -6844,20 +7282,20 @@ "type": "tidelift" } ], - "time": "2023-04-28T13:50:28+00:00" + "time": "2023-05-30T19:03:32+00:00" }, { "name": "symfony/mailer", - "version": "v6.2.8", + "version": "v6.3.0", "source": { "type": "git", "url": "https://github.com/symfony/mailer.git", - "reference": "bfcfa015c67e19c6fdb7ca6fe70700af1e740a17" + "reference": "7b03d9be1dea29bfec0a6c7b603f5072a4c97435" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailer/zipball/bfcfa015c67e19c6fdb7ca6fe70700af1e740a17", - "reference": "bfcfa015c67e19c6fdb7ca6fe70700af1e740a17", + "url": "https://api.github.com/repos/symfony/mailer/zipball/7b03d9be1dea29bfec0a6c7b603f5072a4c97435", + "reference": "7b03d9be1dea29bfec0a6c7b603f5072a4c97435", "shasum": "" }, "require": { @@ -6867,9 +7305,10 @@ "psr/log": "^1|^2|^3", "symfony/event-dispatcher": "^5.4|^6.0", "symfony/mime": "^6.2", - "symfony/service-contracts": "^1.1|^2|^3" + "symfony/service-contracts": "^2.5|^3" }, "conflict": { + "symfony/http-client-contracts": "<2.5", "symfony/http-kernel": "<5.4", "symfony/messenger": "<6.2", "symfony/mime": "<6.2", @@ -6907,7 +7346,7 @@ "description": "Helps sending emails", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailer/tree/v6.2.8" + "source": "https://github.com/symfony/mailer/tree/v6.3.0" }, "funding": [ { @@ -6923,20 +7362,20 @@ "type": "tidelift" } ], - "time": "2023-03-14T15:00:05+00:00" + "time": "2023-05-29T12:49:39+00:00" }, { "name": "symfony/mime", - "version": "v6.2.10", + "version": "v6.3.0", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "b6c137fc53a9f7c4c951cd3f362b3734c7a97723" + "reference": "7b5d2121858cd6efbed778abce9cfdd7ab1f62ad" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/b6c137fc53a9f7c4c951cd3f362b3734c7a97723", - "reference": "b6c137fc53a9f7c4c951cd3f362b3734c7a97723", + "url": "https://api.github.com/repos/symfony/mime/zipball/7b5d2121858cd6efbed778abce9cfdd7ab1f62ad", + "reference": "7b5d2121858cd6efbed778abce9cfdd7ab1f62ad", "shasum": "" }, "require": { @@ -6990,7 +7429,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v6.2.10" + "source": "https://github.com/symfony/mime/tree/v6.3.0" }, "funding": [ { @@ -7006,7 +7445,7 @@ "type": "tidelift" } ], - "time": "2023-04-19T09:54:16+00:00" + "time": "2023-04-28T15:57:00+00:00" }, { "name": "symfony/polyfill-ctype", @@ -7584,6 +8023,83 @@ ], "time": "2022-11-03T14:55:06+00:00" }, + { + "name": "symfony/polyfill-php83", + "version": "v1.27.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php83.git", + "reference": "508c652ba3ccf69f8c97f251534f229791b52a57" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/508c652ba3ccf69f8c97f251534f229791b52a57", + "reference": "508c652ba3ccf69f8c97f251534f229791b52a57", + "shasum": "" + }, + "require": { + "php": ">=7.1", + "symfony/polyfill-php80": "^1.14" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php83\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.3+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php83/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-03T14:55:06+00:00" + }, { "name": "symfony/polyfill-uuid", "version": "v1.27.0", @@ -7668,16 +8184,16 @@ }, { "name": "symfony/process", - "version": "v6.2.10", + "version": "v6.3.0", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "b34cdbc9c5e75d45a3703e63a48ad07aafa8bf2e" + "reference": "8741e3ed7fe2e91ec099e02446fb86667a0f1628" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/b34cdbc9c5e75d45a3703e63a48ad07aafa8bf2e", - "reference": "b34cdbc9c5e75d45a3703e63a48ad07aafa8bf2e", + "url": "https://api.github.com/repos/symfony/process/zipball/8741e3ed7fe2e91ec099e02446fb86667a0f1628", + "reference": "8741e3ed7fe2e91ec099e02446fb86667a0f1628", "shasum": "" }, "require": { @@ -7709,7 +8225,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v6.2.10" + "source": "https://github.com/symfony/process/tree/v6.3.0" }, "funding": [ { @@ -7725,20 +8241,20 @@ "type": "tidelift" } ], - "time": "2023-04-18T13:56:57+00:00" + "time": "2023-05-19T08:06:44+00:00" }, { "name": "symfony/routing", - "version": "v6.2.8", + "version": "v6.3.0", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "69062e2823f03b82265d73a966999660f0e1e404" + "reference": "827f59fdc67eecfc4dfff81f9c93bf4d98f0c89b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/69062e2823f03b82265d73a966999660f0e1e404", - "reference": "69062e2823f03b82265d73a966999660f0e1e404", + "url": "https://api.github.com/repos/symfony/routing/zipball/827f59fdc67eecfc4dfff81f9c93bf4d98f0c89b", + "reference": "827f59fdc67eecfc4dfff81f9c93bf4d98f0c89b", "shasum": "" }, "require": { @@ -7759,12 +8275,6 @@ "symfony/http-foundation": "^5.4|^6.0", "symfony/yaml": "^5.4|^6.0" }, - "suggest": { - "symfony/config": "For using the all-in-one router or any loader", - "symfony/expression-language": "For using expression matching", - "symfony/http-foundation": "For using a Symfony Request object", - "symfony/yaml": "For using the YAML loader" - }, "type": "library", "autoload": { "psr-4": { @@ -7797,7 +8307,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v6.2.8" + "source": "https://github.com/symfony/routing/tree/v6.3.0" }, "funding": [ { @@ -7813,20 +8323,20 @@ "type": "tidelift" } ], - "time": "2023-03-14T15:00:05+00:00" + "time": "2023-04-28T15:57:00+00:00" }, { "name": "symfony/service-contracts", - "version": "v3.2.1", + "version": "v3.3.0", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "a8c9cedf55f314f3a186041d19537303766df09a" + "reference": "40da9cc13ec349d9e4966ce18b5fbcd724ab10a4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/a8c9cedf55f314f3a186041d19537303766df09a", - "reference": "a8c9cedf55f314f3a186041d19537303766df09a", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/40da9cc13ec349d9e4966ce18b5fbcd724ab10a4", + "reference": "40da9cc13ec349d9e4966ce18b5fbcd724ab10a4", "shasum": "" }, "require": { @@ -7836,13 +8346,10 @@ "conflict": { "ext-psr": "<1.1|>=2" }, - "suggest": { - "symfony/service-implementation": "" - }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.3-dev" + "dev-main": "3.4-dev" }, "thanks": { "name": "symfony/contracts", @@ -7882,7 +8389,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.2.1" + "source": "https://github.com/symfony/service-contracts/tree/v3.3.0" }, "funding": [ { @@ -7898,20 +8405,20 @@ "type": "tidelift" } ], - "time": "2023-03-01T10:32:47+00:00" + "time": "2023-05-23T14:45:45+00:00" }, { "name": "symfony/string", - "version": "v6.2.8", + "version": "v6.3.0", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "193e83bbd6617d6b2151c37fff10fa7168ebddef" + "reference": "f2e190ee75ff0f5eced645ec0be5c66fac81f51f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/193e83bbd6617d6b2151c37fff10fa7168ebddef", - "reference": "193e83bbd6617d6b2151c37fff10fa7168ebddef", + "url": "https://api.github.com/repos/symfony/string/zipball/f2e190ee75ff0f5eced645ec0be5c66fac81f51f", + "reference": "f2e190ee75ff0f5eced645ec0be5c66fac81f51f", "shasum": "" }, "require": { @@ -7922,13 +8429,13 @@ "symfony/polyfill-mbstring": "~1.0" }, "conflict": { - "symfony/translation-contracts": "<2.0" + "symfony/translation-contracts": "<2.5" }, "require-dev": { "symfony/error-handler": "^5.4|^6.0", "symfony/http-client": "^5.4|^6.0", "symfony/intl": "^6.2", - "symfony/translation-contracts": "^2.0|^3.0", + "symfony/translation-contracts": "^2.5|^3.0", "symfony/var-exporter": "^5.4|^6.0" }, "type": "library", @@ -7968,7 +8475,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.2.8" + "source": "https://github.com/symfony/string/tree/v6.3.0" }, "funding": [ { @@ -7984,32 +8491,34 @@ "type": "tidelift" } ], - "time": "2023-03-20T16:06:02+00:00" + "time": "2023-03-21T21:06:29+00:00" }, { "name": "symfony/translation", - "version": "v6.2.8", + "version": "v6.3.0", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "817535dbb1721df8b3a8f2489dc7e50bcd6209b5" + "reference": "f72b2cba8f79dd9d536f534f76874b58ad37876f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/817535dbb1721df8b3a8f2489dc7e50bcd6209b5", - "reference": "817535dbb1721df8b3a8f2489dc7e50bcd6209b5", + "url": "https://api.github.com/repos/symfony/translation/zipball/f72b2cba8f79dd9d536f534f76874b58ad37876f", + "reference": "f72b2cba8f79dd9d536f534f76874b58ad37876f", "shasum": "" }, "require": { "php": ">=8.1", "symfony/polyfill-mbstring": "~1.0", - "symfony/translation-contracts": "^2.3|^3.0" + "symfony/translation-contracts": "^2.5|^3.0" }, "conflict": { "symfony/config": "<5.4", "symfony/console": "<5.4", "symfony/dependency-injection": "<5.4", + "symfony/http-client-contracts": "<2.5", "symfony/http-kernel": "<5.4", + "symfony/service-contracts": "<2.5", "symfony/twig-bundle": "<5.4", "symfony/yaml": "<5.4" }, @@ -8023,20 +8532,14 @@ "symfony/console": "^5.4|^6.0", "symfony/dependency-injection": "^5.4|^6.0", "symfony/finder": "^5.4|^6.0", - "symfony/http-client-contracts": "^1.1|^2.0|^3.0", + "symfony/http-client-contracts": "^2.5|^3.0", "symfony/http-kernel": "^5.4|^6.0", "symfony/intl": "^5.4|^6.0", "symfony/polyfill-intl-icu": "^1.21", "symfony/routing": "^5.4|^6.0", - "symfony/service-contracts": "^1.1.2|^2|^3", + "symfony/service-contracts": "^2.5|^3", "symfony/yaml": "^5.4|^6.0" }, - "suggest": { - "nikic/php-parser": "To use PhpAstExtractor", - "psr/log-implementation": "To use logging capability in translator", - "symfony/config": "", - "symfony/yaml": "" - }, "type": "library", "autoload": { "files": [ @@ -8066,7 +8569,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v6.2.8" + "source": "https://github.com/symfony/translation/tree/v6.3.0" }, "funding": [ { @@ -8082,32 +8585,29 @@ "type": "tidelift" } ], - "time": "2023-03-31T09:14:44+00:00" + "time": "2023-05-19T12:46:45+00:00" }, { "name": "symfony/translation-contracts", - "version": "v3.2.1", + "version": "v3.3.0", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "dfec258b9dd17a6b24420d464c43bffe347441c8" + "reference": "02c24deb352fb0d79db5486c0c79905a85e37e86" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/dfec258b9dd17a6b24420d464c43bffe347441c8", - "reference": "dfec258b9dd17a6b24420d464c43bffe347441c8", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/02c24deb352fb0d79db5486c0c79905a85e37e86", + "reference": "02c24deb352fb0d79db5486c0c79905a85e37e86", "shasum": "" }, "require": { "php": ">=8.1" }, - "suggest": { - "symfony/translation-implementation": "" - }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.3-dev" + "dev-main": "3.4-dev" }, "thanks": { "name": "symfony/contracts", @@ -8147,7 +8647,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v3.2.1" + "source": "https://github.com/symfony/translation-contracts/tree/v3.3.0" }, "funding": [ { @@ -8163,20 +8663,20 @@ "type": "tidelift" } ], - "time": "2023-03-01T10:32:47+00:00" + "time": "2023-05-30T17:17:10+00:00" }, { "name": "symfony/uid", - "version": "v6.2.7", + "version": "v6.3.0", "source": { "type": "git", "url": "https://github.com/symfony/uid.git", - "reference": "d30c72a63897cfa043e1de4d4dd2ffa9ecefcdc0" + "reference": "01b0f20b1351d997711c56f1638f7a8c3061e384" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/uid/zipball/d30c72a63897cfa043e1de4d4dd2ffa9ecefcdc0", - "reference": "d30c72a63897cfa043e1de4d4dd2ffa9ecefcdc0", + "url": "https://api.github.com/repos/symfony/uid/zipball/01b0f20b1351d997711c56f1638f7a8c3061e384", + "reference": "01b0f20b1351d997711c56f1638f7a8c3061e384", "shasum": "" }, "require": { @@ -8221,7 +8721,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/uid/tree/v6.2.7" + "source": "https://github.com/symfony/uid/tree/v6.3.0" }, "funding": [ { @@ -8237,20 +8737,20 @@ "type": "tidelift" } ], - "time": "2023-02-14T08:44:56+00:00" + "time": "2023-04-08T07:25:02+00:00" }, { "name": "symfony/var-dumper", - "version": "v6.2.10", + "version": "v6.3.0", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "41a750a23412ca76fdbbf5096943b4134272c1ab" + "reference": "6acdcd5c122074ee9f7b051e4fb177025c277a0e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/41a750a23412ca76fdbbf5096943b4134272c1ab", - "reference": "41a750a23412ca76fdbbf5096943b4134272c1ab", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/6acdcd5c122074ee9f7b051e4fb177025c277a0e", + "reference": "6acdcd5c122074ee9f7b051e4fb177025c277a0e", "shasum": "" }, "require": { @@ -8258,7 +8758,6 @@ "symfony/polyfill-mbstring": "~1.0" }, "conflict": { - "phpunit/phpunit": "<5.4.3", "symfony/console": "<5.4" }, "require-dev": { @@ -8268,11 +8767,6 @@ "symfony/uid": "^5.4|^6.0", "twig/twig": "^2.13|^3.0.4" }, - "suggest": { - "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).", - "ext-intl": "To show region name in time zone dump", - "symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script" - }, "bin": [ "Resources/bin/var-dump-server" ], @@ -8309,7 +8803,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v6.2.10" + "source": "https://github.com/symfony/var-dumper/tree/v6.3.0" }, "funding": [ { @@ -8325,7 +8819,7 @@ "type": "tidelift" } ], - "time": "2023-04-18T13:46:08+00:00" + "time": "2023-05-25T13:09:35+00:00" }, { "name": "tijsverkoyen/css-to-inline-styles", @@ -9245,16 +9739,16 @@ }, { "name": "phpunit/php-code-coverage", - "version": "10.1.1", + "version": "10.1.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "884a0da7f9f46f28b2cb69134217fd810b793974" + "reference": "db1497ec8dd382e82c962f7abbe0320e4882ee4e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/884a0da7f9f46f28b2cb69134217fd810b793974", - "reference": "884a0da7f9f46f28b2cb69134217fd810b793974", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/db1497ec8dd382e82c962f7abbe0320e4882ee4e", + "reference": "db1497ec8dd382e82c962f7abbe0320e4882ee4e", "shasum": "" }, "require": { @@ -9311,7 +9805,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.1" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.2" }, "funding": [ { @@ -9319,7 +9813,7 @@ "type": "github" } ], - "time": "2023-04-17T12:15:40+00:00" + "time": "2023-05-22T09:04:27+00:00" }, { "name": "phpunit/php-file-iterator", @@ -10721,6 +11215,7 @@ "backpack/theme-coreuiv2": 20, "backpack/theme-coreuiv4": 20, "backpack/theme-tabler": 20, + "backpack/medialibrary-uploaders": 20, "backpack/generators": 20 }, "prefer-stable": true, diff --git a/public/products b/public/products new file mode 120000 index 000000000..8f2ec7c3c --- /dev/null +++ b/public/products @@ -0,0 +1 @@ +/Users/tabacitu/Code/bp-2023-05-31/storage/app/public/products \ No newline at end of file From 2dc38ceadfb2e0a10fa4d9fc9cf2c53fd7c55309 Mon Sep 17 00:00:00 2001 From: Pedro X Date: Tue, 13 Jun 2023 15:04:17 +0100 Subject: [PATCH 10/16] add media library demo --- .../Admin/ProductCrudController.php | 37 +-- app/Models/Product.php | 52 ++++ config/media-library.php | 237 ------------------ 3 files changed, 75 insertions(+), 251 deletions(-) delete mode 100644 config/media-library.php diff --git a/app/Http/Controllers/Admin/ProductCrudController.php b/app/Http/Controllers/Admin/ProductCrudController.php index b41a933ac..7446c6a30 100644 --- a/app/Http/Controllers/Admin/ProductCrudController.php +++ b/app/Http/Controllers/Admin/ProductCrudController.php @@ -17,6 +17,7 @@ class ProductCrudController extends CrudController use \Backpack\CRUD\app\Http\Controllers\Operations\BulkDeleteOperation; use \Backpack\CRUD\app\Http\Controllers\Operations\BulkCloneOperation; use \Backpack\CRUD\app\Http\Controllers\Operations\InlineCreateOperation; + use \Backpack\Pro\Http\Controllers\Operations\DropzoneOperation { dropzoneUpload as traitDropzoneUpload;} public function setup() { @@ -211,9 +212,7 @@ protected function setupCreateOperation() ->type('image') ->tab('Media') ->wrapper(['class' => 'form-group col-md-4']) - ->withMedia([ - 'disk' => 'products', - ]); + ->withMedia(); CRUD::field('privacy_policy') ->label('Privacy policy document') @@ -227,9 +226,7 @@ protected function setupCreateOperation() ->type('upload_multiple') ->tab('Media') ->wrapper(['class' => 'form-group col-md-4']) - ->withMedia([ - 'disk' => 'products', - ]); + ->withMedia(); CRUD::field('gallery') ->type('repeatable') @@ -249,9 +246,7 @@ protected function setupCreateOperation() 'wrapper' => [ 'class' => 'form-group col-md-6', ], - 'withMedia' => [ - 'disk' => 'products', - ], + 'withMedia' => true, ], [ @@ -261,9 +256,7 @@ protected function setupCreateOperation() 'wrapper' => [ 'class' => 'form-group col-md-6', ], - 'withMedia' => [ - 'disk' => 'products', - ], + 'withMedia' => true, ], [ 'name' => 'gallery_image_specifications', @@ -272,9 +265,16 @@ protected function setupCreateOperation() 'wrapper' => [ 'class' => 'form-group col-md-6', ], - 'withMedia' => [ - 'disk' => 'products', + 'withMedia' => true, + ], + [ + 'name' => 'gallery_image_certificates', + 'label' => 'Image Certificates', + 'type' => 'dropzone', + 'wrapper' => [ + 'class' => 'form-group col-md-6', ], + 'withMedia' => true, ], ]); @@ -285,4 +285,13 @@ protected function setupUpdateOperation() { $this->setupCreateOperation(); } + + public function dropzoneUpload() + { + if (app('env') === 'production') { + return response()->json([]); + } + + return $this->traitDropzoneUpload(); + } } diff --git a/app/Models/Product.php b/app/Models/Product.php index f38c0f9bf..d6b42a87c 100644 --- a/app/Models/Product.php +++ b/app/Models/Product.php @@ -5,6 +5,7 @@ use App\Enums\ProductStatus; use Backpack\CRUD\app\Models\Traits\CrudTrait; use Backpack\CRUD\app\Models\Traits\SpatieTranslatable\HasTranslations; +use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Spatie\MediaLibrary\HasMedia; @@ -43,6 +44,57 @@ class Product extends Model implements HasMedia 'specifications' => 'array', ]; + public function mainImage(): Attribute + { + return Attribute::make( + set: function($item) { + if (app('env') === 'production') { + return null; + } + return $item; + }, + ); + } + + public function privacyPolicy(): Attribute + { + return Attribute::make( + set: function($item) { + if (app('env') === 'production') { + return null; + } + return $item; + }, + ); + } + + public function specifications(): Attribute + { + return Attribute::make( + set: function($item) { + if (app('env') === 'production') { + return null; + } + return json_encode($item); + }, + ); + } + + public function gallery(): Attribute + { + return Attribute::make( + set: function($item) { + if (app('env') === 'production') { + array_walk($item, function(&$row) { + unset($row['gallery_image'], $row['gallery_image_drm'], $row['gallery_image_specifications'], $row['gallery_image_certificates']); + return $row; + }); + } + + return json_encode($item); + }, + ); + } /* |-------------------------------------------------------------------------- | FUNCTIONS diff --git a/config/media-library.php b/config/media-library.php deleted file mode 100644 index 37d0ccf5f..000000000 --- a/config/media-library.php +++ /dev/null @@ -1,237 +0,0 @@ - env('MEDIA_DISK', 'products'), - - /* - * The maximum file size of an item in bytes. - * Adding a larger file will result in an exception. - */ - 'max_file_size' => 1024 * 1024 * 10, // 10MB - - /* - * This queue connection will be used to generate derived and responsive images. - * Leave empty to use the default queue connection. - */ - 'queue_connection_name' => env('QUEUE_CONNECTION', 'sync'), - - /* - * This queue will be used to generate derived and responsive images. - * Leave empty to use the default queue. - */ - 'queue_name' => '', - - /* - * By default all conversions will be performed on a queue. - */ - 'queue_conversions_by_default' => env('QUEUE_CONVERSIONS_BY_DEFAULT', true), - - /* - * The fully qualified class name of the media model. - */ - 'media_model' => Spatie\MediaLibrary\MediaCollections\Models\Media::class, - - /* - * The fully qualified class name of the model used for temporary uploads. - * - * This model is only used in Media Library Pro (https://medialibrary.pro) - */ - 'temporary_upload_model' => Spatie\MediaLibraryPro\Models\TemporaryUpload::class, - - /* - * When enabled, Media Library Pro will only process temporary uploads that were uploaded - * in the same session. You can opt to disable this for stateless usage of - * the pro components. - */ - 'enable_temporary_uploads_session_affinity' => true, - - /* - * When enabled, Media Library pro will generate thumbnails for uploaded file. - */ - 'generate_thumbnails_for_temporary_uploads' => true, - - /* - * This is the class that is responsible for naming generated files. - */ - 'file_namer' => Spatie\MediaLibrary\Support\FileNamer\DefaultFileNamer::class, - - /* - * The class that contains the strategy for determining a media file's path. - */ - 'path_generator' => Spatie\MediaLibrary\Support\PathGenerator\DefaultPathGenerator::class, - - /* - * Here you can specify which path generator should be used for the given class. - */ - 'custom_path_generators' => [ - // Model::class => PathGenerator::class - // or - // 'model_morph_alias' => PathGenerator::class - ], - - /* - * When urls to files get generated, this class will be called. Use the default - * if your files are stored locally above the site root or on s3. - */ - 'url_generator' => Spatie\MediaLibrary\Support\UrlGenerator\DefaultUrlGenerator::class, - - /* - * Moves media on updating to keep path consistent. Enable it only with a custom - * PathGenerator that uses, for example, the media UUID. - */ - 'moves_media_on_update' => false, - - /* - * Whether to activate versioning when urls to files get generated. - * When activated, this attaches a ?v=xx query string to the URL. - */ - 'version_urls' => false, - - /* - * The media library will try to optimize all converted images by removing - * metadata and applying a little bit of compression. These are - * the optimizers that will be used by default. - */ - 'image_optimizers' => [ - Spatie\ImageOptimizer\Optimizers\Jpegoptim::class => [ - '-m85', // set maximum quality to 85% - '--force', // ensure that progressive generation is always done also if a little bigger - '--strip-all', // this strips out all text information such as comments and EXIF data - '--all-progressive', // this will make sure the resulting image is a progressive one - ], - Spatie\ImageOptimizer\Optimizers\Pngquant::class => [ - '--force', // required parameter for this package - ], - Spatie\ImageOptimizer\Optimizers\Optipng::class => [ - '-i0', // this will result in a non-interlaced, progressive scanned image - '-o2', // this set the optimization level to two (multiple IDAT compression trials) - '-quiet', // required parameter for this package - ], - Spatie\ImageOptimizer\Optimizers\Svgo::class => [ - '--disable=cleanupIDs', // disabling because it is known to cause troubles - ], - Spatie\ImageOptimizer\Optimizers\Gifsicle::class => [ - '-b', // required parameter for this package - '-O3', // this produces the slowest but best results - ], - Spatie\ImageOptimizer\Optimizers\Cwebp::class => [ - '-m 6', // for the slowest compression method in order to get the best compression. - '-pass 10', // for maximizing the amount of analysis pass. - '-mt', // multithreading for some speed improvements. - '-q 90', //quality factor that brings the least noticeable changes. - ], - ], - - /* - * These generators will be used to create an image of media files. - */ - 'image_generators' => [ - Spatie\MediaLibrary\Conversions\ImageGenerators\Image::class, - Spatie\MediaLibrary\Conversions\ImageGenerators\Webp::class, - Spatie\MediaLibrary\Conversions\ImageGenerators\Pdf::class, - Spatie\MediaLibrary\Conversions\ImageGenerators\Svg::class, - Spatie\MediaLibrary\Conversions\ImageGenerators\Video::class, - ], - - /* - * The path where to store temporary files while performing image conversions. - * If set to null, storage_path('media-library/temp') will be used. - */ - 'temporary_directory_path' => null, - - /* - * The engine that should perform the image conversions. - * Should be either `gd` or `imagick`. - */ - 'image_driver' => env('IMAGE_DRIVER', 'gd'), - - /* - * FFMPEG & FFProbe binaries paths, only used if you try to generate video - * thumbnails and have installed the php-ffmpeg/php-ffmpeg composer - * dependency. - */ - 'ffmpeg_path' => env('FFMPEG_PATH', '/usr/bin/ffmpeg'), - 'ffprobe_path' => env('FFPROBE_PATH', '/usr/bin/ffprobe'), - - /* - * Here you can override the class names of the jobs used by this package. Make sure - * your custom jobs extend the ones provided by the package. - */ - 'jobs' => [ - 'perform_conversions' => Spatie\MediaLibrary\Conversions\Jobs\PerformConversionsJob::class, - 'generate_responsive_images' => Spatie\MediaLibrary\ResponsiveImages\Jobs\GenerateResponsiveImagesJob::class, - ], - - /* - * When using the addMediaFromUrl method you may want to replace the default downloader. - * This is particularly useful when the url of the image is behind a firewall and - * need to add additional flags, possibly using curl. - */ - 'media_downloader' => Spatie\MediaLibrary\Downloaders\DefaultDownloader::class, - - 'remote' => [ - /* - * Any extra headers that should be included when uploading media to - * a remote disk. Even though supported headers may vary between - * different drivers, a sensible default has been provided. - * - * Supported by S3: CacheControl, Expires, StorageClass, - * ServerSideEncryption, Metadata, ACL, ContentEncoding - */ - 'extra_headers' => [ - 'CacheControl' => 'max-age=604800', - ], - ], - - 'responsive_images' => [ - /* - * This class is responsible for calculating the target widths of the responsive - * images. By default we optimize for filesize and create variations that each are 30% - * smaller than the previous one. More info in the documentation. - * - * https://docs.spatie.be/laravel-medialibrary/v9/advanced-usage/generating-responsive-images - */ - 'width_calculator' => Spatie\MediaLibrary\ResponsiveImages\WidthCalculator\FileSizeOptimizedWidthCalculator::class, - - /* - * By default rendering media to a responsive image will add some javascript and a tiny placeholder. - * This ensures that the browser can already determine the correct layout. - */ - 'use_tiny_placeholders' => true, - - /* - * This class will generate the tiny placeholder used for progressive image loading. By default - * the media library will use a tiny blurred jpg image. - */ - 'tiny_placeholder_generator' => Spatie\MediaLibrary\ResponsiveImages\TinyPlaceholderGenerator\Blurred::class, - ], - - /* - * When enabling this option, a route will be registered that will enable - * the Media Library Pro Vue and React components to move uploaded files - * in a S3 bucket to their right place. - */ - 'enable_vapor_uploads' => env('ENABLE_MEDIA_LIBRARY_VAPOR_UPLOADS', false), - - /* - * When converting Media instances to response the media library will add - * a `loading` attribute to the `img` tag. Here you can set the default - * value of that attribute. - * - * Possible values: 'lazy', 'eager', 'auto' or null if you don't want to set any loading instruction. - * - * More info: https://css-tricks.com/native-lazy-loading/ - */ - 'default_loading_attribute_value' => null, - - /* - * You can specify a prefix for that is used for storing all media. - * If you set this to `/my-subdir`, all your media will be stored in a `/my-subdir` directory. - */ - 'prefix' => env('MEDIA_PREFIX', ''), -]; From 4cfe51a5921de8a964f36d49f8f61ff8c905ba50 Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Tue, 13 Jun 2023 14:04:36 +0000 Subject: [PATCH 11/16] Apply fixes from StyleCI --- app/Exceptions/Handler.php | 1 - .../Controllers/Admin/ProductCrudController.php | 2 +- app/Models/Product.php | 14 +++++++++----- app/Providers/EventServiceProvider.php | 1 - 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index 462563a41..6acb186ef 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -2,7 +2,6 @@ namespace App\Exceptions; -use Exception; use Illuminate\Auth\Access\AuthorizationException; use Illuminate\Database\Eloquent\ModelNotFoundException; use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler; diff --git a/app/Http/Controllers/Admin/ProductCrudController.php b/app/Http/Controllers/Admin/ProductCrudController.php index 7446c6a30..f2ae648eb 100644 --- a/app/Http/Controllers/Admin/ProductCrudController.php +++ b/app/Http/Controllers/Admin/ProductCrudController.php @@ -17,7 +17,7 @@ class ProductCrudController extends CrudController use \Backpack\CRUD\app\Http\Controllers\Operations\BulkDeleteOperation; use \Backpack\CRUD\app\Http\Controllers\Operations\BulkCloneOperation; use \Backpack\CRUD\app\Http\Controllers\Operations\InlineCreateOperation; - use \Backpack\Pro\Http\Controllers\Operations\DropzoneOperation { dropzoneUpload as traitDropzoneUpload;} + use \Backpack\Pro\Http\Controllers\Operations\DropzoneOperation { dropzoneUpload as traitDropzoneUpload; } public function setup() { diff --git a/app/Models/Product.php b/app/Models/Product.php index d6b42a87c..e5ee7454c 100644 --- a/app/Models/Product.php +++ b/app/Models/Product.php @@ -47,10 +47,11 @@ class Product extends Model implements HasMedia public function mainImage(): Attribute { return Attribute::make( - set: function($item) { + set: function ($item) { if (app('env') === 'production') { return null; } + return $item; }, ); @@ -59,10 +60,11 @@ public function mainImage(): Attribute public function privacyPolicy(): Attribute { return Attribute::make( - set: function($item) { + set: function ($item) { if (app('env') === 'production') { return null; } + return $item; }, ); @@ -71,10 +73,11 @@ public function privacyPolicy(): Attribute public function specifications(): Attribute { return Attribute::make( - set: function($item) { + set: function ($item) { if (app('env') === 'production') { return null; } + return json_encode($item); }, ); @@ -83,10 +86,11 @@ public function specifications(): Attribute public function gallery(): Attribute { return Attribute::make( - set: function($item) { + set: function ($item) { if (app('env') === 'production') { - array_walk($item, function(&$row) { + array_walk($item, function (&$row) { unset($row['gallery_image'], $row['gallery_image_drm'], $row['gallery_image_specifications'], $row['gallery_image_certificates']); + return $row; }); } diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index f5d8b87f8..0b7550a2b 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -3,7 +3,6 @@ namespace App\Providers; use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; -use Illuminate\Support\Facades\Event; class EventServiceProvider extends ServiceProvider { From c95b3ec3f9bc71cf06184560e1a585392b02e9db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cristian=20T=C4=83b=C4=83citu?= Date: Mon, 19 Jun 2023 18:39:42 +0300 Subject: [PATCH 12/16] Delete products symlink --- public/products | 1 - 1 file changed, 1 deletion(-) delete mode 120000 public/products diff --git a/public/products b/public/products deleted file mode 120000 index 8f2ec7c3c..000000000 --- a/public/products +++ /dev/null @@ -1 +0,0 @@ -/Users/tabacitu/Code/bp-2023-05-31/storage/app/public/products \ No newline at end of file From 5bdfe3e2abe3d454e1d0df441b1f6eb8deec6a4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cristian=20T=C4=83b=C4=83citu?= Date: Mon, 19 Jun 2023 18:40:20 +0300 Subject: [PATCH 13/16] Apply suggestions from code review --- config/filesystems.php | 8 -------- 1 file changed, 8 deletions(-) diff --git a/config/filesystems.php b/config/filesystems.php index dc229edf8..2cdef6e64 100644 --- a/config/filesystems.php +++ b/config/filesystems.php @@ -61,13 +61,6 @@ 'root' => public_path('uploads'), ], - 'products' => [ // used for demonstration purposes on Products controler - 'driver' => 'local', - 'root' => storage_path('app/public/products'), - 'url' => '/products', - 'visibility' => 'public', - ], - 'backups' => [ // used for Backpack/BackupManager 'driver' => 'local', 'root' => storage_path('backups'), // that's where your backups are stored by default: storage/backups @@ -89,7 +82,6 @@ ], 'links' => [ public_path('storage') => storage_path('app/public'), - public_path('products') => storage_path('app/public/products'), ], ]; From d91123ff2531debc1206345108448deb6860df60 Mon Sep 17 00:00:00 2001 From: Cristian Tabacitu Date: Tue, 20 Jun 2023 11:00:02 +0300 Subject: [PATCH 14/16] disable or hide the upload fields in production --- .../Controllers/Admin/ProductCrudController.php | 8 +++++++- app/Providers/AppServiceProvider.php | 13 +++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/app/Http/Controllers/Admin/ProductCrudController.php b/app/Http/Controllers/Admin/ProductCrudController.php index f2ae648eb..58208aab9 100644 --- a/app/Http/Controllers/Admin/ProductCrudController.php +++ b/app/Http/Controllers/Admin/ProductCrudController.php @@ -212,6 +212,7 @@ protected function setupCreateOperation() ->type('image') ->tab('Media') ->wrapper(['class' => 'form-group col-md-4']) + ->disabledInProduction() ->withMedia(); CRUD::field('privacy_policy') @@ -219,6 +220,7 @@ protected function setupCreateOperation() ->type('upload') ->tab('Media') ->wrapper(['class' => 'form-group col-md-4']) + ->disabledInProduction() ->withMedia(); CRUD::field('specifications') @@ -226,6 +228,7 @@ protected function setupCreateOperation() ->type('upload_multiple') ->tab('Media') ->wrapper(['class' => 'form-group col-md-4']) + ->disabledInProduction() ->withMedia(); CRUD::field('gallery') @@ -276,7 +279,10 @@ protected function setupCreateOperation() ], 'withMedia' => true, ], - ]); + ]) + ->when(app('env') == 'production', function ($field) { + return $field->remove(); + }); $this->crud->setOperationSetting('contentClass', 'col-md-12'); } diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 38fe05213..330c30e47 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -2,8 +2,9 @@ namespace App\Providers; -use Illuminate\Database\Eloquent\Relations\Relation; +use Backpack\CRUD\app\Library\CrudPanel\CrudField; use Illuminate\Support\ServiceProvider; +use Illuminate\Database\Eloquent\Relations\Relation; class AppServiceProvider extends ServiceProvider { @@ -27,6 +28,14 @@ public function boot() */ public function register() { - // register the services that are only used for development + // a simple helper to make fields disabled in production + CrudField::macro('disabledInProduction', function () { + if (app('env') !== 'production') { + return $this; + } + + return $this->attributes(['disabled' => 'disabled']) + ->hint('Uploads are disabled in production.'); + }); } } From 0a48a988fdca53ba7e4cd0625f063a41c082f52b Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Tue, 20 Jun 2023 08:00:26 +0000 Subject: [PATCH 15/16] Apply fixes from StyleCI --- app/Providers/AppServiceProvider.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 330c30e47..8c2e33fff 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -3,8 +3,8 @@ namespace App\Providers; use Backpack\CRUD\app\Library\CrudPanel\CrudField; -use Illuminate\Support\ServiceProvider; use Illuminate\Database\Eloquent\Relations\Relation; +use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider { From 2886774e8c16033a41e242181955d8f45cd947c2 Mon Sep 17 00:00:00 2001 From: Pedro X Date: Wed, 28 Jun 2023 13:27:09 +0100 Subject: [PATCH 16/16] fix attribute mutator --- app/Models/Product.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/Models/Product.php b/app/Models/Product.php index e5ee7454c..029891f02 100644 --- a/app/Models/Product.php +++ b/app/Models/Product.php @@ -88,6 +88,7 @@ public function gallery(): Attribute return Attribute::make( set: function ($item) { if (app('env') === 'production') { + $item = is_string($item) ? json_decode($item, true) : ($item ?? []); array_walk($item, function (&$row) { unset($row['gallery_image'], $row['gallery_image_drm'], $row['gallery_image_specifications'], $row['gallery_image_certificates']);