Skip to content

Instantly share code, notes, and snippets.

@chengkangzai
Forked from CharlieEtienne/CheckFilamentCompat.php
Last active August 23, 2025 14:51
Show Gist options
  • Save chengkangzai/391668520e229de439badcb8cda799c3 to your computer and use it in GitHub Desktop.
Save chengkangzai/391668520e229de439badcb8cda799c3 to your computer and use it in GitHub Desktop.
Check if your Filament Plugins are ready for v4
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Http;
class CheckFilamentCompat extends Command
{
/**
* The name and signature of the console command.
*/
protected $signature = 'check:filament-compat';
/**
* The console command description.
*/
protected $description = 'Check if installed Filament plugins are compatible with Filament v4';
/**
* Execute the console command.
*/
public function handle(): int
{
$composerPath = base_path('composer.json');
if (! file_exists($composerPath)) {
$this->error('composer.json not found.');
return 1;
}
$composer = json_decode(file_get_contents($composerPath), true);
$dependencies = $composer['require'] ?? [];
$allPackages = collect($dependencies)->keys();
// Filter packages to only those that are Filament-related
$filamentPlugins = $allPackages->filter(function ($package) {
return $this->isFilamentRelatedPackage($package);
});
$this->info('Found '.$filamentPlugins->count().' Filament-related packages');
$results = [];
foreach ($filamentPlugins as $package) {
$compatibility = $this->checkFilamentV4Compatibility($package);
$versionDisplay = '–';
$filamentDeps = $this->getFilamentDependencies($package);
if ($compatibility !== null) {
$versionDisplay = $compatibility['version'];
if ($compatibility['isPrerelease']) {
$versionDisplay .= ' (prerelease)';
}
}
$results[] = [
'package' => $package,
'installed' => $dependencies[$package],
'compatible' => $compatibility ? '✅' : '❌',
'latest_v4_version' => $versionDisplay,
'filament_deps' => implode(', ', $filamentDeps),
];
}
// Display result in a formatted table
$this->table(
['Package', 'Installed Version', 'Compatible with v4?', 'Latest Compatible v4 Version', 'Filament Dependencies'],
$results
);
return 0;
}
/**
* Checks on Packagist whether the given package has any version compatible with Filament v4.
*
* @param string $package The full package name (e.g. vendor/package)
* @return array|null Array with version string and isPrerelease flag, or null if not found
*/
protected function checkFilamentV4Compatibility(string $package): ?array
{
// First check regular releases
$url = "https://repo.packagist.org/p2/{$package}.json";
$compatibleVersion = $this->checkPackageCompatibility($package, $url);
if ($compatibleVersion !== null) {
return [
'version' => $compatibleVersion,
'isPrerelease' => false,
];
}
// If no compatible version found, check dev versions
$devUrl = "https://repo.packagist.org/p2/{$package}~dev.json";
$compatibleVersion = $this->checkPackageCompatibility($package, $devUrl);
if ($compatibleVersion !== null) {
return [
'version' => $compatibleVersion,
'isPrerelease' => true,
];
}
return null;
}
/**
* Checks a specific package URL for Filament v4 compatibility
*
* @param string $package The full package name
* @param string $url The Packagist API URL to check
* @return string|null The compatible version string or null if not found
*/
protected function checkPackageCompatibility(string $package, string $url): ?string
{
try {
$response = Http::get($url);
if (! $response->ok()) {
return null;
}
$data = $response->json();
$versions = $data['packages'][$package] ?? [];
foreach ($versions as $version) {
$requires = $version['require'] ?? [];
// Check for any Filament package dependency
foreach ($requires as $packageName => $constraint) {
if (str_starts_with($packageName, 'filament/')) {
// Match common constraint patterns for v4
if (preg_match('/\^4\.|~4\.|>=4\./', $constraint)) {
return $version['version'];
}
}
}
}
} catch (\Exception $e) {
$this->error("Error checking {$package} at {$url}: ".$e->getMessage());
}
return null;
}
/**
* Checks if a package is Filament-related (requires any filament/* package or has filament in name)
*
* @param string $package The full package name
* @return bool True if the package is Filament-related
*/
protected function isFilamentRelatedPackage(string $package): bool
{
// Include filament/* packages as they're part of the Filament ecosystem
if (str_starts_with($package, 'filament/')) {
return true;
}
// Include packages with 'filament' in the name (likely plugins)
if (str_contains($package, 'filament')) {
return true;
}
try {
// Check regular releases
$url = "https://repo.packagist.org/p2/{$package}.json";
$response = Http::get($url);
if ($response->ok()) {
$data = $response->json();
$versions = $data['packages'][$package] ?? [];
// Check all versions, not just the latest
foreach ($versions as $version) {
$requires = $version['require'] ?? [];
// Check for any filament/* dependency
foreach ($requires as $reqPackage => $constraint) {
if (str_starts_with($reqPackage, 'filament/')) {
return true;
}
}
}
}
// If not found in regular releases, check dev versions
$devUrl = "https://repo.packagist.org/p2/{$package}~dev.json";
$devResponse = Http::get($devUrl);
if ($devResponse->ok()) {
$devData = $devResponse->json();
$devVersions = $devData['packages'][$package] ?? [];
foreach ($devVersions as $version) {
$requires = $version['require'] ?? [];
// Check for any filament/* dependency
foreach ($requires as $reqPackage => $constraint) {
if (str_starts_with($reqPackage, 'filament/')) {
return true;
}
}
}
}
} catch (\Exception $e) {
$this->error("Error checking if {$package} is Filament-related: ".$e->getMessage());
}
return false;
}
/**
* Get the Filament dependencies for a package
*
* @param string $package The full package name
* @return array Array of filament/* packages this package depends on
*/
protected function getFilamentDependencies(string $package): array
{
$filamentDeps = [];
// For filament/* packages, return the package itself
if (str_starts_with($package, 'filament/')) {
return [$package];
}
try {
// Check regular releases for filament dependencies
$url = "https://repo.packagist.org/p2/{$package}.json";
$response = Http::get($url);
if ($response->ok()) {
$data = $response->json();
$versions = $data['packages'][$package] ?? [];
// Get the latest version's dependencies
if (!empty($versions)) {
$latestVersion = reset($versions);
$requires = $latestVersion['require'] ?? [];
foreach ($requires as $reqPackage => $constraint) {
if (str_starts_with($reqPackage, 'filament/')) {
$filamentDeps[] = $reqPackage;
}
}
}
}
// If no dependencies found, check dev versions
if (empty($filamentDeps)) {
$devUrl = "https://repo.packagist.org/p2/{$package}~dev.json";
$devResponse = Http::get($devUrl);
if ($devResponse->ok()) {
$devData = $devResponse->json();
$devVersions = $devData['packages'][$package] ?? [];
if (!empty($devVersions)) {
$latestDevVersion = reset($devVersions);
$requires = $latestDevVersion['require'] ?? [];
foreach ($requires as $reqPackage => $constraint) {
if (str_starts_with($reqPackage, 'filament/')) {
$filamentDeps[] = $reqPackage;
}
}
}
}
}
} catch (\Exception $e) {
// Silently fail for dependency detection
}
return array_unique($filamentDeps);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment