ldc-volena/app/Models/Section.php
2024-06-21 14:58:09 +02:00

433 lines
13 KiB
PHP

<?php
namespace App\Models;
use App\Enums\CkEditorConfigName;
use App\Enums\InputType;
use App\Enums\Sections\PageSectionEnum;
use App\Lib\Helpers\FileStorageHelper;
use App\Lib\Helpers\ToolboxHelper;
use App\Traits\Models\ActivityLog;
use App\Traits\Models\MiniCrudModel;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;
/**
* @property \App\Enums\Sections\PageSectionEnum $section Slider that contains the slide.
* @property string $h2_title Title.
* @property string $text WYSIWYG - Content.
* @property array $data Minicrud content.
* @property-read \Carbon\Carbon $created_at Created date.
* @property-read \Carbon\Carbon $updated_at Updated date.
*
* @property-read \App\Models\StaticPage $page StaticPage Belongs to relationship.
* @property-read \App\Models\ActivityLog $activityLogs Activities logs One-to-many relationship.
*/
class Section extends Model
{
use ActivityLog;
use HasFactory;
use MiniCrudModel;
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'section',
'h2_title',
'text',
'data',
'page_id',
'id',
'created_at',
'updated_at'
];
/**
* The attributes that should be cast.
*
* @var array<string, string>
*/
protected $casts = [
'section' => PageSectionEnum::class,
'data' => 'array',
];
/**
* Perform any actions required after the model boots.
*
* @return void
*/
protected static function booted(): void
{
static::creating(function () {
throw new \RuntimeException("Creating a new section is not authorized");
});
static::updating(function (self $model) {
// * ASSERTIONS
ToolboxHelper::assertNoInternalBoUrls('text', $model->text);
// * TRANSFORMATIONS
$model->text = FileStorageHelper::storeModelFilesFromHtml($model, $model->text);
});
static::updated(function (self $model) {
FileStorageHelper::removeOldModelFilesFromHtml(
$model->text,
ToolboxHelper::getOriginal($model, 'text')
);
});
static::deleting(function () {
throw new \RuntimeException('Deleting a section is not authorized');
});
}
// * METHODS.
// * EMPTY BLOCS.
/**
* Empty bloc for picture.
*
* @param array $data
* @param string $img
* @param string $imgAlt
* @param string $imgTitle
* @param integer $width
* @param integer $height
* @param boolean $required
* @param string $name
* @return array
*/
public static function emptyPictureBloc(
array $data,
string $img = '',
string $imgAlt = '',
string $imgTitle = '',
int $width = 100,
int $height = 100,
bool $required = false,
string $name = 'image',
): array {
$data[sprintf('bloc_%s', Str::of($name)->snake()->ascii()->remove(['\'', '-']))] = [
'label' => $name,
'dimensions' => ['width' => $width, 'height' => $height],
'inputType' => InputType::image->value,
'alt' => $imgAlt,
'title' => $imgTitle,
'value' => $img,
'validate' => $required ? 'required' : 'nullable',
'required' => $required
];
return $data;
}
/**
* Empty bloc for link.
*
* @param array $data
* @param string $url
* @param boolean $required
* @param string $name
* @return array
*/
public static function emptyLinkBloc(
array $data,
string $url = '',
bool $required = false,
string $name = "URL à ouvrir",
): array {
$data[sprintf('bloc_%s', Str::of($name)->snake()->ascii()->remove(['\'', '-']))] = [
'label' => $name,
'inputType' => InputType::url->value,
'value' => $url,
'validate' => 'url|' . ($required ? 'required' : 'nullable'),
'required' => $required
];
return $data;
}
/**
* Empty bloc for boolean new tab link.
*
* @param array $data
* @param string $name
* @return array
*/
public static function emptyLinkNewTabBloc(
array $data,
string $name = 'le lien',
): array {
$data["bloc_link_new_tab"] = [
'label' => "Ouvrir dans un nouvel onglet {$name}",
'inputType' => InputType::boolean->value,
'value' => true,
];
return $data;
}
/**
* Empty bloc for key numbers.
*
* @param array $data
* @param string $name
* @param integer $value
* @param boolean $required
*
* @return array
*/
public static function emptyKeyNumberBloc(
array $data,
string $name,
int $value = 0,
bool $required = false,
): array {
$data['bloc_key_' . Str::of($name)->snake()->ascii()->remove(['\'', '-'])] = [
'label' => "Chiffre clé {$name}",
'inputType' => InputType::number->value,
'value' => $value,
'validate' => $required ? 'required' : 'nullable',
'required' => $required
];
return $data;
}
/**
* Empty bloc for the button boolean.
*
* @param array $data
* @param string $name
* @return array
*/
public static function emptyButtonBooleanBloc(
array $data,
string $name
): array {
$data['bloc_button_' . Str::of($name)->snake()->ascii()->remove(['\'', '-'])] = [
'label' => "Afficher le bouton '{$name}' ?",
'inputType' => InputType::boolean->value,
'value' => false
];
return $data;
}
/**
* Empty bloc for the h3 title.
*
* @param array $data
* @param string $name
* @param string $value
* @param boolean $required
* @return array
*/
public static function emptyStringBloc(
array $data,
string $name,
string $value = '',
bool $required = false
): array {
$data['bloc_string_' . Str::of($name)->snake()->ascii()->remove(['\'', '-'])] = [
'label' => $name,
'inputType' => InputType::string->value,
'validate' => 'max:255|' . ($required ? 'required' : 'nullable'),
'value' => $value,
'required' => $required
];
return $data;
}
/**
* Empty bloc for the WYSIWYG content.
*
* @param array $data
* @param string $name
* @param string $value
* @param \App\Enums\CkEditorConfigName $config
* @param boolean $required
* @return array
*/
public static function emptyWysiwygBloc(
array $data,
string $name,
string $value = '',
CkEditorConfigName $config = CkEditorConfigName::base,
bool $required = false
): array {
$data['bloc_' . Str::of($name)->snake()->ascii()->remove(['\'', '-']) . '_content'] = [
'label' => "Contenu de la section {$name}",
'inputType' => InputType::text->value,
'validate' => $required ? 'required' : 'nullable',
'value' => $value,
'required' => $required,
'config' => $config->name
];
return $data;
}
/**
* Add part piece
*
* @return void
*/
public function addPartPiece(): void
{
$pieceTemplateLinesCount = self::countPartPieces();
$pieceToAdd = self::getAddablePartPieceBlock(
$this->section,
$this->countPartPieces() + 1
);
$linesToSkip = 1;
$data = collect($this->data);
$groupedPieces = $data->skip($linesToSkip)->splitIn($data->count() / ($pieceTemplateLinesCount ?: 1))
->concat([$pieceToAdd])
->sort(function ($aCollect, $bCollect) {
if ($this->section->equals(PageSectionEnum::produce_rhd)) {
return strcmp(
strrev(collect(collect($aCollect)->first())->first()),
strrev(collect(collect($bCollect)->first())->first())
);
}
return 0;
});
$groupedPieces->prepend([$data->keys()->first() => $data->first()]);
$this->data = $groupedPieces->collapse()->all();
}
/**
* Remove part piece
*
* @param integer $index
* @return integer Elements count removed.
*/
public function removePartPiece(int $index): int
{
$pieceTemplate = self::getPartPieces();
$pieceTemplateLinesCount = self::countPartPieces();
if (!$pieceTemplateLinesCount) {
return 0;
}
$linesToSkip = 1;
$data = collect($this->data);
$groupedPieces = $data->skip($linesToSkip)->splitIn($data->count() / count($pieceTemplate));
$removedGroup = $groupedPieces->splice($index - 1, 1);
$this->data = $groupedPieces->collapse()
->prepend($data->first(), $data->keys()->first())
->all();
return $removedGroup->count();
}
/**
* Count part pieces
*
* @return integer
*/
public function countPartPieces(): int
{
$pieceTemplate = self::getPartPieces();
$data = collect($this->data);
$templateKeys = collect($pieceTemplate)->keys();
$dataCount = $data->count();
$repetitionCount = 0;
for ($i = 1; $i <= $dataCount; $i++) {
$indexKeys = $templateKeys->map(fn ($key) => str_replace('__index', strval($i), $key));
if ($indexKeys->every(fn ($key) => $data->has($key))) {
$repetitionCount++;
}
}
return $repetitionCount;
}
/**
* Get part pieces
*
* @return array
*/
private function getPartPieces(): array
{
$pieceTemplate = self::getAddablePartPieceBlockTemplate($this->section);
return is_null($pieceTemplate) ? [] : $pieceTemplate;
}
/**
* Addable part piece block
*
* @param \App\Enums\Sections\PageSectionEnum $sectionEnum
* @param integer $index
* @return array
*/
public static function getAddablePartPieceBlock(PageSectionEnum $sectionEnum, int $index = 1): array|null
{
$data = null;
$pieceTemplate = self::getAddablePartPieceBlockTemplate($sectionEnum);
if (!is_null($pieceTemplate)) {
$data = json_decode(Str::of(json_encode($pieceTemplate))->replace('__index', strval($index)), true);
/** @var array $data */
}
return $data;
}
/**
* Addable part piece block
*
* @param \App\Enums\Sections\PageSectionEnum $sectionEnum
* @return array
*/
public static function getAddablePartPieceBlockIndexes(PageSectionEnum $sectionEnum): array|null
{
$data = self::getAddablePartPieceBlockTemplate($sectionEnum);
if (!is_null($data)) {
return array_keys($data);
}
return $data;
}
/**
* @param \App\Enums\Sections\PageSectionEnum $sectionEnum
* @return array|null
*/
private static function getAddablePartPieceBlockTemplate(PageSectionEnum $sectionEnum): array|null
{
$data = null;
switch ($sectionEnum) {
case PageSectionEnum::produce_export:
$data = array_merge(
self::emptyWysiwygBloc(
[],
"accompagnant l'image __index de la partie",
''
),
self::emptyPictureBloc([], '', '', '', 100, 100, true, "Image __index de la partie"),
self::emptyLinkBloc([], '', false, "Lien de l'image__index de la partie")
);
break;
case PageSectionEnum::produce_rhd:
$data = array_merge(
self::emptyWysiwygBloc(
[],
"accompagnant l'image __index de la partie 1",
''
),
self::emptyPictureBloc([], '', '', '', 100, 100, true, "Image __index de la partie 1"),
self::emptyLinkBloc([], '', false, "Lien de l'image__index de la partie 1")
);
break;
default:
} //end switch
return $data;
}
// * RELATIONS
/**
* Get the page that owns the section.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function page(): \Illuminate\Database\Eloquent\Relations\BelongsTo
{
return $this->belongsTo(StaticPage::class);
}
}