|array>|array $value The actual setting value. * @package App\Models */ class GeneralSetting extends Model { use IsCachedAsCollection; /** * The primary key for the model. * * @var string */ protected $primaryKey = 'type'; /** * The "type" of the primary key ID. * * @var string */ protected $keyType = SettingsType::class; /** * Indicates if the IDs are auto-incrementing. * * @var boolean */ public $incrementing = false; /** * The attributes that are mass assignable. * * @var array */ protected $fillable = [ 'value' ]; /** * The attributes that should be cast. * * @var array */ protected $casts = [ 'type' => SettingsType::class, 'value' => 'json' ]; /** * Perform any actions required after the model boots. * * @return void * @throws \ErrorException Not allowed to create an instance of this. */ protected static function booted(): void { static::creating(fn() => throw new \ErrorException('Not allowed to create an instance of this')); static::updated(function (self $model) { if ($model->type === SettingsType::hotNews) { FileStorageHelper::removeOldFiles( Arr::wrap(Arr::get($model->getOriginal('value'), 'picture')), Arr::wrap($model->value['picture']) ); } self::removeCached(); self::resetCache($model->type); }); static::deleting(fn() => throw new \ErrorException('Not allowed to create an instance of this')); } // * ROUTABLE /** * Get the value of the model's route key. * * @return mixed */ public function getRouteKey(): mixed { /** @var \App\Enums\StaticPageType */ $enum = $this->getAttribute($this->getRouteKeyName()); return $enum->value(); } /** * Get the route key for the model. * * ! Type is the routable parameter * * @return string */ public function getRouteKeyName(): string { return 'type'; } // * GETTERS /** * Mutator for 'value' attribute. * * @return \Illuminate\Database\Eloquent\Casts\Attribute */ public function value(): \Illuminate\Database\Eloquent\Casts\Attribute { return Attribute::make( get: fn($value): array => self::valueFromJson($this->type, $value), ); } // * METHODS /** * Get the json layout for a setting type. * * @param \App\Enums\Settings\SettingsType $type * * ! Note complete this with pipes when adding another SettingsType. * @return array<\App\Lib\Definitions\MenuNode>|array> * @throws \ErrorException If $type is unhandled. */ public static function getJsonLayout(SettingsType $type): array { return match ($type) { SettingsType::mainMenu => collect(MenuNodeType::all()) ->filter(fn(MenuNodeType $menuNodeType) => $menuNodeType !== MenuNodeType::link) ->map(fn(MenuNodeType $nodeType, int $key) => MenuNode::make( $key + 1, $nodeType->value(), true, $nodeType->label(), !empty($nodeType->routeName()) ? // phpcs:ignore Generic.Files.LineLength.TooLong (new Link(routeName: $nodeType->routeName()))->toArray() : (new Link(url: 'https://example.net'))->toArray() ))->all(), SettingsType::hotNews => [ 'text' => 'le texte', 'picture' => null, 'picture_alt' => 'le texte alt de l\'image', 'picture_title' => 'le titre de l\'image', ], SettingsType::offersCount => [ 'count' => 0, ], SettingsType::breederMap => [ 'title' => 'titre', 'main_text' => 'texte principal', 'picto_text' => 'texte du pictogramme', ], // @phpstan-ignore-next-line default => throw new \ErrorException("No instruction to seed setting type '{$type->label()}'") }; //end match } /** * Unserialize setting value. * * @param \App\Enums\Settings\SettingsType $type * @param string $json * ! Note complete this with pipes when adding another SettingsType. * @return array<\App\Lib\Definitions\MenuNode>|array> * @throws \ErrorException If $type is unhandled. */ public static function valueFromJson(SettingsType $type, string $json): array { return match ($type) { SettingsType::mainMenu => collect(json_decode($json, true)) ->map(fn(array $jsonLayout) => MenuNode::make(...$jsonLayout))->all(), SettingsType::hotNews => json_decode($json, true), SettingsType::offersCount => json_decode($json, true), SettingsType::breederMap => json_decode($json, true), // @phpstan-ignore-next-line default => throw new \ErrorException("No instruction to unserialize setting type '{$type->label()}'") }; } /** * Reset all cache elements related to this model. * * @param \App\Enums\Settings\SettingsType $type * @return void */ private static function resetCache(SettingsType $type): void { Cache::forget(sprintf('%sGeneralSetting', $type->name)); self::getCachedGeneralSetting($type); } /** * Get cached general setting associated to a given type. * * @param \App\Enums\Settings\SettingsType $type * @return mixed */ public static function getCachedGeneralSetting(SettingsType $type): mixed { return Cache::rememberForever( sprintf('%sGeneralSetting', $type->name), fn() => self::query()->where('type', $type)->first() ); } }