/
DATKAI
/
ITCUP
Обзор
Документация
Войти
/
DATKAI
/
ITCUP
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
main
app/Models/KnowledgeArticle.php
122 строки
3 KB
ITCUP Admin
feat(knowledge): защита от повторного лайка + увеличена высота редактора
22 апр 2026, 04:56
22 апр 2026, 04:56
baa6e5a
Код
Авторство
О чём код?
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Support\Str; class KnowledgeArticle extends Model { protected $fillable = [ 'knowledge_category_id', 'title', 'slug', 'summary', 'body', 'tags', 'custom_field_values', 'attachments', 'is_public', 'is_pinned', 'views_count', 'helpful_count', 'created_by', 'updated_by', 'published_at', ]; protected $casts = [ 'tags' => 'array', 'custom_field_values' => 'array', 'attachments' => 'array', 'is_public' => 'boolean', 'is_pinned' => 'boolean', 'views_count' => 'integer', 'helpful_count' => 'integer', 'published_at' => 'datetime', ]; protected static function booted(): void { static::creating(function (KnowledgeArticle $a) { if (empty($a->slug)) { $a->slug = static::uniqueSlug($a->title); } if (!$a->published_at) { $a->published_at = now(); } }); static::updating(function (KnowledgeArticle $a) { if ($a->isDirty('title') && empty($a->slug)) { $a->slug = static::uniqueSlug($a->title); } }); } public static function uniqueSlug(string $title): string { $base = Str::slug($title) ?: 'article'; $slug = $base; $i = 1; while (static::where('slug', $slug)->exists()) { $slug = $base . '-' . (++$i); } return $slug; } public function category(): BelongsTo { return $this->belongsTo(KnowledgeCategory::class, 'knowledge_category_id'); } public function author(): BelongsTo { return $this->belongsTo(User::class, 'created_by'); } public function updater(): BelongsTo { return $this->belongsTo(User::class, 'updated_by'); } public function votes(): HasMany { return $this->hasMany(KnowledgeArticleVote::class); } public function incrementViews(): void { $this->increment('views_count'); } public function isLikedBy(?User $user): bool { if (!$user) { return false; } return $this->votes()->where('user_id', $user->id)->exists(); } /** * Отмечает статью полезной от имени пользователя. * Возвращает true — если голос записан впервые, false — если уже был. */ public function markHelpfulBy(User $user): bool { $vote = $this->votes()->firstOrCreate(['user_id' => $user->id]); if ($vote->wasRecentlyCreated) { $this->increment('helpful_count'); return true; } return false; } public function getRenderedBodyAttribute(): string { // body хранится как HTML из RichEditor (TipTap). Filament его уже санитизирует. return $this->body ?? ''; } }