You've already forked Epicnabbo-Catalogus-Updated-Daily
350 lines
12 KiB
PHP
350 lines
12 KiB
PHP
#!/usr/bin/env php
|
|
<?php
|
|
|
|
use function Termwind\{ask, render};
|
|
|
|
require 'vendor/autoload.php';
|
|
|
|
render(<<<'HTML'
|
|
<div>
|
|
<div class="space-y-1">
|
|
<div class="py-1 px-3 bg-amber-600 text-amber-50">
|
|
<strong>Filament v4</strong> Upgrade
|
|
</div>
|
|
|
|
<div>
|
|
Welcome to the <strong>Filament v4</strong> upgrade process!
|
|
|
|
<br />
|
|
|
|
This script will attempt to handle most of the breaking changes for you.
|
|
|
|
<br />
|
|
|
|
If you have any questions, please reach out to us on <a href="https://filamentphp.com/discord" class="underline font-bold">Discord</a> or <a href="https://github.com/filamentphp/filament/discussions/new?category=q-a" class="underline font-bold">GitHub</a>.
|
|
</div>
|
|
|
|
<div>
|
|
To begin, please ensure that you are using a version control system such as Git.
|
|
|
|
<br />
|
|
|
|
We will make changes directly to your files, and you will need to be able to revert them if something goes wrong.
|
|
|
|
<br />
|
|
|
|
<strong>Please commit any changes you have made to your project before continuing.</strong>
|
|
</div>
|
|
</div>
|
|
|
|
<br />
|
|
</div>
|
|
HTML);
|
|
|
|
require __DIR__ . '/../src/check-compatibility.php';
|
|
|
|
$directories = $argv[1] ?? ask(<<<HTML
|
|
<div>
|
|
Please provide a comma-separated list of directories containing Filament code to upgrade (e.g. <strong>app</strong>, <strong>app-modules</strong>, <strong>src</strong>).
|
|
|
|
<br />
|
|
|
|
<span class="bg-amber-600 text-amber-50 mr-1">
|
|
You can skip this if you have a normal Laravel app structure:
|
|
</span>
|
|
</div>
|
|
HTML) ?: 'app';
|
|
|
|
render(<<<HTML
|
|
<p class="bg-green-600 text-green-50">
|
|
Starting upgrade...
|
|
</p>
|
|
HTML);
|
|
|
|
$rectorScriptPath = implode(DIRECTORY_SEPARATOR, ['vendor', 'bin', 'rector']);
|
|
|
|
foreach (explode(',', $directories) as $directory) {
|
|
$directory = trim($directory);
|
|
$directory = trim($directory, DIRECTORY_SEPARATOR);
|
|
|
|
render(<<<HTML
|
|
<p>
|
|
Start processing <strong>/{$directory}</strong> to fix code affected by breaking changes.
|
|
</p>
|
|
HTML);
|
|
|
|
exec("{$rectorScriptPath} process {$directory} --config vendor/filament/upgrade/src/rector.php --clear-cache");
|
|
|
|
render(<<<HTML
|
|
<p class="pt-2">
|
|
Finished processing <strong>/{$directory}</strong>.
|
|
</p>
|
|
HTML);
|
|
}
|
|
|
|
$requireCommands = [];
|
|
|
|
foreach (json_decode(file_get_contents('composer.json'), true)['require'] as $package => $version) {
|
|
if ($package === 'filament/upgrade') {
|
|
continue;
|
|
}
|
|
|
|
if (! str_starts_with($package, 'filament/')) {
|
|
continue;
|
|
}
|
|
|
|
if ($package === 'filament/spatie-laravel-translatable-plugin') {
|
|
$requireCommands[] = "composer remove filament/spatie-laravel-translatable-plugin -W --no-update";
|
|
$requireCommands[] = "composer require lara-zeus/spatie-translatable -W --no-update";
|
|
|
|
continue;
|
|
}
|
|
|
|
$isWindows = str_starts_with(php_uname(), 'Windows');
|
|
|
|
if (! $isWindows) {
|
|
$requireCommands[] = "composer require {$package}:\"^4.0\" -W --no-update";
|
|
} else {
|
|
$requireCommands[] = "composer require {$package}:\"~4.0\" -W --no-update";
|
|
}
|
|
}
|
|
|
|
$requireCommandsHtml = implode("</strong><br /><strong>", $requireCommands);
|
|
|
|
// Suggest commands for third-party Filament plugins that have v4-compatible releases
|
|
$thirdPartyCommands = [];
|
|
|
|
try {
|
|
// Prefer shared cache generated by check-compatibility.php
|
|
$shared = $GLOBALS['FILAMENT_UPGRADE_PACKAGIST'] ?? null;
|
|
|
|
// Fallback detection if cache is not available
|
|
if ($shared === null || empty($shared['plugins'])) {
|
|
$composer = json_decode(file_get_contents('composer.json'), true);
|
|
$deps = $composer['require'] ?? [];
|
|
$allPackages = array_keys($deps);
|
|
|
|
$plugins = array_filter($allPackages, function ($plugin) {
|
|
if (str_starts_with($plugin, 'filament/')) {
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
$composerPath = "vendor/{$plugin}/composer.json";
|
|
if (! file_exists($composerPath)) {
|
|
return false;
|
|
}
|
|
|
|
$composerContent = file_get_contents($composerPath);
|
|
$composer = json_decode($composerContent, true);
|
|
if (! $composer || ! is_array($composer)) {
|
|
return false;
|
|
}
|
|
|
|
$requires = $composer['require'] ?? [];
|
|
foreach ($requires as $key => $value) {
|
|
if (str_starts_with($key, 'filament/')) {
|
|
return true;
|
|
}
|
|
}
|
|
} catch (Throwable $exception) {}
|
|
|
|
return false;
|
|
});
|
|
|
|
// Create a minimal shared structure to continue without extra HTTP (none yet cached though)
|
|
$shared = [
|
|
'plugins' => array_values($plugins),
|
|
'compatibility' => [],
|
|
'versions' => [],
|
|
];
|
|
}
|
|
|
|
$plugins = $shared['plugins'] ?? [];
|
|
$isWindows = str_starts_with(php_uname(), 'Windows');
|
|
|
|
foreach ($plugins as $plugin) {
|
|
// Try to reuse computed compatibility first
|
|
$compatibility = $shared['compatibility'][$plugin] ?? null; // ['version' => string, 'isPrerelease' => bool]
|
|
|
|
// If not computed, try to evaluate using cached versions arrays (no HTTP)
|
|
if ($compatibility === null) {
|
|
$stableVersions = $shared['versions'][$plugin]['stable'] ?? [];
|
|
foreach ($stableVersions as $checkingVersion) {
|
|
$requires = $checkingVersion['require'] ?? [];
|
|
foreach ($requires as $dep => $constraint) {
|
|
if (!str_starts_with($dep, 'filament/')) {
|
|
continue;
|
|
}
|
|
if (preg_match("/\^\s*4(?:\.|$)|~\s*4(?:\.|$)|>=\s*4(?:\.|$)/", (string) $constraint)) {
|
|
$compatibility = [
|
|
'version' => (string) ($checkingVersion['version'] ?? ''),
|
|
'isPrerelease' => false,
|
|
];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($compatibility === null) {
|
|
$devVersions = $shared['versions'][$plugin]['dev'] ?? [];
|
|
|
|
foreach ($devVersions as $checkingVersion) {
|
|
$requires = $checkingVersion['require'] ?? [];
|
|
|
|
foreach ($requires as $dep => $constraint) {
|
|
if (!str_starts_with($dep, 'filament/')) {
|
|
continue;
|
|
}
|
|
|
|
if (preg_match("/\^\s*4(?:\.|$)|~\s*4(?:\.|$)|>=\s*4(?:\.|$)/", (string) $constraint)) {
|
|
$compatibility = [
|
|
'version' => (string) ($checkingVersion['version'] ?? ''),
|
|
'isPrerelease' => true,
|
|
];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// As a last resort, if we still don't have compatibility and there are no cached versions, do HTTP queries
|
|
if ($compatibility === null && empty($shared['versions'][$plugin])) {
|
|
try {
|
|
$url = "https://repo.packagist.org/p2/{$plugin}.json";
|
|
$json = @file_get_contents($url);
|
|
|
|
if ($json) {
|
|
$data = json_decode($json, true);
|
|
$versions = $data['packages'][$plugin] ?? [];
|
|
$shared['versions'][$plugin]['stable'] = $versions;
|
|
|
|
foreach ($versions as $checkingVersion) {
|
|
$requires = $checkingVersion['require'] ?? [];
|
|
|
|
foreach ($requires as $dep => $constraint) {
|
|
if (!str_starts_with($dep, 'filament/')) {
|
|
continue;
|
|
}
|
|
|
|
if (preg_match("/\^\s*4(?:\.|$)|~\s*4(?:\.|$)|>=\s*4(?:\.|$)/", (string) $constraint)) {
|
|
$compatibility = [
|
|
'version' => (string) ($checkingVersion['version'] ?? ''),
|
|
'isPrerelease' => false,
|
|
];
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($compatibility === null) {
|
|
$devUrl = "https://repo.packagist.org/p2/{$plugin}~dev.json";
|
|
$devJson = @file_get_contents($devUrl);
|
|
|
|
if ($devJson) {
|
|
$devData = json_decode($devJson, true);
|
|
$devVersions = $devData['packages'][$plugin] ?? [];
|
|
$shared['versions'][$plugin]['dev'] = $devVersions;
|
|
|
|
foreach ($devVersions as $checkingVersion) {
|
|
$requires = $checkingVersion['require'] ?? [];
|
|
|
|
foreach ($requires as $dep => $constraint) {
|
|
if (!str_starts_with($dep, 'filament/')) {
|
|
continue;
|
|
}
|
|
|
|
if (preg_match("/\^\s*4(?:\.|$)|~\s*4(?:\.|$)|>=\s*4(?:\.|$)/", (string) $constraint)) {
|
|
$compatibility = [
|
|
'version' => (string) ($checkingVersion['version'] ?? ''),
|
|
'isPrerelease' => true,
|
|
];
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} catch (Throwable $exception) {
|
|
// ignore
|
|
}
|
|
}
|
|
|
|
if ($compatibility !== null) {
|
|
// Persist back for other consumers during this run
|
|
$GLOBALS['FILAMENT_UPGRADE_PACKAGIST']['compatibility'][$plugin] = $compatibility;
|
|
|
|
$version = ltrim($compatibility['version'], 'v');
|
|
$isPrerelease = $compatibility['isPrerelease'];
|
|
|
|
if ($version === 'unknown') {
|
|
// Skip suggesting install command for plugins with unknown version (e.g., private/non-Packagist)
|
|
continue;
|
|
}
|
|
|
|
$constraint = null;
|
|
if (! $isPrerelease) {
|
|
// Prefer using major.minor for pre-v1 packages to avoid ^0.0 or ~0.0
|
|
if (preg_match('/^(\d+)\.(\d+)/', $version, $m)) {
|
|
$major = (int) $m[1];
|
|
$minor = (int) $m[2];
|
|
|
|
if ($major === 0) {
|
|
// For 0.x.y, constrain to the minor series, e.g. ^0.12 or ~0.12
|
|
$constraint = $isWindows ? "~0.{$minor}" : "^0.{$minor}";
|
|
} else {
|
|
// For 1.x and above, stick to major series, e.g. ^4.0 or ~4.0
|
|
$constraint = $isWindows ? "~{$major}.0" : "^{$major}.0";
|
|
}
|
|
} elseif (preg_match('/^(\d+)/', $version, $m)) {
|
|
// Fallback: if only a major could be parsed
|
|
$major = (int) $m[1];
|
|
$constraint = $isWindows ? "~{$major}.0" : "^{$major}.0";
|
|
}
|
|
}
|
|
|
|
if ($constraint === null) {
|
|
$constraint = $version;
|
|
}
|
|
|
|
$thirdPartyCommands[] = "composer require {$plugin}:\"{$constraint}\" -W --no-update";
|
|
}
|
|
}
|
|
} catch (Throwable $exception) {
|
|
// If anything goes wrong, we just won't print third-party suggestions
|
|
}
|
|
|
|
$thirdPartyCommandsHtml = $thirdPartyCommands ? '<br />' . implode("</strong><br /><strong>", $thirdPartyCommands) : '';
|
|
|
|
render(<<<HTML
|
|
<div>
|
|
<span class="bg-green-600 text-green-50">
|
|
Now you're ready to update your Composer dependencies!
|
|
</span>
|
|
|
|
<br /> <br />
|
|
|
|
First require new versions of Filament packages:
|
|
|
|
<br />
|
|
|
|
<strong>{$requireCommandsHtml}{$thirdPartyCommandsHtml}</strong>
|
|
|
|
<br /> <br />
|
|
|
|
And then run:
|
|
|
|
<br />
|
|
|
|
<strong>composer update</strong>
|
|
|
|
<br /> <br />
|
|
|
|
If you have any questions, please reach out to us on <a href="https://filamentphp.com/discord" class="underline font-bold">Discord</a> or <a href="https://github.com/filamentphp/filament/discussions/new?category=q-a" class="underline font-bold">GitHub</a>.
|
|
</div>
|
|
HTML);
|