*/ protected $fillable = [ 'title', 'slug', 'content', 'config_id', 'status', 'isLocked', ]; /** * The attributes that should be cast. * * @var array */ protected $casts = [ 'content' => 'array', 'status' => PageStatusEnum::class, 'isLocked' => 'boolean', ]; /** * The translatable columns. * * @var list */ public $translatable = [ 'slug', 'title', 'content', ]; public function inertiaFill(array $attributes) { if (!empty($attributes['content'])) { $attributes['content'] = collect($attributes['content']) ->map(function ($value, $key) { if ( Str::startsWith($key, DynamicFieldTypes::image->name . '_') && $value instanceof UploadedFile ) { return FileHelper::storeFile($this, $value); } return $value; }) ->all(); } parent::fill($attributes); } /** * Perform any actions required after the model boots. * * @return void */ protected static function booted(): void { static::creating(function (self $model) { self::manageFields($model); }); static::created(function () { self::resetCache(); }); static::updating(function (self $model) { self::manageFields($model); }); static::updated(function (self $model) { self::resetCache(); DynamicPageHelper::removeImgs($model); }); static::deleted(function () { self::resetCache(); }); static::restoring(function (self $model) { if ($model->config_id && $model->config()->onlyTrashed()->exists()) { throw ValidationException::withMessages([ 'error' => __('crud.messages.cannot_be_restored', [ 'model' => Str::ucfirst(trans_choice('models.classes.dynamic-page', 1)) ]), ]); } self::resetCache(); $model->status = PageStatusEnum::draft; }); static::forceDeleted(function (self $model) { self::resetCache(); DynamicPageHelper::removeImgs($model, true); }); } // * METHODS /** * Manage model fields. * * @param self $model * @return void */ private static function manageFields(self $model): void { // Check unique fields. $slug = Str::slug($model->title); TranslationHelper::assertTranslationFieldIsUnique($model, $model->title, 'title'); TranslationHelper::assertTranslationFieldIsUnique($model, $slug, 'slug', 'title'); $model->setAttribute('slug', $slug); // Check translations. self::validateFallbackTranslations($model); } /** * Concat all wysiwyg strings in only one. * * @param string|array|null $content * @return string */ private static function flattenContent(string|array|null $content): string { if (is_string($content)) { return $content; } if (is_array($content)) { return implode("\n", array_filter($content, fn($val) => is_string($val))); } return ''; } /** * Assert fallback locale translation is present. * * @param self $model * @return void * @throws \Illuminate\Validation\ValidationException Translations missing. */ public static function validateFallbackTranslations(self $model): void { if (! $model->status->equals(PageStatusEnum::published)) { return; } TranslationHelper::validateFallbackTranslations($model); } /** * Get the view of a specific dynamic page. * * @return string */ public function getView(): string { /** @var string $view The view used for the route. */ $view = 'front.pages.dynamic-page-default'; // Check if the view in config is defined and can be used. if (!empty($this->config->view)) { $candidate = sprintf('front.pages.%s', $this->config->view); if (view()->exists($candidate)) { $view = $candidate; } } // Check if a view with the slug exists. if ($view === 'dynamic-page-default' && !empty($this->slug)) { $candidate = sprintf('front.pages.%s', $this->slug); if (view()->exists($candidate)) { $view = $candidate; } } return $view; } /** * Reset all cache elements related to this model. * * @return void */ public static function resetCache(): void { Cache::forget('publishedDynamicPages'); self::getPublishedDynamicPages(); } /** * Get all published dynamic pages. * * @return \Illuminate\Database\Eloquent\Collection */ public static function getPublishedDynamicPages(): \Illuminate\Database\Eloquent\Collection { return Cache::remember('publishedDynamicPages', 86400, function () { return self::query() ->where('status', PageStatusEnum::published) ->with('config') ->get(); }); } // * RELATIONSHIPS /** * Get the config for the page. * * @return \Illuminate\Database\Eloquent\Relations\BelongsTo<\App\Models\PageConfig,$this> */ public function config(): \Illuminate\Database\Eloquent\Relations\BelongsTo { return $this->belongsTo(PageConfig::class); } }