Compare commits
5 commits
admin-secu
...
migration
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b1d8f5466f | ||
|
|
b44e61de35 | ||
|
|
1ed68ddffa | ||
|
|
f2ae5b39f9 | ||
|
|
663a43d631 |
32 changed files with 1091 additions and 32 deletions
|
|
@ -8,21 +8,15 @@ enum CertificationsEnum : int
|
|||
{
|
||||
use BaseEnum;
|
||||
|
||||
case haltungsform1 = 1;
|
||||
case haltungsform2 = 2;
|
||||
case haltungsform3 = 3;
|
||||
case haltungsform4 = 4;
|
||||
case ecc = 5;
|
||||
|
||||
/**
|
||||
* Custom added images definition
|
||||
*/
|
||||
private const IMAGES = [
|
||||
self::haltungsform1->name => "haltungsform1.png",
|
||||
self::haltungsform2->name => "haltungsform2.png",
|
||||
self::haltungsform3->name => "haltungsform3.png",
|
||||
self::haltungsform4->name => "haltungsform4.png",
|
||||
self::ecc->name => "ecc.png",
|
||||
self::ecc->name => "ECC-Logo-green.svg",
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
|
|||
15
app/Exceptions/AbortRowImportException.php
Normal file
15
app/Exceptions/AbortRowImportException.php
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
|
||||
namespace App\Exceptions;
|
||||
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* This class Exception is used to skip a row import from
|
||||
* database migration (2016 -> 2020)
|
||||
*
|
||||
* @author Jérémy Munsch <jeremy.munsch@ldc.fr>
|
||||
*/
|
||||
class AbortRowImportException extends Exception
|
||||
{
|
||||
}
|
||||
|
|
@ -50,6 +50,7 @@ class StoreProductRequest extends FormRequest
|
|||
'label' => 'required|min:3|max:255',
|
||||
'slug' => 'unique_translation:products',
|
||||
'description' => 'required|string|min:15',
|
||||
'marinade' => 'nullable|string|min:15',
|
||||
'picture_alt' => 'required|min:3|max:255',
|
||||
'picture_title' => 'required|min:3|max:255',
|
||||
'certifications' => 'present|array',
|
||||
|
|
@ -97,6 +98,7 @@ class StoreProductRequest extends FormRequest
|
|||
'label' => trans('label'),
|
||||
'slug' => trans('slug'),
|
||||
'description' => trans('description'),
|
||||
'marinade' => trans('marinade'),
|
||||
'picture_alt' => trans('picture_alt'),
|
||||
'picture_title' => trans('picture_title'),
|
||||
'certifications' => trans('certifications'),
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ class UpdateProductRequest extends StoreProductRequest
|
|||
'label' => 'required|min:3|max:255',
|
||||
'slug' => UniqueTranslationRule::for('products')->ignore($this->product->id),
|
||||
'description' => 'required|string|min:15',
|
||||
'marinade' => 'nullable|string|min:15',
|
||||
'picture_alt' => 'required|min:3|max:255',
|
||||
'picture_title' => 'required|min:3|max:255',
|
||||
'certifications' => 'present|array',
|
||||
|
|
|
|||
|
|
@ -138,8 +138,7 @@ class Concept extends Model
|
|||
{
|
||||
self::setSlug($model);
|
||||
ToolboxHelper::assertNoInternalBoUrls('description', $model->description);
|
||||
$model->description = clean($model->description);
|
||||
$model->picture = FileStorageHelper::storeFile($model, $model->picture, true);
|
||||
$model->picture = FileStorageHelper::storeFile($model, $model->picture, true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -127,11 +127,6 @@ class Home extends Model
|
|||
ToolboxHelper::assertNoInternalBoUrls('part2_list', $item['value']);
|
||||
}
|
||||
}
|
||||
$model->part1_text_1 = clean($model->part1_text_1);
|
||||
$model->part1_text_2 = clean($model->part1_text_2);
|
||||
$model->part1_text_3 = clean($model->part1_text_3);
|
||||
$model->part2_text = clean($model->part2_text);
|
||||
$model->part2_list = clean($model->part2_list);
|
||||
$model->part3_picture = FileStorageHelper::storeFile($model, $model->part3_picture, true);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ use Illuminate\Support\Str;
|
|||
* @property string $label
|
||||
* @property string $slug
|
||||
* @property string $description
|
||||
* @property string|null $marinade
|
||||
* @property string $picture
|
||||
* @property array $certifications
|
||||
* @property array $nutritionnal_values
|
||||
|
|
@ -40,6 +41,7 @@ class Product extends Model
|
|||
'label',
|
||||
'slug',
|
||||
'description',
|
||||
'marinade',
|
||||
'picture',
|
||||
'picture_alt',
|
||||
'picture_title',
|
||||
|
|
@ -74,6 +76,7 @@ class Product extends Model
|
|||
'label',
|
||||
'slug',
|
||||
'description',
|
||||
'marinade',
|
||||
'picture',
|
||||
'picture_alt',
|
||||
'picture_title',
|
||||
|
|
@ -130,9 +133,7 @@ class Product extends Model
|
|||
ToolboxHelper::assertNoInternalBoUrls('nutritionnal_values', $itemNutritionnalValues['value'] ?? '');
|
||||
}
|
||||
}
|
||||
$model->nutritionnal_values = clean($model->nutritionnal_values);
|
||||
$model->list = clean($model->list);
|
||||
$model->picture = FileStorageHelper::storeFile($model, $model->picture, true);
|
||||
$model->picture = FileStorageHelper::storeFile($model, $model->picture, true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -144,9 +144,6 @@ class Recipe extends Model
|
|||
}
|
||||
ToolboxHelper::assertNoInternalBoUrls('steps', $model->steps);
|
||||
ToolboxHelper::assertNoInternalBoUrls('tips', $model->tips);
|
||||
$model->ingredients = clean($model->ingredients);
|
||||
$model->steps = clean($model->steps);
|
||||
$model->tips = clean($model->tips);
|
||||
$model->picture = FileStorageHelper::storeFile($model, $model->picture, true);
|
||||
$model->picture_thumbnail = FileStorageHelper::storeFile($model, $model->picture_thumbnail, true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,6 +39,16 @@ class Store extends Model
|
|||
'updated_at'
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that should be cast.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts = [
|
||||
'latitude' => 'float',
|
||||
'longitude' => 'float'
|
||||
];
|
||||
|
||||
// * EVENTS
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
namespace App\Traits\Enums;
|
||||
|
||||
use Illuminate\Support\Facades\Lang;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
|
|
@ -28,9 +27,17 @@ trait BaseEnum
|
|||
*/
|
||||
public function label(): string
|
||||
{
|
||||
$class = Str::snake(\class_basename(\get_class($this)));
|
||||
return Lang::has("enums.{$class}.{$this->name}") ?
|
||||
Lang::get("enums.{$class}.{$this->name}") : self::toLabels()[$this->name];
|
||||
return self::toLabels()[$this->name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get enum name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function name(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
// * STATIC FETCH METHODS
|
||||
|
|
@ -71,6 +78,16 @@ trait BaseEnum
|
|||
return self::getCache('values');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get enums
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function all(): array
|
||||
{
|
||||
return self::cases();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get enums
|
||||
*
|
||||
|
|
@ -112,6 +129,40 @@ trait BaseEnum
|
|||
\collect(self::cases())->keyBy('value')->get($value) : $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if 2 enum are equals
|
||||
*
|
||||
* @param object ...$others
|
||||
* @return boolean
|
||||
* @throws \Error If provided element are not enums taht extends BaseEnum.
|
||||
*/
|
||||
public function equals(object ...$others): bool
|
||||
{
|
||||
foreach ($others as $other) {
|
||||
if (!\in_array(BaseEnum::class, \class_uses_recursive($other))) {
|
||||
throw new \Error(__METHOD__ .
|
||||
' requires $enum to use ' . BaseEnum::class);
|
||||
}
|
||||
if (
|
||||
get_class($this) === get_class($other)
|
||||
&& $this->value === $other->value
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize to json
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function jsonSerialize(): mixed
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
|
||||
// * CACHE
|
||||
|
||||
|
|
@ -191,7 +242,7 @@ trait BaseEnum
|
|||
private static function getCustomDefinitions(): array
|
||||
{
|
||||
// ? Has custom props in cache ?
|
||||
if (\is_null($GLOBALS[self::class]['customProps'])) {
|
||||
if (!isset($GLOBALS[self::class]) or \is_null($GLOBALS[self::class]['customProps'])) {
|
||||
$names = \collect(self::cases())->keyBy('name');
|
||||
|
||||
$GLOBALS[self::class]['customProps'] = \collect((new \ReflectionClass(self::class))->getConstants())
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@
|
|||
"autoload": {
|
||||
"psr-4": {
|
||||
"App\\": "app/",
|
||||
"Database\\Migrations\\": "database/migrations/",
|
||||
"Database\\Factories\\": "database/factories/",
|
||||
"Database\\Seeders\\": "database/seeders/"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,9 @@ use Illuminate\Support\Str;
|
|||
|
||||
return [
|
||||
|
||||
'oldDB' => 'wdmr_prod',
|
||||
'newDB' => 'mysql',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Database Connection Name
|
||||
|
|
@ -63,6 +66,26 @@ return [
|
|||
]) : [],
|
||||
],
|
||||
|
||||
'wdmr_prod' => [
|
||||
'driver' => 'mysql',
|
||||
'url' => env('DATABASE_URL_NEW'),
|
||||
'host' => env('DB_HOST', '127.0.0.1'),
|
||||
'port' => env('DB_PORT', '3306'),
|
||||
'database' => env('DB_DATABASE_NEW', 'forge'),
|
||||
'username' => env('DB_USERNAME_NEW', 'forge'),
|
||||
'password' => env('DB_PASSWORD_NEW', ''),
|
||||
'unix_socket' => env('DB_SOCKET_NEW', ''),
|
||||
'charset' => 'utf8mb4',
|
||||
'collation' => 'utf8mb4_unicode_ci',
|
||||
'prefix' => '',
|
||||
'prefix_indexes' => true,
|
||||
'strict' => true,
|
||||
'engine' => null,
|
||||
'options' => extension_loaded('pdo_mysql') ? array_filter([
|
||||
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
|
||||
]) : [],
|
||||
],
|
||||
|
||||
'pgsql' => [
|
||||
'driver' => 'pgsql',
|
||||
'url' => env('DATABASE_URL'),
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ final class ProductFactory extends Factory
|
|||
'label' => $label,
|
||||
'slug' => Str::slug($label),
|
||||
'description' => fake()->word,
|
||||
'marinade' => fake()->boolean() ? fake()->word : null,
|
||||
'picture_alt' => fake()->word,
|
||||
'picture_title' => fake()->word,
|
||||
'certifications' => [\collect(CertificationsEnum::cases())->random()],
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ return new class extends Migration
|
|||
$table->json('label')->comment('Libellé du produit');
|
||||
$table->json('slug')->unique()->comment('Slug du label');
|
||||
$table->json('description')->comment('Description du produit');
|
||||
$table->string('picture')->comment('Path de l\'image du produit, 600px x 600x');
|
||||
$table->json('picture')->comment('Path de l\'image du produit, 600px x 600x');
|
||||
$table->json('picture_alt')->comment('Attribut alt de l\'image');
|
||||
$table->json('picture_title')->comment('Titre de l\'image');
|
||||
$table->string('certifications')->comment('Tableau d\'entier (CertificationsEnum)');
|
||||
|
|
|
|||
|
|
@ -19,10 +19,10 @@ return new class extends Migration
|
|||
$table->json('seo_description')->comment('Description SEO de la page');
|
||||
$table->json('name')->comment('Nom de la recette');
|
||||
$table->json('slug')->unique()->comment('Slug du nom');
|
||||
$table->string('picture')->comment('Image de la recette');
|
||||
$table->json('picture')->comment('Image de la recette');
|
||||
$table->json('picture_alt')->comment('Attribut alt de l\'image');
|
||||
$table->json('picture_title')->comment('Titre de l\'image');
|
||||
$table->string('picture_thumbnail')->comment('Vignette de la recette');
|
||||
$table->json('picture_thumbnail')->comment('Vignette de la recette');
|
||||
$table->json('picture_thumbnail_alt')->comment('Attribut alt de l\'image');
|
||||
$table->json('picture_thumbnail_title')->comment('Titre de l\'image');
|
||||
$table->json('ingredients')->comment('Liste d\'ingrédients de la recette');
|
||||
|
|
|
|||
43
database/migrations/2023_05_30_1049007_migrate_users.php
Normal file
43
database/migrations/2023_05_30_1049007_migrate_users.php
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
use App\Models\User;
|
||||
use Database\Migrations\LeGaulois2016Migration;
|
||||
|
||||
return new class extends LeGaulois2016Migration
|
||||
{
|
||||
/**
|
||||
* Run migration instructions
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function instruct(): array
|
||||
{
|
||||
self::consoleLog("Users \n", true);
|
||||
return [
|
||||
'users' => [
|
||||
'model' => User::class,
|
||||
'comment' => 'Migrate Users',
|
||||
'bind' => [
|
||||
'id' => 'id',
|
||||
'firstname' => [
|
||||
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
|
||||
'apply' => function ($args, $model) {
|
||||
$args = collect(explode(' ', $args));
|
||||
$model->firstname = $args->get(0, 'Firstname');
|
||||
$model->lastname = $args->get(0, 'Lastname');
|
||||
return $model->firstname;
|
||||
},
|
||||
'name' => 'name',
|
||||
'default' => ''
|
||||
],
|
||||
'email' => 'email',
|
||||
'email_verified_at' => 'email_verified_at',
|
||||
'password' => 'password',
|
||||
'remember_token' => 'remember_token',
|
||||
'created_at' => 'created_at',
|
||||
'updated_at' => 'updated_at',
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
use App\Lib\Helpers\FileStorageHelper;
|
||||
use App\Models\StoreGroup;
|
||||
use Database\Migrations\LeGaulois2016Migration;
|
||||
|
||||
return new class extends LeGaulois2016Migration
|
||||
{
|
||||
/**
|
||||
* Run migration instructions
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function instruct(): array
|
||||
{
|
||||
self::consoleLog("StoreGroups \n", true);
|
||||
return [
|
||||
'retailgroups' => [
|
||||
'model' => StoreGroup::class,
|
||||
'comment' => 'Migrate StoreGroups',
|
||||
'bind' => [
|
||||
'id' => 'id',
|
||||
'name' => 'group_name',
|
||||
'picture' => [
|
||||
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
|
||||
'apply' => function ($args, $model) {
|
||||
if (empty($args)) {
|
||||
return $args;
|
||||
}
|
||||
$model->picture = FileStorageHelper::storeFile(
|
||||
$model,
|
||||
new \SplFileInfo(storage_path("app/public/{$args}")),
|
||||
true
|
||||
);
|
||||
return $model->picture;
|
||||
},
|
||||
'name' => 'group_logo',
|
||||
'default' => ''
|
||||
],
|
||||
'created_at' => 'created_at',
|
||||
'updated_at' => 'updated_at',
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('products', function (Blueprint $table) {
|
||||
$table->text('marinade', 'Marinade champs migré sur la fin non demandé par le client')
|
||||
->nullable()->after('description');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('products', function (Blueprint $table) {
|
||||
$table->dropColumn('marinade');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
use App\Models\StoreRegion;
|
||||
use Database\Migrations\LeGaulois2016Migration;
|
||||
|
||||
return new class extends LeGaulois2016Migration
|
||||
{
|
||||
/**
|
||||
* Run migration instructions
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function instruct(): array
|
||||
{
|
||||
self::consoleLog("StoreRegions \n", true);
|
||||
return [
|
||||
'retailregions' => [
|
||||
'model' => StoreRegion::class,
|
||||
'comment' => 'Migrate StoreRegions',
|
||||
'bind' => [
|
||||
'id' => 'id',
|
||||
'name' => 'region_name',
|
||||
'picture' => 'region_logo',
|
||||
'group_id' => 'region_group',
|
||||
'created_at' => 'created_at',
|
||||
'updated_at' => 'updated_at',
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
};
|
||||
127
database/migrations/2023_05_31_1049001_migrate_stores.php
Normal file
127
database/migrations/2023_05_31_1049001_migrate_stores.php
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
<?php
|
||||
|
||||
use App\Models\Store;
|
||||
use App\Models\StoreType;
|
||||
use Carbon\Exceptions\InvalidFormatException;
|
||||
use Database\Migrations\LeGaulois2016Migration;
|
||||
use Illuminate\Support\Carbon;
|
||||
|
||||
return new class extends LeGaulois2016Migration
|
||||
{
|
||||
/**
|
||||
* Run migration instructions
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function instruct(): array
|
||||
{
|
||||
self::consoleLog("Store \n", true);
|
||||
return [
|
||||
'stores' => [
|
||||
'model' => Store::class,
|
||||
'comment' => 'Migrate Stores',
|
||||
'bind' => [
|
||||
'id' => 'id',
|
||||
'state' => 'state',
|
||||
'street' => 'street',
|
||||
'zipcode' => 'zipcode',
|
||||
'city' => 'city',
|
||||
'latitude' => [
|
||||
'apply' => function ($args, $model) {
|
||||
$args = explode('||', $args);
|
||||
$ID = $args[0];
|
||||
$long = $args[1];
|
||||
$lat = $args[2];
|
||||
|
||||
$model->longitude = !empty(floatval($long)) ? floatval($long) : 0;
|
||||
$model->latitude = !empty(floatval($lat)) ? floatval($lat) : 0;
|
||||
|
||||
return $model->latitude;
|
||||
},
|
||||
'name' => [
|
||||
'id', 'long', 'lat'
|
||||
],
|
||||
'default' => ''
|
||||
],
|
||||
'longitude' => [
|
||||
'apply' => function ($args, $model) {
|
||||
$args = explode('||', $args);
|
||||
$ID = $args[0];
|
||||
$long = $args[1];
|
||||
$lat = $args[2];
|
||||
|
||||
$model->longitude = !empty(floatval($long)) ? floatval($long) : 0;
|
||||
$model->latitude = !empty(floatval($lat)) ? floatval($lat) : 0;
|
||||
|
||||
return $model->longitude;
|
||||
},
|
||||
'name' => [
|
||||
'id', 'long', 'lat'
|
||||
],
|
||||
'default' => ''
|
||||
],
|
||||
'type_id' => [
|
||||
'apply' => function ($args, $model) {
|
||||
$args = explode('||', $args);
|
||||
$ID = $args[0];
|
||||
$name = $args[1];
|
||||
|
||||
$storeType = StoreType::query()->where('name', $name)->firstOrNew([
|
||||
'name' => $name
|
||||
]);
|
||||
$storeType->saveOrFail();
|
||||
|
||||
/** @var \App\Models\Store $model */
|
||||
$model->type_id = $storeType->id;
|
||||
|
||||
return $model->type_id;
|
||||
},
|
||||
'name' => [
|
||||
'id', 'type'
|
||||
],
|
||||
'default' => ''
|
||||
],
|
||||
'region_id' => 'region_id',
|
||||
'created_at' => [
|
||||
'apply' => function ($args, $model) {
|
||||
$args = explode('||', $args);
|
||||
$ID = $args[0];
|
||||
$created_at = $args[1];
|
||||
|
||||
try {
|
||||
$model->created_at = Carbon::parse($created_at);
|
||||
} catch (InvalidFormatException) {
|
||||
$model->created_at = now();
|
||||
}
|
||||
|
||||
return $model->type_id;
|
||||
},
|
||||
'name' => [
|
||||
'id', 'created_at'
|
||||
],
|
||||
'default' => ''
|
||||
],
|
||||
'updated_at' => [
|
||||
'apply' => function ($args, $model) {
|
||||
$args = explode('||', $args);
|
||||
$ID = $args[0];
|
||||
$updated_at = $args[1];
|
||||
|
||||
try {
|
||||
$model->updated_at = Carbon::parse($updated_at);
|
||||
} catch (InvalidFormatException) {
|
||||
$model->updated_at = now();
|
||||
}
|
||||
|
||||
return $model->type_id;
|
||||
},
|
||||
'name' => [
|
||||
'id', 'updated_at'
|
||||
],
|
||||
'default' => ''
|
||||
],
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
};
|
||||
28
database/migrations/2023_05_31_1049002_migrate_ranges.php
Normal file
28
database/migrations/2023_05_31_1049002_migrate_ranges.php
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
use App\Enums\Ranges\PictoEnum;
|
||||
use App\Models\Range;
|
||||
use Database\Migrations\LeGaulois2016Migration;
|
||||
|
||||
return new class extends LeGaulois2016Migration
|
||||
{
|
||||
/**
|
||||
* Run migration instructions
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function instruct(): array
|
||||
{
|
||||
self::consoleLog("Range \n", true);
|
||||
collect(PictoEnum::all())->map(function (PictoEnum $pictoEnum) {
|
||||
Range::query()->where('id', $pictoEnum->value())->firstOrCreate([
|
||||
'seo_title' => $pictoEnum->label(),
|
||||
'seo_description' => $pictoEnum->label(),
|
||||
'label' => $pictoEnum->label(),
|
||||
'picto' => $pictoEnum,
|
||||
'status' => true
|
||||
])->saveOrFail();
|
||||
});
|
||||
return [];
|
||||
}
|
||||
};
|
||||
178
database/migrations/2023_05_31_1049003_migrate_products.php
Normal file
178
database/migrations/2023_05_31_1049003_migrate_products.php
Normal file
|
|
@ -0,0 +1,178 @@
|
|||
<?php
|
||||
|
||||
use App\Enums\Products\CertificationsEnum;
|
||||
use App\Enums\Ranges\PictoEnum;
|
||||
use App\Lib\Helpers\FileStorageHelper;
|
||||
use App\Models\Product;
|
||||
use Database\Migrations\LeGaulois2016Migration;
|
||||
|
||||
return new class extends LeGaulois2016Migration
|
||||
{
|
||||
/**
|
||||
* Run migration instructions
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function instruct(): array
|
||||
{
|
||||
self::consoleLog("Products \n", true);
|
||||
return [
|
||||
'products' => [
|
||||
'model' => Product::class,
|
||||
'comment' => 'Migrate Products',
|
||||
'bind' => [
|
||||
'id' => 'id',
|
||||
'seo_title' => 'name',
|
||||
'seo_description' => 'name',
|
||||
'label' => 'name',
|
||||
'description' => 'description',
|
||||
|
||||
|
||||
'range_id' => [
|
||||
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed
|
||||
'apply' => function ($args, $model) {
|
||||
return match ($args) {
|
||||
'01_chicken' => PictoEnum::chicken->value,
|
||||
'02_duck' => PictoEnum::duck->value,
|
||||
'03_turkey' => PictoEnum::turkey->value,
|
||||
'05_soupchicken' => PictoEnum::soupchicken->value,
|
||||
'06_guineafowl' => PictoEnum::guineafowl->value,
|
||||
'07_goose' => PictoEnum::goose->value,
|
||||
default => throw new \Error("unhandled {$args}")
|
||||
};
|
||||
},
|
||||
'name' => 'poultry',
|
||||
'default' => ''
|
||||
],
|
||||
|
||||
|
||||
'list' => [
|
||||
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed
|
||||
'apply' => function ($args, $model) {
|
||||
$args = collect($args);
|
||||
|
||||
$html = $args->get(0);
|
||||
$html = !empty($html) ? $html : '<div></div>';
|
||||
|
||||
$doc = new \DOMDocument();
|
||||
$doc->loadHTML($html);
|
||||
|
||||
$list = collect();
|
||||
|
||||
collect($doc->getElementsByTagName('ul'))
|
||||
->each(fn (\DOMElement $domNode) => collect($domNode->getElementsByTagName('li'))
|
||||
->each(fn (\DOMElement $domNode) => $list->push([
|
||||
'value' => $domNode->textContent
|
||||
])));
|
||||
|
||||
return $list->all();
|
||||
},
|
||||
'name' => [
|
||||
'advantages',
|
||||
],
|
||||
'default' => ''
|
||||
],
|
||||
'certifications' => [
|
||||
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed
|
||||
'apply' => function ($args, $model) {
|
||||
$parsed = collect(json_decode($args));
|
||||
$enums = [];
|
||||
if ($parsed->has('checkbox1')) {
|
||||
$enums[] = CertificationsEnum::haltungsform3;
|
||||
}
|
||||
if ($parsed->has('checkbox2')) {
|
||||
$enums[] = CertificationsEnum::ecc;
|
||||
}
|
||||
return $enums;
|
||||
},
|
||||
'name' => 'type',
|
||||
'default' => ''
|
||||
],
|
||||
|
||||
'nutritionnal_values' => [
|
||||
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed
|
||||
'apply' => function ($args, $model) {
|
||||
$args = collect(explode(' ', $args));
|
||||
$data = [
|
||||
[
|
||||
// Energy.
|
||||
'label' => 'Energie',
|
||||
'value' => $args->get(0),
|
||||
],
|
||||
[
|
||||
// Fat.
|
||||
'label' => 'Fett',
|
||||
'value' => $args->get(1),
|
||||
],
|
||||
[
|
||||
// Hereof: saturated fatty acids.
|
||||
'label' => '• davon gesättigte Fettsäuren',
|
||||
'value' => $args->get(2),
|
||||
],
|
||||
[
|
||||
// Carbohydrates.
|
||||
'label' => 'Kohlenhydrate',
|
||||
'value' => $args->get(3),
|
||||
],
|
||||
[
|
||||
// Of which sugars.
|
||||
'label' => '• davon Zucker',
|
||||
'value' => $args->get(4),
|
||||
],
|
||||
[
|
||||
// Protein.
|
||||
'label' => 'Eiweiß',
|
||||
'value' => $args->get(5),
|
||||
],
|
||||
[
|
||||
// Salt.
|
||||
'label' => 'Salz',
|
||||
'value' => $args->get(6),
|
||||
],
|
||||
[
|
||||
// Fiber.
|
||||
'label' => 'Balaststoffe',
|
||||
'value' => $args->get(7),
|
||||
],
|
||||
];
|
||||
|
||||
return $data;
|
||||
},
|
||||
'name' => [
|
||||
'energy', 'fat', 'sat_fat', 'carbs',
|
||||
'sugar', 'protein', 'salt', 'fiber',
|
||||
],
|
||||
'default' => ''
|
||||
],
|
||||
|
||||
'status' => [
|
||||
'apply' => function () {
|
||||
return true;
|
||||
},
|
||||
'name' => 'packshot_top',
|
||||
'default' => ''
|
||||
],
|
||||
|
||||
'picture' => [
|
||||
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
|
||||
'apply' => function ($args, $model) {
|
||||
$model->picture = FileStorageHelper::storeFile(
|
||||
$model,
|
||||
new \SplFileInfo(storage_path("app/public/{$args}")),
|
||||
true
|
||||
);
|
||||
return $model->picture;
|
||||
},
|
||||
'name' => 'packshot_top',
|
||||
'default' => ''
|
||||
],
|
||||
'picture_alt' => 'name',
|
||||
'picture_title' => 'name',
|
||||
|
||||
'created_at' => 'created_at',
|
||||
'updated_at' => 'updated_at',
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
};
|
||||
149
database/migrations/2023_05_31_1049004_migrate_recipes.php
Normal file
149
database/migrations/2023_05_31_1049004_migrate_recipes.php
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
<?php
|
||||
|
||||
use App\Enums\Ranges\PictoEnum;
|
||||
use App\Enums\Recipes\DifficultyEnum;
|
||||
use App\Lib\Helpers\FileStorageHelper;
|
||||
use App\Models\Recipe;
|
||||
use Database\Migrations\LeGaulois2016Migration;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
return new class extends LeGaulois2016Migration
|
||||
{
|
||||
/**
|
||||
* Run migration instructions
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function instruct(): array
|
||||
{
|
||||
collect(File::allFiles(storage_path('app/public/recipes')))
|
||||
->each(function (\SplFileInfo $splFileInfo) {
|
||||
$path = pathinfo($splFileInfo->getPath(), PATHINFO_DIRNAME);
|
||||
$file = Str::slug(pathinfo($splFileInfo->getBasename(), PATHINFO_FILENAME));
|
||||
$ext = pathinfo($splFileInfo->getBasename(), PATHINFO_EXTENSION);
|
||||
if (!empty($ext)) {
|
||||
$file = "{$file}.{$ext}";
|
||||
}
|
||||
$path = "{$path}/recipes/{$file}";
|
||||
File::move(
|
||||
$splFileInfo,
|
||||
$path
|
||||
);
|
||||
});
|
||||
self::consoleLog("Recipes \n", true);
|
||||
return [
|
||||
'recipes' => [
|
||||
'model' => Recipe::class,
|
||||
'comment' => 'Migrate Recipes',
|
||||
'bind' => [
|
||||
'id' => 'id',
|
||||
|
||||
'seo_title' => 'name',
|
||||
'seo_description' => 'name',
|
||||
'name' => 'name',
|
||||
'picture' => [
|
||||
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
|
||||
'apply' => function ($args, $model) {
|
||||
|
||||
$path = pathinfo($args, PATHINFO_DIRNAME);
|
||||
$file = Str::slug(pathinfo($args, PATHINFO_FILENAME));
|
||||
$ext = pathinfo($args, PATHINFO_EXTENSION);
|
||||
if (!empty($ext)) {
|
||||
$file = "{$file}.{$ext}";
|
||||
}
|
||||
$path = "{$path}/{$file}";
|
||||
|
||||
$model->picture = FileStorageHelper::storeFile(
|
||||
$model,
|
||||
new \SplFileInfo(storage_path("app/public/{$path}")),
|
||||
true
|
||||
);
|
||||
return $model->picture;
|
||||
},
|
||||
'name' => 'heropic',
|
||||
'default' => ''
|
||||
],
|
||||
'picture_alt' => 'name',
|
||||
'picture_title' => 'name',
|
||||
|
||||
'picture_thumbnail' => [
|
||||
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
|
||||
'apply' => function ($args, $model) {
|
||||
if (empty($args)) {
|
||||
return '';
|
||||
}
|
||||
$path = pathinfo($args, PATHINFO_DIRNAME);
|
||||
$file = Str::slug(pathinfo($args, PATHINFO_FILENAME));
|
||||
$ext = pathinfo($args, PATHINFO_EXTENSION);
|
||||
if (!empty($ext)) {
|
||||
$file = "{$file}.{$ext}";
|
||||
}
|
||||
$path = "{$path}/{$file}";
|
||||
|
||||
$model->picture_thumbnail = FileStorageHelper::storeFile(
|
||||
$model,
|
||||
new \SplFileInfo(storage_path("app/public/{$path}")),
|
||||
true
|
||||
);
|
||||
return $model->picture_thumbnail;
|
||||
},
|
||||
'name' => 'thumbnail',
|
||||
'default' => ''
|
||||
],
|
||||
'picture_thumbnail_alt' => 'name',
|
||||
'picture_thumbnail_title' => 'name',
|
||||
|
||||
'range_id' => [
|
||||
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed
|
||||
'apply' => function ($args, $model) {
|
||||
return match ($args) {
|
||||
'chicken' => PictoEnum::chicken->value,
|
||||
'goose' => PictoEnum::goose->value,
|
||||
default => throw new \Error("unhandled {$args}")
|
||||
};
|
||||
},
|
||||
'name' => 'cat',
|
||||
'default' => ''
|
||||
],
|
||||
|
||||
'tips' => 'tipps',
|
||||
'teaser' => 'teaser',
|
||||
'duration' => 'duration',
|
||||
'difficulty' => [
|
||||
'apply' => function ($args) {
|
||||
return match ($args) {
|
||||
'easy' => DifficultyEnum::easy->value,
|
||||
'medium' => DifficultyEnum::medium->value,
|
||||
'hard' => DifficultyEnum::hard->value,
|
||||
default => throw new \Error("unhandled {$args}")
|
||||
};
|
||||
},
|
||||
'name' => 'difficulty',
|
||||
'default' => ''
|
||||
],
|
||||
'ingredients' => [
|
||||
'apply' => function ($args) {
|
||||
return [];
|
||||
},
|
||||
'name' => 'ingredients',
|
||||
'default' => ''
|
||||
],
|
||||
|
||||
'steps' => 'instructions',
|
||||
|
||||
'status' => [
|
||||
'apply' => function () {
|
||||
return true;
|
||||
},
|
||||
'name' => 'difficulty',
|
||||
'default' => ''
|
||||
],
|
||||
|
||||
'created_at' => 'created_at',
|
||||
'updated_at' => 'updated_at',
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
};
|
||||
314
database/migrations/LeGaulois2016Migration.php
Normal file
314
database/migrations/LeGaulois2016Migration.php
Normal file
|
|
@ -0,0 +1,314 @@
|
|||
<?php
|
||||
|
||||
namespace Database\Migrations;
|
||||
|
||||
use App\Exceptions\AbortRowImportException;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use ReflectionFunction;
|
||||
use Symfony\Component\Console\Output\ConsoleOutput;
|
||||
use Symfony\Component\Console\Terminal;
|
||||
|
||||
/**
|
||||
* Migration Intructions
|
||||
* Examples
|
||||
*[
|
||||
* 'content_ocb' => [
|
||||
* 'model' => OCBContent::class,
|
||||
* 'bind' => [
|
||||
* 'id' => 'ocb_id',
|
||||
* 'picture' => 'ocb_img',
|
||||
* 'content' => 'ocb_content',
|
||||
* 'status' => 'ocb_is_published',
|
||||
* 'type' => [
|
||||
* 'apply' => function ($value) {
|
||||
* switch ($value) {
|
||||
* case 'VOLAILLE':
|
||||
* return OCBType::poultry();
|
||||
* case 'LAPIN':
|
||||
* return OCBType::rabbit();
|
||||
* case 'OEUF':
|
||||
* return OCBType::egg();
|
||||
* }
|
||||
* },
|
||||
* 'name' => 'ocb_type',
|
||||
* 'default' => ''
|
||||
* ],
|
||||
* 'order' => 'ocb_position',
|
||||
* 'created_at' => [
|
||||
* 'name' => '',
|
||||
* 'default' => date('Y-m-d H:i:s')
|
||||
* ],
|
||||
* 'updated_at' => [
|
||||
* 'name' => '',
|
||||
* 'default' => date('Y-m-d H:i:s')
|
||||
* ]
|
||||
* ]
|
||||
* ],
|
||||
* 'Recipe ratings' => [
|
||||
* 'table' => 'recipe',
|
||||
* 'comment' => 'Add ratings to recipes',
|
||||
* 'model' => Rating::class,
|
||||
* 'bind' => [
|
||||
* 'anyprop' => [
|
||||
* 'apply' => function ($recipe_id) {
|
||||
* $recipe_rating = $this->oldDB->table('recipe_rating')
|
||||
* ->select('recipe_rating_value')
|
||||
* ->where('recipe_rating_recipe_id', '=', $recipe_id)
|
||||
* ->get();
|
||||
* $count = $recipe_rating->count();
|
||||
* $sum = $recipe_rating->sum(function ($obj) {
|
||||
* return $obj->recipe_rating_value;
|
||||
* });
|
||||
* $this->newDB->table('ratings')
|
||||
* ->insert([
|
||||
* 'total' => $sum,
|
||||
* 'count' => $count,
|
||||
* 'rating' => $count ? floatval($sum / $count) : 0,
|
||||
* 'recipes_id' => $recipe_id,
|
||||
* 'created_at' => date('Y-m-d H:i:s'),
|
||||
* 'updated_at' => date('Y-m-d H:i:s'),
|
||||
* ]);
|
||||
* throw new AbortRowImportException();
|
||||
* },
|
||||
* 'name' => 'recipe_id'
|
||||
* ]
|
||||
* ]
|
||||
* ],
|
||||
*]
|
||||
*
|
||||
* @property \Illuminate\Database\ConnectionInterface $oldDB
|
||||
* @property \Illuminate\Database\ConnectionInterface $newDB
|
||||
* @param array $instructions
|
||||
* @return void
|
||||
*
|
||||
* Helps to migration from legaulois2016 to legaulois2020
|
||||
* @author Jérémy Munsch <jeremy.munsch@ldc.fr>
|
||||
*/
|
||||
abstract class LeGaulois2016Migration extends Migration
|
||||
{
|
||||
/** @var ConsoleOutput */
|
||||
private static $output = null;
|
||||
|
||||
/** @var ConsoleSectionOutput */
|
||||
private static $outputSection = null;
|
||||
|
||||
/** @var \Illuminate\Database\ConnectionInterface */
|
||||
private $oldDB = null;
|
||||
|
||||
/** @var \Illuminate\Database\ConnectionInterface */
|
||||
private $newDB = null;
|
||||
|
||||
/** @var array */
|
||||
private $instructions = null;
|
||||
|
||||
/**
|
||||
* LeGaulois2016Migration
|
||||
* @throws \ErrorException If failed to connect db.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$oldDB = config(sprintf('database.connections.%s', config('database.oldDB')));
|
||||
$newDB = config(sprintf('database.connections.%s', config('database.newDB')));
|
||||
if (!$oldDB) {
|
||||
throw new \ErrorException(sprintf('Unknown database connection %s for newDB', config('database.newDB')));
|
||||
}
|
||||
if (!$newDB) {
|
||||
throw new \ErrorException(sprintf('Unknown database connection %s for oldDB', config('database.oldDB')));
|
||||
}
|
||||
$this->oldDB = DB::connection(config('database.oldDB'));
|
||||
$this->newDB = DB::connection(config('database.newDB'));
|
||||
}
|
||||
|
||||
/**
|
||||
* run migration
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
$this->instructions = $this->instruct();
|
||||
$this->processData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Do nothing
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @param string $name
|
||||
* @return \Illuminate\Database\ConnectionInterface
|
||||
*/
|
||||
public function __get(string $name)
|
||||
{
|
||||
if ($name === 'oldDB') {
|
||||
return $this->oldDB;
|
||||
}
|
||||
if ($name === 'newDB') {
|
||||
return $this->newDB;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set migration instructions to execute on "up" only
|
||||
* see Instructions in \App\Database\Migrations\LeGaulois2016Migration
|
||||
* @return array
|
||||
*/
|
||||
abstract public function instruct(): array;
|
||||
|
||||
/**
|
||||
* Core execution on instruction
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function processData()
|
||||
{
|
||||
$getOldData = function ($keyOrKeys, $array) {
|
||||
if (is_array($keyOrKeys)) {
|
||||
$o = [];
|
||||
foreach ($keyOrKeys as $key) {
|
||||
$o[] = strval($array[$key]);
|
||||
}
|
||||
return implode('||', $o);
|
||||
}
|
||||
return $array[$keyOrKeys] ?? null;
|
||||
};
|
||||
|
||||
foreach ($this->instructions as $oldTableName => $modelData) {
|
||||
$migrationName = $oldTableName;
|
||||
$oldTableName = $modelData['table'] ?? $oldTableName;
|
||||
$rowNbrs = $this->oldDB->table($oldTableName)->count();
|
||||
$rowInserted = 0;
|
||||
$orderBy = $modelData['orderBy'] ?? false;
|
||||
|
||||
self::consoleLog($this->renderProgress($migrationName, $rowInserted, $rowNbrs));
|
||||
|
||||
$i = 0;
|
||||
$page = 1;
|
||||
$perPage = env('MIGRATIONPAGINATION', 300);
|
||||
do {
|
||||
$q = $this->oldDB->table($oldTableName);
|
||||
if ($orderBy) {
|
||||
$q = $q->orderBy($orderBy);
|
||||
}
|
||||
$results = $q->paginate($perPage, ['*'], 'page', $page);
|
||||
$i += $perPage;
|
||||
$page++;
|
||||
foreach ($results as $oldData) {
|
||||
$model = null;
|
||||
try {
|
||||
// * Try to get exisiting model ID (to avoid SQL Integrity violations doing delete and create)
|
||||
$model = $modelData['model']::findOrFail(
|
||||
$getOldData($modelData['bind']['id'] ?? 0, (array)$oldData)
|
||||
);
|
||||
} catch (ModelNotFoundException $e) {
|
||||
$model = new $modelData['model']();
|
||||
}
|
||||
try {
|
||||
// * bind each property to it's data and save
|
||||
foreach ($modelData['bind'] as $modelAttr => $oldModelAttr) {
|
||||
if (is_array($oldModelAttr)) {
|
||||
if (array_key_exists('apply', $oldModelAttr)) {
|
||||
$argC = (new ReflectionFunction($oldModelAttr['apply']))->getNumberOfParameters();
|
||||
$argV = [
|
||||
$getOldData($oldModelAttr['name'], (array)$oldData)
|
||||
];
|
||||
if ($argC > 1) {
|
||||
$argV[] = $model;
|
||||
}
|
||||
$model[$modelAttr] =
|
||||
call_user_func_array($oldModelAttr['apply'], $argV) ??
|
||||
$oldModelAttr['default'] ??
|
||||
null;
|
||||
} else {
|
||||
$model[$modelAttr] =
|
||||
$getOldData($oldModelAttr['name'], (array)$oldData) ??
|
||||
$oldModelAttr['default'] ??
|
||||
null;
|
||||
}
|
||||
} else {
|
||||
$model[$modelAttr] = ((array)$oldData)[$oldModelAttr];
|
||||
} //end if
|
||||
} //end foreach
|
||||
$model->saveOrFail();
|
||||
// phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedCatch
|
||||
} catch (AbortRowImportException $e) {
|
||||
// * DO nothing
|
||||
} finally {
|
||||
++$rowInserted;
|
||||
if (rand(0, 15) == 10) {
|
||||
// * prevent screen ficklering
|
||||
self::consoleLog($this->renderProgress($migrationName, $rowInserted, $rowNbrs));
|
||||
}
|
||||
} //end try
|
||||
} //end foreach
|
||||
} while ($i <= $rowNbrs);
|
||||
if (array_key_exists('comment', $modelData)) {
|
||||
$migrationName .= sprintf(' <%s> ', $modelData['comment']);
|
||||
}
|
||||
$terminal = new Terminal();
|
||||
$consoleLength = $terminal->getWidth();
|
||||
|
||||
$r = round(80 * 100 / $consoleLength) - strlen($migrationName);
|
||||
$r = $r >= 0 ? $r : 0;
|
||||
self::consoleLog(sprintf('%s%smigrated', $migrationName, str_repeat(' ', $r)));
|
||||
// * Cariage return
|
||||
self::consoleLog("", true);
|
||||
} //end foreach
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a message to the console
|
||||
*
|
||||
* @param string $message
|
||||
* @param boolean $newLine
|
||||
* @return void
|
||||
*/
|
||||
public static function consoleLog(string $message, bool $newLine = false)
|
||||
{
|
||||
if (!self::$output) {
|
||||
self::$output = new ConsoleOutput();
|
||||
}
|
||||
if ($newLine) {
|
||||
self::$outputSection = null;
|
||||
self::$output->write(sprintf("<info>%s</info>", $message));
|
||||
} else {
|
||||
if (!self::$outputSection) {
|
||||
self::$outputSection = self::$output->section();
|
||||
}
|
||||
self::$outputSection->overwrite(sprintf('<info>%s</info>', $message));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the progressbar to a string
|
||||
*
|
||||
* @param string $oldTableName
|
||||
* @param integer $count
|
||||
* @param integer $total
|
||||
* @return string
|
||||
*/
|
||||
protected function renderProgress(string $oldTableName, int $count, int $total)
|
||||
{
|
||||
$total = !$total ? 1 : $total;
|
||||
$oldTableName = sprintf('%s ', $oldTableName);
|
||||
$percent = $count * 100 / $total;
|
||||
$percentText = sprintf(' [%d of %d]', $count, $total);
|
||||
$terminal = new Terminal();
|
||||
$consoleLength = $terminal->getWidth();
|
||||
$bar = $consoleLength - strlen($oldTableName) - strlen($percentText);
|
||||
$bar = $bar < 0 ? 0 : $bar;
|
||||
$prog = round($percent / 100 * $bar);
|
||||
$rep = $bar - $prog;
|
||||
|
||||
return $oldTableName . str_repeat('#', $prog) . str_repeat('_', $rep >= 0 ? $rep : 0) . $percentText;
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 22 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 7.6 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 7.6 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 7.6 KiB |
|
|
@ -186,6 +186,24 @@
|
|||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
{{-- MARINADE --}}
|
||||
<div class="col-12 mb-3">
|
||||
<fieldset class="border bg-white p-3">
|
||||
<legend>{{ __('Marinade') }}</legend>
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
@include('bo.partials.inputs.text-html', [
|
||||
'id' => 'productMarinade',
|
||||
'label' => __('Marinade of the :model', ['model' => Str::singular(__('models.classes.products'))]),
|
||||
'name' => 'marinade',
|
||||
'model' => $productModel ?? null,
|
||||
'required' => false,
|
||||
'helper' => __('Proofread your content before publishing it (minimum 15 characters).'),
|
||||
])
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
{{-- PICTURE --}}
|
||||
<div class="col-12 mb-3">
|
||||
<fieldset class="border h-100 bg-white p-3">
|
||||
|
|
|
|||
|
|
@ -1,9 +1,6 @@
|
|||
@php
|
||||
$pictoUrl = match($picto) {
|
||||
\App\Enums\Products\CertificationsEnum::haltungsform1 => Vite::asset('resources/assets/images/Icons/haltungsform1.png'),
|
||||
\App\Enums\Products\CertificationsEnum::haltungsform2 => Vite::asset('resources/assets/images/Icons/haltungsform2.png'),
|
||||
\App\Enums\Products\CertificationsEnum::haltungsform3 => Vite::asset('resources/assets/images/Icons/haltungsform3.png'),
|
||||
\App\Enums\Products\CertificationsEnum::haltungsform4 => Vite::asset('resources/assets/images/Icons/haltungsform4.png'),
|
||||
\App\Enums\Products\CertificationsEnum::ecc => Vite::asset('resources/assets/images/Icons/ecc.png'),
|
||||
default => throw new \Error("Undefined \App\Enums\Products\CertificationsEnum::class value {$picto->value}")
|
||||
};
|
||||
|
|
|
|||
|
|
@ -79,6 +79,11 @@
|
|||
</ul>
|
||||
@endforeach
|
||||
</div>
|
||||
@if ($productModel->marinade)
|
||||
<div id="marinade" class="col-span-2 mt-4 ck-content">
|
||||
{!! clean($productModel->marinade) !!}
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ Route::prefix('bo')
|
|||
// * PRODUCTS
|
||||
Route::resource('products', ProductController::class)->except(['show'])
|
||||
->withoutMiddleware('htmlsanitize')
|
||||
->middleware(['htmlsanitize:description']);
|
||||
->middleware(['htmlsanitize:description,marinade']);
|
||||
Route::post('/products/{product}/change-order', [ProductController::class, 'changeOrder'])
|
||||
->name('products.change-order');
|
||||
Route::post('/products/{product}/change-published', [ProductController::class, 'changePublished'])
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue