add models
This commit is contained in:
parent
1beaeece03
commit
9d6c7fdb60
25 changed files with 1178 additions and 27 deletions
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace App\Enums\Concepts;
|
||||
|
||||
enum ColorsEnum : int {
|
||||
enum ColorsEnum : int {
|
||||
case redwine = 1;
|
||||
case orange = 2;
|
||||
case blue = 3;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace App\Enums\Ranges;
|
||||
|
||||
enum PictosEnum : int {
|
||||
enum PictosEnum : int {
|
||||
case chicken = 1;
|
||||
case duck = 2;
|
||||
case turkey = 3;
|
||||
|
|
|
|||
92
app/Models/Concept.php
Normal file
92
app/Models/Concept.php
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Lib\Helpers\FileStorageHelper;
|
||||
use App\Lib\Helpers\ToolboxHelper;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* @property integer $id
|
||||
* @property string $seo_title
|
||||
* @property string $seo_description
|
||||
* @property string $name
|
||||
* @property string $slug
|
||||
* @property string $title
|
||||
* @property string $title_span
|
||||
* @property string $description
|
||||
* @property string $content
|
||||
* @property string $picture
|
||||
* @property string $created_at
|
||||
* @property string $updated_at
|
||||
*/
|
||||
class Concept extends Model
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
'seo_title',
|
||||
'seo_description',
|
||||
'name',
|
||||
'slug',
|
||||
'title',
|
||||
'title_span',
|
||||
'description',
|
||||
'content',
|
||||
'picture',
|
||||
'created_at',
|
||||
'updated_at'
|
||||
];
|
||||
|
||||
// * EVENTS
|
||||
|
||||
/**
|
||||
* Perform any actions required after the model boots.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected static function booted()
|
||||
{
|
||||
static::creating(function (self $model) {
|
||||
self::manageFields($model);
|
||||
});
|
||||
static::updating(function (self $model) {
|
||||
self::manageFields($model);
|
||||
});
|
||||
static::updated(function (self $model) {
|
||||
FileStorageHelper::removeOldFile($model, 'picture');
|
||||
});
|
||||
static::deleted(function (self $model) {
|
||||
FileStorageHelper::removeFile($model, 'picture');
|
||||
});
|
||||
}
|
||||
|
||||
// * METHODS
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @param Model $model
|
||||
* @return void
|
||||
*/
|
||||
private static function manageFields(Model $model)
|
||||
{
|
||||
self::assertFieldIsUnique('name', $model->name);
|
||||
$model->picture = FileStorageHelper::storeFile($model, $model->picture, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts using validation that the field is unique.
|
||||
*
|
||||
* @param string $nameField
|
||||
* @param mixed $valueField
|
||||
* @param integer|null $id
|
||||
* @return void
|
||||
*/
|
||||
private static function assertFieldIsUnique(string $nameField, string $valueField, ?int $id = null)
|
||||
{
|
||||
$table = (new self())->getTable();
|
||||
ToolboxHelper::assertFieldIsUnique($table, $nameField, $valueField, $id);
|
||||
}
|
||||
}
|
||||
128
app/Models/Home.php
Normal file
128
app/Models/Home.php
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Lib\Helpers\FileStorageHelper;
|
||||
use App\Lib\Helpers\ToolboxHelper;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* @property integer $id
|
||||
* @property integer $part2_product1_id
|
||||
* @property integer $part2_product2_id
|
||||
* @property string $seo_title
|
||||
* @property string $seo_description
|
||||
* @property string $part1_title
|
||||
* @property string $part1_title_span
|
||||
* @property string $part1_text_1
|
||||
* @property string $part1_text_2
|
||||
* @property string $part1_text_3
|
||||
* @property string $part2_title
|
||||
* @property string $part2_title_span
|
||||
* @property string $part2_text
|
||||
* @property string $part2_list
|
||||
* @property string $part3_picture
|
||||
* @property string $created_at
|
||||
* @property string $updated_at
|
||||
* @property Product $product
|
||||
* @property Product $product
|
||||
*/
|
||||
class Home extends Model
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
'part2_product1_id',
|
||||
'part2_product2_id',
|
||||
'seo_title',
|
||||
'seo_description',
|
||||
'part1_title',
|
||||
'part1_title_span',
|
||||
'part1_text_1',
|
||||
'part1_text_2',
|
||||
'part1_text_3',
|
||||
'part2_title',
|
||||
'part2_title_span',
|
||||
'part2_text',
|
||||
'part2_list',
|
||||
'part3_picture',
|
||||
'created_at',
|
||||
'updated_at'
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that should be cast.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts = [
|
||||
'part2_list' => 'json',
|
||||
];
|
||||
|
||||
// * EVENTS
|
||||
|
||||
/**
|
||||
* Perform any actions required after the model boots.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected static function booted()
|
||||
{
|
||||
static::creating(function (self $model) {
|
||||
self::manageFields($model);
|
||||
});
|
||||
static::updating(function (self $model) {
|
||||
self::manageFields($model);
|
||||
});
|
||||
static::updated(function (self $model) {
|
||||
FileStorageHelper::removeOldFile($model, 'part3_picture');
|
||||
});
|
||||
static::deleted(function (self $model) {
|
||||
FileStorageHelper::removeFile($model, 'part3_picture');
|
||||
});
|
||||
}
|
||||
|
||||
// * METHODS
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @param Model $model
|
||||
* @return void
|
||||
*/
|
||||
private static function manageFields(Model $model)
|
||||
{
|
||||
ToolboxHelper::assertNoInternalBoUrls('part1_text_1', $model->part1_text_1);
|
||||
ToolboxHelper::assertNoInternalBoUrls('part1_text_2', $model->part1_text_2);
|
||||
ToolboxHelper::assertNoInternalBoUrls('part1_text_3', $model->part1_text_3);
|
||||
ToolboxHelper::assertNoInternalBoUrls('part2_text', $model->part2_text);
|
||||
foreach ($model->part2_list as $pack) {
|
||||
ToolboxHelper::assertNoInternalBoUrls('part2_list', $pack['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);
|
||||
}
|
||||
|
||||
// * RELATIONSHIPS
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function product1()
|
||||
{
|
||||
return $this->belongsTo('App\Models\Product', 'part2_product1_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function product2()
|
||||
{
|
||||
return $this->belongsTo('App\Models\Product', 'part2_product2_id');
|
||||
}
|
||||
}
|
||||
154
app/Models/Product.php
Normal file
154
app/Models/Product.php
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Lib\Helpers\FileStorageHelper;
|
||||
use App\Lib\Helpers\ToolboxHelper;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* @property integer $id
|
||||
* @property integer $range_id
|
||||
* @property string $seo_title
|
||||
* @property string $seo_description
|
||||
* @property string $label
|
||||
* @property string $slug
|
||||
* @property string $description
|
||||
* @property string $picture
|
||||
* @property string $certifications
|
||||
* @property string $nutritionnal_values
|
||||
* @property string $list
|
||||
* @property boolean $status
|
||||
* @property integer $order
|
||||
* @property string $created_at
|
||||
* @property string $updated_at
|
||||
* @property Recipe[] $recipes
|
||||
* @property Range $range
|
||||
* @property Home[] $homes
|
||||
* @property Home[] $homes
|
||||
*/
|
||||
class Product extends Model
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
'range_id',
|
||||
'seo_title',
|
||||
'seo_description',
|
||||
'label',
|
||||
'slug',
|
||||
'description',
|
||||
'picture',
|
||||
'certifications',
|
||||
'nutritionnal_values',
|
||||
'list',
|
||||
'status',
|
||||
'order',
|
||||
'created_at',
|
||||
'updated_at'
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that should be cast.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts = [
|
||||
'certifications' => 'json',
|
||||
'nutritionnal_values' => 'json',
|
||||
'list' => 'json',
|
||||
];
|
||||
|
||||
// * EVENTS
|
||||
|
||||
/**
|
||||
* Perform any actions required after the model boots.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected static function booted()
|
||||
{
|
||||
static::creating(function (self $model) {
|
||||
self::manageFields($model);
|
||||
});
|
||||
static::updating(function (self $model) {
|
||||
self::manageFields($model);
|
||||
});
|
||||
static::updated(function (self $model) {
|
||||
FileStorageHelper::removeOldFile($model, 'picture');
|
||||
});
|
||||
static::deleted(function (self $model) {
|
||||
FileStorageHelper::removeFile($model, 'picture');
|
||||
});
|
||||
}
|
||||
|
||||
// * METHODS
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @param Model $model
|
||||
* @return void
|
||||
*/
|
||||
private static function manageFields(Model $model)
|
||||
{
|
||||
self::assertFieldIsUnique('label', $model->label);
|
||||
self::assertFieldIsUnique('slug', $model->slug);
|
||||
ToolboxHelper::assertNoInternalBoUrls('certifications', $model->certifications);
|
||||
ToolboxHelper::assertNoInternalBoUrls('nutritionnal_values', $model->nutritionnal_values);
|
||||
ToolboxHelper::assertNoInternalBoUrls('list', $model->list);
|
||||
$model->certifications = clean($model->certifications);
|
||||
$model->nutritionnal_values = clean($model->nutritionnal_values);
|
||||
$model->list = clean($model->list);
|
||||
$model->picture = FileStorageHelper::storeFile($model, $model->picture, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts using validation that the field is unique.
|
||||
*
|
||||
* @param string $nameField
|
||||
* @param mixed $valueField
|
||||
* @param integer|null $id
|
||||
* @return void
|
||||
*/
|
||||
private static function assertFieldIsUnique(string $nameField, string $valueField, ?int $id = null)
|
||||
{
|
||||
$table = (new self())->getTable();
|
||||
ToolboxHelper::assertFieldIsUnique($table, $nameField, $valueField, $id);
|
||||
}
|
||||
|
||||
// * RELATIONSHIPS
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function recipes()
|
||||
{
|
||||
return $this->belongsToMany('App\Models\Recipe', 'recipes_products');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function range()
|
||||
{
|
||||
return $this->belongsTo('App\Models\Range');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function homes1()
|
||||
{
|
||||
return $this->hasMany('App\Models\Home', 'part2_product1_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function homes2()
|
||||
{
|
||||
return $this->hasMany('App\Models\Home', 'part2_product2_id');
|
||||
}
|
||||
}
|
||||
112
app/Models/Range.php
Normal file
112
app/Models/Range.php
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Enums\Ranges\PictosEnum;
|
||||
use App\Lib\Helpers\FileStorageHelper;
|
||||
use App\Lib\Helpers\ToolboxHelper;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* @property integer $id
|
||||
* @property string $seo_title
|
||||
* @property string $seo_description
|
||||
* @property string $label
|
||||
* @property string $slug
|
||||
* @property boolean $picto
|
||||
* @property integer $order
|
||||
* @property boolean $status
|
||||
* @property string $created_at
|
||||
* @property string $updated_at
|
||||
* @property Recipe[] $recipes
|
||||
* @property Product[] $products
|
||||
*/
|
||||
class Range extends Model
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
'seo_title',
|
||||
'seo_description',
|
||||
'label',
|
||||
'slug',
|
||||
'picto',
|
||||
'order',
|
||||
'status',
|
||||
'created_at',
|
||||
'updated_at'
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that should be cast.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts = [
|
||||
'picto' => PictosEnum::class,
|
||||
];
|
||||
|
||||
// * EVENTS
|
||||
|
||||
/**
|
||||
* Perform any actions required after the model boots.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected static function booted()
|
||||
{
|
||||
static::creating(function (self $model) {
|
||||
self::manageFields($model);
|
||||
});
|
||||
static::updating(function (self $model) {
|
||||
self::manageFields($model);
|
||||
});
|
||||
}
|
||||
|
||||
// * METHODS
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @param Model $model
|
||||
* @return void
|
||||
*/
|
||||
private static function manageFields(Model $model)
|
||||
{
|
||||
self::assertFieldIsUnique('label', $model->label);
|
||||
self::assertFieldIsUnique('slug', $model->slug);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts using validation that the field is unique.
|
||||
*
|
||||
* @param string $nameField
|
||||
* @param mixed $valueField
|
||||
* @param integer|null $id
|
||||
* @return void
|
||||
*/
|
||||
private static function assertFieldIsUnique(string $nameField, string $valueField, ?int $id = null)
|
||||
{
|
||||
$table = (new self())->getTable();
|
||||
ToolboxHelper::assertFieldIsUnique($table, $nameField, $valueField, $id);
|
||||
}
|
||||
|
||||
// * RELATIONSHIPS
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function recipes()
|
||||
{
|
||||
return $this->hasMany('App\Models\Recipe');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function products()
|
||||
{
|
||||
return $this->hasMany('App\Models\Product');
|
||||
}
|
||||
}
|
||||
150
app/Models/Recipe.php
Normal file
150
app/Models/Recipe.php
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Enums\Recipes\DifficultyEnum;
|
||||
use App\Enums\Recipes\CookingEnum;
|
||||
use App\Lib\Helpers\FileStorageHelper;
|
||||
use App\Lib\Helpers\ToolboxHelper;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* @property integer $id
|
||||
* @property integer $range_id
|
||||
* @property string $seo_title
|
||||
* @property string $seo_description
|
||||
* @property string $name
|
||||
* @property string $slug
|
||||
* @property string $picture
|
||||
* @property string $picture_thumbnail
|
||||
* @property string $ingredients
|
||||
* @property string $teaser
|
||||
* @property string $steps
|
||||
* @property boolean $difficulty
|
||||
* @property boolean $preparation
|
||||
* @property boolean $duration
|
||||
* @property string $astuces
|
||||
* @property boolean $cooking
|
||||
* @property boolean $status
|
||||
* @property integer $order
|
||||
* @property string $created_at
|
||||
* @property string $updated_at
|
||||
* @property Product[] $products
|
||||
* @property Range $range
|
||||
*/
|
||||
class Recipe extends Model
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
'range_id',
|
||||
'seo_title',
|
||||
'seo_description',
|
||||
'name',
|
||||
'slug',
|
||||
'picture',
|
||||
'picture_thumbnail',
|
||||
'ingredients',
|
||||
'teaser',
|
||||
'steps',
|
||||
'difficulty',
|
||||
'preparation',
|
||||
'duration',
|
||||
'astuces',
|
||||
'cooking',
|
||||
'status',
|
||||
'order',
|
||||
'created_at',
|
||||
'updated_at'
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that should be cast.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts = [
|
||||
'ingredients' => 'json',
|
||||
'steps' => 'json',
|
||||
'difficulty' => DifficultyEnum::class,
|
||||
'cooking' => CookingEnum::class,
|
||||
];
|
||||
|
||||
// * EVENTS
|
||||
|
||||
/**
|
||||
* Perform any actions required after the model boots.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected static function booted()
|
||||
{
|
||||
static::creating(function (self $model) {
|
||||
self::manageFields($model);
|
||||
});
|
||||
static::updating(function (self $model) {
|
||||
self::manageFields($model);
|
||||
});
|
||||
static::updated(function (self $model) {
|
||||
FileStorageHelper::removeOldFile($model, 'picture');
|
||||
FileStorageHelper::removeOldFile($model, 'picture_thumbnail');
|
||||
});
|
||||
static::deleted(function (self $model) {
|
||||
FileStorageHelper::removeFile($model, 'picture');
|
||||
FileStorageHelper::removeFile($model, 'picture_thumbnail');
|
||||
});
|
||||
}
|
||||
|
||||
// * METHODS
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @param Model $model
|
||||
* @return void
|
||||
*/
|
||||
private static function manageFields(Model $model)
|
||||
{
|
||||
self::assertFieldIsUnique('name', $model->name);
|
||||
self::assertFieldIsUnique('slug', $model->slug);
|
||||
ToolboxHelper::assertNoInternalBoUrls('ingredients', $model->ingredients);
|
||||
ToolboxHelper::assertNoInternalBoUrls('steps', $model->steps);
|
||||
$model->ingredients = clean($model->ingredients);
|
||||
$model->steps = clean($model->steps);
|
||||
$model->picture = FileStorageHelper::storeFile($model, $model->picture, true);
|
||||
$model->picture_thumbnail = FileStorageHelper::storeFile($model, $model->picture_thumbnail, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts using validation that the field is unique.
|
||||
*
|
||||
* @param string $nameField
|
||||
* @param mixed $valueField
|
||||
* @param integer|null $id
|
||||
* @return void
|
||||
*/
|
||||
private static function assertFieldIsUnique(string $nameField, string $valueField, ?int $id = null)
|
||||
{
|
||||
$table = (new self())->getTable();
|
||||
ToolboxHelper::assertFieldIsUnique($table, $nameField, $valueField, $id);
|
||||
}
|
||||
|
||||
// * RELATIONSHIPS
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function products()
|
||||
{
|
||||
return $this->belongsToMany('App\Models\Product', 'recipes_products');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function range()
|
||||
{
|
||||
return $this->belongsTo('App\Models\Range');
|
||||
}
|
||||
}
|
||||
110
app/Models/Slider.php
Normal file
110
app/Models/Slider.php
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Lib\Helpers\FileStorageHelper;
|
||||
use App\Lib\Helpers\ToolboxHelper;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* @property integer $id
|
||||
* @property boolean $type
|
||||
* @property string $title
|
||||
* @property string $subtitle
|
||||
* @property string $description
|
||||
* @property string $link
|
||||
* @property string $link_title
|
||||
* @property boolean $link_new_tab
|
||||
* @property string $picture
|
||||
* @property boolean $status
|
||||
* @property integer $order
|
||||
* @property string $unpublish_at
|
||||
* @property string $publish_at
|
||||
* @property string $created_at
|
||||
* @property string $updated_at
|
||||
*/
|
||||
class Slider extends Model
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
'type',
|
||||
'title',
|
||||
'subtitle',
|
||||
'description',
|
||||
'link',
|
||||
'link_title',
|
||||
'link_new_tab',
|
||||
'picture',
|
||||
'status',
|
||||
'order',
|
||||
'unpublish_at',
|
||||
'publish_at',
|
||||
'created_at',
|
||||
'updated_at'
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that should be cast.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts = [
|
||||
'ingredients' => 'json',
|
||||
'steps' => 'json',
|
||||
'difficulty' => DifficultyEnum::class,
|
||||
'cooking' => CookingEnum::class,
|
||||
];
|
||||
|
||||
// * EVENTS
|
||||
|
||||
/**
|
||||
* Perform any actions required after the model boots.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected static function booted()
|
||||
{
|
||||
static::creating(function (self $model) {
|
||||
self::manageFields($model);
|
||||
});
|
||||
static::updating(function (self $model) {
|
||||
self::manageFields($model);
|
||||
});
|
||||
static::updated(function (self $model) {
|
||||
FileStorageHelper::removeOldFile($model, 'picture');
|
||||
});
|
||||
static::deleted(function (self $model) {
|
||||
FileStorageHelper::removeFile($model, 'picture');
|
||||
});
|
||||
}
|
||||
|
||||
// * METHODS
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @param Model $model
|
||||
* @return void
|
||||
*/
|
||||
private static function manageFields(Model $model)
|
||||
{
|
||||
self::assertFieldIsUnique('title', $model->title);
|
||||
$model->picture = FileStorageHelper::storeFile($model, $model->picture, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts using validation that the field is unique.
|
||||
*
|
||||
* @param string $nameField
|
||||
* @param mixed $valueField
|
||||
* @param integer|null $id
|
||||
* @return void
|
||||
*/
|
||||
private static function assertFieldIsUnique(string $nameField, string $valueField, ?int $id = null)
|
||||
{
|
||||
$table = (new self())->getTable();
|
||||
ToolboxHelper::assertFieldIsUnique($table, $nameField, $valueField, $id);
|
||||
}
|
||||
}
|
||||
73
app/Models/Store.php
Normal file
73
app/Models/Store.php
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Lib\Helpers\FileStorageHelper;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* @property integer $id
|
||||
* @property integer $type_id
|
||||
* @property integer $region_id
|
||||
* @property string $state
|
||||
* @property string $street
|
||||
* @property string $zipcode
|
||||
* @property string $city
|
||||
* @property float $latitude
|
||||
* @property float $longitude
|
||||
* @property string $created_at
|
||||
* @property string $updated_at
|
||||
* @property StoreType $storeType
|
||||
* @property StoreRegion $storeRegion
|
||||
*/
|
||||
class Store extends Model
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
'type_id',
|
||||
'region_id',
|
||||
'state',
|
||||
'street',
|
||||
'zipcode',
|
||||
'city',
|
||||
'latitude',
|
||||
'longitude',
|
||||
'created_at',
|
||||
'updated_at'
|
||||
];
|
||||
|
||||
// * EVENTS
|
||||
|
||||
/**
|
||||
* Perform any actions required after the model boots.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected static function booted()
|
||||
{
|
||||
static::creating(function (self $model) {
|
||||
});
|
||||
static::updating(function (self $model) {
|
||||
});
|
||||
}
|
||||
|
||||
// * RELATIONSHIPS
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function storeType()
|
||||
{
|
||||
return $this->belongsTo('App\Models\StoreType', 'type_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function storeRegion()
|
||||
{
|
||||
return $this->belongsTo('App\Models\StoreRegion', 'region_id');
|
||||
}
|
||||
}
|
||||
89
app/Models/StoreGroup.php
Normal file
89
app/Models/StoreGroup.php
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Lib\Helpers\FileStorageHelper;
|
||||
use App\Lib\Helpers\ToolboxHelper;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* @property integer $id
|
||||
* @property string $name
|
||||
* @property string $picture
|
||||
* @property string $created_at
|
||||
* @property string $updated_at
|
||||
* @property StoreRegion[] $storeRegions
|
||||
*/
|
||||
class StoreGroup extends Model
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'picture',
|
||||
'created_at',
|
||||
'updated_at'
|
||||
];
|
||||
|
||||
// * EVENTS
|
||||
|
||||
/**
|
||||
* Perform any actions required after the model boots.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected static function booted()
|
||||
{
|
||||
static::creating(function (self $model) {
|
||||
self::manageFields($model);
|
||||
});
|
||||
static::updating(function (self $model) {
|
||||
self::manageFields($model);
|
||||
});
|
||||
static::updated(function (self $model) {
|
||||
FileStorageHelper::removeOldFile($model, 'picture');
|
||||
});
|
||||
static::deleted(function (self $model) {
|
||||
FileStorageHelper::removeFile($model, 'picture');
|
||||
});
|
||||
}
|
||||
|
||||
// * METHODS
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @param Model $model
|
||||
* @return void
|
||||
*/
|
||||
private static function manageFields(Model $model)
|
||||
{
|
||||
self::assertFieldIsUnique('name', $model->name);
|
||||
$model->picture = FileStorageHelper::storeFile($model, $model->picture, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts using validation that the field is unique.
|
||||
*
|
||||
* @param string $nameField
|
||||
* @param mixed $valueField
|
||||
* @param integer|null $id
|
||||
* @return void
|
||||
*/
|
||||
private static function assertFieldIsUnique(string $nameField, string $valueField, ?int $id = null)
|
||||
{
|
||||
$table = (new self())->getTable();
|
||||
ToolboxHelper::assertFieldIsUnique($table, $nameField, $valueField, $id);
|
||||
}
|
||||
|
||||
// * RELATIONSHIPS
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function storeRegions()
|
||||
{
|
||||
return $this->hasMany('App\Models\StoreRegion', 'group_id');
|
||||
}
|
||||
}
|
||||
100
app/Models/StoreRegion.php
Normal file
100
app/Models/StoreRegion.php
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Lib\Helpers\FileStorageHelper;
|
||||
use App\Lib\Helpers\ToolboxHelper;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* @property integer $id
|
||||
* @property integer $group_id
|
||||
* @property string $name
|
||||
* @property string $picture
|
||||
* @property string $created_at
|
||||
* @property string $updated_at
|
||||
* @property Store[] $stores
|
||||
* @property StoreGroup $storeGroup
|
||||
*/
|
||||
class StoreRegion extends Model
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
'group_id',
|
||||
'name',
|
||||
'picture',
|
||||
'created_at',
|
||||
'updated_at'
|
||||
];
|
||||
|
||||
// * EVENTS
|
||||
|
||||
/**
|
||||
* Perform any actions required after the model boots.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected static function booted()
|
||||
{
|
||||
static::creating(function (self $model) {
|
||||
self::manageFields($model);
|
||||
});
|
||||
static::updating(function (self $model) {
|
||||
self::manageFields($model);
|
||||
});
|
||||
static::updated(function (self $model) {
|
||||
FileStorageHelper::removeOldFile($model, 'picture');
|
||||
});
|
||||
static::deleted(function (self $model) {
|
||||
FileStorageHelper::removeFile($model, 'picture');
|
||||
});
|
||||
}
|
||||
|
||||
// * METHODS
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @param Model $model
|
||||
* @return void
|
||||
*/
|
||||
private static function manageFields(Model $model)
|
||||
{
|
||||
self::assertFieldIsUnique('name', $model->name);
|
||||
$model->picture = FileStorageHelper::storeFile($model, $model->picture, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts using validation that the field is unique.
|
||||
*
|
||||
* @param string $nameField
|
||||
* @param mixed $valueField
|
||||
* @param integer|null $id
|
||||
* @return void
|
||||
*/
|
||||
private static function assertFieldIsUnique(string $nameField, string $valueField, ?int $id = null)
|
||||
{
|
||||
$table = (new self())->getTable();
|
||||
ToolboxHelper::assertFieldIsUnique($table, $nameField, $valueField, $id);
|
||||
}
|
||||
|
||||
// * RELATIONSHIPS
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function stores()
|
||||
{
|
||||
return $this->hasMany('App\Models\Store', 'region_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function storeGroup()
|
||||
{
|
||||
return $this->belongsTo('App\Models\StoreGroup', 'group_id');
|
||||
}
|
||||
}
|
||||
79
app/Models/StoreType.php
Normal file
79
app/Models/StoreType.php
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Lib\Helpers\ToolboxHelper;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* @property integer $id
|
||||
* @property string $name
|
||||
* @property string $created_at
|
||||
* @property string $updated_at
|
||||
* @property Store[] $stores
|
||||
*/
|
||||
class StoreType extends Model
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'created_at',
|
||||
'updated_at'
|
||||
];
|
||||
|
||||
// * EVENTS
|
||||
|
||||
/**
|
||||
* Perform any actions required after the model boots.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected static function booted()
|
||||
{
|
||||
static::creating(function (self $model) {
|
||||
self::manageFields($model);
|
||||
});
|
||||
static::updating(function (self $model) {
|
||||
self::manageFields($model);
|
||||
});
|
||||
}
|
||||
|
||||
// * METHODS
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @param Model $model
|
||||
* @return void
|
||||
*/
|
||||
private static function manageFields(Model $model)
|
||||
{
|
||||
self::assertFieldIsUnique('name', $model->name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts using validation that the field is unique.
|
||||
*
|
||||
* @param string $nameField
|
||||
* @param mixed $valueField
|
||||
* @param integer|null $id
|
||||
* @return void
|
||||
*/
|
||||
private static function assertFieldIsUnique(string $nameField, string $valueField, ?int $id = null)
|
||||
{
|
||||
$table = (new self())->getTable();
|
||||
ToolboxHelper::assertFieldIsUnique($table, $nameField, $valueField, $id);
|
||||
}
|
||||
|
||||
// * RELATIONSHIPS
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function stores()
|
||||
{
|
||||
return $this->hasMany('App\Models\Store', 'type_id');
|
||||
}
|
||||
}
|
||||
64
app/Models/User.php
Normal file
64
app/Models/User.php
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
|
||||
class User extends Authenticatable
|
||||
{
|
||||
use Notifiable;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'firstname',
|
||||
'lastname',
|
||||
'email',
|
||||
'password',
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that should be hidden for serialization.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $hidden = [
|
||||
'password',
|
||||
'remember_token',
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that should be cast.
|
||||
*
|
||||
* @var array<string, string>
|
||||
*/
|
||||
protected $casts = [
|
||||
'email_verified_at' => 'datetime',
|
||||
];
|
||||
|
||||
/**
|
||||
* Perform any actions required after the model boots.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected static function booted()
|
||||
{
|
||||
// * EVENT CLOSURES.
|
||||
static::creating(function (self $model) {
|
||||
if (Hash::needsRehash($model->password)) {
|
||||
$model->password = Hash::make($model->password);
|
||||
}
|
||||
});
|
||||
static::updating(function (self $model) {
|
||||
if (Hash::needsRehash($model->password)) {
|
||||
$model->password = Hash::make($model->password);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -14,7 +14,7 @@ return new class extends Migration
|
|||
public function up()
|
||||
{
|
||||
Schema::create('concepts', function (Blueprint $table) {
|
||||
$table->biginteger('id')->primary()->comment('Id du concept');
|
||||
$table->id()->comment('Id du concept');
|
||||
$table->string('seo_title')->comment('Titre SEO de la page');
|
||||
$table->string('seo_description')->comment('Description SEO de la page');
|
||||
$table->string('name')->comment('Nom du concept');
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@ return new class extends Migration
|
|||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('home', function (Blueprint $table) {
|
||||
$table->biginteger('id')->primary()->comment('Id de la homepage');
|
||||
Schema::create('homes', function (Blueprint $table) {
|
||||
$table->id()->comment('Id de la homepage');
|
||||
$table->string('seo_title')->comment('Utilisé pour la balise title de la page');
|
||||
$table->string('seo_description')->comment('Utilisé pour la balise méta description de la page');
|
||||
$table->string('part1_title')->comment('Titre de la partie 1');
|
||||
|
|
@ -26,8 +26,8 @@ return new class extends Migration
|
|||
$table->string('part2_title_span')->comment('Seconde partie du titre de la partie 2');
|
||||
$table->json('part2_text')->comment('WYSWYG');
|
||||
$table->json('part2_list')->comment('Tableau JSON de string');
|
||||
$table->biginteger('part2_product1_id')->comment('Produit lié 1, FK');
|
||||
$table->biginteger('part2_product2_id')->comment('Produit lié 2, FK');
|
||||
$table->unsignedBigInteger('part2_product1_id')->comment('Produit lié 1, FK');
|
||||
$table->unsignedBigInteger('part2_product2_id')->comment('Produit lié 2, FK');
|
||||
$table->string('part3_picture')->comment('Path de l\'image, 2048px x 1366px');
|
||||
$table->timestamps();
|
||||
});
|
||||
|
|
@ -40,6 +40,6 @@ return new class extends Migration
|
|||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('home');
|
||||
Schema::dropIfExists('homes');
|
||||
}
|
||||
};
|
||||
|
|
@ -14,7 +14,7 @@ return new class extends Migration
|
|||
public function up()
|
||||
{
|
||||
Schema::create('products', function (Blueprint $table) {
|
||||
$table->biginteger('id')->primary()->comment('Id du produit');
|
||||
$table->id()->comment('Id du produit');
|
||||
$table->string('seo_title')->comment('Utilisé pour la balise title de la page');
|
||||
$table->string('seo_description')->comment('Utilisé pour la balise méta description de la page');
|
||||
$table->string('label')->comment('Libellé du produit');
|
||||
|
|
@ -26,7 +26,7 @@ return new class extends Migration
|
|||
$table->json('list')->comment('Tableau JSON de string');
|
||||
$table->boolean('status')->comment('Le produit est-il publié ? - Boolean');
|
||||
$table->integer('order')->comment('Pour ordonner les produits dans une gamme');
|
||||
$table->biginteger('range_id')->comment('Gamme liée, FK');
|
||||
$table->unsignedBigInteger('range_id')->comment('Gamme liée, FK');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ return new class extends Migration
|
|||
public function up()
|
||||
{
|
||||
Schema::create('ranges', function (Blueprint $table) {
|
||||
$table->biginteger('id')->primary()->comment('Id de la gamme');
|
||||
$table->id()->comment('Id de la gamme');
|
||||
$table->string('seo_title')->comment('Utilisé pour la balise title de la page');
|
||||
$table->string('seo_description')->comment('Utilisé pour la balise méta description de la page');
|
||||
$table->string('label')->comment('Label de la gamme');
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@ return new class extends Migration
|
|||
public function up()
|
||||
{
|
||||
Schema::create('recipes_products', function (Blueprint $table) {
|
||||
$table->biginteger('recipe_id')->comment('Id de la recette');
|
||||
$table->biginteger('product_id')->comment('Id du produit');
|
||||
$table->unsignedBigInteger('recipe_id')->comment('Id de la recette');
|
||||
$table->unsignedBigInteger('product_id')->comment('Id du produit');
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ return new class extends Migration
|
|||
public function up()
|
||||
{
|
||||
Schema::create('recipes', function (Blueprint $table) {
|
||||
$table->biginteger('id')->primary()->comment('Id de la recette');
|
||||
$table->id()->comment('Id de la recette');
|
||||
$table->string('seo_title')->comment('Titre SEO de la page');
|
||||
$table->string('seo_description')->comment('Description SEO de la page');
|
||||
$table->string('name')->comment('Nom de la recette');
|
||||
|
|
@ -29,7 +29,7 @@ return new class extends Migration
|
|||
$table->tinyInteger('duration')->comment('Temps de réalisation de la recette');
|
||||
$table->string('astuces')->comment('Astuces concernant cette recette');
|
||||
$table->tinyInteger('cooking')->comment('Cuisson de la recette');
|
||||
$table->biginteger('range_id')->comment('Espèce d\'animal utilisé');
|
||||
$table->unsignedBigInteger('range_id')->comment('Espèce d\'animal utilisé');
|
||||
$table->boolean('status')->comment('État de la recette');
|
||||
$table->integer('order')->comment('Classement de la recette');
|
||||
$table->timestamps();
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ return new class extends Migration
|
|||
public function up()
|
||||
{
|
||||
Schema::create('sliders', function (Blueprint $table) {
|
||||
$table->biginteger('id')->primary()->comment('Id de la slide');
|
||||
$table->id()->comment('Id de la slide');
|
||||
$table->unsignedTinyInteger('type')->comment('Enums\\\\SliderType type de slider');
|
||||
$table->string('title')->comment('Titre');
|
||||
$table->string('subtitle')->comment('Sous-titre');
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ return new class extends Migration
|
|||
public function up()
|
||||
{
|
||||
Schema::create('store_groups', function (Blueprint $table) {
|
||||
$table->biginteger('id')->primary()->comment('Id du group');
|
||||
$table->id()->comment('Id du group');
|
||||
$table->string('name')->comment('Nom du group');
|
||||
$table->string('picture')->comment('Image du group');
|
||||
$table->timestamps();
|
||||
|
|
|
|||
|
|
@ -14,10 +14,10 @@ return new class extends Migration
|
|||
public function up()
|
||||
{
|
||||
Schema::create('store_regions', function (Blueprint $table) {
|
||||
$table->biginteger('id')->primary()->comment('Id de la région');
|
||||
$table->id()->comment('Id de la région');
|
||||
$table->string('name')->comment('Nom de la région');
|
||||
$table->string('picture')->comment('Image de la région');
|
||||
$table->biginteger('group_id')->comment('Id du group associé');
|
||||
$table->unsignedBigInteger('group_id')->comment('Id du group associé');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ return new class extends Migration
|
|||
public function up()
|
||||
{
|
||||
Schema::create('store_types', function (Blueprint $table) {
|
||||
$table->biginteger('id')->primary()->comment('Id du type de magasin');
|
||||
$table->id()->comment('Id du type de magasin');
|
||||
$table->string('name')->comment('Nom du type du magasin');
|
||||
$table->timestamps();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -14,15 +14,15 @@ return new class extends Migration
|
|||
public function up()
|
||||
{
|
||||
Schema::create('stores', function (Blueprint $table) {
|
||||
$table->biginteger('id')->primary()->comment('Id du magasin');
|
||||
$table->id()->comment('Id du magasin');
|
||||
$table->string('state')->comment('État dans lequel se trouve le magasin');
|
||||
$table->bigInteger('type_id')->comment('Type de magasin');
|
||||
$table->unsignedBigInteger('type_id')->comment('Type de magasin');
|
||||
$table->string('street')->comment('Rue dans laquelle se trouve magasin');
|
||||
$table->string('zipcode')->comment('Code postal dans lequel se trouve le magasin');
|
||||
$table->string('city')->comment('Ville dans laquelle se trouve le magasin');
|
||||
$table->float('latitude', 10, 0)->comment('Latitude du magasin');
|
||||
$table->float('longitude', 10, 0)->comment('Longitude du magasin');
|
||||
$table->bigInteger('region_id')->comment('Région dans laquelle se trouve le magasin');
|
||||
$table->unsignedBigInteger('region_id')->comment('Région dans laquelle se trouve le magasin');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ return new class extends Migration
|
|||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('home', function (Blueprint $table) {
|
||||
Schema::table('homes', function (Blueprint $table) {
|
||||
$table->foreign(['part2_product1_id'])->references(['id'])->on('products')->onUpdate('RESTRICT')->onDelete('RESTRICT');
|
||||
$table->foreign(['part2_product2_id'])->references(['id'])->on('products')->onUpdate('RESTRICT')->onDelete('RESTRICT');
|
||||
});
|
||||
|
|
@ -26,9 +26,9 @@ return new class extends Migration
|
|||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('home', function (Blueprint $table) {
|
||||
$table->dropForeign('home_part2_product1_id_foreign');
|
||||
$table->dropForeign('home_part2_product2_id_foreign');
|
||||
Schema::table('homes', function (Blueprint $table) {
|
||||
$table->dropForeign('homes_part2_product1_id_foreign');
|
||||
$table->dropForeign('homes_part2_product2_id_foreign');
|
||||
});
|
||||
}
|
||||
};
|
||||
Loading…
Add table
Reference in a new issue