Files
RomhackPlaza/app/Models/Entry.php
2026-06-29 19:24:35 +02:00

283 lines
9.9 KiB
PHP

<?php
namespace App\Models;
use App\Helpers\EntryHelpers;
use App\Models\Scopes\NsfwScope;
use App\Traits\HasGallery;
use App\Traits\HasXenforoUserId;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use League\CommonMark\GithubFlavoredMarkdownConverter;
use Monolog\Level;
use Spatie\Activitylog\Models\Concerns\LogsActivity;
use Spatie\Activitylog\Support\LogOptions;
/**
* @property int $id
* @property string $type
* @property string|null $title
* @property string|null $slug
* @property string|null $description
* @property string|null $main_image
* @property string $state
* @property string|null $staff_comment
* @property \Illuminate\Support\Carbon|null $rejected_at
* @property bool $featured
* @property \Illuminate\Support\Carbon|null $featured_at
* @property int|null $game_id
* @property int|null $platform_id
* @property int|null $status_id
* @property string|null $version
* @property \Illuminate\Support\Carbon|null $release_date
* @property string|null $staff_credits
* @property string|null $relevant_link
* @property string|null $youtube_link
* @property int $user_id
* @property int|null $comments_thread_id
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @property string|null $complete_title
* @property \Illuminate\Support\Carbon|null $deleted_at
* @property int|null $level_id
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Author> $authors
* @property-read int|null $authors_count
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Category> $categories
* @property-read int|null $categories_count
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\EntryFile> $files
* @property-read int|null $files_count
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Gallery> $gallery
* @property-read int|null $gallery_count
* @property-read \App\Models\Game|null $game
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\EntryHash> $hashes
* @property-read int|null $hashes_count
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Language> $languages
* @property-read int|null $languages_count
* @property-read \App\Models\Level|null $level
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Modification> $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<int, \App\Models\System> $systems
* @property-read int|null $systems_count
* @method static Builder<static>|Entry inQueue(int $daysRejected = 7)
* @method static Builder<static>|Entry newModelQuery()
* @method static Builder<static>|Entry newQuery()
* @method static Builder<static>|Entry onlyTrashed()
* @method static Builder<static>|Entry published()
* @method static Builder<static>|Entry query()
* @method static Builder<static>|Entry whereCommentsThreadId($value)
* @method static Builder<static>|Entry whereCompleteTitle($value)
* @method static Builder<static>|Entry whereCreatedAt($value)
* @method static Builder<static>|Entry whereDeletedAt($value)
* @method static Builder<static>|Entry whereDescription($value)
* @method static Builder<static>|Entry whereFeatured($value)
* @method static Builder<static>|Entry whereFeaturedAt($value)
* @method static Builder<static>|Entry whereGameId($value)
* @method static Builder<static>|Entry whereId($value)
* @method static Builder<static>|Entry whereLevelId($value)
* @method static Builder<static>|Entry whereMainImage($value)
* @method static Builder<static>|Entry wherePlatformId($value)
* @method static Builder<static>|Entry whereRejectedAt($value)
* @method static Builder<static>|Entry whereReleaseDate($value)
* @method static Builder<static>|Entry whereRelevantLink($value)
* @method static Builder<static>|Entry whereSlug($value)
* @method static Builder<static>|Entry whereStaffComment($value)
* @method static Builder<static>|Entry whereStaffCredits($value)
* @method static Builder<static>|Entry whereState($value)
* @method static Builder<static>|Entry whereStatusId($value)
* @method static Builder<static>|Entry whereTitle($value)
* @method static Builder<static>|Entry whereType($value)
* @method static Builder<static>|Entry whereUpdatedAt($value)
* @method static Builder<static>|Entry whereUserId($value)
* @method static Builder<static>|Entry whereVersion($value)
* @method static Builder<static>|Entry whereYoutubeLink($value)
* @method static Builder<static>|Entry withTrashed(bool $withTrashed = true)
* @method static Builder<static>|Entry withoutTrashed()
* @property-read \Illuminate\Database\Eloquent\Collection<int, \Spatie\Activitylog\Models\Activity> $activitiesAsSubject
* @property-read int|null $activities_as_subject_count
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\EntryReview> $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}");
}
}