Files
Epicnabbo-Catalogus-Updated…/Updated_Cms/app/Models/Article.php
T
2026-01-07 20:31:19 +01:00

148 lines
4.1 KiB
PHP

<?php
namespace App\Models;
use App\Enums\NotificationType;
use App\Models\Article\ArticleComment;
use App\Models\Article\ArticleReaction;
use App\Models\Compositions\HasNotificationUrl;
use Auth;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Str;
class Article extends Model
{
use HasFactory;
use HasNotificationUrl;
protected $guarded = [];
protected $table = 'website_articles';
#[\Override]
public static function boot()
{
parent::boot();
static::creating(function (Article $article): void {
$article->user_id = Auth::id();
$article->slug = Str::slug($article->title);
$article->predominant_color = getPredominantImageColor($article->image);
});
static::updating(function (Article $article): void {
$article->slug = Str::slug($article->title);
if ($article->isDirty('image')) {
$article->predominant_color = getPredominantImageColor($article->image);
}
});
}
public function syncPaginatedComments(): void
{
$this->setRelation('comments',
$this->comments()->defaultRelationships()->paginate(10)->fragment('comments'),
);
}
public static function fromIdAndSlug(string $id, string $slug, bool $withDefaultRelationships = true): Builder
{
return Article::valid()
->when($withDefaultRelationships, fn ($query) => $query->defaultRelationships())
->whereId($id)
->whereSlug($slug);
}
public static function getLatestValidArticle(bool $withDefaultRelationships = true): ?Article
{
$article = Article::valid()
->when($withDefaultRelationships, fn ($query) => $query->defaultRelationships())
->latest()
->first();
if (! $article) {
return null;
}
$article->syncPaginatedComments();
return $article;
}
public static function forIndex(int $limit): Builder
{
return Article::valid()
->with(['user:id,username,look,avatar_background'])
->select(['id', 'user_id', 'title', 'slug', 'is_promotion', 'image', 'description', 'promotion_ends_at', 'created_at', 'fixed'])
->limit($limit)
->latest();
}
#[\Illuminate\Database\Eloquent\Attributes\Scope]
protected function valid(Builder $query): void
{
$query->whereVisible(true);
}
#[\Illuminate\Database\Eloquent\Attributes\Scope]
protected function defaultRelationships(Builder $query): void
{
$query->with([
'user:id,username,look,gender',
'tags',
'reactions' => fn ($query) => $query->defaultRelationships(),
'user.followers',
]);
}
public function comments(): HasMany
{
return $this->hasMany(ArticleComment::class)->defaultBehavior();
}
public function reactions(): HasMany
{
return $this->hasMany(ArticleReaction::class)->defaultBehavior();
}
public function user()
{
return $this->belongsTo(User::class);
}
public function tags()
{
return $this->morphToMany(Tag::class, 'taggable');
}
protected function titleColor(): Attribute
{
return new Attribute(
get: fn () => isDarkColor($this->predominant_color) ? '#fff' : '#000',
);
}
public function createFollowersNotification(): void
{
$this->user->followers()
->with('user:id,username')
->each(fn (AuthorNotification $follower) => $follower->user->notify($this->user, NotificationType::ArticlePosted, $this->getNotificationUrl()),
);
}
protected function casts(): array
{
return [
'visible' => 'boolean',
'fixed' => 'boolean',
'allow_comments' => 'boolean',
'is_promotion' => 'boolean',
'promotion_ends_at' => 'datetime',
];
}
}