$authors * @property-read int|null $authors_count * @property-read \Illuminate\Database\Eloquent\Collection $categories * @property-read int|null $categories_count * @property-read \Illuminate\Database\Eloquent\Collection $files * @property-read int|null $files_count * @property-read \Illuminate\Database\Eloquent\Collection $gallery * @property-read int|null $gallery_count * @property-read \App\Models\Game|null $game * @property-read \Illuminate\Database\Eloquent\Collection $hashes * @property-read int|null $hashes_count * @property-read \Illuminate\Database\Eloquent\Collection $languages * @property-read int|null $languages_count * @property-read \App\Models\Level|null $level * @property-read \Illuminate\Database\Eloquent\Collection $modifications * @property-read int|null $modifications_count * @property-read \App\Models\Platform|null $platform * @property-read \App\Models\Status|null $status * @property-read \Illuminate\Database\Eloquent\Collection $systems * @property-read int|null $systems_count * @method static Builder|Entry inQueue(int $daysRejected = 7) * @method static Builder|Entry newModelQuery() * @method static Builder|Entry newQuery() * @method static Builder|Entry onlyTrashed() * @method static Builder|Entry published() * @method static Builder|Entry query() * @method static Builder|Entry whereCommentsThreadId($value) * @method static Builder|Entry whereCompleteTitle($value) * @method static Builder|Entry whereCreatedAt($value) * @method static Builder|Entry whereDeletedAt($value) * @method static Builder|Entry whereDescription($value) * @method static Builder|Entry whereFeatured($value) * @method static Builder|Entry whereFeaturedAt($value) * @method static Builder|Entry whereGameId($value) * @method static Builder|Entry whereId($value) * @method static Builder|Entry whereLevelId($value) * @method static Builder|Entry whereMainImage($value) * @method static Builder|Entry wherePlatformId($value) * @method static Builder|Entry whereRejectedAt($value) * @method static Builder|Entry whereReleaseDate($value) * @method static Builder|Entry whereRelevantLink($value) * @method static Builder|Entry whereSlug($value) * @method static Builder|Entry whereStaffComment($value) * @method static Builder|Entry whereStaffCredits($value) * @method static Builder|Entry whereState($value) * @method static Builder|Entry whereStatusId($value) * @method static Builder|Entry whereTitle($value) * @method static Builder|Entry whereType($value) * @method static Builder|Entry whereUpdatedAt($value) * @method static Builder|Entry whereUserId($value) * @method static Builder|Entry whereVersion($value) * @method static Builder|Entry whereYoutubeLink($value) * @method static Builder|Entry withTrashed(bool $withTrashed = true) * @method static Builder|Entry withoutTrashed() * @property-read \Illuminate\Database\Eloquent\Collection $activitiesAsSubject * @property-read int|null $activities_as_subject_count * @property-read \Illuminate\Database\Eloquent\Collection $reviews * @property-read int|null $reviews_count * @property-read float $average_rating * @property-read int $reviews_count_cached * @property-read string $description_html * @mixin \Eloquent */ class Entry extends Model { use SoftDeletes, HasGallery, LogsActivity, HasXenforoUserId; /** * @var string[] */ protected $fillable = [ 'type', 'title', 'slug', 'description', 'main_image', 'state', 'featured', 'featured_at', 'game_id', 'platform_id', 'status_id', 'version', 'release_date', 'staff_credits', 'relevant_link', 'youtube_link', 'user_id', 'complete_title', 'comments_thread_id', 'staff_comment', 'rejected_at', 'level_id', 'created_at', 'nsfw' ]; /** * @var string[] */ protected $casts = [ 'featured' => 'boolean', 'release_date' => 'date', 'rejected_at' => 'datetime', 'featured_at' => 'datetime', ]; protected static function booted(): void { static::addGlobalScope(new NsfwScope); static::saving( function( $entry ) { if( $entry->isDirty('version') ) { $entry->created_at = now(); } }); } public function scopePublished( Builder $query ): Builder { return $query->where( 'state', 'published' ); } public function scopeInQueue( Builder $query, int $daysRejected = 7 ): Builder { return $query->withTrashed()->where(function($q) use($daysRejected) { $q->where('state', 'pending')->whereNull('deleted_at'); })->orWhere(function($q) use($daysRejected) { $q->where('state', 'rejected')->whereNotNull('rejected_at')->where('rejected_at', '>=', now()->subDays($daysRejected) ); }); } /** * Return game link. * @return BelongsTo */ public function game(): BelongsTo { return $this->belongsTo(Game::class); } public function platform(): BelongsTo { return $this->belongsTo(Platform::class); } public function getRealPlatform(): ?Platform { return $this->game?->platform ?? $this->platform; } public function status(): BelongsTo { return $this->belongsTo(Status::class ); } public function level(): BelongsTo { return $this->belongsTo(\App\Models\Level::class); } public function authors(): BelongsToMany { return $this->belongsToMany(Author::class, 'entry_authors'); } public function languages(): BelongsToMany { return $this->belongsToMany(Language::class, 'entry_languages'); } public function modifications(): BelongsToMany { return $this->belongsToMany( Modification::class, 'entry_modifications'); } public function categories(): BelongsToMany { return $this->belongsToMany(Category::class, 'entry_categories'); } public function systems(): BelongsToMany { return $this->belongsToMany(System::class, 'entry_systems'); } public function files(): HasMany { return $this->hasMany(EntryFile::class)->orderBy('filename'); } public function hashes(): HasMany { return $this->hasMany(EntryHash::class); } public function reviews(): HasMany { return $this->hasMany(EntryReview::class); } public function getAverageRatingAttribute(): float { return round( $this->reviews->avg('rating') ?? 0, 1 ); } public function getReviewsCountCachedAttribute(): int { return $this->reviews->count(); } public function getDescriptionHtmlAttribute(): string { $converter = new GithubFlavoredMarkdownConverter([ 'html_input' => 'strip', 'allow_unsafe_links' => false, ]); return $converter->convert($this->description)->getContent(); } public function getTotalDownloadsAttribute(): int { return $this->files->sum('download_count') + $this->old_download_count; } public function parseStaffCredits(): ?array { return json_decode( $this->staff_credits ?? "", true ); } public function getYoutubeVideoId(): ?string { if( !$this->youtube_link ) return null; return EntryHelpers::getYoutubeVideoId( $this->youtube_link ); } public function getActivitylogOptions(): LogOptions { return LogOptions::defaults() ->useLogName('entry') ->logAll() ->logOnlyDirty() ->dontLogEmptyChanges() ->setDescriptionForEvent(fn(string $eventName) => "Entry {$eventName}"); } }