forge/app/Models/ModVersion.php

214 lines
6.7 KiB
PHP
Raw Normal View History

2024-05-15 00:31:24 -04:00
<?php
2025-01-30 00:23:55 -05:00
declare(strict_types=1);
2024-05-15 00:31:24 -04:00
namespace App\Models;
use App\Exceptions\InvalidVersionNumberException;
use App\Models\Scopes\DisabledScope;
2024-07-26 09:35:09 -04:00
use App\Models\Scopes\PublishedScope;
use App\Support\Version;
2025-01-30 20:49:56 -05:00
use Database\Factories\ModVersionFactory;
2025-01-30 15:44:05 -05:00
use Illuminate\Database\Eloquent\Collection;
2024-05-15 00:31:24 -04:00
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOneThrough;
2024-05-15 00:31:24 -04:00
use Illuminate\Database\Eloquent\SoftDeletes;
2025-01-30 15:44:05 -05:00
use Illuminate\Support\Carbon;
2025-01-30 00:23:55 -05:00
use Override;
2024-05-15 00:31:24 -04:00
2025-01-30 15:44:05 -05:00
/**
* ModVersion Model
*
* @property int $id
* @property int|null $hub_id
* @property int $mod_id
* @property string $version
* @property int $version_major
* @property int $version_minor
* @property int $version_patch
* @property string $version_pre_release
* @property string $description
* @property string $link
* @property string $spt_version_constraint
* @property string $virus_total_link
* @property int $downloads
* @property bool $disabled
* @property Carbon|null $deleted_at
* @property Carbon|null $published_at
* @property Carbon $created_at
* @property Carbon $updated_at
* @property-read Mod $mod
* @property-read Collection<int, ModDependency> $dependencies
* @property-read Collection<int, ModVersion> $resolvedDependencies
* @property-read Collection<int, ModVersion> $latestResolvedDependencies
* @property-read SptVersion|null $latestSptVersion
* @property-read Collection<int, SptVersion> $sptVersions
*/
2024-05-15 00:31:24 -04:00
class ModVersion extends Model
{
2025-01-30 20:49:56 -05:00
/** @use HasFactory<ModVersionFactory> */
2024-09-12 13:19:52 -04:00
use HasFactory;
2025-01-30 20:49:56 -05:00
2024-09-12 13:19:52 -04:00
use SoftDeletes;
2024-05-15 00:31:24 -04:00
/**
* Update the parent mod's updated_at timestamp when the mod version is updated.
2025-01-30 20:49:56 -05:00
*
* @var string[]
*/
protected $touches = ['mod'];
2024-07-20 19:52:36 -04:00
/**
* Post boot method to configure the model.
*/
2025-01-30 00:23:55 -05:00
#[Override]
protected static function booted(): void
{
static::addGlobalScope(new DisabledScope);
2024-07-26 09:35:09 -04:00
static::addGlobalScope(new PublishedScope);
2025-01-30 00:23:55 -05:00
static::saving(function (ModVersion $modVersion): void {
// Extract the version sections from the version string.
try {
2025-01-30 00:23:55 -05:00
$version = new Version($modVersion->version);
$modVersion->version_major = $version->getMajor();
$modVersion->version_minor = $version->getMinor();
$modVersion->version_patch = $version->getPatch();
$modVersion->version_pre_release = $version->getPreRelease();
} catch (InvalidVersionNumberException) {
$modVersion->version_major = 0;
$modVersion->version_minor = 0;
$modVersion->version_patch = 0;
$modVersion->version_pre_release = '';
}
});
}
2024-07-20 19:52:36 -04:00
/**
* The relationship between a mod version and mod.
2024-09-12 13:19:52 -04:00
*
2025-01-30 15:44:05 -05:00
* @return BelongsTo<Mod, $this>
2024-07-20 19:52:36 -04:00
*/
2024-05-15 00:31:24 -04:00
public function mod(): BelongsTo
{
return $this->belongsTo(Mod::class);
}
/**
* The relationship between a mod version and its dependencies.
2024-09-12 13:19:52 -04:00
*
2025-01-30 15:44:05 -05:00
* @return HasMany<ModDependency, $this>
*/
public function dependencies(): HasMany
{
return $this->hasMany(ModDependency::class)
->chaperone();
}
/**
* The relationship between a mod version and its resolved dependencies.
2024-09-12 13:19:52 -04:00
*
2025-01-30 15:44:05 -05:00
* @return BelongsToMany<ModVersion, $this>
*/
public function resolvedDependencies(): BelongsToMany
{
return $this->belongsToMany(ModVersion::class, 'mod_resolved_dependencies', 'mod_version_id', 'resolved_mod_version_id')
->withPivot('dependency_id')
->withTimestamps();
}
/**
* The relationship between a mod version and its each of it's resolved dependencies' latest versions.
2024-09-12 13:19:52 -04:00
*
2025-01-30 15:44:05 -05:00
* @return BelongsToMany<ModVersion, $this>
*/
public function latestResolvedDependencies(): BelongsToMany
{
return $this->belongsToMany(ModVersion::class, 'mod_resolved_dependencies', 'mod_version_id', 'resolved_mod_version_id')
->withPivot('dependency_id')
2025-01-30 00:23:55 -05:00
->join('mod_versions as latest_versions', function ($join): void {
$join->on('latest_versions.id', '=', 'mod_versions.id')
->whereRaw('latest_versions.version = (SELECT MAX(mv.version) FROM mod_versions mv WHERE mv.mod_id = mod_versions.mod_id)');
})
->with('mod:id,name,slug')
->withTimestamps();
}
/**
* The relationship between a mod version and its latest SPT version.
2024-09-12 13:19:52 -04:00
*
2025-01-30 15:44:05 -05:00
* @return HasOneThrough<SptVersion, ModVersionSptVersion, $this>
*/
public function latestSptVersion(): HasOneThrough
{
return $this->hasOneThrough(SptVersion::class, ModVersionSptVersion::class, 'mod_version_id', 'id', 'id', 'spt_version_id')
->orderByDesc('spt_versions.version_major')
->orderByDesc('spt_versions.version_minor')
->orderByDesc('spt_versions.version_patch')
->orderByDesc('spt_versions.version_pre_release')
->limit(1);
}
2024-07-20 19:52:36 -04:00
/**
* The relationship between a mod version and its SPT versions.
2024-09-12 13:19:52 -04:00
*
2025-01-30 15:44:05 -05:00
* @return BelongsToMany<SptVersion, $this>
2024-07-20 19:52:36 -04:00
*/
public function sptVersions(): BelongsToMany
2024-05-15 00:31:24 -04:00
{
return $this->belongsToMany(SptVersion::class)
->using(ModVersionSptVersion::class)
->orderByDesc('version_major')
->orderByDesc('version_minor')
->orderByDesc('version_patch')
->orderByDesc('version_pre_release');
2024-05-17 17:11:54 -04:00
}
2024-09-20 10:37:16 -04:00
/**
* Build the download URL for this mod version.
*/
public function downloadUrl(bool $absolute = false): string
2024-09-20 10:37:16 -04:00
{
return route('mod.version.download', [$this->mod->id, $this->mod->slug, $this->version], absolute: $absolute);
}
/**
* Increment the download count for this mod version.
*/
public function incrementDownloads(): int
{
2025-01-30 00:50:28 -05:00
$this->downloads++;
$this->save();
// Recalculate the total download count for this mod.
$this->mod->calculateDownloads();
return $this->downloads;
2024-09-20 10:37:16 -04:00
}
2024-10-12 13:18:04 -06:00
/**
* The attributes that should be cast to native types.
*/
protected function casts(): array
{
return [
'hub_id' => 'integer',
'version_major' => 'integer',
'version_minor' => 'integer',
'version_patch' => 'integer',
'downloads' => 'integer',
'disabled' => 'boolean',
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
'published_at' => 'datetime',
];
}
2024-05-15 00:31:24 -04:00
}