Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Laravel 12.x Compatibility #59

Merged
merged 7 commits into from
Mar 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@ jobs:
ref: ${{ github.head_ref }}

- name: Run PHP CS Fixer
uses: docker://oskarstark/php-cs-fixer-ga
with:
args: --config=.php_cs.dist.php --allow-risky=yes
uses: aglipanci/[email protected]

- name: Commit changes
uses: stefanzweifel/git-auto-commit-action@v5
Expand Down
19 changes: 10 additions & 9 deletions .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,28 @@ name: run-tests

on:
push:
branches: [main]
branches:
- main
pull_request:
branches: [main]
branches:
- main

jobs:
test:
runs-on: ${{ matrix.os }}

strategy:
fail-fast: true
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
php: [8.1, 8.2]
laravel: [10.*, 11.x]
php: [8.2, 8.3, 8.4]
laravel: [11.x, '12.*']
stability: [prefer-lowest, prefer-stable]
include:
- laravel: 10.*
testbench: 8.*
collision: ^6.0
- laravel: 11.*
testbench: 9.*
collision: ^8.1
- laravel: 12.*
testbench: 10.*

name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.stability }} - ${{ matrix.os }}

Expand All @@ -44,7 +45,7 @@ jobs:

- name: Install dependencies
run: |
composer require "laravel/framework:${{ matrix.laravel }}" "orchestra/testbench:${{ matrix.testbench }}" "nesbot/carbon:^2.64.1" --no-interaction --no-update
composer require "laravel/framework:${{ matrix.laravel }}" "orchestra/testbench:${{ matrix.testbench }}" --no-interaction --no-update
composer update --${{ matrix.stability }} --prefer-dist --no-interaction

- name: Execute tests
Expand Down
15 changes: 7 additions & 8 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,19 @@
}
],
"require": {
"php": "^8.1|^8.2",
"illuminate/contracts": "^10.0|^11.0",
"illuminate/support": "^10.0|^11.0",
"php": "^8.2",
"illuminate/contracts": "^11.0|^12.0",
"illuminate/support": "^11.0|^12.0",
"spatie/laravel-package-tools": "^1.9"
},
"require-dev": {
"guzzlehttp/guzzle": "^7.4",
"laravel/pint": "^1.10",
"nunomaduro/collision": "^6.0|^8.1",
"orchestra/testbench": "^7.17|^8.0",
"orchestra/testbench": "^9.0|^10.0",
"phpstan/extension-installer": "^1.1",
"phpstan/phpstan-deprecation-rules": "^1.0",
"phpstan/phpstan-phpunit": "^1.0",
"phpunit/phpunit": "^10.5"
"phpstan/phpstan-deprecation-rules": "^1.0|^2.0",
"phpstan/phpstan-phpunit": "^1.0|^2.0",
"phpunit/phpunit": "^10.5|^11.5.3"
},
"bin": [
"bin/importmap"
Expand Down
22 changes: 22 additions & 0 deletions rector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

declare(strict_types=1);

use Rector\Config\RectorConfig;
use Rector\ValueObject\PhpVersion;

return RectorConfig::configure()
->withPaths([
__DIR__.'/src',
__DIR__.'/tests',
])
->withPreparedSets(
deadCode: true,
codeQuality: true,
typeDeclarations: true,
privatization: true,
earlyReturn: true,
)
->withAttributesSets()
->withPhpSets()
->withPhpVersion(PhpVersion::PHP_82);
18 changes: 9 additions & 9 deletions src/Actions/FixJsImportPaths.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,47 +15,47 @@ public function __construct(public string $root, public ?string $output = null)
$this->output ??= $root;
}

public function __invoke()
public function __invoke(): void
{
collect(File::allFiles($this->root))
->filter(fn (SplFileInfo $file) => in_array($file->getExtension(), ['js', 'mjs']))
->filter(fn (SplFileInfo $file): bool => in_array($file->getExtension(), ['js', 'mjs']))
->each(fn (SplFileInfo $file) => File::ensureDirectoryExists($this->absoluteOutputPathFor($file)))
->each(fn (SplFileInfo $file) => File::put(
$this->absoluteOutputPathWithFileFor($file),
$this->updatedJsImports($file),
));
}

private function absoluteOutputPathFor(SplFileInfo $file)
private function absoluteOutputPathFor(SplFileInfo $file): string
{
return str_replace($this->root, $this->output, dirname($file->getRealPath()));
}

private function absoluteOutputPathWithFileFor(SplFileInfo $file)
private function absoluteOutputPathWithFileFor(SplFileInfo $file): string
{
return rtrim($this->absoluteOutputPathFor($file), DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.$file->getFilename();
return rtrim((string) $this->absoluteOutputPathFor($file), DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.$file->getFilename();
}

private function updatedJsImports(SplFileInfo $file)
private function updatedJsImports(SplFileInfo $file): string
{
$lines = File::lines($file->getRealPath())->all();

foreach ($lines as $index => $line) {
if (! str_starts_with($line, 'import ')) {
if (! str_starts_with((string) $line, 'import ')) {
continue;
}

try {
$lines[$index] = preg_replace_callback(
'#import.+["\']([\.]+.*)["\']#',
function ($matches) use ($file) {
function ($matches) use ($file): string {
$replaced = $this->replaceDotImports($file, $matches[1], $matches[0]);

$relative = trim(str_replace($this->root, '', $replaced), DIRECTORY_SEPARATOR);

return str_replace(DIRECTORY_SEPARATOR, '/', str_replace($matches[1], $relative, $matches[0]));
},
$line,
(string) $line,
);
} catch (FailedToFixImportStatementException $exception) {
event(new FailedToFixImportStatement($exception->file, $exception->importStatement));
Expand Down
5 changes: 3 additions & 2 deletions src/Actions/ReplaceOrAppendTags.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
class ReplaceOrAppendTags
{
public const VITE_DIRECTIVE_PATTERN = '/(\s*)\@vite\(.*\)/';

public const CLOSING_HEAD_TAG_PATTERN = '/(\s*)(<\/head>)/';

public function __invoke(string $contents)
Expand All @@ -16,14 +17,14 @@ public function __invoke(string $contents)
if (str_contains($contents, '@vite')) {
return preg_replace(
static::VITE_DIRECTIVE_PATTERN,
"\\1<x-importmap::tags />",
'\\1<x-importmap::tags />',
$contents,
);
}

return preg_replace(
static::CLOSING_HEAD_TAG_PATTERN,
PHP_EOL."\\1 <x-importmap::tags />\\1\\2",
PHP_EOL.'\\1 <x-importmap::tags />\\1\\2',
$contents,
);
}
Expand Down
4 changes: 2 additions & 2 deletions src/AssetResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ class AssetResolver
public function __invoke(string $fileRelativePath)
{
if (str_starts_with(trim($fileRelativePath, '/'), 'vendor/') && File::exists($absolutePath = public_path($fileRelativePath))) {
return asset($fileRelativePath).'?digest='.(new FileDigest())($absolutePath);
return asset($fileRelativePath).'?digest='.(new FileDigest)($absolutePath);
}

if (! File::exists($absolutePath = Importmap::getFileAbsolutePath('/resources/'.trim($fileRelativePath, '/')))) {
return asset($fileRelativePath);
}

return asset($fileRelativePath).'?digest='.(new FileDigest())($absolutePath);
return asset($fileRelativePath).'?digest='.(new FileDigest)($absolutePath);
}
}
6 changes: 3 additions & 3 deletions src/Commands/AuditCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,17 @@ public function handle(Npm $npm): int
$this->table(
['Package', 'Severity', 'Vulnerable Versions', 'Vulnerability'],
$vulnerablePackages
->map(fn (VulnerablePackage $package) => [$package->name, $package->severity, $package->vulnerableVersions, $package->vulnerability])
->map(fn (VulnerablePackage $package): array => [$package->name, $package->severity, $package->vulnerableVersions, $package->vulnerability])
->all()
);

$this->newLine();

$summary = $vulnerablePackages
->groupBy('severity')
->map(fn ($vulns) => $vulns->count())
->map(fn ($vulns): int => $vulns->count())
->sortDesc()
->map(fn ($count, $severity) => "$count {$severity}")
->map(fn ($count, $severity): string => "$count {$severity}")
->join(', ');

$this->error(sprintf(
Expand Down
24 changes: 12 additions & 12 deletions src/Commands/InstallCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ private function importDependenciesFromNpm(): void
$packageJson = json_decode(File::get($packageJsonFile), true);

$dependencies = collect(array_replace($packageJson['dependencies'] ?? [], $packageJson['devDependencies'] ?? []))
->filter(fn ($_version, $package) => ! in_array($package, $filteredOutDependencies))
->filter(function ($_version, $package) {
->filter(fn ($_version, $package): bool => ! in_array($package, $filteredOutDependencies))
->filter(function ($_version, $package): bool {
if ($package !== 'axios') {
return true;
}
Expand All @@ -93,7 +93,7 @@ private function importDependenciesFromNpm(): void
return false;
})
// Axios has an issue with importmaps, so we'll hardcode the version for now...
->map(fn ($version, $package) => $package === 'axios' ? '[email protected]' : "\"{$package}@{$version}\"");
->map(fn ($version, $package): string => $package === 'axios' ? '[email protected]' : "\"{$package}@{$version}\"");

if (trim($dependencies->join('')) === '') {
return;
Expand All @@ -103,7 +103,7 @@ private function importDependenciesFromNpm(): void
$this->phpBinary(),
'artisan',
'importmap:pin',
], $dependencies->all()), function ($_type, $output) {
], $dependencies->all()), function ($_type, $output): void {
$this->output->write($output);
});
}
Expand All @@ -112,7 +112,7 @@ private function updateAppLayouts(): void
{
$this->existingLayoutFiles()->each(fn ($file) => File::put(
$file,
(new ReplaceOrAppendTags())(File::get($file)),
(new ReplaceOrAppendTags)(File::get($file)),
));
}

Expand All @@ -123,7 +123,7 @@ private function existingLayoutFiles()
->filter(fn ($file) => File::exists($file));
}

private function configureIgnoredFolder()
private function configureIgnoredFolder(): void
{
if (Str::contains(File::get(base_path('.gitignore')), 'public/js')) {
return;
Expand All @@ -132,31 +132,31 @@ private function configureIgnoredFolder()
File::append(base_path('.gitignore'), "\n/public/js\n");
}

private function runStorageLinkCommand()
private function runStorageLinkCommand(): void
{
if ($this->components->confirm('To be able to serve your assets in development, the resource/js folder will be symlinked to your public/js. Would you like to do that now?', true)) {
if ($this->usingSail() && ! env('LARAVEL_SAIL')) {
Process::forever()->run([
'./vendor/bin/sail',
'up',
'-d',
], function ($_type, $output) {
], function ($_type, $output): void {
$this->output->write($output);
});

Process::forever()->run([
'./vendor/bin/sail',
'artisan',
'storage:link',
], function ($_type, $output) {
], function ($_type, $output): void {
$this->output->write($output);
});
} else {
Process::forever()->run([
$this->phpBinary(),
'artisan',
'storage:link',
], function ($_type, $output) {
], function ($_type, $output): void {
$this->output->write($output);
});
}
Expand All @@ -168,8 +168,8 @@ private function usingSail(): bool
return file_exists(base_path('docker-compose.yml')) && str_contains(file_get_contents(base_path('composer.json')), 'laravel/sail');
}

private function phpBinary()
private function phpBinary(): string
{
return (new PhpExecutableFinder())->find(false) ?: 'php';
return (new PhpExecutableFinder)->find(false) ?: 'php';
}
}
2 changes: 1 addition & 1 deletion src/Commands/JsonCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class JsonCommand extends Command

public function handle(Importmap $importmap): int
{
$imports = $importmap->asArray(new AssetResolver());
$imports = $importmap->asArray(new AssetResolver);

$this->output->writeln(json_encode($imports, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));

Expand Down
14 changes: 6 additions & 8 deletions src/Commands/OptimizeCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,11 @@ public function handle(Importmap $importmap): int
$preloadModulePaths = $importmap->preloadedModulePaths(fn ($file) => $file);

$optmizedJson = collect($imports['imports'])
->map(function (string $oldFilename, string $module) use ($preloadModulePaths, $optimizedImports) {
return [
'module' => $module,
'path' => $optimizedImports[$module] ?? $oldFilename,
'preload' => in_array($oldFilename, $preloadModulePaths),
];
})
->map(fn (string $oldFilename, string $module): array => [
'module' => $module,
'path' => $optimizedImports[$module] ?? $oldFilename,
'preload' => in_array($oldFilename, $preloadModulePaths),
])
->values()
->all();

Expand All @@ -70,7 +68,7 @@ private function digest(string $filename, string $fileSource): string
{
return preg_replace(
'#(\.jsm?)$#',
sprintf('-%s$1', (new FileDigest())($fileSource)),
sprintf('-%s$1', (new FileDigest)($fileSource)),
$filename
);
}
Expand Down
2 changes: 1 addition & 1 deletion src/Commands/OutdatedCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public function handle(Npm $npm): int
$this->table(
['Package', 'Current', 'Latest'],
$outdatedPackages
->map(fn (OutdatedPackage $package) => [$package->name, $package->currentVersion, $package->latestVersion ?: $package->error])
->map(fn (OutdatedPackage $package): array => [$package->name, $package->currentVersion, $package->latestVersion ?: $package->error])
->all(),
);

Expand Down
6 changes: 2 additions & 4 deletions src/Commands/PinCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,8 @@ class PinCommand extends Command

/**
* Execute the console command.
*
* @return int
*/
public function handle(Packager $packager)
public function handle(Packager $packager): int
{
$this->call('importmap:clear');

Expand All @@ -55,7 +53,7 @@ public function handle(Packager $packager)

private function importPackages(Packager $packager, Collection $imports): void
{
$imports->each(function (string $url, string $package) use ($packager) {
$imports->each(function (string $url, string $package) use ($packager): void {
$this->info(sprintf(
'Pinning "%s" to %s/%s.js via download from %s',
$package,
Expand Down
Loading