diff --git a/app/Console/Commands/ImportWoltlabData.php b/app/Console/Commands/ImportWoltlabData.php index d5a8530..26b3c01 100644 --- a/app/Console/Commands/ImportWoltlabData.php +++ b/app/Console/Commands/ImportWoltlabData.php @@ -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 ''; + } } diff --git a/app/Helpers/ColorHelper.php b/app/Helpers/ColorHelper.php index 8627997..eed2f1e 100644 --- a/app/Helpers/ColorHelper.php +++ b/app/Helpers/ColorHelper.php @@ -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', diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 79d93bb..452e6b6 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -2,7 +2,6 @@ namespace App\Providers; -use Illuminate\Support\Facades\Blade; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider diff --git a/app/View/Components/ModList.php b/app/View/Components/ModList.php index de64e32..715ae58 100644 --- a/app/View/Components/ModList.php +++ b/app/View/Components/ModList.php @@ -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) diff --git a/app/View/Components/ModListSection.php b/app/View/Components/ModListSection.php index 5f22b67..fe20bbf 100644 --- a/app/View/Components/ModListSection.php +++ b/app/View/Components/ModListSection.php @@ -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', ], ]; } diff --git a/composer.json b/composer.json index b9ae0d0..56e2f3c 100644 --- a/composer.json +++ b/composer.json @@ -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": { diff --git a/composer.lock b/composer.lock index 642229e..6ac5ce2 100644 --- a/composer.lock +++ b/composer.lock @@ -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", diff --git a/config/database.php b/config/database.php index d780ab8..016efe6 100644 --- a/config/database.php +++ b/config/database.php @@ -129,7 +129,6 @@ return [ ]) : [], ], - ], /* diff --git a/database/factories/ModVersionFactory.php b/database/factories/ModVersionFactory.php index d092fcf..cbefc16 100644 --- a/database/factories/ModVersionFactory.php +++ b/database/factories/ModVersionFactory.php @@ -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(), diff --git a/database/migrations/0001_01_01_000000_create_users_table.php b/database/migrations/0001_01_01_000000_create_users_table.php index 84d5fb5..4d36f1f 100644 --- a/database/migrations/0001_01_01_000000_create_users_table.php +++ b/database/migrations/0001_01_01_000000_create_users_table.php @@ -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(); diff --git a/database/migrations/2024_05_15_022315_create_licenses_table.php b/database/migrations/2024_05_15_022315_create_licenses_table.php index fbfcdce..033d0d0 100644 --- a/database/migrations/2024_05_15_022315_create_licenses_table.php +++ b/database/migrations/2024_05_15_022315_create_licenses_table.php @@ -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(); diff --git a/database/migrations/2024_05_15_022710_create_mods_table.php b/database/migrations/2024_05_15_022710_create_mods_table.php index a611a73..d03e6dc 100644 --- a/database/migrations/2024_05_15_022710_create_mods_table.php +++ b/database/migrations/2024_05_15_022710_create_mods_table.php @@ -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'); diff --git a/database/migrations/2024_05_15_023430_create_spt_versions_table.php b/database/migrations/2024_05_15_023430_create_spt_versions_table.php index c9d3f17..502e059 100644 --- a/database/migrations/2024_05_15_023430_create_spt_versions_table.php +++ b/database/migrations/2024_05_15_023430_create_spt_versions_table.php @@ -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(); diff --git a/database/migrations/2024_05_15_023705_create_mod_versions_table.php b/database/migrations/2024_05_15_023705_create_mod_versions_table.php index cfb840c..6aa8090 100644 --- a/database/migrations/2024_05_15_023705_create_mod_versions_table.php +++ b/database/migrations/2024_05_15_023705_create_mod_versions_table.php @@ -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'); diff --git a/phpstan.neon b/phpstan.neon index 05ba64b..1905b7b 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -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