*/ protected $fillable = [ 'seo_title', 'seo_description', 'title', 'subtitle', 'slug', 'picture', 'picture_alt', 'picture_title', 'thumbnail', 'thumbnail_alt', 'thumbnail_title', 'news_category_id', 'content', 'highlight', 'published', 'publish_at', 'unpublish_at', ]; /** * The attributes that should be cast. * * @var array */ protected $casts = [ 'publish_at' => 'datetime', 'unpublish_at' => 'datetime', 'published' => 'boolean', 'highlight' => 'boolean', ]; /** * Perform any actions required after the model boots. * * @return void */ protected static function booted(): void { static::creating(function (self $news) { self::makeStatusSense($news); self::checkHighlightField($news); self::assertTitleIsUnique($news->title); self::manageFields($news); }); static::updating(function (self $news) { self::makeStatusSense($news); self::checkHighlightField($news); self::manageFields($news); }); static::updated(function (self $news) { FileStorageHelper::removeOldFile($news, 'picture'); FileStorageHelper::removeOldFile($news, 'thumbnail'); FileStorageHelper::removeOldModelFilesFromHtml($news->content, $news->getOriginal("content")); }); static::deleted(function (self $news) { FileStorageHelper::removeFile($news, 'picture'); FileStorageHelper::removeFile($news, 'thumbnail'); FileStorageHelper::removeOldModelFilesFromHtml($news->content, $news->getOriginal("content")); }); } // * METHODS /** * Adjusts news status using current status and publish dates. * * @param self $news * @return void */ private static function makeStatusSense(self $news): void { /** @var \Carbon\Carbon|null */ $publish_at = $news->publish_at; /** @var \Carbon\Carbon|null */ $unpublish_at = $news->unpublish_at; $wantedStatus = $news->published; if ($publish_at or $unpublish_at) { $news->published = $news->planificated_status; } if ($wantedStatus !== $news->published) { session()->flash('bo.info', \trans( 'La publication est modifiée en concordance avec les dates enregistrées. Pour modifier l\'état de publication, veuillez modifier ou enlever les dates correspondantes.' )); } } /** * Adjusts news status using current status and publish dates. * * @param self $news * @return void */ private static function checkHighlightField(self $news): void { $hotNewsModels = News::query() ->where('published', true) ->where('highlight', true) ->where('id', '!=', $news->getKey()) ->orderBy('publish_at', 'ASC') ->get(); if ($hotNewsModels->count() >= 2 && $news->highlight) { $hotNewsModel = $hotNewsModels->first(); $hotNewsModel->highlight = false; $hotNewsModel->saveOrFail(); Session::flash('warning', trans( 'Maximum 2 :model1 peuvent être mise en avant, la plus ancienne a donc été enlevée des :model2', [ 'model1' => Str::of(trans('models.classes.news'))->plural(), 'model2' => trans('models.classes.hot_news'), ] )); } } /** * Getter the current status following planification dates planificated_status. * * @return boolean */ public function getPlanificatedStatusAttribute(): bool { /** @var \Carbon\Carbon|null */ $publish_at = $this->publish_at; /** @var \Carbon\Carbon|null */ $unpublish_at = $this->unpublish_at; if ($publish_at and $unpublish_at) { return $unpublish_at->greaterThanOrEqualTo(now()) and $publish_at->lessThan(now()); } if ($publish_at) { return $publish_at->lessThan(now()); } if ($unpublish_at) { return $unpublish_at->greaterThanOrEqualTo(now()); } return false; } /** * Manage model fields. * * @param self $model * @return void */ private static function manageFields(self $model): void { self::assertTitleIsUnique($model->title, $model->getKey()); $model->slug = str($model->title)->slug(); $model->thumbnail = FileStorageHelper::storeFile($model, $model->thumbnail, true); $model->picture = FileStorageHelper::storeFile($model, $model->picture, true); } /** * Asserts using validation that the title is unique. * * @param string|null $title * @param integer|null $id * @return void * @throws \Illuminate\Validation\ValidationException If an actu title already exists. */ private static function assertTitleIsUnique(string|null $title, ?int $id = null): void { $table = (new self())->getTable(); ToolboxHelper::assertFieldIsUnique($table, 'title', $title, $id); ToolboxHelper::assertFieldIsUnique($table, 'slug', str($title)->slug(), $id); } /** * Get News views by News category. * * @param string|null $slug * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator */ public static function getNewsViewsByNewsCategory( string|null $slug = null ): \Illuminate\Contracts\Pagination\LengthAwarePaginator { $detect = new MobileDetect(); /** @var \App\Models\NewsCategory|null */ $newsCategoryModel = !is_null($slug) && !empty($slug) ? NewsCategory::query()->where('slug', $slug)->first() : null; return News::query() ->with('newsCategory') ->when(!is_null($newsCategoryModel), function (Builder $q) use ($newsCategoryModel) { $q->whereHas('newsCategory', function (Builder $q) use ($newsCategoryModel) { $q->where('id', $newsCategoryModel->getKey()); }); }) ->where('published', true) ->orderByDesc('created_at') ->paginate($detect->isMobile() ? 3 : 6) ->through(function ($newsModel) { return view('fo.partials.news-card', ['newsModel' => $newsModel])->render(); }); } /** * Get Social news views by filter social category. * * @param string|null $slug * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator */ public static function getSocialViewsByFilter( string|null $slug = null ): \Illuminate\Contracts\Pagination\LengthAwarePaginator { $detect = new MobileDetect(); /** @var \App\Models\NewsCategory|null */ $socialCategory = !is_null($slug) && !empty($slug) ? NewsCategory::query()->where('slug', $slug)->first() : null; return News::query() ->with('newsCategory') ->when(!is_null($socialCategory), function (Builder $q) use ($socialCategory) { $q->whereHas('newsCategory', function (Builder $q) use ($socialCategory) { $q->where('id', $socialCategory->getKey()); }); }) ->where('published', true) ->orderByDesc('created_at') ->paginate($detect->isMobile() ? 4 : 12) ->through(function ($socialModel) { return view('fo.partials.news-card', ['newsModel' => $socialModel])->render(); }); } // * RELATIONS /** * Get the category that owns the news. * * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ public function newsCategory(): \Illuminate\Database\Eloquent\Relations\BelongsTo { return $this->belongsTo(NewsCategory::class); } }