Mod & Mod Version Imports

This commit is contained in:
Refringe 2024-05-22 01:00:37 -04:00
parent 8e11892f57
commit 3a81afe488
Signed by: Refringe
GPG Key ID: 7715B85B4A6306ED
15 changed files with 317 additions and 139 deletions

View File

@ -4,6 +4,8 @@ namespace App\Console\Commands;
use App\Models\License;
use App\Models\Mod;
use App\Models\ModVersion;
use App\Models\SptVersion;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Console\Command;
@ -14,28 +16,37 @@ use Illuminate\Support\Str;
class ImportWoltlabData extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'app:import-woltlab-data';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Connects to the Woltlab database and imports the data into the Laravel database.';
protected array $fileOptionValues = [];
protected array $fileContent = [];
protected array $fileVersionContent = [];
protected array $fileVersionLabels = [];
/**
* Execute the console command.
*/
public function handle(): void
{
$this->importUsers();
$this->importLicenses();
$this->importSptVersions();
$this->fileOptionValues = $this->getFileOptionValues();
$this->fileContent = $this->getFileContent();
$this->importMods();
$this->fileVersionContent = $this->getFileVersionContent();
$this->fileVersionLabels = $this->getFileVersionLabels();
$this->importModVersions();
$this->info('Data imported successfully.');
}
@ -62,17 +73,17 @@ class ImportWoltlabData extends Command
];
}
if (!empty($insertData)) {
if (! empty($insertData)) {
User::upsert($insertData, ['hub_id'], ['name', 'email', 'password', 'created_at', 'updated_at']);
$totalInserted += count($insertData);
$this->line('Processed ' . count($insertData) . ' users. Total processed so far: ' . $totalInserted);
$this->line('Processed '.count($insertData).' users. Total processed so far: '.$totalInserted);
}
unset($insertData);
unset($users);
}, 'userID');
$this->info('Total users processed: ' . $totalInserted);
$this->info('Total users processed: '.$totalInserted);
$this->newLine();
}
@ -90,17 +101,45 @@ class ImportWoltlabData extends Command
];
}
if (!empty($insertData)) {
if (! empty($insertData)) {
DB::table('licenses')->upsert($insertData, ['hub_id'], ['name', 'link']);
$totalInserted += count($insertData);
$this->line('Processed ' . count($insertData) . ' licenses. Total processed so far: ' . $totalInserted);
$this->line('Processed '.count($insertData).' licenses. Total processed so far: '.$totalInserted);
}
unset($insertData);
unset($licenses);
}, 'licenseID');
$this->info('Total licenses processed: ' . $totalInserted);
$this->info('Total licenses processed: '.$totalInserted);
$this->newLine();
}
protected function importSptVersions(): void
{
$totalInserted = 0;
DB::connection('mysql_woltlab')->table('wcf1_label')->where('groupID', 1)->chunkById(100, function (Collection $versions) use (&$totalInserted) {
$insertData = [];
foreach ($versions as $version) {
$insertData[] = [
'hub_id' => $version->labelID,
'version' => $version->label,
'color_class' => $version->cssClassName,
];
}
if (! empty($insertData)) {
DB::table('spt_versions')->upsert($insertData, ['hub_id'], ['version', 'color_class']);
$totalInserted += count($insertData);
$this->line('Processed '.count($insertData).' SPT Versions. Total processed so far: '.$totalInserted);
}
unset($insertData);
unset($versions);
}, 'labelID');
$this->info('Total licenses processed: '.$totalInserted);
$this->newLine();
}
@ -109,76 +148,117 @@ class ImportWoltlabData extends Command
$command = $this;
$totalInserted = 0;
DB::connection('mysql_woltlab')->table('filebase1_file')->chunkById(5, function (Collection $mods) use (&$command, &$totalInserted) {
$curl = curl_init();
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
foreach ($mods as $mod)
{
$modContent = DB::connection('mysql_woltlab')->table('filebase1_file_content')->where('fileID', $mod->fileID)->first();
DB::connection('mysql_woltlab')->table('filebase1_file')->chunkById(100, function (Collection $mods) use (&$command, &$curl, &$totalInserted) {
foreach ($mods as $mod) {
if ($mod->fileID == 1 || $mod->fileID == 116 || $mod->fileID == 480) {
// These are special cases that we don't want to import. Installers, base files, and the patchers.
continue;
}
$modContent = $this->fileContent[$mod->fileID] ?? [];
$modOptions = $this->fileOptionValues[$mod->fileID] ?? [];
$insertData[] = [
'hub_id' => $mod->fileID,
'user_id' => User::whereName($mod->username)->value('id'),
'name' => $modContent->subject,
'slug' => Str::slug($modContent->subject),
'teaser' => $modContent->teaser,
'description' => $modContent->message,
'thumbnail' => $this->fetchModThumbnail($command, $mod->fileID, $mod->iconHash, $mod->iconExtension),
'user_id' => User::whereHubId($mod->userID)->value('id'),
'name' => $modContent ? $modContent->subject : '',
'slug' => $modContent ? Str::slug($modContent->subject) : '',
'teaser' => $modContent ? $modContent->teaser : '',
'description' => $modContent ? $modContent->message : '',
'thumbnail' => $this->fetchModThumbnail($command, $curl, $mod->fileID, $mod->iconHash, $mod->iconExtension),
'license_id' => License::whereHubId($mod->licenseID)->value('id'),
'source_code_link' => $this->fetchSourceLinkValue($mod->fileID),
'source_code_link' => $this->fetchSourceLinkValue($modOptions),
'featured' => $mod->isFeatured,
'contains_ai_content' => $this->fetchContainsAiContentValue($mod->fileID),
'contains_ai_content' => $this->fetchContainsAiContentValue($modOptions),
'disabled' => $mod->isDisabled,
'created_at' => Carbon::parse($mod->time, 'UTC'),
'updated_at' => Carbon::parse($mod->lastChangeTime, 'UTC'),
];
}
if (!empty($insertData)) {
if (! empty($insertData)) {
Mod::upsert($insertData, ['hub_id'], ['user_id', 'name', 'slug', 'teaser', 'description', 'thumbnail', 'license_id', 'source_code_link', 'featured', 'contains_ai_content', 'disabled', 'created_at', 'updated_at']);
$totalInserted += count($insertData);
$command->line('Processed ' . count($insertData) . ' mods. Total processed so far: ' . $totalInserted);
$command->line('Processed '.count($insertData).' mods. Total processed so far: '.$totalInserted);
}
unset($insertData);
unset($mods);
}, 'fileID');
$this->info('Total mods processed: ' . $totalInserted);
curl_close($curl);
$this->info('Total mods processed: '.$totalInserted);
$this->newLine();
}
protected function fetchSourceLinkValue(string $fileID): string
protected function getFileOptionValues(): array
{
$options = DB::connection('mysql_woltlab')->table('filebase1_file_option_value')->where('fileID', $fileID)->get();
// Fetch all the data from the `filebase1_file_option_value` table.
$options = DB::connection('mysql_woltlab')->table('filebase1_file_option_value')->get();
// Iterate over the options and find the 'optionID' of 5 or 1. That record will contain the source code link in
// the 'optionValue' column. The 'optionID' of 5 should take precedence over 1. If neither are found, return an
// empty string.
// Convert the collection into an associative array
$optionValues = [];
foreach ($options as $option) {
if ($option->optionID == 5 && !empty($option->optionValue)) {
$optionValues[$option->fileID][] = $option;
}
return $optionValues;
}
protected function getFileContent(): array
{
$content = [];
// Fetch select data from the `filebase1_file_content` table.
DB::connection('mysql_woltlab')
->table('filebase1_file_content')
->select(['fileID', 'subject', 'teaser', 'message'])
->orderBy('fileID', 'desc')
->chunk(200, function ($contents) use (&$content) {
foreach ($contents as $contentItem) {
$content[$contentItem->fileID] = $contentItem;
}
});
return $content;
}
protected function fetchSourceLinkValue(array $options): string
{
// Iterate over the options and find the 'optionID' of 5 or 1. Those records will contain the source code link
// in the 'optionValue' column. The 'optionID' of 5 should take precedence over 1. If neither are found, return
// an empty string.
foreach ($options as $option) {
if ($option->optionID == 5 && ! empty($option->optionValue)) {
return $option->optionValue;
}
if ($option->optionID == 1 && !empty($option->optionValue)) {
if ($option->optionID == 1 && ! empty($option->optionValue)) {
return $option->optionValue;
}
}
return '';
}
protected function fetchContainsAiContentValue(string $fileID): bool
protected function fetchContainsAiContentValue(array $options): bool
{
$options = DB::connection('mysql_woltlab')->table('filebase1_file_option_value')->where('fileID', $fileID)->get();
// Iterate over the options and find the 'optionID' of 7. That record will contain the AI flag.
foreach ($options as $option) {
if ($option->optionID == 7) {
return (bool) $option->optionValue;
}
}
return '';
return false;
}
protected function fetchModThumbnail($command, string $fileID, string $thumbnailHash, string $thumbnailExtension): string
protected function fetchModThumbnail($command, &$curl, string $fileID, string $thumbnailHash, string $thumbnailExtension): string
{
if (empty($fileID) || empty($thumbnailHash) || empty($thumbnailExtension)) {
return '';
@ -196,10 +276,116 @@ class ImportWoltlabData extends Command
}
$command->output->write("Downloading mod thumbnail: $hubUrl... ");
Storage::disk('public')->put($localPath, file_get_contents($hubUrl));
$command->info('Done.');
curl_setopt($curl, CURLOPT_URL, $hubUrl);
$image = curl_exec($curl);
if ($image === false) {
$command->error('Error: '.curl_error($curl));
} else {
Storage::disk('public')->put($localPath, $image);
$command->info('Done.');
}
// Return the path to the saved thumbnail.
return "/storage/$localPath";
}
protected function getFileVersionContent(): array
{
$content = [];
// Fetch select data from the `filebase1_file_version_content` table.
DB::connection('mysql_woltlab')
->table('filebase1_file_version_content')
->select(['versionID', 'description'])
->orderBy('versionID', 'desc')
->chunk(100, function ($contents) use (&$content) {
foreach ($contents as $contentItem) {
$content[$contentItem->versionID] = $content;
}
});
return $content;
}
protected function getFileVersionLabels(): array
{
$labels = [];
// Fetch select data from the `wcf1_label_object` table.
DB::connection('mysql_woltlab')
->table('wcf1_label_object')
->select(['labelID', 'objectID'])
->where('objectTypeID', 387)
->orderBy('labelID', 'desc')
->chunk(100, function ($labelData) use (&$labels) {
foreach ($labelData as $labelItem) {
$labels[$labelItem->objectID] = $labelItem->labelID;
}
});
return $labels;
}
protected function importModVersions(): void
{
$command = $this;
$totalInserted = 0;
DB::connection('mysql_woltlab')->table('filebase1_file_version')->chunkById(100, function (Collection $versions) use (&$command, &$totalInserted) {
foreach ($versions as $version) {
$versionContent = $this->fileVersionContent[$version->versionID] ?? [];
$modOptions = $this->fileOptionValues[$version->fileID] ?? [];
$versionLabel = $this->fileVersionLabels[$version->fileID] ?? [];
$modId = Mod::whereHubId($version->fileID)->value('id');
if (empty($versionLabel) || empty($modId)) {
continue;
}
$insertData[] = [
'hub_id' => $version->versionID,
'mod_id' => $modId,
'version' => $version->versionNumber,
'description' => $versionContent['description'] ?? '',
'link' => $version->downloadURL,
'spt_version_id' => SptVersion::whereHubId($versionLabel)->value('id'),
'virus_total_link' => $this->fetchVirusTotalLink($modOptions),
'downloads' => (int) $version->downloads,
'created_at' => Carbon::parse($version->uploadTime, 'UTC'),
'updated_at' => Carbon::parse($version->uploadTime, 'UTC'),
];
}
if (! empty($insertData)) {
ModVersion::upsert($insertData, ['hub_id'], ['mod_id', 'version', 'description', 'link', 'spt_version_id', 'virus_total_link', 'downloads', 'created_at', 'updated_at']);
$totalInserted += count($insertData);
$command->line('Processed '.count($insertData).' mod versions. Total processed so far: '.$totalInserted);
}
unset($insertData);
unset($version);
}, 'versionID');
$this->info('Total mod versions processed: '.$totalInserted);
$this->newLine();
}
protected function fetchVirusTotalLink(array $options): string
{
// Iterate over the options and find the 'optionID' of 6 or 2. Those records will contain the Virus Total link
// in the 'optionValue' column. The 'optionID' of 6 should take precedence over 1. If neither are found, return
// an empty string.
foreach ($options as $option) {
if ($option->optionID == 5 && ! empty($option->optionValue)) {
return $option->optionValue;
}
if ($option->optionID == 1 && ! empty($option->optionValue)) {
return $option->optionValue;
}
}
return '';
}
}

View File

@ -6,8 +6,7 @@ class ColorHelper
{
public static function tagColorClasses($color): string
{
return match ($color)
{
return match ($color) {
'red' => 'bg-red-50 text-red-700 ring-red-600/20',
'green' => 'bg-green-50 text-green-700 ring-green-600/20',
'yellow' => 'bg-yellow-50 text-yellow-700 ring-yellow-600/20',

View File

@ -2,7 +2,6 @@
namespace App\Providers;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider

View File

@ -2,13 +2,14 @@
namespace App\View\Components;
use App\Helpers\ColorHelper;
use Illuminate\Contracts\View\View;
use Illuminate\View\Component;
use App\Helpers\ColorHelper;
class ModList extends Component
{
public $mods;
public string $versionScope;
public function __construct($mods, $versionScope)

View File

@ -10,7 +10,9 @@ use Illuminate\View\Component;
class ModListSection extends Component
{
public Collection $modsFeatured;
public Collection $modsLatest;
public Collection $modsUpdated;
public function __construct()
@ -41,17 +43,17 @@ class ModListSection extends Component
[
'title' => 'Featured Mods',
'mods' => $this->modsFeatured,
'versionScope' => 'versionLatestSptVersion'
'versionScope' => 'versionLatestSptVersion',
],
[
'title' => 'Latest Mods',
'mods' => $this->modsLatest,
'versionScope' => 'versionLatestSptVersion'
'versionScope' => 'versionLatestSptVersion',
],
[
'title' => 'Recently Updated Mods',
'mods' => $this->modsUpdated,
'versionScope' => 'versionLastUpdated'
'versionScope' => 'versionLastUpdated',
],
];
}

View File

@ -2,7 +2,10 @@
"name": "laravel/laravel",
"type": "project",
"description": "The skeleton application for the Laravel framework.",
"keywords": ["laravel", "framework"],
"keywords": [
"laravel",
"framework"
],
"license": "MIT",
"require": {
"php": "^8.3",
@ -12,7 +15,8 @@
"laravel/pulse": "^1.1",
"laravel/sanctum": "^4.0",
"laravel/tinker": "^2.9",
"livewire/livewire": "^3.0"
"livewire/livewire": "^3.0",
"ext-curl": "*"
},
"require-dev": {
"barryvdh/laravel-debugbar": "^3.13",
@ -31,7 +35,7 @@
"Database\\Seeders\\": "database/seeders/"
},
"files": [
"app/helpers.php"
"app/Helpers/ColorHelper.php"
]
},
"autoload-dev": {

121
composer.lock generated
View File

@ -1424,22 +1424,23 @@
},
{
"name": "inertiajs/inertia-laravel",
"version": "v1.1.0",
"version": "v1.2.0",
"source": {
"type": "git",
"url": "https://github.com/inertiajs/inertia-laravel.git",
"reference": "576fba4da6f2ba6348ddf57a750c73231904d598"
"reference": "5675663d9619528544cc2dca60e0f8b9603980ae"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/inertiajs/inertia-laravel/zipball/576fba4da6f2ba6348ddf57a750c73231904d598",
"reference": "576fba4da6f2ba6348ddf57a750c73231904d598",
"url": "https://api.github.com/repos/inertiajs/inertia-laravel/zipball/5675663d9619528544cc2dca60e0f8b9603980ae",
"reference": "5675663d9619528544cc2dca60e0f8b9603980ae",
"shasum": ""
},
"require": {
"ext-json": "*",
"laravel/framework": "^8.74|^9.0|^10.0|^11.0",
"php": "^7.3|~8.0.0|~8.1.0|~8.2.0|~8.3.0"
"php": "^7.3|~8.0.0|~8.1.0|~8.2.0|~8.3.0",
"symfony/console": "^5.3|^6.0|^7.0"
},
"require-dev": {
"mockery/mockery": "^1.3.3",
@ -1487,7 +1488,7 @@
],
"support": {
"issues": "https://github.com/inertiajs/inertia-laravel/issues",
"source": "https://github.com/inertiajs/inertia-laravel/tree/v1.1.0"
"source": "https://github.com/inertiajs/inertia-laravel/tree/v1.2.0"
},
"funding": [
{
@ -1495,20 +1496,20 @@
"type": "github"
}
],
"time": "2024-05-16T01:41:06+00:00"
"time": "2024-05-17T22:12:22+00:00"
},
{
"name": "laravel/fortify",
"version": "v1.21.2",
"version": "v1.21.3",
"source": {
"type": "git",
"url": "https://github.com/laravel/fortify.git",
"reference": "cb122ceec7f8d0231985c1dde8161b3c561bfe90"
"reference": "a725684d17959c4750f3b441ff2e94ecde7793a1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/fortify/zipball/cb122ceec7f8d0231985c1dde8161b3c561bfe90",
"reference": "cb122ceec7f8d0231985c1dde8161b3c561bfe90",
"url": "https://api.github.com/repos/laravel/fortify/zipball/a725684d17959c4750f3b441ff2e94ecde7793a1",
"reference": "a725684d17959c4750f3b441ff2e94ecde7793a1",
"shasum": ""
},
"require": {
@ -1560,20 +1561,20 @@
"issues": "https://github.com/laravel/fortify/issues",
"source": "https://github.com/laravel/fortify"
},
"time": "2024-04-25T14:17:43+00:00"
"time": "2024-05-08T18:07:38+00:00"
},
{
"name": "laravel/framework",
"version": "v11.7.0",
"version": "v11.8.0",
"source": {
"type": "git",
"url": "https://github.com/laravel/framework.git",
"reference": "e5ac72f513f635f208024aa76b8a04efc1b47f93"
"reference": "ceb892a25817c888ef3df4d1a2af9cac53978300"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/framework/zipball/e5ac72f513f635f208024aa76b8a04efc1b47f93",
"reference": "e5ac72f513f635f208024aa76b8a04efc1b47f93",
"url": "https://api.github.com/repos/laravel/framework/zipball/ceb892a25817c888ef3df4d1a2af9cac53978300",
"reference": "ceb892a25817c888ef3df4d1a2af9cac53978300",
"shasum": ""
},
"require": {
@ -1698,7 +1699,7 @@
"ext-pcntl": "Required to use all features of the queue worker and console signal trapping.",
"ext-pdo": "Required to use all database features.",
"ext-posix": "Required to use all features of the queue worker.",
"ext-redis": "Required to use the Redis cache and queue drivers (^4.0|^5.0).",
"ext-redis": "Required to use the Redis cache and queue drivers (^4.0|^5.0|^6.0).",
"fakerphp/faker": "Required to use the eloquent factory builder (^1.9.1).",
"filp/whoops": "Required for friendly error pages in development (^2.14.3).",
"laravel/tinker": "Required to use the tinker console command (^2.0).",
@ -1765,20 +1766,20 @@
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"time": "2024-05-07T13:41:51+00:00"
"time": "2024-05-21T17:57:45+00:00"
},
{
"name": "laravel/jetstream",
"version": "v5.1.0",
"version": "v5.1.1",
"source": {
"type": "git",
"url": "https://github.com/laravel/jetstream.git",
"reference": "8bffd5336bfac4d6f0098b50ee7c3e3559714ddc"
"reference": "30bde139ca1c41d10a58c67f8daa2e8cd3a0be93"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/jetstream/zipball/8bffd5336bfac4d6f0098b50ee7c3e3559714ddc",
"reference": "8bffd5336bfac4d6f0098b50ee7c3e3559714ddc",
"url": "https://api.github.com/repos/laravel/jetstream/zipball/30bde139ca1c41d10a58c67f8daa2e8cd3a0be93",
"reference": "30bde139ca1c41d10a58c67f8daa2e8cd3a0be93",
"shasum": ""
},
"require": {
@ -1832,7 +1833,7 @@
"issues": "https://github.com/laravel/jetstream/issues",
"source": "https://github.com/laravel/jetstream"
},
"time": "2024-05-06T17:10:37+00:00"
"time": "2024-05-13T17:01:27+00:00"
},
{
"name": "laravel/nova",
@ -1962,16 +1963,16 @@
},
{
"name": "laravel/prompts",
"version": "v0.1.21",
"version": "v0.1.22",
"source": {
"type": "git",
"url": "https://github.com/laravel/prompts.git",
"reference": "23ea808e8a145653e0ab29e30d4385e49f40a920"
"reference": "37f94de71758dbfbccc9d299b0e5eb76e02a40f5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/prompts/zipball/23ea808e8a145653e0ab29e30d4385e49f40a920",
"reference": "23ea808e8a145653e0ab29e30d4385e49f40a920",
"url": "https://api.github.com/repos/laravel/prompts/zipball/37f94de71758dbfbccc9d299b0e5eb76e02a40f5",
"reference": "37f94de71758dbfbccc9d299b0e5eb76e02a40f5",
"shasum": ""
},
"require": {
@ -2014,22 +2015,22 @@
"description": "Add beautiful and user-friendly forms to your command-line applications.",
"support": {
"issues": "https://github.com/laravel/prompts/issues",
"source": "https://github.com/laravel/prompts/tree/v0.1.21"
"source": "https://github.com/laravel/prompts/tree/v0.1.22"
},
"time": "2024-04-30T12:46:16+00:00"
"time": "2024-05-10T19:22:18+00:00"
},
{
"name": "laravel/pulse",
"version": "v1.1.0",
"version": "v1.2.0",
"source": {
"type": "git",
"url": "https://github.com/laravel/pulse.git",
"reference": "16746346a6cb2cd12d9e93db206aaf2b9d792b21"
"reference": "37fcc8e77dc437c01ee1a73ba58fd70615c84855"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/pulse/zipball/16746346a6cb2cd12d9e93db206aaf2b9d792b21",
"reference": "16746346a6cb2cd12d9e93db206aaf2b9d792b21",
"url": "https://api.github.com/repos/laravel/pulse/zipball/37fcc8e77dc437c01ee1a73ba58fd70615c84855",
"reference": "37fcc8e77dc437c01ee1a73ba58fd70615c84855",
"shasum": ""
},
"require": {
@ -2103,7 +2104,7 @@
"issues": "https://github.com/laravel/pulse/issues",
"source": "https://github.com/laravel/pulse"
},
"time": "2024-05-06T17:11:35+00:00"
"time": "2024-05-17T16:22:20+00:00"
},
{
"name": "laravel/sanctum",
@ -2297,16 +2298,16 @@
},
{
"name": "laravel/ui",
"version": "v4.5.1",
"version": "v4.5.2",
"source": {
"type": "git",
"url": "https://github.com/laravel/ui.git",
"reference": "a3562953123946996a503159199d6742d5534e61"
"reference": "c75396f63268c95b053c8e4814eb70e0875e9628"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/ui/zipball/a3562953123946996a503159199d6742d5534e61",
"reference": "a3562953123946996a503159199d6742d5534e61",
"url": "https://api.github.com/repos/laravel/ui/zipball/c75396f63268c95b053c8e4814eb70e0875e9628",
"reference": "c75396f63268c95b053c8e4814eb70e0875e9628",
"shasum": ""
},
"require": {
@ -2354,9 +2355,9 @@
"ui"
],
"support": {
"source": "https://github.com/laravel/ui/tree/v4.5.1"
"source": "https://github.com/laravel/ui/tree/v4.5.2"
},
"time": "2024-03-21T18:12:29+00:00"
"time": "2024-05-08T18:07:10+00:00"
},
{
"name": "league/commonmark",
@ -3394,16 +3395,16 @@
},
{
"name": "openspout/openspout",
"version": "v4.24.0",
"version": "v4.24.1",
"source": {
"type": "git",
"url": "https://github.com/openspout/openspout.git",
"reference": "51f2a627d4cdcdb06eb451c6f434daeb190c4afb"
"reference": "003991abc5cfee93423254774c71766d38cbe340"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/openspout/openspout/zipball/51f2a627d4cdcdb06eb451c6f434daeb190c4afb",
"reference": "51f2a627d4cdcdb06eb451c6f434daeb190c4afb",
"url": "https://api.github.com/repos/openspout/openspout/zipball/003991abc5cfee93423254774c71766d38cbe340",
"reference": "003991abc5cfee93423254774c71766d38cbe340",
"shasum": ""
},
"require": {
@ -3417,12 +3418,12 @@
},
"require-dev": {
"ext-zlib": "*",
"friendsofphp/php-cs-fixer": "^3.56.0",
"friendsofphp/php-cs-fixer": "^3.57.1",
"infection/infection": "^0.28.1",
"phpbench/phpbench": "^1.2.15",
"phpstan/phpstan": "^1.10.67",
"phpstan/phpstan-phpunit": "^1.3.16",
"phpstan/phpstan-strict-rules": "^1.5.5",
"phpstan/phpstan": "^1.11.1",
"phpstan/phpstan-phpunit": "^1.4.0",
"phpstan/phpstan-strict-rules": "^1.6.0",
"phpunit/phpunit": "^10.5.20"
},
"suggest": {
@ -3471,7 +3472,7 @@
],
"support": {
"issues": "https://github.com/openspout/openspout/issues",
"source": "https://github.com/openspout/openspout/tree/v4.24.0"
"source": "https://github.com/openspout/openspout/tree/v4.24.1"
},
"funding": [
{
@ -3483,7 +3484,7 @@
"type": "github"
}
],
"time": "2024-05-10T09:06:16+00:00"
"time": "2024-05-20T09:32:59+00:00"
},
{
"name": "paragonie/constant_time_encoding",
@ -7541,16 +7542,16 @@
},
{
"name": "laravel/pint",
"version": "v1.15.3",
"version": "v1.16.0",
"source": {
"type": "git",
"url": "https://github.com/laravel/pint.git",
"reference": "3600b5d17aff52f6100ea4921849deacbbeb8656"
"reference": "1b3a3dc5bc6a81ff52828ba7277621f1d49d6d98"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/pint/zipball/3600b5d17aff52f6100ea4921849deacbbeb8656",
"reference": "3600b5d17aff52f6100ea4921849deacbbeb8656",
"url": "https://api.github.com/repos/laravel/pint/zipball/1b3a3dc5bc6a81ff52828ba7277621f1d49d6d98",
"reference": "1b3a3dc5bc6a81ff52828ba7277621f1d49d6d98",
"shasum": ""
},
"require": {
@ -7561,11 +7562,11 @@
"php": "^8.1.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.54.0",
"illuminate/view": "^10.48.8",
"larastan/larastan": "^2.9.5",
"laravel-zero/framework": "^10.3.0",
"mockery/mockery": "^1.6.11",
"friendsofphp/php-cs-fixer": "^3.57.1",
"illuminate/view": "^10.48.10",
"larastan/larastan": "^2.9.6",
"laravel-zero/framework": "^10.4.0",
"mockery/mockery": "^1.6.12",
"nunomaduro/termwind": "^1.15.1",
"pestphp/pest": "^2.34.7"
},
@ -7603,7 +7604,7 @@
"issues": "https://github.com/laravel/pint/issues",
"source": "https://github.com/laravel/pint"
},
"time": "2024-04-30T15:02:26+00:00"
"time": "2024-05-21T18:08:25+00:00"
},
{
"name": "maximebf/debugbar",

View File

@ -129,7 +129,6 @@ return [
]) : [],
],
],
/*

View File

@ -18,6 +18,7 @@ class ModVersionFactory extends Factory
'mod_id' => Mod::factory(),
'version' => $this->faker->numerify('1.#.#'),
'description' => $this->faker->text(),
'link' => $this->faker->url(),
'spt_version_id' => SptVersion::factory(),
'virus_total_link' => $this->faker->url(),
'downloads' => $this->faker->randomNumber(),

View File

@ -13,7 +13,7 @@ return new class extends Migration
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('hub_id')->nullable()->unique();
$table->string('hub_id')->nullable()->unique()->default(null);
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();

View File

@ -10,7 +10,7 @@ return new class extends Migration
{
Schema::create('licenses', function (Blueprint $table) {
$table->id();
$table->string('hub_id')->nullable()->unique();
$table->string('hub_id')->nullable()->unique()->default(null);
$table->string('name');
$table->string('link');
$table->softDeletes();

View File

@ -12,7 +12,7 @@ return new class extends Migration
{
Schema::create('mods', function (Blueprint $table) {
$table->id();
$table->string('hub_id')->nullable()->unique();
$table->string('hub_id')->nullable()->unique()->default(null);
$table->foreignIdFor(User::class)->constrained('users');
$table->string('name');
$table->string('slug');

View File

@ -10,7 +10,7 @@ return new class extends Migration
{
Schema::create('spt_versions', function (Blueprint $table) {
$table->id();
$table->string('hub_id')->nullable()->unique();
$table->string('hub_id')->nullable()->unique()->default(null);
$table->string('version');
$table->string('color_class');
$table->softDeletes();

View File

@ -12,10 +12,11 @@ return new class extends Migration
{
Schema::create('mod_versions', function (Blueprint $table) {
$table->id();
$table->string('hub_id')->nullable()->unique();
$table->string('hub_id')->nullable()->unique()->default(null);
$table->foreignIdFor(Mod::class)->constrained('mods');
$table->string('version');
$table->longText('description');
$table->string('link');
$table->foreignIdFor(SptVersion::class)->constrained('spt_versions');
$table->string('virus_total_link');
$table->unsignedBigInteger('downloads');

View File

@ -1,22 +1,7 @@
includes:
- vendor/larastan/larastan/extension.neon
- ./vendor/larastan/larastan/extension.neon
parameters:
level: 6
paths:
- app/
- tests/
scanFiles:
- tests/Pest.php
- vendor/mockery/mockery/library/helpers.php
ignoreErrors:
- message: '#^Undefined variable: \$this$#'
paths:
- tests/*
- message: '#Call to an undefined method Pest\\Expectation|Pest\\Support\\Extendable::#'
paths:
- tests/*
- app/
level: 5