From 3bd87098c1fdb68db3ab80bb9a84459aecec0be7 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Fri, 18 Sep 2026 16:47:00 +0700 Subject: [PATCH] chore: Use StructArmed on QA --- .gitattributes | 1 + .github/workflows/coding-conventions.yml | 21 ++++- composer.json | 3 +- .../PolicyBasedAccessControl.php | 6 +- .../src/OAuth/Testing/TestingOAuthClient.php | 6 +- .../cache/src/Commands/CacheClearCommand.php | 4 +- packages/cache/src/GenericCache.php | 2 +- .../FileCommandRepository.php | 2 +- .../command-bus/src/MonitorAsyncCommands.php | 2 +- .../src/Actions/RenderConsoleCommand.php | 2 +- .../src/Actions/ResolveConsoleCommand.php | 2 +- .../console/src/Commands/AboutCommand.php | 4 +- .../src/Commands/MakeCommandCommand.php | 2 +- .../Commands/MakeGeneratorCommandCommand.php | 2 +- .../src/Commands/MakeMiddlewareCommand.php | 2 +- .../Components/Concerns/RendersControls.php | 2 +- .../Interactive/ProgressBarComponent.php | 2 +- .../Components/Interactive/TaskComponent.php | 4 +- .../InteractiveComponentRenderer.php | 6 +- .../src/Components/OptionCollection.php | 10 +-- .../Renderers/InstructionsRenderer.php | 2 +- .../Components/Renderers/KeyValueRenderer.php | 6 +- .../Components/Renderers/MessageRenderer.php | 2 +- .../src/Components/Renderers/TaskRenderer.php | 2 +- .../Renderers/TextInputRenderer.php | 4 +- .../Static/StaticMultipleChoiceComponent.php | 8 +- .../Static/StaticProgressBarComponent.php | 2 +- .../Static/StaticSingleChoiceComponent.php | 2 +- .../Components/Static/StaticTaskComponent.php | 2 +- packages/console/src/ConsoleInputBuilder.php | 2 +- .../Exceptions/ConsoleExceptionHandler.php | 4 +- .../Exceptions/InvalidCommandException.php | 2 +- .../src/Exceptions/InvalidEnumArgument.php | 2 +- .../Exceptions/UnknownArgumentsException.php | 2 +- .../Injections/DynamicInjection.php | 2 +- .../Injections/FileInjection.php | 2 +- .../Injections/LinkInjection.php | 2 +- .../src/Highlight/TempestTerminalTheme.php | 2 +- .../ConsoleApplicationInitializer.php | 2 +- .../console/src/Input/MemoryInputBuffer.php | 2 +- .../src/Installers/ConsoleInstaller.php | 2 +- .../console/src/Middleware/HelpMiddleware.php | 6 +- .../src/Middleware/OverviewMiddleware.php | 6 +- .../Middleware/ResolveOrRescueMiddleware.php | 6 +- .../ValidateNamedArgumentsMiddleware.php | 10 +-- .../console/src/Output/MemoryOutputBuffer.php | 2 +- packages/console/src/Output/TailReader.php | 2 +- .../src/Scheduler/GenericScheduler.php | 2 +- .../src/Stubs/GeneratorCommandStub.php | 2 +- packages/console/src/Terminal/Terminal.php | 4 +- .../console/src/Testing/ConsoleTester.php | 4 +- .../src/Commands/MakeInitializerCommand.php | 2 +- .../CircularDependencyEncountered.php | 2 +- .../DependencyCouldNotBeAutowired.php | 2 +- .../TaggedDependencyCouldNotBeResolved.php | 2 +- packages/core/src/Commands/InstallCommand.php | 8 +- .../core/src/EnvironmentValueWasInvalid.php | 2 +- .../EnvironmentVariableValidationFailed.php | 2 +- .../core/src/Exceptions/ExceptionTester.php | 2 +- packages/core/src/FrameworkKernel.php | 2 +- packages/core/src/IsComponentInstaller.php | 2 +- packages/core/src/Kernel/LoadConfig.php | 4 +- packages/core/src/Middleware.php | 6 +- packages/core/src/PublishesFiles.php | 4 +- .../database/src/Builder/ModelInspector.php | 2 +- .../QueryBuilders/CountQueryBuilder.php | 2 +- .../HasConvenientWhereMethods.php | 6 +- .../QueryBuilders/SelectQueryBuilder.php | 8 +- .../src/Commands/MakeMigrationCommand.php | 2 +- .../Exceptions/InsertColumnsMismatched.php | 4 +- packages/database/src/IsDatabaseModel.php | 4 +- .../src/Mappers/SelectModelMapper.php | 2 +- .../QueryStatements/AlterTableStatement.php | 4 +- .../src/QueryStatements/CompoundStatement.php | 2 +- .../src/QueryStatements/CountStatement.php | 4 +- .../CreateEnumTypeStatement.php | 6 +- .../QueryStatements/CreateTableStatement.php | 6 +- .../src/QueryStatements/DeleteStatement.php | 4 +- .../src/QueryStatements/EnumStatement.php | 6 +- .../src/QueryStatements/FieldStatement.php | 4 +- .../src/QueryStatements/InsertStatement.php | 4 +- .../src/QueryStatements/SelectStatement.php | 14 ++-- .../src/QueryStatements/UpdateStatement.php | 6 +- .../QueryStatements/WhereExistsStatement.php | 4 +- .../QueryStatements/WhereGroupStatement.php | 4 +- .../DataTransferObjectSerializer.php | 2 +- packages/debug/src/Debug.php | 2 +- packages/debug/src/Stacktrace/Frame.php | 2 +- packages/debug/src/Stacktrace/Stacktrace.php | 6 +- .../src/Commands/MakeDiscoveryCommand.php | 2 +- packages/discovery/src/Composer.php | 6 +- packages/discovery/src/DiscoveryConfig.php | 2 +- packages/discovery/src/DiscoveryItems.php | 2 +- packages/discovery/src/DiscoveryLocation.php | 2 +- .../event-bus/src/Testing/EventBusTester.php | 2 +- .../src/Php/SimplifiesClassNames.php | 4 +- .../generation/src/Php/StubFileGenerator.php | 6 +- .../src/TypeScript/TypeResolverDiscovery.php | 4 +- .../TypeScript/Writers/DirectoryWriter.php | 4 +- packages/http/src/Input/StdinInputStream.php | 2 +- packages/http/src/IsResponse.php | 2 +- .../PsrRequestToGenericRequestMapper.php | 2 +- .../src/Mappers/RequestToObjectMapper.php | 4 +- packages/http/src/RequestHeaders.php | 2 +- .../Formatter/MessageFormatter.php | 16 ++-- .../Parser/MessageFormatParser.php | 2 +- .../intl/src/TranslationMessageDiscovery.php | 2 +- .../kv-store/src/Redis/PhpRedisClient.php | 2 +- packages/kv-store/src/Redis/PredisClient.php | 2 +- packages/log/src/TailLogsCommand.php | 2 +- packages/mail/src/Attachment.php | 4 +- .../mail/src/EmailToSymfonyEmailMapper.php | 2 +- packages/mail/src/Testing/MailTester.php | 18 ++-- .../src/Transports/RoundRobinMailerConfig.php | 2 +- .../src/Mappers/ArrayToObjectMapper.php | 4 +- packages/process/src/InvokedProcessPool.php | 12 +-- packages/process/src/InvokedSystemProcess.php | 2 +- packages/process/src/ProcessPoolResults.php | 12 +-- .../src/Testing/InvokedProcessDescription.php | 2 +- packages/reflection/src/ClassReflector.php | 6 +- packages/reflection/src/EnumReflector.php | 2 +- packages/reflection/src/FunctionReflector.php | 2 +- packages/reflection/src/MethodReflector.php | 2 +- packages/reflection/src/TypeReflector.php | 2 +- .../src/Commands/MakeControllerCommand.php | 2 +- .../src/Exceptions/JsonExceptionRenderer.php | 2 +- packages/router/src/GenericRouter.php | 2 +- .../src/HandleRouteSpecificMiddleware.php | 2 +- packages/router/src/MatchRouteMiddleware.php | 2 +- .../src/ResolveRouteRequestMiddleware.php | 2 +- packages/support/src/Arr/ManipulatesArray.php | 2 +- packages/support/src/Arr/functions.php | 4 +- packages/support/src/Html/functions.php | 8 +- packages/support/src/IsEnumHelper.php | 2 +- .../src/JavaScript/DependencyInstaller.php | 2 +- .../support/src/JavaScript/PackageManager.php | 2 +- packages/support/src/Namespace/functions.php | 4 +- packages/support/src/Path/functions.php | 10 +-- packages/support/src/Regex/functions.php | 6 +- packages/support/src/Str/functions.php | 8 +- packages/support/src/Uri/Uri.php | 2 +- .../UpdateKernelDiscoveryPropertiesRector.php | 2 +- packages/validation/src/Validator.php | 4 +- packages/view/src/Components/x-icon.view.php | 12 +-- packages/view/src/Elements/TextElement.php | 4 +- .../src/Elements/ViewComponentElement.php | 36 ++++---- .../view/src/Export/ViewObjectExporter.php | 4 +- packages/view/src/Parser/TempestViewAst.php | 2 +- .../view/src/Parser/TempestViewCompiler.php | 4 +- packages/view/src/Parser/TokenCollection.php | 2 +- packages/view/src/ViewCachePool.php | 2 +- packages/vite/src/Installer/ViteInstaller.php | 2 +- packages/vite/src/Manifest/Manifest.php | 2 +- .../TagsResolver/DevelopmentTagsResolver.php | 4 +- .../src/TagsResolver/ManifestTagsResolver.php | 8 +- .../Framework/Commands/ConfigShowCommand.php | 4 +- .../Commands/MetaViewComponentCommand.php | 16 ++-- .../Framework/Installers/ConfigInstaller.php | 6 +- .../Installers/FrameworkInstaller.php | 4 +- .../Installers/ViewComponentsInstaller.php | 2 +- .../Testing/Http/HttpRouterTester.php | 2 +- .../Testing/Http/TestResponseHelper.php | 6 +- .../Framework/Testing/IntegrationTest.php | 10 +-- src/Tempest/Framework/Testing/ViteTester.php | 4 +- structarmed.php | 84 +++++++++++++++++++ 165 files changed, 436 insertions(+), 331 deletions(-) create mode 100644 structarmed.php diff --git a/.gitattributes b/.gitattributes index 69f3fefa96..cd1bae2b3c 100644 --- a/.gitattributes +++ b/.gitattributes @@ -19,6 +19,7 @@ phpunit.xml export-ignore phpunit.xml.dist export-ignore README.md export-ignore rector.php export-ignore +structarmed.php export-ignore cliff.toml export-ignore .commitlintrc.json export-ignore diff --git a/.github/workflows/coding-conventions.yml b/.github/workflows/coding-conventions.yml index f2ec89b07d..2152a0f415 100644 --- a/.github/workflows/coding-conventions.yml +++ b/.github/workflows/coding-conventions.yml @@ -65,7 +65,7 @@ jobs: phpstan-result-cache- - name: Run PHPStan - run: vendor/bin/phpstan --error-format=github -vv + run: vendor/bin/phpstan --error-format=github -vv - name: Save PHPStan result cache uses: actions/cache/save@v4 @@ -92,3 +92,22 @@ jobs: # # - name: Run Rector # run: vendor/bin/rector process --no-ansi --dry-run --no-progress-bar + + + structarmed: + name: "Run static analysis: StructArmed" + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: 8.5 + coverage: none + + - name: Install composer dependencies + uses: ramsey/composer-install@v3 + + - name: Run StructArmed + run: vendor/bin/structarmed analyze diff --git a/composer.json b/composer.json index f96a0580c4..954283967d 100644 --- a/composer.json +++ b/composer.json @@ -92,7 +92,8 @@ "thenetworg/oauth2-azure": "^2.2", "twig/twig": "^3.16", "vertisan/oauth2-twitch-helix": "^2.0", - "wohali/oauth2-discord-new": "^1.2" + "wohali/oauth2-discord-new": "^1.2", + "boundwize/structarmed": "^0.17.9" }, "replace": { "tempest/auth": "self.version", diff --git a/packages/auth/src/AccessControl/PolicyBasedAccessControl.php b/packages/auth/src/AccessControl/PolicyBasedAccessControl.php index 88cb780da9..069ecba9d5 100644 --- a/packages/auth/src/AccessControl/PolicyBasedAccessControl.php +++ b/packages/auth/src/AccessControl/PolicyBasedAccessControl.php @@ -86,7 +86,7 @@ private function findPoliciesForResourceAction(object|string $resource, UnitEnum $actionBeingEvaluated = Str\parse($action); return new ImmutableArray($this->authConfig->policies[$resource] ?? []) - ->filter(fn ($_, string $action) => $action === $actionBeingEvaluated) + ->filter(static fn ($_, string $action) => $action === $actionBeingEvaluated) ->flatten(); } @@ -97,13 +97,13 @@ private function evaluatePolicy(MethodReflector $policy, ?object $resource, ?obj $this->ensureParameterAcceptsInput( reflector: $policy->getParameter(key: 0), input: $resource, - throw: fn (string $expected) => throw PolicyMethodWasInvalid::resourceParameterIsInvalid($policyName, $expected), + throw: static fn (string $expected) => throw PolicyMethodWasInvalid::resourceParameterIsInvalid($policyName, $expected), ); $this->ensureParameterAcceptsInput( reflector: $policy->getParameter(key: 1), input: $subject, - throw: fn (string $expected) => throw PolicyMethodWasInvalid::subjectParameterIsInvalid($policyName, $expected), + throw: static fn (string $expected) => throw PolicyMethodWasInvalid::subjectParameterIsInvalid($policyName, $expected), ); $decision = $policy->invokeArgs( diff --git a/packages/auth/src/OAuth/Testing/TestingOAuthClient.php b/packages/auth/src/OAuth/Testing/TestingOAuthClient.php index 5a791ea05e..d5bceb7fb0 100644 --- a/packages/auth/src/OAuth/Testing/TestingOAuthClient.php +++ b/packages/auth/src/OAuth/Testing/TestingOAuthClient.php @@ -245,7 +245,7 @@ public function assertAuthorizationUrlGenerated(?array $scopes = null, ?array $o public function assertUserFetched(string $code): void { Assert::assertNotEmpty( - actual: array_filter($this->users, fn (array $user) => $user['code'] === $code), + actual: array_filter($this->users, static fn (array $user) => $user['code'] === $code), message: sprintf('User with code "%s" was not handled.', $code), ); } @@ -259,7 +259,7 @@ public function assertAccessTokenRetrieved(?string $code = null): void if ($code !== null) { Assert::assertNotEmpty( - actual: array_filter($this->accessTokens, fn (array $token) => $token['code'] === $code), + actual: array_filter($this->accessTokens, static fn (array $token) => $token['code'] === $code), message: sprintf('No access token was retrieved for code "%s".', $code), ); } @@ -275,7 +275,7 @@ public function assertAccessTokenRefreshed(?string $refreshToken = null): void if ($refreshToken !== null) { // @mago-expect lint:no-insecure-comparison Assert::assertNotEmpty( - actual: array_filter($this->refreshedTokens, fn (array $token) => $token['refresh_token'] === $refreshToken), + actual: array_filter($this->refreshedTokens, static fn (array $token) => $token['refresh_token'] === $refreshToken), message: sprintf('No access token was refreshed for refresh token "%s".', $refreshToken), ); } diff --git a/packages/cache/src/Commands/CacheClearCommand.php b/packages/cache/src/Commands/CacheClearCommand.php index 4d0e4343b3..249e0b2ec8 100644 --- a/packages/cache/src/Commands/CacheClearCommand.php +++ b/packages/cache/src/Commands/CacheClearCommand.php @@ -93,8 +93,8 @@ private function clearUserCaches(?string $tag = null, bool $all = false): void /** @var GenericContainer $container */ $container = $this->container; $cacheTags = arr($container->getSingletons(CacheConfig::class)) - ->map(fn ($_, string $key) => $key === CacheConfig::class ? self::DEFAULT_CACHE : Str\after_last($key, '#')) - ->filter(fn (string $value) => $tag === null || $value === $tag) + ->map(static fn ($_, string $key) => $key === CacheConfig::class ? self::DEFAULT_CACHE : Str\after_last($key, '#')) + ->filter(static fn (string $value) => $tag === null || $value === $tag) ->values(); if ($all === false && count($cacheTags) > 1) { diff --git a/packages/cache/src/GenericCache.php b/packages/cache/src/GenericCache.php index 3750d06fd9..820bffebda 100644 --- a/packages/cache/src/GenericCache.php +++ b/packages/cache/src/GenericCache.php @@ -134,7 +134,7 @@ public function getMany(iterable $key): array if (! $this->enabled) { return Arr\map_with_keys( array: $key, - map: fn (string|Stringable $key) => yield (string) $key => null, + map: static fn (string|Stringable $key) => yield (string) $key => null, ); } diff --git a/packages/command-bus/src/AsyncCommandRepositories/FileCommandRepository.php b/packages/command-bus/src/AsyncCommandRepositories/FileCommandRepository.php index b7759e9822..cfa7c47f3b 100644 --- a/packages/command-bus/src/AsyncCommandRepositories/FileCommandRepository.php +++ b/packages/command-bus/src/AsyncCommandRepositories/FileCommandRepository.php @@ -52,7 +52,7 @@ public function markAsFailed(string $uuid): void public function getPendingCommands(): array { return arr(glob(__DIR__ . '/../stored-commands/*.pending.txt')) - ->mapWithKeys(function (string $path) { + ->mapWithKeys(static function (string $path) { if (! Filesystem\is_file($path)) { return; } diff --git a/packages/command-bus/src/MonitorAsyncCommands.php b/packages/command-bus/src/MonitorAsyncCommands.php index 89ec6cba28..77c426317d 100644 --- a/packages/command-bus/src/MonitorAsyncCommands.php +++ b/packages/command-bus/src/MonitorAsyncCommands.php @@ -71,7 +71,7 @@ public function __invoke(): void } $availableCommands = arr($this->repository->getPendingCommands()) - ->filter(fn (object $_, string $uuid) => ! array_key_exists($uuid, $processes)); + ->filter(static fn (object $_, string $uuid) => ! array_key_exists($uuid, $processes)); if (count($processes) === 5) { $this->sleep(0.5); diff --git a/packages/console/src/Actions/RenderConsoleCommand.php b/packages/console/src/Actions/RenderConsoleCommand.php index 6ef462af5b..0bef53c793 100644 --- a/packages/console/src/Actions/RenderConsoleCommand.php +++ b/packages/console/src/Actions/RenderConsoleCommand.php @@ -75,7 +75,7 @@ private function renderArgument(ConsoleArgumentDefinition $argument): string private function renderEnumArgument(ConsoleArgumentDefinition $argument): string { $parts = array_map( - callback: fn (BackedEnum $case) => $case->value, + callback: static fn (BackedEnum $case) => $case->value, array: $argument->type::cases(), ); diff --git a/packages/console/src/Actions/ResolveConsoleCommand.php b/packages/console/src/Actions/ResolveConsoleCommand.php index 6ff6da1f76..1fc5795a86 100644 --- a/packages/console/src/Actions/ResolveConsoleCommand.php +++ b/packages/console/src/Actions/ResolveConsoleCommand.php @@ -27,7 +27,7 @@ public function __invoke(array|string $command): ConsoleCommand if (is_array($command)) { $command = array_find( array: $this->consoleConfig->commands, - callback: fn (ConsoleCommand $consoleCommand) => ( + callback: static fn (ConsoleCommand $consoleCommand) => ( $consoleCommand->handler->getDeclaringClass()->getName() === $command[0] && $consoleCommand->handler->getName() === $command[1] ), diff --git a/packages/console/src/Commands/AboutCommand.php b/packages/console/src/Commands/AboutCommand.php index 33a85b403d..492a7c7e54 100644 --- a/packages/console/src/Commands/AboutCommand.php +++ b/packages/console/src/Commands/AboutCommand.php @@ -76,7 +76,7 @@ private function formatInsight(Stringable|Insight|array|string $value): string { return arr($value) ->filter() - ->map(function (Stringable|Insight|string $value) { + ->map(static function (Stringable|Insight|string $value) { if ($value instanceof Insight) { return $value->formattedValue; } @@ -91,7 +91,7 @@ private function rawInsight(Stringable|Insight|array|string $value): array { return arr($value) ->filter() - ->map(function (Stringable|Insight|string $value) { + ->map(static function (Stringable|Insight|string $value) { if ($value instanceof Insight) { return $value->value; } diff --git a/packages/console/src/Commands/MakeCommandCommand.php b/packages/console/src/Commands/MakeCommandCommand.php index ff03458bfa..34b177d596 100644 --- a/packages/console/src/Commands/MakeCommandCommand.php +++ b/packages/console/src/Commands/MakeCommandCommand.php @@ -39,7 +39,7 @@ public function __invoke( 'dummy-command-slug' => str($className)->kebab()->toString(), ], manipulations: [ - fn (ClassManipulator $class) => $class->removeClassAttribute(SkipDiscovery::class), + static fn (ClassManipulator $class) => $class->removeClassAttribute(SkipDiscovery::class), ], ); diff --git a/packages/console/src/Commands/MakeGeneratorCommandCommand.php b/packages/console/src/Commands/MakeGeneratorCommandCommand.php index b3ef45c23b..5c3e70e127 100644 --- a/packages/console/src/Commands/MakeGeneratorCommandCommand.php +++ b/packages/console/src/Commands/MakeGeneratorCommandCommand.php @@ -39,7 +39,7 @@ public function __invoke( 'dummy-command-slug' => str($className)->kebab()->toString(), ], manipulations: [ - fn (ClassManipulator $class) => $class->removeClassAttribute(SkipDiscovery::class), + static fn (ClassManipulator $class) => $class->removeClassAttribute(SkipDiscovery::class), ], ); diff --git a/packages/console/src/Commands/MakeMiddlewareCommand.php b/packages/console/src/Commands/MakeMiddlewareCommand.php index 9a041f721a..070bc1bb4b 100644 --- a/packages/console/src/Commands/MakeMiddlewareCommand.php +++ b/packages/console/src/Commands/MakeMiddlewareCommand.php @@ -42,7 +42,7 @@ public function __invoke( targetPath: $targetPath, shouldOverride: $shouldOverride, manipulations: [ - fn (ClassManipulator $class) => $class->removeClassAttribute(SkipDiscovery::class), + static fn (ClassManipulator $class) => $class->removeClassAttribute(SkipDiscovery::class), ], ); diff --git a/packages/console/src/Components/Concerns/RendersControls.php b/packages/console/src/Components/Concerns/RendersControls.php index 5e42d13d9c..6dbf6b006d 100644 --- a/packages/console/src/Components/Concerns/RendersControls.php +++ b/packages/console/src/Components/Concerns/RendersControls.php @@ -43,7 +43,7 @@ private function renderControls(array $controls, int $maxWidth): string $separator = ' · '; $marginLeft = ' '; $render = arr($controls) - ->map(fn (string $label, string $shortcut) => "{$shortcut} {$label}") + ->map(static fn (string $label, string $shortcut) => "{$shortcut} {$label}") ->implode($separator) ->prepend($marginLeft); diff --git a/packages/console/src/Components/Interactive/ProgressBarComponent.php b/packages/console/src/Components/Interactive/ProgressBarComponent.php index c6bc4a07c0..897fefe5e5 100644 --- a/packages/console/src/Components/Interactive/ProgressBarComponent.php +++ b/packages/console/src/Components/Interactive/ProgressBarComponent.php @@ -43,7 +43,7 @@ public function render(Terminal $terminal): Generator $count = iterator_count($this->data); $step = 1; - $format = $this->format ?? function (int $step, int $count): string { + $format = $this->format ?? static function (int $step, int $count): string { $width = 30; $progress = (int) round(($step / $count) * $width); diff --git a/packages/console/src/Components/Interactive/TaskComponent.php b/packages/console/src/Components/Interactive/TaskComponent.php index 5d39118c3f..6f3cc90e7e 100644 --- a/packages/console/src/Components/Interactive/TaskComponent.php +++ b/packages/console/src/Components/Interactive/TaskComponent.php @@ -153,7 +153,7 @@ private function executeHandler(): never { $log = function (string ...$lines): void { arr($lines) - ->flatMap(fn (string $line) => explode("\n", $line)) + ->flatMap(static fn (string $line) => explode("\n", $line)) ->each(function (string $line): void { fwrite($this->sockets[0], $line); }); @@ -173,7 +173,7 @@ private function resolveHandler(Process|Closure|null $handler): ?Closure } if ($handler instanceof Process) { - return static fn (Closure $log): bool => $handler->run(function (string $type, string $buffer) use ($log): void { + return static fn (Closure $log): bool => $handler->run(static function (string $type, string $buffer) use ($log): void { if ($type === Process::ERR) { return; } diff --git a/packages/console/src/Components/InteractiveComponentRenderer.php b/packages/console/src/Components/InteractiveComponentRenderer.php index bfa7dfed69..6bf7d884a8 100644 --- a/packages/console/src/Components/InteractiveComponentRenderer.php +++ b/packages/console/src/Components/InteractiveComponentRenderer.php @@ -113,14 +113,14 @@ private function applyKey(InteractiveConsoleComponent $component, Console $conso // If we have multiple handlers, we put the ones that return nothing // first because the ones that return something will be overridden otherwise. - usort($handlersForKey, fn (MethodReflector $a, MethodReflector $b) => $b->getReturnType()->equals('void') <=> $a->getReturnType()->equals('void')); + usort($handlersForKey, static fn (MethodReflector $a, MethodReflector $b) => $b->getReturnType()->equals('void') <=> $a->getReturnType()->equals('void')); // CTRL+C and CTRL+D means we exit the CLI, but only if there is no custom // handler. When we exit, we want one last render to display pretty // styles, so we will throw the exception in the next loop. if ($handlersForKey === [] && ($key === Key::CTRL_C->value || $key === Key::CTRL_D->value)) { $component->setState(ComponentState::CANCELLED); - $this->afterRenderCallbacks[] = fn () => throw new InterruptException(); + $this->afterRenderCallbacks[] = static fn () => throw new InterruptException(); $this->shouldRerender = true; Fiber::suspend(); @@ -324,7 +324,7 @@ private function validate(mixed $value, array $validation): ?string public function isComponentSupported(Console $console, InteractiveConsoleComponent $component): bool { - if (! arr($component->extensions ?? [])->every(fn (string $ext) => extension_loaded($ext))) { + if (! arr($component->extensions ?? [])->every(static fn (string $ext) => extension_loaded($ext))) { return false; } diff --git a/packages/console/src/Components/OptionCollection.php b/packages/console/src/Components/OptionCollection.php index ad922e0393..1858e2374b 100644 --- a/packages/console/src/Components/OptionCollection.php +++ b/packages/console/src/Components/OptionCollection.php @@ -38,7 +38,7 @@ public function setCollection(iterable $options): void $this->preserveKeys = $options->isAssociative(); $this->options = $options - ->map(fn (mixed $value, string|int $key) => new Option($key, $value)) + ->map(static fn (mixed $value, string|int $key) => new Option($key, $value)) ->toArray(); $this->filter(null); @@ -50,11 +50,11 @@ public function filter(?string $query): void $previouslySelectedOptions = $this->selectedOptions; $this->filteredOptions = arr($this->options) - ->filter(fn (Option $option) => ! $query || str_contains(mb_strtolower((string) $option->value), mb_strtolower(trim($query)))) + ->filter(static fn (Option $option) => ! $query || str_contains(mb_strtolower((string) $option->value), mb_strtolower(trim($query)))) ->values() ->toArray(); - $this->selectedOptions = array_filter($this->filteredOptions, fn (Option $option) => in_array($option, $previouslySelectedOptions, strict: true)); + $this->selectedOptions = array_filter($this->filteredOptions, static fn (Option $option) => in_array($option, $previouslySelectedOptions, strict: true)); $this->activeOption = array_search($previouslyActiveOption ?? $this->filteredOptions[0] ?? '', $this->filteredOptions, strict: true) ?: 0; } @@ -90,7 +90,7 @@ public function toggleCurrent(): void if (! $this->isSelected($active)) { $this->selectedOptions[] = $active; } else { - $this->selectedOptions = array_filter($this->selectedOptions, fn (Option $option) => ! $active->equals($option)); + $this->selectedOptions = array_filter($this->selectedOptions, static fn (Option $option) => ! $active->equals($option)); } } @@ -186,7 +186,7 @@ public function setActive(Stringable|UnitEnum|string|null $value): void }; $this->activeOption = array_search( - array_find($this->filteredOptions, fn (Option $option) => $option->key === $value || $option->value === $value), + array_find($this->filteredOptions, static fn (Option $option) => $option->key === $value || $option->value === $value), $this->filteredOptions, strict: true, ) ?: 0; diff --git a/packages/console/src/Components/Renderers/InstructionsRenderer.php b/packages/console/src/Components/Renderers/InstructionsRenderer.php index d2d8b57e94..1652115943 100644 --- a/packages/console/src/Components/Renderers/InstructionsRenderer.php +++ b/packages/console/src/Components/Renderers/InstructionsRenderer.php @@ -15,7 +15,7 @@ public function render(string|array $lines): string { $lines = arr($lines) ->filter() - ->flatMap(fn (string $string) => str($string)->chunk(self::MAX_WIDTH)->toArray()) + ->flatMap(static fn (string $string) => str($string)->chunk(self::MAX_WIDTH)->toArray()) ->toArray(); $text = str(PHP_EOL); diff --git a/packages/console/src/Components/Renderers/KeyValueRenderer.php b/packages/console/src/Components/Renderers/KeyValueRenderer.php index dbe945b471..6fe0b23973 100644 --- a/packages/console/src/Components/Renderers/KeyValueRenderer.php +++ b/packages/console/src/Components/Renderers/KeyValueRenderer.php @@ -20,8 +20,8 @@ public function render(Stringable|string $key, Stringable|string|null $value = n { $key = $this->cleanText($key)->append(' '); $value = $this->cleanText($value)->when( - condition: fn ($s) => $s->stripTags()->length() !== 0, - callback: fn ($s) => $s->prepend(' '), + condition: static fn ($s) => $s->stripTags()->length() !== 0, + callback: static fn ($s) => $s->prepend(' '), ); $maximumWidth = $useAvailableWidth @@ -58,7 +58,7 @@ private function cleanText(Stringable|string|null $text): ImmutableString return $text ->replaceRegex('/\[([^]]+)]/', '[$1]') - ->when(fn ($s) => $s->endsWith(['.', '?', '!', ':']), fn ($s) => $s->replaceAt(-1, 1, '')) + ->when(static fn ($s) => $s->endsWith(['.', '?', '!', ':']), static fn ($s) => $s->replaceAt(-1, 1, '')) ->erase(root_path()) ->trim(); } diff --git a/packages/console/src/Components/Renderers/MessageRenderer.php b/packages/console/src/Components/Renderers/MessageRenderer.php index 398725c4f7..2941e8ec16 100644 --- a/packages/console/src/Components/Renderers/MessageRenderer.php +++ b/packages/console/src/Components/Renderers/MessageRenderer.php @@ -19,7 +19,7 @@ public function render(string $contents, ?string $title = null): string { $title = str($title ?? $this->label)->toString(); $lines = ImmutableArray::explode($contents, "\n") - ->map(fn ($s, $i) => str_repeat(' ', $i === 0 ? 1 : strlen($title) + 4) . $s) + ->map(static fn ($s, $i) => str_repeat(' ', $i === 0 ? 1 : strlen($title) + 4) . $s) ->implode("\n"); return str() diff --git a/packages/console/src/Components/Renderers/TaskRenderer.php b/packages/console/src/Components/Renderers/TaskRenderer.php index d4e1ffa7fa..da7262a811 100644 --- a/packages/console/src/Components/Renderers/TaskRenderer.php +++ b/packages/console/src/Components/Renderers/TaskRenderer.php @@ -23,7 +23,7 @@ public function render(Terminal $terminal, ComponentState $state, float $started $this->prepareRender($terminal, $state); $this->label($this->label); - $runtime = fn (float $finishedAt) => $finishedAt !== 0.0 + $runtime = static fn (float $finishedAt) => $finishedAt !== 0.0 ? number_format(($finishedAt - $startedAt) / 1_000_000, decimals: 0) : null; diff --git a/packages/console/src/Components/Renderers/TextInputRenderer.php b/packages/console/src/Components/Renderers/TextInputRenderer.php index a1b2ce2cf6..0e6a456d1d 100644 --- a/packages/console/src/Components/Renderers/TextInputRenderer.php +++ b/packages/console/src/Components/Renderers/TextInputRenderer.php @@ -51,8 +51,8 @@ public function render( // if there is nothing to display after the component is done, show "no input" // TODO(innocenzi): clean up - if ($this->state->isFinished() && $lines->filter(fn (ImmutableString $line) => $line->trim()->isNotEmpty())->isEmpty()) { - $displayLines = $displayLines->filter(fn (ImmutableString $line) => $line->trim()->isNotEmpty()); + if ($this->state->isFinished() && $lines->filter(static fn (ImmutableString $line) => $line->trim()->isNotEmpty())->isEmpty()) { + $displayLines = $displayLines->filter(static fn (ImmutableString $line) => $line->trim()->isNotEmpty()); $this->line($this->style('italic dim', 'No input.'))->newLine(); } diff --git a/packages/console/src/Components/Static/StaticMultipleChoiceComponent.php b/packages/console/src/Components/Static/StaticMultipleChoiceComponent.php index 46c529b437..1fc38969b3 100644 --- a/packages/console/src/Components/Static/StaticMultipleChoiceComponent.php +++ b/packages/console/src/Components/Static/StaticMultipleChoiceComponent.php @@ -35,7 +35,7 @@ public function render(Console $console): array $answers = $this->askQuestion($console); $answerAsString = arr($answers) - ->map(fn (Option $option) => $option->displayValue) + ->map(static fn (Option $option) => $option->displayValue) ->join(', ', ' and ') ->trim() ->toString() ?: 'no option'; @@ -52,7 +52,7 @@ public function render(Console $console): array return $this->default; } - return array_map(fn (Option $option) => $option->value, $answers); + return array_map(static fn (Option $option) => $option->value, $answers); } private function askQuestion(Console $console): array @@ -66,7 +66,7 @@ private function askQuestion(Console $console): array fn (Option $option, int $index) => str($index) ->when( condition: in_array($option->value, $this->default, strict: true), - callback: fn ($s) => $s->wrap('', ''), + callback: static fn ($s) => $s->wrap('', ''), ) ->wrap('[', ']') ->prepend('- ') @@ -101,7 +101,7 @@ private function askQuestion(Console $console): array }); }) ->filter() - ->unique(fn (Option $option) => $option->value) + ->unique(static fn (Option $option) => $option->value) ->toArray(); } } diff --git a/packages/console/src/Components/Static/StaticProgressBarComponent.php b/packages/console/src/Components/Static/StaticProgressBarComponent.php index 0cdeaf8ce7..426899e4af 100644 --- a/packages/console/src/Components/Static/StaticProgressBarComponent.php +++ b/packages/console/src/Components/Static/StaticProgressBarComponent.php @@ -24,7 +24,7 @@ public function render(Console $console): array $count = iterator_count($this->data); $step = 1; - $format = $this->format ?? function (int $step, int $count): string { + $format = $this->format ?? static function (int $step, int $count): string { $width = 30; $progress = (int) round(($step / $count) * $width); diff --git a/packages/console/src/Components/Static/StaticSingleChoiceComponent.php b/packages/console/src/Components/Static/StaticSingleChoiceComponent.php index 897884e959..517d1c970b 100644 --- a/packages/console/src/Components/Static/StaticSingleChoiceComponent.php +++ b/packages/console/src/Components/Static/StaticSingleChoiceComponent.php @@ -38,7 +38,7 @@ public function render(Console $console): int|UnitEnum|string|null fn (Option $option, int $index) => str($index) ->when( condition: $option->key === $this->default || $option->value === $this->default, - callback: fn ($s) => $s->wrap('', ''), + callback: static fn ($s) => $s->wrap('', ''), ) ->wrap('[', ']') ->prepend('- ') diff --git a/packages/console/src/Components/Static/StaticTaskComponent.php b/packages/console/src/Components/Static/StaticTaskComponent.php index 4262bf3426..668df5e838 100644 --- a/packages/console/src/Components/Static/StaticTaskComponent.php +++ b/packages/console/src/Components/Static/StaticTaskComponent.php @@ -39,7 +39,7 @@ public function render(Console $console): bool private function executeClosureHandler(Closure $handler): bool { try { - return $handler(fn () => null) !== false; + return $handler(static fn () => null) !== false; } catch (Throwable) { return false; } diff --git a/packages/console/src/ConsoleInputBuilder.php b/packages/console/src/ConsoleInputBuilder.php index 2d034d1deb..861d6854d4 100644 --- a/packages/console/src/ConsoleInputBuilder.php +++ b/packages/console/src/ConsoleInputBuilder.php @@ -31,7 +31,7 @@ public function build(): array } return array_map( - callback: fn (ConsoleInputArgument $argument) => $argument->value, + callback: static fn (ConsoleInputArgument $argument) => $argument->value, array: $validArguments, ); } diff --git a/packages/console/src/Exceptions/ConsoleExceptionHandler.php b/packages/console/src/Exceptions/ConsoleExceptionHandler.php index 3c9d20f9fe..0a178e54aa 100644 --- a/packages/console/src/Exceptions/ConsoleExceptionHandler.php +++ b/packages/console/src/Exceptions/ConsoleExceptionHandler.php @@ -41,7 +41,7 @@ public function handle(Throwable $throwable): void ->error($throwable::class) ->when( condition: $throwable->getMessage(), - callback: fn (Console $console) => $console->error($throwable->getMessage()), + callback: static fn (Console $console) => $console->error($throwable->getMessage()), ) ->writeln() ->writeln('In ' . $this->formatFileWithLine($throwable->getFile() . ':' . $throwable->getLine())) @@ -81,7 +81,7 @@ private function getSnippet(string $file, int $lineNumber): string $lines = explode(PHP_EOL, $code); $lines[$lineNumber - 1] = str($lines[$lineNumber - 1]) - ->replaceRegex('/^\d+/', fn (array $match) => "{$match[0]}") + ->replaceRegex('/^\d+/', static fn (array $match) => "{$match[0]}") ->append(' <<<') ->toString(); diff --git a/packages/console/src/Exceptions/InvalidCommandException.php b/packages/console/src/Exceptions/InvalidCommandException.php index 2a5309ddac..2e2ea78547 100644 --- a/packages/console/src/Exceptions/InvalidCommandException.php +++ b/packages/console/src/Exceptions/InvalidCommandException.php @@ -21,7 +21,7 @@ public function __construct( public function render(Console $console): void { $missingArguments = implode(', ', array_map( - fn (ConsoleArgumentDefinition $argumentDefinition) => $argumentDefinition->name, + static fn (ConsoleArgumentDefinition $argumentDefinition) => $argumentDefinition->name, $this->invalidArguments, )); diff --git a/packages/console/src/Exceptions/InvalidEnumArgument.php b/packages/console/src/Exceptions/InvalidEnumArgument.php index 7c6a04f878..8b998e8a56 100644 --- a/packages/console/src/Exceptions/InvalidEnumArgument.php +++ b/packages/console/src/Exceptions/InvalidEnumArgument.php @@ -32,7 +32,7 @@ public function render(Console $console): void } $cases = array_map( - callback: fn (BackedEnum $case) => $case->value, + callback: static fn (BackedEnum $case) => $case->value, array: $this->argumentType::cases(), ); diff --git a/packages/console/src/Exceptions/UnknownArgumentsException.php b/packages/console/src/Exceptions/UnknownArgumentsException.php index 1d2beb269a..03f0a710a0 100644 --- a/packages/console/src/Exceptions/UnknownArgumentsException.php +++ b/packages/console/src/Exceptions/UnknownArgumentsException.php @@ -20,7 +20,7 @@ public function render(Console $console): void $console->error(sprintf( 'Unknown arguments: %s', $this->invalidArguments - ->map(fn (ConsoleInputArgument $argument) => sprintf( + ->map(static fn (ConsoleInputArgument $argument) => sprintf( '%s', $argument->name, )) diff --git a/packages/console/src/Highlight/TempestConsoleLanguage/Injections/DynamicInjection.php b/packages/console/src/Highlight/TempestConsoleLanguage/Injections/DynamicInjection.php index 66ed85f539..ccf90606e0 100644 --- a/packages/console/src/Highlight/TempestConsoleLanguage/Injections/DynamicInjection.php +++ b/packages/console/src/Highlight/TempestConsoleLanguage/Injections/DynamicInjection.php @@ -20,7 +20,7 @@ public function parse(string $content, Highlighter $highlighter): ParsedInjectio do { $content = preg_replace_callback( pattern: $pattern, - callback: function ($matches) use ($highlighter) { + callback: static function ($matches) use ($highlighter) { $theme = $highlighter->getTheme(); $quote = $matches['quote']; $match = $matches['match']; diff --git a/packages/console/src/Highlight/TempestConsoleLanguage/Injections/FileInjection.php b/packages/console/src/Highlight/TempestConsoleLanguage/Injections/FileInjection.php index fc0868ddf2..cd65abcac3 100644 --- a/packages/console/src/Highlight/TempestConsoleLanguage/Injections/FileInjection.php +++ b/packages/console/src/Highlight/TempestConsoleLanguage/Injections/FileInjection.php @@ -19,7 +19,7 @@ public function parse(string $content, Highlighter $highlighter): ParsedInjectio { return new ParsedInjection(preg_replace_callback( pattern: '/(?\[\"\'])(?.+)\k\s*\/?>)/', - callback: function (array $matches) { + callback: static function (array $matches) { $href = $matches['file']; $exists = Filesystem\normalize_path($href) !== null; $file = $exists diff --git a/packages/console/src/Highlight/TempestConsoleLanguage/Injections/LinkInjection.php b/packages/console/src/Highlight/TempestConsoleLanguage/Injections/LinkInjection.php index 79b068e046..1324b1e03a 100644 --- a/packages/console/src/Highlight/TempestConsoleLanguage/Injections/LinkInjection.php +++ b/packages/console/src/Highlight/TempestConsoleLanguage/Injections/LinkInjection.php @@ -16,7 +16,7 @@ public function parse(string $content, Highlighter $highlighter): ParsedInjectio { return new ParsedInjection(preg_replace_callback( pattern: '/(?\[\"\'])(?.+)\k\>(?:(?!\)/', - callback: function (array $matches) { + callback: static function (array $matches) { $quote = $matches['quote']; $match = $matches['match']; $href = $matches['href']; diff --git a/packages/console/src/Highlight/TempestTerminalTheme.php b/packages/console/src/Highlight/TempestTerminalTheme.php index 1d8c4666e8..a4ae825776 100644 --- a/packages/console/src/Highlight/TempestTerminalTheme.php +++ b/packages/console/src/Highlight/TempestTerminalTheme.php @@ -55,7 +55,7 @@ private function style(TerminalStyle ...$styles): string return implode( '', array_map( - fn (TerminalStyle $style) => TerminalStyle::ESC->value . $style->value, + static fn (TerminalStyle $style) => TerminalStyle::ESC->value . $style->value, $styles, ), ); diff --git a/packages/console/src/Initializers/ConsoleApplicationInitializer.php b/packages/console/src/Initializers/ConsoleApplicationInitializer.php index 6fd620ee53..caa6367e83 100644 --- a/packages/console/src/Initializers/ConsoleApplicationInitializer.php +++ b/packages/console/src/Initializers/ConsoleApplicationInitializer.php @@ -21,7 +21,7 @@ public function initialize(Container $container): ConsoleApplication argumentBag: $container->get(ConsoleArgumentBag::class), ); - $container->singleton(Application::class, fn () => $application); + $container->singleton(Application::class, static fn () => $application); return $application; } diff --git a/packages/console/src/Input/MemoryInputBuffer.php b/packages/console/src/Input/MemoryInputBuffer.php index 0600eb26f8..aa82a7937d 100644 --- a/packages/console/src/Input/MemoryInputBuffer.php +++ b/packages/console/src/Input/MemoryInputBuffer.php @@ -35,7 +35,7 @@ public function add(int|string|Key ...$input): void implode( separator: ', ', array: array_map( - callback: fn (int|string|Key $i) => is_string($i) + callback: static fn (int|string|Key $i) => is_string($i) ? rtrim($i) : $i->value, array: $input, diff --git a/packages/console/src/Installers/ConsoleInstaller.php b/packages/console/src/Installers/ConsoleInstaller.php index f6c4996bb9..8efd37f9f4 100644 --- a/packages/console/src/Installers/ConsoleInstaller.php +++ b/packages/console/src/Installers/ConsoleInstaller.php @@ -21,7 +21,7 @@ public function install(): void $tempest = $this->publish( source: __DIR__ . '/tempest', destination: root_path('tempest'), - callback: function (string $_, string $destination): void { + callback: static function (string $_, string $destination): void { if (PHP_OS_FAMILY !== 'Windows') { /** @phpstan-ignore-next-line */ exec("chmod +x {$destination}"); diff --git a/packages/console/src/Middleware/HelpMiddleware.php b/packages/console/src/Middleware/HelpMiddleware.php index f58ce97c85..3d68b72dcb 100644 --- a/packages/console/src/Middleware/HelpMiddleware.php +++ b/packages/console/src/Middleware/HelpMiddleware.php @@ -55,9 +55,9 @@ private function renderHelp(ConsoleCommand $consoleCommand): void $this->console ->writeln() ->write("{$argumentDefinition->name}") - ->when($argumentDefinition->aliases !== [], fn (Console $console) => $console->write(' (' . implode(', ', $argumentDefinition->aliases) . ')')) - ->when($argumentDefinition->description, fn (Console $console) => $console->writeln()->writeln($argumentDefinition->description)) - ->when($argumentDefinition->help, fn (Console $console) => $console->writeln()->writeln('' . $argumentDefinition->help . '')); + ->when($argumentDefinition->aliases !== [], static fn (Console $console) => $console->write(' (' . implode(', ', $argumentDefinition->aliases) . ')')) + ->when($argumentDefinition->description, static fn (Console $console) => $console->writeln()->writeln($argumentDefinition->description)) + ->when($argumentDefinition->help, static fn (Console $console) => $console->writeln()->writeln('' . $argumentDefinition->help . '')); } $this->console->writeln(); diff --git a/packages/console/src/Middleware/OverviewMiddleware.php b/packages/console/src/Middleware/OverviewMiddleware.php index ff63724233..699858f0aa 100644 --- a/packages/console/src/Middleware/OverviewMiddleware.php +++ b/packages/console/src/Middleware/OverviewMiddleware.php @@ -73,8 +73,8 @@ private function renderOverview(bool $showHidden = false): void $longestCommandName = max( arr($commands) - ->flatMap(fn (array $group) => $group) - ->map(fn (ConsoleCommand $command) => mb_strlen($command->getName())) + ->flatMap(static fn (array $group) => $group) + ->map(static fn (ConsoleCommand $command) => mb_strlen($command->getName())) ->toArray(), ) + 4; @@ -96,7 +96,7 @@ private function renderOverview(bool $showHidden = false): void $this->console ->unless( condition: $this->discoveryCache->valid, - callback: fn (Console $console) => $console->writeln()->error('Discovery cache invalid. Run discovery:generate to enable discovery caching.'), + callback: static fn (Console $console) => $console->writeln()->error('Discovery cache invalid. Run discovery:generate to enable discovery caching.'), ); } } diff --git a/packages/console/src/Middleware/ResolveOrRescueMiddleware.php b/packages/console/src/Middleware/ResolveOrRescueMiddleware.php index fb54cca4f8..48b209be88 100644 --- a/packages/console/src/Middleware/ResolveOrRescueMiddleware.php +++ b/packages/console/src/Middleware/ResolveOrRescueMiddleware.php @@ -92,7 +92,7 @@ private function getSimilarCommands(ImmutableString $search): ImmutableArray $searchParts = $search->explode(':'); // `dis:st` will match `discovery:status` - if ($searchParts->count() === $currentParts->count() && $searchParts->every(fn (string $part, int $index) => str_starts_with($currentParts[$index], $part))) { + if ($searchParts->count() === $currentParts->count() && $searchParts->every(static fn (string $part, int $index) => str_starts_with($currentParts[$index], $part))) { $suggestions[$currentName->toString()] = $currentName; continue; } @@ -148,8 +148,8 @@ private function getSimilarCommands(ImmutableString $search): ImmutableArray } return $sorted - ->sortByCallback(fn (array $a, array $b) => $a['levenshtein'] <=> $b['levenshtein']) - ->map(fn (array $item) => $item['suggestion']); + ->sortByCallback(static fn (array $a, array $b) => $a['levenshtein'] <=> $b['levenshtein']) + ->map(static fn (array $item) => $item['suggestion']); } private function runIntendedCommand(Stringable $commandName): ExitCode|int diff --git a/packages/console/src/Middleware/ValidateNamedArgumentsMiddleware.php b/packages/console/src/Middleware/ValidateNamedArgumentsMiddleware.php index 0758315a48..8851f3b673 100644 --- a/packages/console/src/Middleware/ValidateNamedArgumentsMiddleware.php +++ b/packages/console/src/Middleware/ValidateNamedArgumentsMiddleware.php @@ -24,13 +24,13 @@ public function __invoke(Invocation $invocation, ConsoleMiddlewareCallable $next } $allowedParameterNames = arr($invocation->consoleCommand->getArgumentDefinitions()) - ->flatMap(fn (ConsoleArgumentDefinition $definition) => [$definition->name, ...$definition->aliases]) - ->map(fn (string $name) => ltrim($name, '-')); + ->flatMap(static fn (ConsoleArgumentDefinition $definition) => [$definition->name, ...$definition->aliases]) + ->map(static fn (string $name) => ltrim($name, '-')); $invalidInput = arr($invocation->argumentBag->arguments) - ->filter(fn (ConsoleInputArgument $argument) => $argument->name !== null) - ->filter(fn (ConsoleInputArgument $argument) => ! $allowedParameterNames->hasValue(ltrim($argument->name, '-'))) - ->filter(fn (ConsoleInputArgument $argument) => ! in_array($argument->name, GlobalFlags::values(), strict: true)); + ->filter(static fn (ConsoleInputArgument $argument) => $argument->name !== null) + ->filter(static fn (ConsoleInputArgument $argument) => ! $allowedParameterNames->hasValue(ltrim($argument->name, '-'))) + ->filter(static fn (ConsoleInputArgument $argument) => ! in_array($argument->name, GlobalFlags::values(), strict: true)); if ($invalidInput->isNotEmpty()) { throw new UnknownArgumentsException( diff --git a/packages/console/src/Output/MemoryOutputBuffer.php b/packages/console/src/Output/MemoryOutputBuffer.php index d7d1824974..a92a977677 100644 --- a/packages/console/src/Output/MemoryOutputBuffer.php +++ b/packages/console/src/Output/MemoryOutputBuffer.php @@ -25,7 +25,7 @@ public function getBufferWithFormatting(): array public function getBufferWithoutFormatting(): array { return array_map( - fn (string $line) => preg_replace('/\x1b\[[0-9;]*m/', '', $line), + static fn (string $line) => preg_replace('/\x1b\[[0-9;]*m/', '', $line), $this->buffer, ); } diff --git a/packages/console/src/Output/TailReader.php b/packages/console/src/Output/TailReader.php index b4024fa684..c122046f46 100644 --- a/packages/console/src/Output/TailReader.php +++ b/packages/console/src/Output/TailReader.php @@ -11,7 +11,7 @@ { public function tail(string $path, ?Closure $format = null): void { - $format ??= fn (string $text) => $text; + $format ??= static fn (string $text) => $text; $handle = fopen($path, 'r'); diff --git a/packages/console/src/Scheduler/GenericScheduler.php b/packages/console/src/Scheduler/GenericScheduler.php index b98c1bec84..fea67c26bd 100644 --- a/packages/console/src/Scheduler/GenericScheduler.php +++ b/packages/console/src/Scheduler/GenericScheduler.php @@ -66,7 +66,7 @@ private function getInvocationsToRun(DateTime $date): array $eligibleToRun = array_filter( $this->config->scheduledInvocations, - fn (ScheduledInvocation $invocation) => $invocation->canRunAt( + static fn (ScheduledInvocation $invocation) => $invocation->canRunAt( date: $date, lastRunTimestamp: $previousRuns[$invocation->handler->getName()] ?? null, ), diff --git a/packages/console/src/Stubs/GeneratorCommandStub.php b/packages/console/src/Stubs/GeneratorCommandStub.php index 246fff407c..a608f82ee4 100644 --- a/packages/console/src/Stubs/GeneratorCommandStub.php +++ b/packages/console/src/Stubs/GeneratorCommandStub.php @@ -30,7 +30,7 @@ public function __invoke( targetPath: $targetPath, shouldOverride: $shouldOverride, manipulations: [ - fn (ClassManipulator $class) => $class->removeClassAttribute(SkipDiscovery::class), + static fn (ClassManipulator $class) => $class->removeClassAttribute(SkipDiscovery::class), ], ); diff --git a/packages/console/src/Terminal/Terminal.php b/packages/console/src/Terminal/Terminal.php index 35a4cf1b6a..890775b571 100644 --- a/packages/console/src/Terminal/Terminal.php +++ b/packages/console/src/Terminal/Terminal.php @@ -96,7 +96,7 @@ public function render(InteractiveConsoleComponent $component, array $validation ->render($this); if (! $rendered instanceof Generator) { - $rendered = (function (string $content): Generator { + $rendered = (static function (string $content): Generator { yield $content; return null; @@ -108,7 +108,7 @@ public function render(InteractiveConsoleComponent $component, array $validation if (! $component->getState()->isFinished() && $validationErrors) { $content .= PHP_EOL . arr($validationErrors) - ->map(fn (string $error) => " {$error}") + ->map(static fn (string $error) => " {$error}") ->implode(PHP_EOL) ->append(PHP_EOL) ->toString(); diff --git a/packages/console/src/Testing/ConsoleTester.php b/packages/console/src/Testing/ConsoleTester.php index a33541c9dd..b7ccd6b1b4 100644 --- a/packages/console/src/Testing/ConsoleTester.php +++ b/packages/console/src/Testing/ConsoleTester.php @@ -78,7 +78,7 @@ public function call(string|Closure|array $command, string|array $arguments = [] $clone->input = $memoryInputBuffer; if ($command instanceof Closure) { - $fiber = new Fiber(function () use ($clone, $command, $console): void { + $fiber = new Fiber(static function () use ($clone, $command, $console): void { $clone->exitCode = $command($console) ?? ExitCode::SUCCESS; }); } else { @@ -107,7 +107,7 @@ public function complete(?string $command = null): self $input = explode(' ', $command); $inputString = implode(' ', array_map( - fn (string $item) => "--input=\"{$item}\"", + static fn (string $item) => "--input=\"{$item}\"", $input, )); } else { diff --git a/packages/container/src/Commands/MakeInitializerCommand.php b/packages/container/src/Commands/MakeInitializerCommand.php index bc86fd0d70..89d878dc65 100644 --- a/packages/container/src/Commands/MakeInitializerCommand.php +++ b/packages/container/src/Commands/MakeInitializerCommand.php @@ -38,7 +38,7 @@ public function __invoke( targetPath: $targetPath, shouldOverride: $shouldOverride, manipulations: [ - function (ClassManipulator $stubClass) use ($isSingleton) { + static function (ClassManipulator $stubClass) use ($isSingleton) { $stubClass->removeClassAttribute(SkipDiscovery::class); if ($isSingleton) { diff --git a/packages/container/src/Exceptions/CircularDependencyEncountered.php b/packages/container/src/Exceptions/CircularDependencyEncountered.php index 36c75e5dc5..b162b0c14a 100644 --- a/packages/container/src/Exceptions/CircularDependencyEncountered.php +++ b/packages/container/src/Exceptions/CircularDependencyEncountered.php @@ -35,7 +35,7 @@ public function __construct(DependencyChain $chain, Dependency $circularDependen $selectionLine = preg_replace_callback( pattern: '/(?(.*))(?' . $circularDependency->getTypeName() . '\s\$\w+)(.*)/', - callback: fn ($matches) => '└' . str_repeat('─', strlen($matches['prefix']) + 3) . str_repeat('▒', strlen($matches['selection'])), + callback: static fn ($matches) => '└' . str_repeat('─', strlen($matches['prefix']) + 3) . str_repeat('▒', strlen($matches['selection'])), subject: $chain->last()->getShortName(), ); diff --git a/packages/container/src/Exceptions/DependencyCouldNotBeAutowired.php b/packages/container/src/Exceptions/DependencyCouldNotBeAutowired.php index da50c70203..9ebf324dc3 100644 --- a/packages/container/src/Exceptions/DependencyCouldNotBeAutowired.php +++ b/packages/container/src/Exceptions/DependencyCouldNotBeAutowired.php @@ -34,7 +34,7 @@ public function __construct(DependencyChain $chain, Dependency $brokenDependency $selectionLine = preg_replace_callback( pattern: '/(?(.*))(?' . $brokenDependency->getTypeName() . '\s\$\w+)(.*)/', - callback: fn ($matches) => str_repeat(' ', strlen($matches['prefix']) + 4) . str_repeat('▒', strlen($matches['selection'])), + callback: static fn ($matches) => str_repeat(' ', strlen($matches['prefix']) + 4) . str_repeat('▒', strlen($matches['selection'])), subject: $chain->last()->getShortName(), ); diff --git a/packages/container/src/Exceptions/TaggedDependencyCouldNotBeResolved.php b/packages/container/src/Exceptions/TaggedDependencyCouldNotBeResolved.php index 62a6b336ca..1791a66137 100644 --- a/packages/container/src/Exceptions/TaggedDependencyCouldNotBeResolved.php +++ b/packages/container/src/Exceptions/TaggedDependencyCouldNotBeResolved.php @@ -47,7 +47,7 @@ public function __construct(DependencyChain $chain, Dependency $brokenDependency $selectionLine = preg_replace_callback( pattern: '/(?(.*))(?' . $brokenDependency->getTypeName() . '\s\$\w+)(.*)/', - callback: fn ($matches) => str_repeat(' ', strlen($matches['prefix']) + 4) . str_repeat('▒', strlen($matches['selection'])), + callback: static fn ($matches) => str_repeat(' ', strlen($matches['prefix']) + 4) . str_repeat('▒', strlen($matches['selection'])), subject: $chain->last()->getShortName(), ); diff --git a/packages/core/src/Commands/InstallCommand.php b/packages/core/src/Commands/InstallCommand.php index 18793273a4..bb06c11296 100644 --- a/packages/core/src/Commands/InstallCommand.php +++ b/packages/core/src/Commands/InstallCommand.php @@ -69,7 +69,7 @@ private function resolveInstaller(?string $search): ?InstallerDefinition question: 'Choose an installer', options: Arr\map_with_keys( array: $this->installerConfig->installers, - map: fn (InstallerDefinition $installer) => yield $installer->id => $installer->name, + map: static fn (InstallerDefinition $installer) => yield $installer->id => $installer->name, ), ); @@ -79,7 +79,7 @@ private function resolveInstaller(?string $search): ?InstallerDefinition return Arr\first( array: $this->installerConfig->installers, - filter: fn (InstallerDefinition $installer) => in_array($search, $installer->aliases, strict: true) || $installer->id === $search, + filter: static fn (InstallerDefinition $installer) => in_array($search, $installer->aliases, strict: true) || $installer->id === $search, ); } @@ -100,7 +100,7 @@ private function resolveInstallerArguments(InstallerDefinition $installer): ?arr if (! $this->console->supportsPrompting()) { $missingArguments = implode(', ', array_map( - callback: fn (ConsoleArgumentDefinition $argumentDefinition) => $argumentDefinition->name, + callback: static fn (ConsoleArgumentDefinition $argumentDefinition) => $argumentDefinition->name, array: $invalidArguments, )); @@ -119,7 +119,7 @@ private function resolveInstallerArguments(InstallerDefinition $installer): ?arr } return array_map( - callback: fn (ConsoleInputArgument $argument) => $argument->value, + callback: static fn (ConsoleInputArgument $argument) => $argument->value, array: $validArguments, ); } diff --git a/packages/core/src/EnvironmentValueWasInvalid.php b/packages/core/src/EnvironmentValueWasInvalid.php index 77fd56a13e..fd12a4a0f1 100644 --- a/packages/core/src/EnvironmentValueWasInvalid.php +++ b/packages/core/src/EnvironmentValueWasInvalid.php @@ -13,7 +13,7 @@ final class EnvironmentValueWasInvalid extends Exception public function __construct(string $value) { $possibleValues = arr(Environment::cases()) - ->map(fn (Environment $environment) => $environment->value) + ->map(static fn (Environment $environment) => $environment->value) ->join(); parent::__construct("Invalid environment [{$value}]. Possible values are {$possibleValues}."); diff --git a/packages/core/src/EnvironmentVariableValidationFailed.php b/packages/core/src/EnvironmentVariableValidationFailed.php index 696278f1b1..634b96e785 100644 --- a/packages/core/src/EnvironmentVariableValidationFailed.php +++ b/packages/core/src/EnvironmentVariableValidationFailed.php @@ -22,7 +22,7 @@ public function __construct( parent::__construct(vsprintf("Environment variable [%s] is not valid:\n- %s", [ $name, arr($failingRules) - ->map(fn (FailingRule $failingRule) => $validator->getErrorMessage($failingRule, $name)) + ->map(static fn (FailingRule $failingRule) => $validator->getErrorMessage($failingRule, $name)) ->implode("\n- ") ->toString(), ])); diff --git a/packages/core/src/Exceptions/ExceptionTester.php b/packages/core/src/Exceptions/ExceptionTester.php index a8e72ad894..bcae21a718 100644 --- a/packages/core/src/Exceptions/ExceptionTester.php +++ b/packages/core/src/Exceptions/ExceptionTester.php @@ -87,7 +87,7 @@ public function assertNothingProcessed(): self private function findRecordedProcessings(string|object $exception): array { - return array_filter($this->processor->processed, function (string|object $reported) use ($exception) { + return array_filter($this->processor->processed, static function (string|object $reported) use ($exception) { if ($reported === $exception) { return true; } diff --git a/packages/core/src/FrameworkKernel.php b/packages/core/src/FrameworkKernel.php index 9f43adb6e2..58238732c6 100644 --- a/packages/core/src/FrameworkKernel.php +++ b/packages/core/src/FrameworkKernel.php @@ -159,7 +159,7 @@ public function registerShutdownFunction(): self // Fix for classes that don't have a proper PSR-4 namespace, // they break discovery with an unrecoverable error, // but you don't know why because PHP simply says "duplicate classname" instead of something reasonable. - register_shutdown_function(function (): void { + register_shutdown_function(static function (): void { $error = error_get_last(); $message = $error['message'] ?? ''; diff --git a/packages/core/src/IsComponentInstaller.php b/packages/core/src/IsComponentInstaller.php index d049b346ad..323baed73b 100644 --- a/packages/core/src/IsComponentInstaller.php +++ b/packages/core/src/IsComponentInstaller.php @@ -28,7 +28,7 @@ private function installMainNamespace(): void ->replaceStart(root_path(), '') ->trim('/') ->explode('/') - ->map(fn (string $part) => ucfirst($part)) + ->map(static fn (string $part) => ucfirst($part)) ->implode('\\') ->append('\\') ->toString(); diff --git a/packages/core/src/Kernel/LoadConfig.php b/packages/core/src/Kernel/LoadConfig.php index 934aa31a65..5e5e480592 100644 --- a/packages/core/src/Kernel/LoadConfig.php +++ b/packages/core/src/Kernel/LoadConfig.php @@ -67,8 +67,8 @@ public function find(): array $this->environment->isStaging() => ! Str\contains($path, [...$suffixes['testing'], ...$suffixes['development'], ...$suffixes['production']]), default => true, }) - ->sortByCallback(function (string $path1, string $path2) use ($suffixes): int { - $getPriority = fn (string $path): int => match (true) { + ->sortByCallback(static function (string $path1, string $path2) use ($suffixes): int { + $getPriority = static fn (string $path): int => match (true) { Str\contains($path, '/vendor/') => 0, ! Str\contains($path, root_path()) => 0, Str\contains($path, $suffixes['testing']) => 6, diff --git a/packages/core/src/Middleware.php b/packages/core/src/Middleware.php index d805b36119..12e8c5c587 100644 --- a/packages/core/src/Middleware.php +++ b/packages/core/src/Middleware.php @@ -65,7 +65,7 @@ public function unwrap(): Generator /** @return self */ private function sort(): self { - uasort($this->middlewareClasses, function (ClassReflector $a, ClassReflector $b): int { + uasort($this->middlewareClasses, static function (ClassReflector $a, ClassReflector $b): int { $priorityA = $a->getAttribute(Priority::class)->priority ?? Priority::NORMAL; $priorityB = $b->getAttribute(Priority::class)->priority ?? Priority::NORMAL; @@ -79,7 +79,7 @@ public function __serialize(): array { return [ 'middlewareClasses' => arr($this->middlewareClasses) - ->map(fn (ClassReflector $class) => $class->getName()) + ->map(static fn (ClassReflector $class) => $class->getName()) ->toArray(), ]; } @@ -87,7 +87,7 @@ public function __serialize(): array public function __unserialize(array $data): void { $this->middlewareClasses = arr($data['middlewareClasses']) - ->map(fn (string $className) => new ClassReflector($className)) + ->map(static fn (string $className) => new ClassReflector($className)) ->toArray(); } } diff --git a/packages/core/src/PublishesFiles.php b/packages/core/src/PublishesFiles.php index 8518ddc4fe..fbd6c79b46 100644 --- a/packages/core/src/PublishesFiles.php +++ b/packages/core/src/PublishesFiles.php @@ -89,7 +89,7 @@ public function publish(string $source, string $destination, ?Closure $callback targetPath: $destination, shouldOverride: true, manipulations: [ - fn (ClassManipulator $class) => $class->removeClassAttribute(SkipDiscovery::class), + static fn (ClassManipulator $class) => $class->removeClassAttribute(SkipDiscovery::class), ], ); @@ -264,7 +264,7 @@ function (string $content) use ($callback) { $content = preg_replace_callback( '/^ +/m', - fn ($m) => str_repeat($indent, strlen($m[0]) / 4), + static fn ($m) => str_repeat($indent, strlen($m[0]) / 4), Json\encode($json, pretty: true), ); diff --git a/packages/database/src/Builder/ModelInspector.php b/packages/database/src/Builder/ModelInspector.php index c3f8e86902..c1525a4330 100644 --- a/packages/database/src/Builder/ModelInspector.php +++ b/packages/database/src/Builder/ModelInspector.php @@ -751,7 +751,7 @@ private function resolvePrimaryKeyProperty(): ?PropertyReflector } $primaryKeys = arr($this->reflector->getProperties()) - ->filter(fn (PropertyReflector $property) => $property->getType()->matches(PrimaryKey::class)); + ->filter(static fn (PropertyReflector $property) => $property->getType()->matches(PrimaryKey::class)); return match ($primaryKeys->count()) { 0 => null, diff --git a/packages/database/src/Builder/QueryBuilders/CountQueryBuilder.php b/packages/database/src/Builder/QueryBuilders/CountQueryBuilder.php index d665ec45e1..7b85dc893b 100644 --- a/packages/database/src/Builder/QueryBuilders/CountQueryBuilder.php +++ b/packages/database/src/Builder/QueryBuilders/CountQueryBuilder.php @@ -144,7 +144,7 @@ public function build(mixed ...$bindings): Query { if ($this->joins !== []) { $this->count->joins = arr($this->joins) - ->map(fn (JoinStatement|string $join) => $join instanceof JoinStatement ? $join : new JoinStatement($join)); + ->map(static fn (JoinStatement|string $join) => $join instanceof JoinStatement ? $join : new JoinStatement($join)); } return new Query($this->count, [...$this->bindings, ...$bindings])->onDatabase($this->onDatabase); diff --git a/packages/database/src/Builder/QueryBuilders/HasConvenientWhereMethods.php b/packages/database/src/Builder/QueryBuilders/HasConvenientWhereMethods.php index a6927bef04..fdfdd9f8f3 100644 --- a/packages/database/src/Builder/QueryBuilders/HasConvenientWhereMethods.php +++ b/packages/database/src/Builder/QueryBuilders/HasConvenientWhereMethods.php @@ -46,7 +46,7 @@ protected function buildCondition(string $fieldDefinition, WhereOperator $operat throw new InvalidArgumentException("{$operator->value} operator requires an array of values"); } - $value = array_map(fn (mixed $value) => match (true) { + $value = array_map(static fn (mixed $value) => match (true) { $value instanceof BackedEnum => $value->value, $value instanceof UnitEnum => $value->name, $value instanceof ArrayAccess => (array) $value, @@ -66,7 +66,7 @@ protected function buildCondition(string $fieldDefinition, WhereOperator $operat $sql .= " {$operator->value} ? AND ?"; $bindings = array_map( - fn (DateTimeInterface|string|float|int|Countable $value) => match (true) { + static fn (DateTimeInterface|string|float|int|Countable $value) => match (true) { $value instanceof Countable => count($value), default => $value, }, @@ -101,7 +101,7 @@ private function looksLikeWhereRawStatement(string $statement, array $bindings): return false; } - return Str\contains($statement, [' ', ...array_map(fn (WhereOperator $op) => $op->value, WhereOperator::cases())]); + return Str\contains($statement, [' ', ...array_map(static fn (WhereOperator $op) => $op->value, WhereOperator::cases())]); } /** diff --git a/packages/database/src/Builder/QueryBuilders/SelectQueryBuilder.php b/packages/database/src/Builder/QueryBuilders/SelectQueryBuilder.php index 496da87eb8..fdd6fb39cc 100644 --- a/packages/database/src/Builder/QueryBuilders/SelectQueryBuilder.php +++ b/packages/database/src/Builder/QueryBuilders/SelectQueryBuilder.php @@ -539,15 +539,15 @@ public function getResolvedRelations(): array private function shouldUsePropertyNameAlias(array $relations): array { $rootTables = arr(input: $relations) - ->filter(filter: fn (Relation $_, string $path) => ! str_contains(haystack: $path, needle: '.')) - ->map(map: fn (Relation $relation) => inspect(model: $relation)->getTableName()) + ->filter(filter: static fn (Relation $_, string $path) => ! str_contains(haystack: $path, needle: '.')) + ->map(map: static fn (Relation $relation) => inspect(model: $relation)->getTableName()) ->toArray(); $counts = array_count_values(array: $rootTables); arr(input: $rootTables) - ->filter(filter: fn (string $table) => $counts[$table] > 1) - ->each(each: fn (string $_, string $path) => $relations[$path]->withPropertyNameAlias()); + ->filter(filter: static fn (string $table) => $counts[$table] > 1) + ->each(each: static fn (string $_, string $path) => $relations[$path]->withPropertyNameAlias()); return $relations; } diff --git a/packages/database/src/Commands/MakeMigrationCommand.php b/packages/database/src/Commands/MakeMigrationCommand.php index 8a7cfa19d7..c12b2f5bbc 100644 --- a/packages/database/src/Commands/MakeMigrationCommand.php +++ b/packages/database/src/Commands/MakeMigrationCommand.php @@ -177,7 +177,7 @@ private function generateClassFile(string $name, StubFile $stub, string $classNa $classFileName = str($className) ->when( condition: str($name)->contains(['\\', '/']), - callback: fn ($path) => $path->prepend(str($name)->beforeLast(['\\', '/'])->toString(), '/'), + callback: static fn ($path) => $path->prepend(str($name)->beforeLast(['\\', '/'])->toString(), '/'), ) ->toString(); diff --git a/packages/database/src/Exceptions/InsertColumnsMismatched.php b/packages/database/src/Exceptions/InsertColumnsMismatched.php index 121c463f94..4f5f00dfbc 100644 --- a/packages/database/src/Exceptions/InsertColumnsMismatched.php +++ b/packages/database/src/Exceptions/InsertColumnsMismatched.php @@ -11,8 +11,8 @@ public function __construct( ImmutableArray $expected, ImmutableArray $actual, ) { - $expected = $expected->map(fn ($column) => "`{$column}`")->join(); - $actual = $actual->map(fn ($column) => "`{$column}`")->join(); + $expected = $expected->map(static fn ($column) => "`{$column}`")->join(); + $actual = $actual->map(static fn ($column) => "`{$column}`")->join(); parent::__construct("Expected columns {$expected}; but got {$actual}"); } diff --git a/packages/database/src/IsDatabaseModel.php b/packages/database/src/IsDatabaseModel.php index bf00187a85..59fb82765f 100644 --- a/packages/database/src/IsDatabaseModel.php +++ b/packages/database/src/IsDatabaseModel.php @@ -252,7 +252,7 @@ public function refresh(): static $new = static::queryBuilder() ->onDatabase($this->onDatabase) ->select() - ->with(...$loadedRelations->map(fn (Relation $relation) => $relation->name)) + ->with(...$loadedRelations->map(static fn (Relation $relation) => $relation->name)) ->get($primaryKeyValue); foreach ($loadedRelations as $relation) { @@ -310,7 +310,7 @@ public function load(string ...$relations): static ->get($primaryKeyValue, $relations); $fieldsToUpdate = arr($relations) - ->map(fn (string $relation) => str($relation)->before('.')->toString()) + ->map(static fn (string $relation) => str($relation)->before('.')->toString()) ->unique(); foreach ($fieldsToUpdate as $fieldToUpdate) { diff --git a/packages/database/src/Mappers/SelectModelMapper.php b/packages/database/src/Mappers/SelectModelMapper.php index dcade8eae0..d24545ebae 100644 --- a/packages/database/src/Mappers/SelectModelMapper.php +++ b/packages/database/src/Mappers/SelectModelMapper.php @@ -38,7 +38,7 @@ public function map(mixed $from, mixed $to): array $idField = $model->getQualifiedPrimaryKey(); $parsed = arr($from) - ->groupBy(fn (array $data, int|string $i) => $idField !== null ? $data[$idField] ?? $i : $i) + ->groupBy(static fn (array $data, int|string $i) => $idField !== null ? $data[$idField] ?? $i : $i) ->map(fn (array $rows) => $this->normalizeFields($model, $rows)) ->values(); diff --git a/packages/database/src/QueryStatements/AlterTableStatement.php b/packages/database/src/QueryStatements/AlterTableStatement.php index 7250ee7542..c4ba51e6b0 100644 --- a/packages/database/src/QueryStatements/AlterTableStatement.php +++ b/packages/database/src/QueryStatements/AlterTableStatement.php @@ -93,8 +93,8 @@ public function compile(DatabaseDialect $dialect): string 'ALTER TABLE %s %s;', $dialect->quoteIdentifier($this->tableName), arr($this->statements) - ->map(fn (QueryStatement $queryStatement) => str($queryStatement->compile($dialect))->trim()->replace(' ', ' ')) - ->filter(fn (ImmutableString $line) => $line->isNotEmpty()) + ->map(static fn (QueryStatement $queryStatement) => str($queryStatement->compile($dialect))->trim()->replace(' ', ' ')) + ->filter(static fn (ImmutableString $line) => $line->isNotEmpty()) ->implode(', ' . PHP_EOL . ' ') ->wrap(before: PHP_EOL . ' ', after: PHP_EOL) ->toString(), diff --git a/packages/database/src/QueryStatements/CompoundStatement.php b/packages/database/src/QueryStatements/CompoundStatement.php index afb75d04f7..df088afab2 100644 --- a/packages/database/src/QueryStatements/CompoundStatement.php +++ b/packages/database/src/QueryStatements/CompoundStatement.php @@ -22,7 +22,7 @@ public function __construct(QueryStatement ...$statements) public function compile(DatabaseDialect $dialect): string { return arr($this->statements) - ->map(fn (QueryStatement $statement) => $statement->compile($dialect)) + ->map(static fn (QueryStatement $statement) => $statement->compile($dialect)) ->implode(';' . PHP_EOL) ->append(';') ->toString(); diff --git a/packages/database/src/QueryStatements/CountStatement.php b/packages/database/src/QueryStatements/CountStatement.php index b417561915..eb0ab31f41 100644 --- a/packages/database/src/QueryStatements/CountStatement.php +++ b/packages/database/src/QueryStatements/CountStatement.php @@ -44,8 +44,8 @@ public function compile(DatabaseDialect $dialect): string if ($this->where->isNotEmpty()) { $query[] = 'WHERE ' . $this->where - ->map(fn (QueryStatement $where) => $where->compile($dialect)) - ->filter(fn (string $compiled) => $compiled !== '') + ->map(static fn (QueryStatement $where) => $where->compile($dialect)) + ->filter(static fn (string $compiled) => $compiled !== '') ->implode(' '); } diff --git a/packages/database/src/QueryStatements/CreateEnumTypeStatement.php b/packages/database/src/QueryStatements/CreateEnumTypeStatement.php index 9640b4e8ee..40ae74ee22 100644 --- a/packages/database/src/QueryStatements/CreateEnumTypeStatement.php +++ b/packages/database/src/QueryStatements/CreateEnumTypeStatement.php @@ -22,9 +22,9 @@ public function __construct( public function compile(DatabaseDialect $dialect): string { $cases = arr($this->enumClass::cases()) - ->map(fn (UnitEnum|BackedEnum $case) => $case instanceof BackedEnum ? $case->value : $case->name) - ->map(fn (string $value) => str_replace('\\', '\\\\', $value)) - ->map(fn (string $value) => "'{$value}'"); + ->map(static fn (UnitEnum|BackedEnum $case) => $case instanceof BackedEnum ? $case->value : $case->name) + ->map(static fn (string $value) => str_replace('\\', '\\\\', $value)) + ->map(static fn (string $value) => "'{$value}'"); return match ($dialect) { DatabaseDialect::MYSQL, DatabaseDialect::SQLITE => '', diff --git a/packages/database/src/QueryStatements/CreateTableStatement.php b/packages/database/src/QueryStatements/CreateTableStatement.php index ab883e3646..6df94fd5ca 100644 --- a/packages/database/src/QueryStatements/CreateTableStatement.php +++ b/packages/database/src/QueryStatements/CreateTableStatement.php @@ -404,9 +404,9 @@ public function compile(DatabaseDialect $dialect): string $dialect->quoteIdentifier($this->tableName), arr($this->statements) // Remove BelongsTo for sqlLite as it does not support those queries - ->filter(fn (QueryStatement $queryStatement) => $dialect !== DatabaseDialect::SQLITE || ! $queryStatement instanceof BelongsToStatement) - ->map(fn (QueryStatement $queryStatement) => str($queryStatement->compile($dialect))->trim()->replace(' ', ' ')) - ->filter(fn (ImmutableString $str) => $str->isNotEmpty()) + ->filter(static fn (QueryStatement $queryStatement) => $dialect !== DatabaseDialect::SQLITE || ! $queryStatement instanceof BelongsToStatement) + ->map(static fn (QueryStatement $queryStatement) => str($queryStatement->compile($dialect))->trim()->replace(' ', ' ')) + ->filter(static fn (ImmutableString $str) => $str->isNotEmpty()) ->implode(', ' . PHP_EOL . ' ') ->wrap(before: PHP_EOL . ' ', after: PHP_EOL) ->toString(), diff --git a/packages/database/src/QueryStatements/DeleteStatement.php b/packages/database/src/QueryStatements/DeleteStatement.php index f7e88c2f30..fa0a4e94fc 100644 --- a/packages/database/src/QueryStatements/DeleteStatement.php +++ b/packages/database/src/QueryStatements/DeleteStatement.php @@ -30,8 +30,8 @@ public function compile(DatabaseDialect $dialect): string if ($this->where->isNotEmpty()) { $query[] = 'WHERE ' . $this->where - ->map(fn (QueryStatement $where) => $where->compile($dialect)) - ->filter(fn (string $compiled) => $compiled !== '') + ->map(static fn (QueryStatement $where) => $where->compile($dialect)) + ->filter(static fn (string $compiled) => $compiled !== '') ->implode(' '); } diff --git a/packages/database/src/QueryStatements/EnumStatement.php b/packages/database/src/QueryStatements/EnumStatement.php index 502b6d1177..f85c44b899 100644 --- a/packages/database/src/QueryStatements/EnumStatement.php +++ b/packages/database/src/QueryStatements/EnumStatement.php @@ -25,9 +25,9 @@ public function __construct( public function compile(DatabaseDialect $dialect): string { $cases = arr($this->enumClass::cases()) - ->map(fn (UnitEnum|BackedEnum $case) => $case instanceof BackedEnum ? $case->value : $case->name) - ->map(fn (string $value) => str_replace('\\', '\\\\', $value)) - ->map(fn (string $value) => "'{$value}'"); + ->map(static fn (UnitEnum|BackedEnum $case) => $case instanceof BackedEnum ? $case->value : $case->name) + ->map(static fn (string $value) => str_replace('\\', '\\\\', $value)) + ->map(static fn (string $value) => "'{$value}'"); if ($this->default instanceof UnitEnum) { $defaultValue = $this->default instanceof BackedEnum ? $this->default->value : $this->default->name; diff --git a/packages/database/src/QueryStatements/FieldStatement.php b/packages/database/src/QueryStatements/FieldStatement.php index 2ad2eac153..905942b8c0 100644 --- a/packages/database/src/QueryStatements/FieldStatement.php +++ b/packages/database/src/QueryStatements/FieldStatement.php @@ -38,9 +38,9 @@ public function compile(DatabaseDialect $dialect): string } $field = arr(explode('.', $field)) - ->map(fn (string $part) => trim($part, '`" ')) + ->map(static fn (string $part) => trim($part, '`" ')) ->map( - function (string $part) use ($dialect) { + static function (string $part) use ($dialect) { if (str_contains($part, '(')) { return $part; } diff --git a/packages/database/src/QueryStatements/InsertStatement.php b/packages/database/src/QueryStatements/InsertStatement.php index 899d1be628..7ae5fc70c6 100644 --- a/packages/database/src/QueryStatements/InsertStatement.php +++ b/packages/database/src/QueryStatements/InsertStatement.php @@ -30,7 +30,7 @@ public function compile(DatabaseDialect $dialect): string $columns = arr($this->entries->first())->keys(); $entryPlaceholders = $this->entries - ->map(function (array|ImmutableArray $row) use ($columns) { + ->map(static function (array|ImmutableArray $row) use ($columns) { $row = arr($row); $rowColumns = $row->keys(); @@ -41,7 +41,7 @@ public function compile(DatabaseDialect $dialect): string return sprintf( '(%s)', - $row->map(fn () => '?')->implode(', '), + $row->map(static fn () => '?')->implode(', '), ); }) ->implode(', '); diff --git a/packages/database/src/QueryStatements/SelectStatement.php b/packages/database/src/QueryStatements/SelectStatement.php index 879cb23e91..28011985e2 100644 --- a/packages/database/src/QueryStatements/SelectStatement.php +++ b/packages/database/src/QueryStatements/SelectStatement.php @@ -71,32 +71,32 @@ public function compile(DatabaseDialect $dialect): string if ($this->join->isNotEmpty()) { $query[] = $this->join - ->map(fn (JoinStatement $join) => $join->compile($dialect)) + ->map(static fn (JoinStatement $join) => $join->compile($dialect)) ->implode(' '); } if ($this->where->isNotEmpty()) { $query[] = 'WHERE ' . $this->where - ->map(fn (WhereStatement|WhereGroupStatement|WhereExistsStatement $where) => $where->compile($dialect)) - ->filter(fn (string $compiled) => $compiled !== '') + ->map(static fn (WhereStatement|WhereGroupStatement|WhereExistsStatement $where) => $where->compile($dialect)) + ->filter(static fn (string $compiled) => $compiled !== '') ->implode(' '); } if ($this->groupBy->isNotEmpty()) { $query[] = 'GROUP BY ' . $this->groupBy - ->map(fn (GroupByStatement $groupBy) => $groupBy->compile($dialect)) + ->map(static fn (GroupByStatement $groupBy) => $groupBy->compile($dialect)) ->implode(', '); } if ($this->having->isNotEmpty()) { $query[] = 'HAVING ' . $this->having - ->map(fn (HavingStatement $having) => $having->compile($dialect)) + ->map(static fn (HavingStatement $having) => $having->compile($dialect)) ->implode(' '); } if ($this->orderBy->isNotEmpty()) { $query[] = 'ORDER BY ' . $this->orderBy - ->map(fn (OrderByStatement|RawStatement $orderBy) => $orderBy->compile($dialect)) + ->map(static fn (OrderByStatement|RawStatement $orderBy) => $orderBy->compile($dialect)) ->implode(', '); } @@ -110,7 +110,7 @@ public function compile(DatabaseDialect $dialect): string if ($this->raw->isNotEmpty()) { $query[] = $this->raw - ->map(fn (RawStatement $raw) => $raw->compile($dialect)) + ->map(static fn (RawStatement $raw) => $raw->compile($dialect)) ->implode(' ') ->toString(); } diff --git a/packages/database/src/QueryStatements/UpdateStatement.php b/packages/database/src/QueryStatements/UpdateStatement.php index 2fb69f094a..040ab7c5b2 100644 --- a/packages/database/src/QueryStatements/UpdateStatement.php +++ b/packages/database/src/QueryStatements/UpdateStatement.php @@ -35,13 +35,13 @@ public function compile(DatabaseDialect $dialect): string } $query[] = 'SET ' . $this->values - ->map(fn (mixed $_, mixed $key) => $dialect->quoteIdentifier($key) . ' = ?') + ->map(static fn (mixed $_, mixed $key) => $dialect->quoteIdentifier($key) . ' = ?') ->implode(', '); if ($this->where->isNotEmpty()) { $query[] = 'WHERE ' . $this->where - ->map(fn (WhereStatement|WhereGroupStatement|WhereExistsStatement $where) => $where->compile($dialect)) - ->filter(fn (string $compiled) => $compiled !== '') + ->map(static fn (WhereStatement|WhereGroupStatement|WhereExistsStatement $where) => $where->compile($dialect)) + ->filter(static fn (string $compiled) => $compiled !== '') ->implode(' '); } diff --git a/packages/database/src/QueryStatements/WhereExistsStatement.php b/packages/database/src/QueryStatements/WhereExistsStatement.php index f28d4224e0..e2ecdcf8a3 100644 --- a/packages/database/src/QueryStatements/WhereExistsStatement.php +++ b/packages/database/src/QueryStatements/WhereExistsStatement.php @@ -29,11 +29,11 @@ public function compile(DatabaseDialect $dialect): string if ($this->innerWheres->isNotEmpty()) { $compiled = $this->innerWheres - ->map(map: fn ( + ->map(map: static fn ( QueryStatement $where, ) => $where->compile(dialect: $dialect)) ->filter( - filter: fn ( + filter: static fn ( string $compiled, ) => $compiled !== '', ) diff --git a/packages/database/src/QueryStatements/WhereGroupStatement.php b/packages/database/src/QueryStatements/WhereGroupStatement.php index 2bdc2d95cc..3f1a2e5d54 100644 --- a/packages/database/src/QueryStatements/WhereGroupStatement.php +++ b/packages/database/src/QueryStatements/WhereGroupStatement.php @@ -22,8 +22,8 @@ public function compile(DatabaseDialect $dialect): string } $compiled = $this->conditions - ->map(fn (QueryStatement $condition) => $condition->compile($dialect)) - ->filter(fn (string $condition) => $condition !== ''); + ->map(static fn (QueryStatement $condition) => $condition->compile($dialect)) + ->filter(static fn (string $condition) => $condition !== ''); if ($compiled->isEmpty()) { return ''; diff --git a/packages/database/src/Serializers/DataTransferObjectSerializer.php b/packages/database/src/Serializers/DataTransferObjectSerializer.php index d03cb10ff9..cf5c90fb6c 100644 --- a/packages/database/src/Serializers/DataTransferObjectSerializer.php +++ b/packages/database/src/Serializers/DataTransferObjectSerializer.php @@ -93,7 +93,7 @@ private function extractObjectData(object $input): array return Arr\map_with_keys( array: new ClassReflector($input)->getPublicProperties(), - map: fn (PropertyReflector $property) => yield $property->getName() => $property->getValue($input), + map: static fn (PropertyReflector $property) => yield $property->getName() => $property->getValue($input), ); } } diff --git a/packages/debug/src/Debug.php b/packages/debug/src/Debug.php index 9fa7461ad9..039cfa84d1 100644 --- a/packages/debug/src/Debug.php +++ b/packages/debug/src/Debug.php @@ -131,7 +131,7 @@ private function createCliDump(mixed $input): string $cloner = new VarCloner(); $output = ''; - $dumper = new CliDumper(function ($line, $depth) use (&$output): void { + $dumper = new CliDumper(static function ($line, $depth) use (&$output): void { if ($depth < 0) { return; } diff --git a/packages/debug/src/Stacktrace/Frame.php b/packages/debug/src/Stacktrace/Frame.php index 8d86f24a1e..95974d02bb 100644 --- a/packages/debug/src/Stacktrace/Frame.php +++ b/packages/debug/src/Stacktrace/Frame.php @@ -72,7 +72,7 @@ public static function extractArguments(array $frame): array : new ReflectionFunction(function: $frame['function']); $parameterNames = array_map( - callback: fn (ReflectionParameter $param) => $param->getName(), + callback: static fn (ReflectionParameter $param) => $param->getName(), array: $reflection->getParameters(), ); } catch (Throwable) { diff --git a/packages/debug/src/Stacktrace/Stacktrace.php b/packages/debug/src/Stacktrace/Stacktrace.php index 16ad4cd002..f00e513694 100644 --- a/packages/debug/src/Stacktrace/Stacktrace.php +++ b/packages/debug/src/Stacktrace/Stacktrace.php @@ -14,7 +14,7 @@ final class Stacktrace public array $applicationFrames { get => array_values(array_filter( array: $this->frames, - callback: fn (Frame $frame) => ! $frame->isVendor, + callback: static fn (Frame $frame) => ! $frame->isVendor, )); } @@ -22,7 +22,7 @@ final class Stacktrace public array $vendorFrames { get => array_values(array_filter( array: $this->frames, - callback: fn (Frame $frame) => $frame->isVendor, + callback: static fn (Frame $frame) => $frame->isVendor, )); } @@ -103,7 +103,7 @@ function: $frame->function, index: 1, ), // and shift the frame index by one for each frame - ...array_map(fn (Frame $frame) => new Frame( + ...array_map(static fn (Frame $frame) => new Frame( line: $frame->line, class: $frame->class, function: $frame->function, diff --git a/packages/discovery/src/Commands/MakeDiscoveryCommand.php b/packages/discovery/src/Commands/MakeDiscoveryCommand.php index 48d5369220..dca58cf02c 100644 --- a/packages/discovery/src/Commands/MakeDiscoveryCommand.php +++ b/packages/discovery/src/Commands/MakeDiscoveryCommand.php @@ -35,7 +35,7 @@ public function __invoke( targetPath: $targetPath, shouldOverride: $shouldOverride, manipulations: [ - fn (ClassManipulator $class) => $class->removeClassAttribute(SkipDiscovery::class), + static fn (ClassManipulator $class) => $class->removeClassAttribute(SkipDiscovery::class), ], ); diff --git a/packages/discovery/src/Composer.php b/packages/discovery/src/Composer.php index 8b7598ddba..9c6b26a233 100644 --- a/packages/discovery/src/Composer.php +++ b/packages/discovery/src/Composer.php @@ -53,7 +53,7 @@ public function load(): self $this->namespaces = new ImmutableArray([$this->mainNamespace, ...$this->namespaces]) ->filter() - ->unique(fn (Psr4Namespace $ns) => "{$ns->namespace}:{$ns->path}") + ->unique(static fn (Psr4Namespace $ns) => "{$ns->namespace}:{$ns->path}") ->toArray(); $this->devNamespaces = $this->resolvePsr4Namespaces('autoload-dev.psr-4'); @@ -123,8 +123,8 @@ private function resolvePsr4Namespaces(string $path): array { return new ImmutableArray($this->composer) ->get($path, default: new ImmutableArray()) - ->flatMap(fn (string|iterable $paths, string $namespace) => Arr\map(Arr\wrap($paths), fn (string $path) => new Psr4Namespace($namespace, $path))) - ->sortByCallback(fn (Psr4Namespace $ns1, Psr4Namespace $ns2) => strlen($ns1->path) <=> strlen($ns2->path)) + ->flatMap(static fn (string|iterable $paths, string $namespace) => Arr\map(Arr\wrap($paths), static fn (string $path) => new Psr4Namespace($namespace, $path))) + ->sortByCallback(static fn (Psr4Namespace $ns1, Psr4Namespace $ns2) => strlen($ns1->path) <=> strlen($ns2->path)) ->values() ->toArray(); } diff --git a/packages/discovery/src/DiscoveryConfig.php b/packages/discovery/src/DiscoveryConfig.php index 86ec4b0f23..c3ac6c900e 100644 --- a/packages/discovery/src/DiscoveryConfig.php +++ b/packages/discovery/src/DiscoveryConfig.php @@ -33,7 +33,7 @@ public function shouldSkip(string $input): bool return true; } - return array_any($this->skipUsing, fn ($closure) => $closure($input) === true); + return array_any($this->skipUsing, static fn ($closure) => $closure($input) === true); } /** @param (Closure(string): bool) $closure */ diff --git a/packages/discovery/src/DiscoveryItems.php b/packages/discovery/src/DiscoveryItems.php index 8b5e1b30ca..4de868ec01 100644 --- a/packages/discovery/src/DiscoveryItems.php +++ b/packages/discovery/src/DiscoveryItems.php @@ -59,7 +59,7 @@ public function onlyVendor(): self { return new self( arr($this->items) - ->filter(fn (array $_, string $path) => str_contains($path, '/vendor/') || str_contains($path, '\\vendor\\')) + ->filter(static fn (array $_, string $path) => str_contains($path, '/vendor/') || str_contains($path, '\\vendor\\')) ->toArray(), ); } diff --git a/packages/discovery/src/DiscoveryLocation.php b/packages/discovery/src/DiscoveryLocation.php index e27e00aab4..367164aff6 100644 --- a/packages/discovery/src/DiscoveryLocation.php +++ b/packages/discovery/src/DiscoveryLocation.php @@ -40,7 +40,7 @@ public function isVendor(): bool public function isIgnored(string $path): bool { - return array_any($this->ignore, fn (string $ignore) => str_starts_with($path, $ignore)); + return array_any($this->ignore, static fn (string $ignore) => str_starts_with($path, $ignore)); } public function toClassName(string $path): string diff --git a/packages/event-bus/src/Testing/EventBusTester.php b/packages/event-bus/src/Testing/EventBusTester.php index 869f093545..b9dfb3611b 100644 --- a/packages/event-bus/src/Testing/EventBusTester.php +++ b/packages/event-bus/src/Testing/EventBusTester.php @@ -106,7 +106,7 @@ public function assertListeningTo(string $event, ?int $count = null): self private function findDispatches(string|object $event): array { - return array_filter($this->fakeEventBus->dispatched, function (string|object $dispatched) use ($event) { + return array_filter($this->fakeEventBus->dispatched, static function (string|object $dispatched) use ($event) { if ($dispatched === $event) { return true; } diff --git a/packages/generation/src/Php/SimplifiesClassNames.php b/packages/generation/src/Php/SimplifiesClassNames.php index 9843a89369..a0bab075d2 100644 --- a/packages/generation/src/Php/SimplifiesClassNames.php +++ b/packages/generation/src/Php/SimplifiesClassNames.php @@ -118,7 +118,7 @@ private function simplifyClassNames(PhpFile $file): PhpFile } array_map( - function ($param) use (&$types): void { + static function ($param) use (&$types): void { $types[] = $param->getType(true); }, $class->getProperties(), @@ -158,7 +158,7 @@ private function extractFqcnFromBody(string $body): array preg_match_all('/(?:\\\\?[A-Za-z_][\w\d_]*\\\\)+[A-Za-z_][\w\d_]*/', $body, $matches); return array_filter(array_unique( - array_map(fn (string $fqcn) => rtrim(ltrim($fqcn, '\\'), ':'), $matches[0]), + array_map(static fn (string $fqcn) => rtrim(ltrim($fqcn, '\\'), ':'), $matches[0]), )); } } diff --git a/packages/generation/src/Php/StubFileGenerator.php b/packages/generation/src/Php/StubFileGenerator.php index b2db010057..1e901a793e 100644 --- a/packages/generation/src/Php/StubFileGenerator.php +++ b/packages/generation/src/Php/StubFileGenerator.php @@ -64,13 +64,13 @@ public function generateClassFile( continue; } - $classManipulator->manipulate(fn (ImmutableString $code) => $code->replace($placeholder, $replacement)); + $classManipulator->manipulate(static fn (ImmutableString $code) => $code->replace($placeholder, $replacement)); } // Run all manipulations $classManipulator = array_reduce( array: $manipulations, - callback: fn (ClassManipulator $manipulator, Closure $manipulation) => $manipulation($manipulator), + callback: static fn (ClassManipulator $manipulator, Closure $manipulation) => $manipulation($manipulator), initial: $classManipulator, ); @@ -126,7 +126,7 @@ public function generateRawFile( // Run all manipulations $fileContent = array_reduce( array: $manipulations, - callback: fn (ImmutableString $content, Closure $manipulation) => $manipulation($content), + callback: static fn (ImmutableString $content, Closure $manipulation) => $manipulation($content), initial: $fileContent, ); diff --git a/packages/generation/src/TypeScript/TypeResolverDiscovery.php b/packages/generation/src/TypeScript/TypeResolverDiscovery.php index cdf2032006..bd63a246ac 100644 --- a/packages/generation/src/TypeScript/TypeResolverDiscovery.php +++ b/packages/generation/src/TypeScript/TypeResolverDiscovery.php @@ -33,8 +33,8 @@ public function discover(DiscoveryLocation $location, ClassReflector $class): vo public function apply(): void { $this->config->resolvers = arr([...$this->discoveryItems]) - ->sortByCallback(fn (array $a, array $b) => $a[1] <=> $b[1]) - ->map(fn (array $item) => $item[0]) + ->sortByCallback(static fn (array $a, array $b) => $a[1] <=> $b[1]) + ->map(static fn (array $item) => $item[0]) ->toArray(); } } diff --git a/packages/generation/src/TypeScript/Writers/DirectoryWriter.php b/packages/generation/src/TypeScript/Writers/DirectoryWriter.php index 619bf893b9..d5b1aca8c0 100644 --- a/packages/generation/src/TypeScript/Writers/DirectoryWriter.php +++ b/packages/generation/src/TypeScript/Writers/DirectoryWriter.php @@ -165,7 +165,7 @@ private function generateDefinition(TypeDefinition|InterfaceDefinition $definiti private function namespaceToFilePath(string $namespace): string { $parts = explode('\\', $namespace); - $kebabParts = Arr\map($parts, fn (string $part) => Str\to_kebab_case($part)); + $kebabParts = Arr\map($parts, static fn (string $part) => Str\to_kebab_case($part)); $path = (string) Arr\implode($kebabParts, glue: '/'); return $this->config->directory . '/' . $path . '/index.ts'; @@ -189,7 +189,7 @@ private function computeImportPath(string $sourceNamespace, string $targetNamesp $upLevels = count($sourceParts) - $commonLength; $targetDiff = array_slice($targetParts, $commonLength); - $targetKebab = Arr\map($targetDiff, fn (string $part) => Str\to_kebab_case($part)); + $targetKebab = Arr\map($targetDiff, static fn (string $part) => Str\to_kebab_case($part)); if ($upLevels === 0 && $targetKebab === []) { return './'; diff --git a/packages/http/src/Input/StdinInputStream.php b/packages/http/src/Input/StdinInputStream.php index 5a5a2871f7..64a0b15858 100644 --- a/packages/http/src/Input/StdinInputStream.php +++ b/packages/http/src/Input/StdinInputStream.php @@ -20,7 +20,7 @@ public function parse(): array $inputStreamData = str($input) ->explode('&') - ->mapWithKeys(function (string $item) { + ->mapWithKeys(static function (string $item) { $parts = explode('=', $item, 2); $key = urldecode($parts[0]); diff --git a/packages/http/src/IsResponse.php b/packages/http/src/IsResponse.php index 0eda90fb79..3c7c821087 100644 --- a/packages/http/src/IsResponse.php +++ b/packages/http/src/IsResponse.php @@ -38,7 +38,7 @@ public function getHeader(string $name): ?Header { return array_find( array: $this->headers, - callback: fn (Header $header) => strcasecmp($header->name, $name) === 0, + callback: static fn (Header $header) => strcasecmp($header->name, $name) === 0, ); } diff --git a/packages/http/src/Mappers/PsrRequestToGenericRequestMapper.php b/packages/http/src/Mappers/PsrRequestToGenericRequestMapper.php index 38b12f1521..a27b43850d 100644 --- a/packages/http/src/Mappers/PsrRequestToGenericRequestMapper.php +++ b/packages/http/src/Mappers/PsrRequestToGenericRequestMapper.php @@ -47,7 +47,7 @@ public function map(mixed $from, mixed $to): GenericRequest } $headersAsString = array_map( - fn (array $items) => implode(',', $items), + static fn (array $items) => implode(',', $items), $from->getHeaders(), ); diff --git a/packages/http/src/Mappers/RequestToObjectMapper.php b/packages/http/src/Mappers/RequestToObjectMapper.php index 36db970a7a..2efab5997f 100644 --- a/packages/http/src/Mappers/RequestToObjectMapper.php +++ b/packages/http/src/Mappers/RequestToObjectMapper.php @@ -33,8 +33,8 @@ public function map(mixed $from, mixed $to): array|object if (is_a($to, Request::class, true)) { $invalidReservedProperties = arr(new ClassReflector(Request::class)->getProperties()) - ->map(fn (PropertyReflector $property) => $property->getName()) - ->filter(fn (string $property) => array_key_exists($property, $data)); + ->map(static fn (PropertyReflector $property) => $property->getName()) + ->filter(static fn (string $property) => array_key_exists($property, $data)); if ($invalidReservedProperties->isNotEmpty()) { throw new RequestParametersIncludedReservedNames($to, $invalidReservedProperties); diff --git a/packages/http/src/RequestHeaders.php b/packages/http/src/RequestHeaders.php index b4253b906c..e8a135c310 100644 --- a/packages/http/src/RequestHeaders.php +++ b/packages/http/src/RequestHeaders.php @@ -20,7 +20,7 @@ public static function normalizeFromArray(array $headers): self { return new self(array_combine( array_map(strtolower(...), array_keys($headers)), - array_values(array_map(fn (mixed $value) => Str\parse($value), $headers)), + array_values(array_map(static fn (mixed $value) => Str\parse($value), $headers)), )); } diff --git a/packages/intl/src/MessageFormat/Formatter/MessageFormatter.php b/packages/intl/src/MessageFormat/Formatter/MessageFormatter.php index fea3ed83b0..2bfb1ad321 100644 --- a/packages/intl/src/MessageFormat/Formatter/MessageFormatter.php +++ b/packages/intl/src/MessageFormat/Formatter/MessageFormatter.php @@ -376,8 +376,8 @@ private function getMarkupFormatter(?string $tag): ?MarkupFormatter } return arr($this->markupFormatters) - ->filter(fn (MarkupFormatter|StandaloneMarkupFormatter $fn) => $fn instanceof MarkupFormatter) - ->first(fn (MarkupFormatter $fn) => $fn->supportsTag($tag)); + ->filter(static fn (MarkupFormatter|StandaloneMarkupFormatter $fn) => $fn instanceof MarkupFormatter) + ->first(static fn (MarkupFormatter $fn) => $fn->supportsTag($tag)); } private function getStandaloneMarkupFormatter(?string $tag): ?StandaloneMarkupFormatter @@ -387,8 +387,8 @@ private function getStandaloneMarkupFormatter(?string $tag): ?StandaloneMarkupFo } return arr($this->markupFormatters) - ->filter(fn (MarkupFormatter|StandaloneMarkupFormatter $fn) => $fn instanceof StandaloneMarkupFormatter) - ->first(fn (StandaloneMarkupFormatter $fn) => $fn->supportsTag($tag)); + ->filter(static fn (MarkupFormatter|StandaloneMarkupFormatter $fn) => $fn instanceof StandaloneMarkupFormatter) + ->first(static fn (StandaloneMarkupFormatter $fn) => $fn->supportsTag($tag)); } private function getSelectorFunction(?string $name): ?SelectorFunction @@ -398,8 +398,8 @@ private function getSelectorFunction(?string $name): ?SelectorFunction } return arr($this->functions) - ->filter(fn (FormattingFunction|SelectorFunction $fn) => $fn instanceof SelectorFunction) - ->first(fn (SelectorFunction $fn) => $fn->name === $name); + ->filter(static fn (FormattingFunction|SelectorFunction $fn) => $fn instanceof SelectorFunction) + ->first(static fn (SelectorFunction $fn) => $fn->name === $name); } private function getFormattingFunction(?string $name): ?FormattingFunction @@ -409,7 +409,7 @@ private function getFormattingFunction(?string $name): ?FormattingFunction } return arr($this->functions) - ->filter(fn (FormattingFunction|SelectorFunction $fn) => $fn instanceof FormattingFunction) - ->first(fn (FormattingFunction $fn) => $fn->name === $name); + ->filter(static fn (FormattingFunction|SelectorFunction $fn) => $fn instanceof FormattingFunction) + ->first(static fn (FormattingFunction $fn) => $fn->name === $name); } } diff --git a/packages/intl/src/MessageFormat/Parser/MessageFormatParser.php b/packages/intl/src/MessageFormat/Parser/MessageFormatParser.php index dcc7ee1130..06e68b42aa 100644 --- a/packages/intl/src/MessageFormat/Parser/MessageFormatParser.php +++ b/packages/intl/src/MessageFormat/Parser/MessageFormatParser.php @@ -132,7 +132,7 @@ private function parseInputDeclaration(): InputDeclaration $optional = (bool) array_find( array: $expression->function->options ?? [], - callback: fn (Option $option) => $option->identifier->name === 'default', + callback: static fn (Option $option) => $option->identifier->name === 'default', ); return new InputDeclaration($expression, $optional); diff --git a/packages/intl/src/TranslationMessageDiscovery.php b/packages/intl/src/TranslationMessageDiscovery.php index 89e3d616f4..b277c42bad 100644 --- a/packages/intl/src/TranslationMessageDiscovery.php +++ b/packages/intl/src/TranslationMessageDiscovery.php @@ -54,7 +54,7 @@ public function apply(): void private function isLocale(string $candidate): bool { $locale = arr(Locale::cases()) - ->first(function (Locale $locale) use ($candidate) { + ->first(static function (Locale $locale) use ($candidate) { if (strtolower($locale->value) === strtolower($candidate)) { return true; } diff --git a/packages/kv-store/src/Redis/PhpRedisClient.php b/packages/kv-store/src/Redis/PhpRedisClient.php index 46b8643fa6..5dd7ca22e6 100644 --- a/packages/kv-store/src/Redis/PhpRedisClient.php +++ b/packages/kv-store/src/Redis/PhpRedisClient.php @@ -83,7 +83,7 @@ public function command(Stringable|string $command, Stringable|string ...$argume } $command = (string) $command; - $arguments = array_map(fn (Stringable|string $argument) => (string) $argument, $arguments); + $arguments = array_map(static fn (Stringable|string $argument) => (string) $argument, $arguments); $startedAt = DateTime::now(); $result = $this->client->rawcommand($command, ...$arguments); diff --git a/packages/kv-store/src/Redis/PredisClient.php b/packages/kv-store/src/Redis/PredisClient.php index ff72f047c6..5bbcf1851d 100644 --- a/packages/kv-store/src/Redis/PredisClient.php +++ b/packages/kv-store/src/Redis/PredisClient.php @@ -45,7 +45,7 @@ public function flush(): void public function command(Stringable|string $command, Stringable|string ...$arguments): mixed { $command = (string) $command; - $arguments = array_map(fn (Stringable|string $argument) => (string) $argument, $arguments); + $arguments = array_map(static fn (Stringable|string $argument) => (string) $argument, $arguments); $startedAt = DateTime::now(); $result = $this->client->executeRaw(array_merge([$command], $arguments)); diff --git a/packages/log/src/TailLogsCommand.php b/packages/log/src/TailLogsCommand.php index c3d36f6230..c1a1465c93 100644 --- a/packages/log/src/TailLogsCommand.php +++ b/packages/log/src/TailLogsCommand.php @@ -25,7 +25,7 @@ public function __construct( #[ConsoleCommand('tail:logs', description: 'Tails the project logs', aliases: ['log:tail', 'logs:tail'])] public function __invoke(): void { - $appendLogChannel = array_find($this->config->logChannels, fn ($channel) => $channel instanceof AppendLogChannel); + $appendLogChannel = array_find($this->config->logChannels, static fn ($channel) => $channel instanceof AppendLogChannel); if ($appendLogChannel === null) { $this->console->error('Tailing logs is only supported when a AppendLogChannel is configured.'); return; diff --git a/packages/mail/src/Attachment.php b/packages/mail/src/Attachment.php index b0a88f9805..85a3c8389d 100644 --- a/packages/mail/src/Attachment.php +++ b/packages/mail/src/Attachment.php @@ -47,7 +47,7 @@ public static function fromStorage(Storage $storage, string $path, ?string $name $path = Path\normalize($path); return new self( - resolve: fn () => $storage->readStream($path), + resolve: static fn () => $storage->readStream($path), name: $name ?? basename($path), contentType: $contentType ?? $storage->mimeType($path), ); @@ -65,7 +65,7 @@ public static function fromFilesystem(string $path, ?string $name = null, ?strin } return new self( - resolve: fn () => Filesystem\read_file($path), + resolve: static fn () => Filesystem\read_file($path), name: $name ?? basename($path), contentType: $contentType ?? finfo_file(finfo_open(FILEINFO_MIME_TYPE), $path), ); diff --git a/packages/mail/src/EmailToSymfonyEmailMapper.php b/packages/mail/src/EmailToSymfonyEmailMapper.php index 7c26b7ec12..8ebdfb908d 100644 --- a/packages/mail/src/EmailToSymfonyEmailMapper.php +++ b/packages/mail/src/EmailToSymfonyEmailMapper.php @@ -119,7 +119,7 @@ public function map(mixed $from, mixed $to): SymfonyEmail private function convertAddresses(string|array|EmailAddress|null $addresses): array { return arr($addresses) - ->map(fn (string|EmailAddress|SymfonyAddress $address) => match (true) { + ->map(static fn (string|EmailAddress|SymfonyAddress $address) => match (true) { $address instanceof SymfonyAddress => $address, $address instanceof EmailAddress => new SymfonyAddress($address->email, $address->name ?? ''), default => SymfonyAddress::create($address), diff --git a/packages/mail/src/Testing/MailTester.php b/packages/mail/src/Testing/MailTester.php index ebb03f6c2d..2cf19f1197 100644 --- a/packages/mail/src/Testing/MailTester.php +++ b/packages/mail/src/Testing/MailTester.php @@ -46,7 +46,7 @@ public function assertSent(string $email, ?Closure $callback = null): self { $this->assertClassStringIsEmail($email); - $sentEmail = Arr\first($this->mailer->sent, filter: fn (Email $sent) => $sent instanceof $email); + $sentEmail = Arr\first($this->mailer->sent, filter: static fn (Email $sent) => $sent instanceof $email); Assert::assertTrue( condition: (bool) $sentEmail, @@ -79,7 +79,7 @@ public function assertNotSent(string $email): self $this->assertClassStringIsEmail($email); Assert::assertFalse( - condition: (bool) Arr\first($this->mailer->sent, filter: fn (Email $sent) => $sent instanceof $email), + condition: (bool) Arr\first($this->mailer->sent, filter: static fn (Email $sent) => $sent instanceof $email), message: sprintf('Email `%s` was unexpectedly sent.', $email), ); @@ -93,21 +93,21 @@ public function assertNotSent(string $email): self public array $from { get => Arr\map( array: $this->sentSymfonyEmail->getFrom(), - map: fn (SymfonyAddress $address) => new EmailAddress($address->getAddress(), $address->getName()), + map: static fn (SymfonyAddress $address) => new EmailAddress($address->getAddress(), $address->getName()), ); } public array $to { get => Arr\map( array: $this->sentSymfonyEmail->getTo(), - map: fn (SymfonyAddress $address) => new EmailAddress($address->getAddress(), $address->getName()), + map: static fn (SymfonyAddress $address) => new EmailAddress($address->getAddress(), $address->getName()), ); } public array $attachments { get => Arr\map( array: $this->sentSymfonyEmail->getAttachments(), - map: fn (DataPart $attachment) => new Attachment( + map: static fn (DataPart $attachment) => new Attachment( resolve: $attachment->getBody(...), name: $attachment->getFilename(), contentType: $attachment->getMediaType() . '/' . $attachment->getMediaSubtype(), @@ -384,7 +384,7 @@ public function assertAttached(string $filename, ?Closure $callback = null): sel Assert::fail(sprintf( 'Failed asserting that the email has an attachment named `%s`. Existing attachments: %s.', $filename, - Arr\join(Arr\map($attachments, fn (DataPart $attachment) => $attachment->getName())), + Arr\join(Arr\map($attachments, static fn (DataPart $attachment) => $attachment->getName())), )); } @@ -447,7 +447,7 @@ private function assertAddressListDoesNotContain(string|array|EmailAddress|null private function convertAddresses(string|array|EmailAddress|null $addresses): array { return arr($addresses) - ->map(fn (string|EmailAddress|SymfonyAddress $address) => match (true) { + ->map(static fn (string|EmailAddress|SymfonyAddress $address) => match (true) { $address instanceof SymfonyAddress => $address->getAddress(), $address instanceof EmailAddress => $address->email, default => $address, @@ -478,7 +478,7 @@ public function assertFailed(string $email, ?Closure $callback = null, ?string $ { $this->assertClassStringIsEmail(email: $email); - $failed = Arr\first($this->mailer->failed, filter: fn (FailedEmail $failed) => $failed->email instanceof $email); + $failed = Arr\first($this->mailer->failed, filter: static fn (FailedEmail $failed) => $failed->email instanceof $email); Assert::assertTrue( condition: (bool) $failed, @@ -527,7 +527,7 @@ public function assertNotFailed(string $email): self $this->assertClassStringIsEmail(email: $email); Assert::assertFalse( - condition: (bool) Arr\first($this->mailer->failed, filter: fn (FailedEmail $failed) => $failed->email instanceof $email), + condition: (bool) Arr\first($this->mailer->failed, filter: static fn (FailedEmail $failed) => $failed->email instanceof $email), message: sprintf('Email `%s` unexpectedly failed.', $email), ); diff --git a/packages/mail/src/Transports/RoundRobinMailerConfig.php b/packages/mail/src/Transports/RoundRobinMailerConfig.php index 59f4b78f45..5b41abfaaa 100644 --- a/packages/mail/src/Transports/RoundRobinMailerConfig.php +++ b/packages/mail/src/Transports/RoundRobinMailerConfig.php @@ -42,6 +42,6 @@ public function createTransport(): TransportInterface /** @return TransportInterface[] */ private function buildTransports(): array { - return Arr\map($this->transports, fn (MailerConfig $config) => $config->createTransport()); + return Arr\map($this->transports, static fn (MailerConfig $config) => $config->createTransport()); } } diff --git a/packages/mapper/src/Mappers/ArrayToObjectMapper.php b/packages/mapper/src/Mappers/ArrayToObjectMapper.php index dbdba1ca91..71ba2d1944 100644 --- a/packages/mapper/src/Mappers/ArrayToObjectMapper.php +++ b/packages/mapper/src/Mappers/ArrayToObjectMapper.php @@ -140,7 +140,7 @@ private function setParentRelations(object $parent, ClassReflector $parentClass) $key = $parentClass->getName(); $plans[$key] ??= array_filter(array_map( - function (PropertyReflector $property): ?array { + static function (PropertyReflector $property): ?array { if ($property->isVirtual()) { return null; } @@ -182,7 +182,7 @@ private function setChildParentRelation(object $parent, mixed $child, ClassRefle $key = $childClass->getName() . '|' . $parent::class; $plans[$key] ??= array_filter(array_map( - function (PropertyReflector $childProperty) use ($parent): ?array { + static function (PropertyReflector $childProperty) use ($parent): ?array { if ($childProperty->isVirtual()) { return null; } diff --git a/packages/process/src/InvokedProcessPool.php b/packages/process/src/InvokedProcessPool.php index 949a6a1395..c5553ddeac 100644 --- a/packages/process/src/InvokedProcessPool.php +++ b/packages/process/src/InvokedProcessPool.php @@ -16,7 +16,7 @@ final class InvokedProcessPool implements Countable public ImmutableArray $running { get => $this->processes ->toImmutableArray() - ->filter(fn (InvokedProcess $process) => $process->running); + ->filter(static fn (InvokedProcess $process) => $process->running); } /** @@ -38,7 +38,7 @@ public function __construct( */ public function signal(int $signal): ImmutableArray { - return $this->running->each(fn (InvokedProcess $process) => $process->signal($signal)); + return $this->running->each(static fn (InvokedProcess $process) => $process->signal($signal)); } /** @@ -46,7 +46,7 @@ public function signal(int $signal): ImmutableArray */ public function stop(float|int|Duration $timeout = 10, ?int $signal = null): ImmutableArray { - return $this->running->each(fn (InvokedProcess $process) => $process->stop($timeout, $signal)); + return $this->running->each(static fn (InvokedProcess $process) => $process->stop($timeout, $signal)); } /** @@ -55,7 +55,7 @@ public function stop(float|int|Duration $timeout = 10, ?int $signal = null): Imm public function wait(): ProcessPoolResults { return new ProcessPoolResults( - $this->all->map(fn (InvokedProcess $process) => $process->wait()), + $this->all->map(static fn (InvokedProcess $process) => $process->wait()), ); } @@ -66,7 +66,7 @@ public function wait(): ProcessPoolResults */ public function forEachRunning(Closure $callback): self { - $this->running->each(fn (InvokedProcess $process) => $callback($process)); + $this->running->each(static fn (InvokedProcess $process) => $callback($process)); return $this; } @@ -78,7 +78,7 @@ public function forEachRunning(Closure $callback): self */ public function forEach(Closure $callback): self { - $this->processes->each(fn (InvokedProcess $process) => $callback($process)); + $this->processes->each(static fn (InvokedProcess $process) => $callback($process)); return $this; } diff --git a/packages/process/src/InvokedSystemProcess.php b/packages/process/src/InvokedSystemProcess.php index dada1c23aa..0f42edf5f0 100644 --- a/packages/process/src/InvokedSystemProcess.php +++ b/packages/process/src/InvokedSystemProcess.php @@ -66,7 +66,7 @@ public function wait(?callable $output = null): ProcessResult { try { $callback = $output - ? fn (string $type, mixed $data) => $output(OutputChannel::fromSymfonyOutputType($type), $data) + ? static fn (string $type, mixed $data) => $output(OutputChannel::fromSymfonyOutputType($type), $data) : null; $this->process->wait($callback); diff --git a/packages/process/src/ProcessPoolResults.php b/packages/process/src/ProcessPoolResults.php index 7379fab64b..61d832a8d6 100644 --- a/packages/process/src/ProcessPoolResults.php +++ b/packages/process/src/ProcessPoolResults.php @@ -20,7 +20,7 @@ public function __construct( */ public function allSuccessful(): bool { - return $this->results->every(fn (ProcessResult $result) => $result->successful()); + return $this->results->every(static fn (ProcessResult $result) => $result->successful()); } /** @@ -28,7 +28,7 @@ public function allSuccessful(): bool */ public function allFailed(): bool { - return $this->results->every(fn (ProcessResult $result) => $result->failed()); + return $this->results->every(static fn (ProcessResult $result) => $result->failed()); } /** @@ -36,7 +36,7 @@ public function allFailed(): bool */ public function someSuccessful(): bool { - return $this->results->filter(fn (ProcessResult $result) => $result->successful())->count() > 0; + return $this->results->filter(static fn (ProcessResult $result) => $result->successful())->count() > 0; } /** @@ -44,7 +44,7 @@ public function someSuccessful(): bool */ public function someFailed(): bool { - return $this->results->filter(fn (ProcessResult $result) => $result->failed())->count() > 0; + return $this->results->filter(static fn (ProcessResult $result) => $result->failed())->count() > 0; } /** @@ -52,7 +52,7 @@ public function someFailed(): bool */ public function successful(): ImmutableArray { - return $this->results->filter(fn (ProcessResult $result) => $result->successful()); + return $this->results->filter(static fn (ProcessResult $result) => $result->successful()); } /** @@ -60,7 +60,7 @@ public function successful(): ImmutableArray */ public function failed(): ImmutableArray { - return $this->results->filter(fn (ProcessResult $result) => ! $result->successful()); + return $this->results->filter(static fn (ProcessResult $result) => ! $result->successful()); } public function toImmutableArray(): ImmutableArray diff --git a/packages/process/src/Testing/InvokedProcessDescription.php b/packages/process/src/Testing/InvokedProcessDescription.php index fa0a942d74..80d62e7075 100644 --- a/packages/process/src/Testing/InvokedProcessDescription.php +++ b/packages/process/src/Testing/InvokedProcessDescription.php @@ -113,7 +113,7 @@ public function resolveOutput(bool $error = false): string ->filter(static fn (array $output) => $output['type'] === $expectedType) ->map(static fn (array $output) => rtrim($output['buffer'], "\n")) ->implode("\n") - ->when(fn ($s) => $s->isNotEmpty(), fn ($s) => $s->finish("\n")) + ->when(static fn ($s) => $s->isNotEmpty(), static fn ($s) => $s->finish("\n")) ->toString(); } } diff --git a/packages/reflection/src/ClassReflector.php b/packages/reflection/src/ClassReflector.php index dfb73d8043..93b9d31e25 100644 --- a/packages/reflection/src/ClassReflector.php +++ b/packages/reflection/src/ClassReflector.php @@ -58,7 +58,7 @@ public function getParent(): ?ClassReflector public function getInterfaces(): array { return array_map( - fn (PHPReflectionClass $interface) => new TypeReflector($interface), + static fn (PHPReflectionClass $interface) => new TypeReflector($interface), $this->reflectionClass->getInterfaces(), ); } @@ -90,7 +90,7 @@ private function resolvePublicProperties(): array public function getProperties(): array { return array_map( - fn (PHPReflectionProperty $property) => new PropertyReflector($property), + static fn (PHPReflectionProperty $property) => new PropertyReflector($property), $this->reflectionClass->getProperties(), ); } @@ -101,7 +101,7 @@ public function getPublicMethods(): array return $this->memoize( 'public_methods', fn () => array_map( - fn (PHPReflectionMethod $method) => new MethodReflector($method), + static fn (PHPReflectionMethod $method) => new MethodReflector($method), $this->reflectionClass->getMethods(PHPReflectionMethod::IS_PUBLIC), ), ); diff --git a/packages/reflection/src/EnumReflector.php b/packages/reflection/src/EnumReflector.php index a60f04b9f1..fbad4d77c3 100644 --- a/packages/reflection/src/EnumReflector.php +++ b/packages/reflection/src/EnumReflector.php @@ -89,7 +89,7 @@ public function getCases(): array return $this->memoize( key: 'cases', closure: fn () => array_map( - callback: fn (ReflectionEnumUnitCase $case) => $case->getValue(), + callback: static fn (ReflectionEnumUnitCase $case) => $case->getValue(), array: $this->getReflectionCases(), ), ); diff --git a/packages/reflection/src/FunctionReflector.php b/packages/reflection/src/FunctionReflector.php index c7cb027b0c..ac1b39d1ac 100644 --- a/packages/reflection/src/FunctionReflector.php +++ b/packages/reflection/src/FunctionReflector.php @@ -37,7 +37,7 @@ public function getParameter(int|string $key): ?ParameterReflector { $parameter = array_find( array: $this->reflectionFunction->getParameters(), - callback: fn (ReflectionParameter $parameter) => $parameter->getName() === $key || $parameter->getPosition() === $key, + callback: static fn (ReflectionParameter $parameter) => $parameter->getName() === $key || $parameter->getPosition() === $key, ); if ($parameter === null) { diff --git a/packages/reflection/src/MethodReflector.php b/packages/reflection/src/MethodReflector.php index 523287b139..c38cedd24c 100644 --- a/packages/reflection/src/MethodReflector.php +++ b/packages/reflection/src/MethodReflector.php @@ -39,7 +39,7 @@ public function getParameter(int|string $key): ?ParameterReflector { $parameter = array_find( array: $this->reflectionMethod->getParameters(), - callback: fn (ReflectionParameter $parameter) => $parameter->getName() === $key || $parameter->getPosition() === $key, + callback: static fn (ReflectionParameter $parameter) => $parameter->getName() === $key || $parameter->getPosition() === $key, ); if ($parameter === null) { diff --git a/packages/reflection/src/TypeReflector.php b/packages/reflection/src/TypeReflector.php index a9b5bd2f14..db52ba01c2 100644 --- a/packages/reflection/src/TypeReflector.php +++ b/packages/reflection/src/TypeReflector.php @@ -238,7 +238,7 @@ public function isIntersection(): bool public function split(): array { return array_map( - fn (string $part) => new self($part), + static fn (string $part) => new self($part), preg_split('/[&|]/', $this->definition), ); } diff --git a/packages/router/src/Commands/MakeControllerCommand.php b/packages/router/src/Commands/MakeControllerCommand.php index 5e0cd4c91e..4daf680af8 100644 --- a/packages/router/src/Commands/MakeControllerCommand.php +++ b/packages/router/src/Commands/MakeControllerCommand.php @@ -43,7 +43,7 @@ public function __invoke( 'dummy-view' => $controllerView, ], manipulations: [ - fn (ClassManipulator $class) => $class->removeClassAttribute(SkipDiscovery::class), + static fn (ClassManipulator $class) => $class->removeClassAttribute(SkipDiscovery::class), ], ); diff --git a/packages/router/src/Exceptions/JsonExceptionRenderer.php b/packages/router/src/Exceptions/JsonExceptionRenderer.php index 3afe725da9..cd1ffb6ddf 100644 --- a/packages/router/src/Exceptions/JsonExceptionRenderer.php +++ b/packages/router/src/Exceptions/JsonExceptionRenderer.php @@ -96,7 +96,7 @@ private function renderErrorResponse(Status $status, ?string $message = null, ?T 'line' => $throwable->getLine(), 'trace' => Arr\map( array: $throwable->getTrace(), - map: fn (array $trace) => Arr\remove_keys($trace, 'args'), + map: static fn (array $trace) => Arr\remove_keys($trace, 'args'), ), ]); } diff --git a/packages/router/src/GenericRouter.php b/packages/router/src/GenericRouter.php index 6bedfe0e0e..69ad507cc5 100644 --- a/packages/router/src/GenericRouter.php +++ b/packages/router/src/GenericRouter.php @@ -29,7 +29,7 @@ public function dispatch(Request|PsrRequest $request): Response $request = map($request)->with(PsrRequestToGenericRequestMapper::class)->do(); } - $this->container->singleton(Request::class, fn () => $request); + $this->container->singleton(Request::class, static fn () => $request); $callable = $this->getCallable(); diff --git a/packages/router/src/HandleRouteSpecificMiddleware.php b/packages/router/src/HandleRouteSpecificMiddleware.php index 1498b77fc7..4233eafd19 100644 --- a/packages/router/src/HandleRouteSpecificMiddleware.php +++ b/packages/router/src/HandleRouteSpecificMiddleware.php @@ -20,7 +20,7 @@ public function __invoke(Request $request, HttpMiddlewareCallable $next): Respon { $middlewareStack = new Middleware(...$this->matchedRoute->route->middleware); - $callable = new HttpMiddlewareCallable(fn (Request $request) => $next($request)); + $callable = new HttpMiddlewareCallable(static fn (Request $request) => $next($request)); foreach ($middlewareStack->unwrap() as $middlewareClass) { $callable = new HttpMiddlewareCallable(function (Request $request) use ($middlewareClass, $callable) { diff --git a/packages/router/src/MatchRouteMiddleware.php b/packages/router/src/MatchRouteMiddleware.php index 50d6cd81fa..3720c4447d 100644 --- a/packages/router/src/MatchRouteMiddleware.php +++ b/packages/router/src/MatchRouteMiddleware.php @@ -36,7 +36,7 @@ public function __invoke(Request $request, HttpMiddlewareCallable $next): Respon } // We register the matched route in the container, some internal framework components will need it - $this->container->singleton(MatchedRoute::class, fn () => $matchedRoute); + $this->container->singleton(MatchedRoute::class, static fn () => $matchedRoute); return $next($request); } diff --git a/packages/router/src/ResolveRouteRequestMiddleware.php b/packages/router/src/ResolveRouteRequestMiddleware.php index ef66a647cd..fa51fca387 100644 --- a/packages/router/src/ResolveRouteRequestMiddleware.php +++ b/packages/router/src/ResolveRouteRequestMiddleware.php @@ -28,7 +28,7 @@ public function __invoke(Request $request, HttpMiddlewareCallable $next): Respon // We register this newly created request object in the container // This makes it so that RequestInitializer is bypassed entirely when the controller action needs the request class // Making it so that we don't need to set any $_SERVER variables and stuff like that - $this->container->singleton($request::class, fn () => $request); + $this->container->singleton($request::class, static fn () => $request); return $next($request); } diff --git a/packages/support/src/Arr/ManipulatesArray.php b/packages/support/src/Arr/ManipulatesArray.php index 8e2bd52504..2ded087a55 100644 --- a/packages/support/src/Arr/ManipulatesArray.php +++ b/packages/support/src/Arr/ManipulatesArray.php @@ -91,7 +91,7 @@ public function findKey(mixed $value, bool $strict = false): int|string|null */ public function chunk(int $size, bool $preserveKeys = true): self { - return $this->createOrModify(array_map(fn (array $array) => new static($array), namespace\chunk($this->value, $size, $preserveKeys))); + return $this->createOrModify(array_map(static fn (array $array) => new static($array), namespace\chunk($this->value, $size, $preserveKeys))); } /** diff --git a/packages/support/src/Arr/functions.php b/packages/support/src/Arr/functions.php index f0b8a66308..9a3ac51362 100644 --- a/packages/support/src/Arr/functions.php +++ b/packages/support/src/Arr/functions.php @@ -217,7 +217,7 @@ function forget_values(array &$array, mixed $values): array $values = is_array($values) ? $values : [$values]; foreach ($values as $value) { - if (is_null($key = array_find_key($array, fn (mixed $match) => $value === $match))) { + if (is_null($key = array_find_key($array, static fn (mixed $match) => $value === $match))) { continue; } @@ -1060,7 +1060,7 @@ function undot(iterable $array): array { $array = to_array($array); - $unwrapValue = function (string|int $key, mixed $value) { + $unwrapValue = static function (string|int $key, mixed $value) { if (is_int($key)) { return [$key => $value]; } diff --git a/packages/support/src/Html/functions.php b/packages/support/src/Html/functions.php index 1dde0cb19f..02d74dfd23 100644 --- a/packages/support/src/Html/functions.php +++ b/packages/support/src/Html/functions.php @@ -181,13 +181,13 @@ function is_html_tag(Stringable|string $tag): bool function format_attributes(array $attributes = []): string { return $attributes = arr($attributes) - ->filter(fn (mixed $value) => ! in_array($value, [false, null], strict: true)) - ->map(fn (mixed $value, int|string $key) => $value === true ? $key : $key . '="' . $value . '"') + ->filter(static fn (mixed $value) => ! in_array($value, [false, null], strict: true)) + ->map(static fn (mixed $value, int|string $key) => $value === true ? $key : $key . '="' . $value . '"') ->values() ->implode(' ') ->when( - condition: fn ($string) => $string->length() !== 0, - callback: fn ($string) => $string->prepend(' '), + condition: static fn ($string) => $string->length() !== 0, + callback: static fn ($string) => $string->prepend(' '), ) ->toString(); } diff --git a/packages/support/src/IsEnumHelper.php b/packages/support/src/IsEnumHelper.php index dece585359..b75dae03ed 100644 --- a/packages/support/src/IsEnumHelper.php +++ b/packages/support/src/IsEnumHelper.php @@ -39,7 +39,7 @@ public static function tryFromName(string $name): ?static { $cases = array_filter( static::cases(), - fn (UnitEnum $case) => $case->name === $name, + static fn (UnitEnum $case) => $case->name === $name, ); return array_shift($cases); diff --git a/packages/support/src/JavaScript/DependencyInstaller.php b/packages/support/src/JavaScript/DependencyInstaller.php index 762c687557..8621ea2e58 100644 --- a/packages/support/src/JavaScript/DependencyInstaller.php +++ b/packages/support/src/JavaScript/DependencyInstaller.php @@ -75,7 +75,7 @@ private function getInstallProcess(PackageManager $packageManager, string $cwd, $dev ? '-D' : null, ...$dependencies, ], - fn (?string $arg): bool => $arg !== null, + static fn (?string $arg): bool => $arg !== null, )); return new Process( diff --git a/packages/support/src/JavaScript/PackageManager.php b/packages/support/src/JavaScript/PackageManager.php index b2649ff8ac..1eb0b23d22 100644 --- a/packages/support/src/JavaScript/PackageManager.php +++ b/packages/support/src/JavaScript/PackageManager.php @@ -62,7 +62,7 @@ public static function detect(string $cwd): ?self { return array_find( array: PackageManager::cases(), - callback: fn (PackageManager $packageManager): bool => array_any($packageManager->getLockFiles(), fn (string $lockFile): bool => Filesystem\is_file( + callback: static fn (PackageManager $packageManager): bool => array_any($packageManager->getLockFiles(), static fn (string $lockFile): bool => Filesystem\is_file( $cwd . '/' . $lockFile, )), ); diff --git a/packages/support/src/Namespace/functions.php b/packages/support/src/Namespace/functions.php index e296c903ed..1509cbde14 100644 --- a/packages/support/src/Namespace/functions.php +++ b/packages/support/src/Namespace/functions.php @@ -24,7 +24,7 @@ function to_fqcn(Stringable|string $path, Stringable|string|null $root = null): $namespace = prepare_namespace($path, $root) ->stripEnd('\\') ->explode('\\') - ->map(fn (string $segment) => Str\to_pascal_case($segment)) + ->map(static fn (string $segment) => Str\to_pascal_case($segment)) ->implode('\\') ->toString(); @@ -55,7 +55,7 @@ function to_namespace(Stringable|string $path, Stringable|string|null $root = nu return prepare_namespace($path, $root) ->stripEnd('\\') ->explode('\\') - ->map(fn (string $segment) => Str\to_pascal_case($segment)) + ->map(static fn (string $segment) => Str\to_pascal_case($segment)) ->implode('\\') ->toString(); } diff --git a/packages/support/src/Path/functions.php b/packages/support/src/Path/functions.php index f1c5faeff5..07a576981d 100644 --- a/packages/support/src/Path/functions.php +++ b/packages/support/src/Path/functions.php @@ -118,17 +118,17 @@ function normalize(Stringable|string|null ...$paths): string } $paths = array_map( - fn (Stringable|string|null $path) => $path === null ? '' : (string) $path, + static fn (Stringable|string|null $path) => $path === null ? '' : (string) $path, $paths, ); // Split paths items on forward and backward slashes - $parts = array_reduce($paths, fn (array $carry, string $part) => [...$carry, ...explode('/', $part)], []); - $parts = array_reduce($parts, fn (array $carry, string $part) => [...$carry, ...explode('\\', $part)], []); + $parts = array_reduce($paths, static fn (array $carry, string $part) => [...$carry, ...explode('/', $part)], []); + $parts = array_reduce($parts, static fn (array $carry, string $part) => [...$carry, ...explode('\\', $part)], []); // Trim forward and backward slashes - $parts = array_map(fn (string $part) => trim($part, '/\\'), $parts); - $parts = array_filter($parts, fn (string $part) => $part !== '' && $part !== '.'); + $parts = array_map(static fn (string $part) => trim($part, '/\\'), $parts); + $parts = array_filter($parts, static fn (string $part) => $part !== '' && $part !== '.'); // Glue parts together $path = implode('/', $parts); diff --git a/packages/support/src/Regex/functions.php b/packages/support/src/Regex/functions.php index a59e604948..5c467bfb93 100644 --- a/packages/support/src/Regex/functions.php +++ b/packages/support/src/Regex/functions.php @@ -74,7 +74,7 @@ function get_all_matches( $result = get_matches($subject, $pattern, true, PREG_SET_ORDER, $offset); return arr($result) - ->map(fn (array $result) => filter($result, fn ($_, string|int $key) => in_array($key, wrap($matches), strict: false))) + ->map(static fn (array $result) => filter($result, static fn ($_, string|int $key) => in_array($key, wrap($matches), strict: false))) ->toArray(); } @@ -114,8 +114,8 @@ function get_match( if (is_array($match)) { return arr($result) - ->filter(fn ($_, string|int $key) => in_array($key, $match, strict: false)) - ->mapWithKeys(fn (array $matches, string|int $key) => yield $key => first($matches)) + ->filter(static fn ($_, string|int $key) => in_array($key, $match, strict: false)) + ->mapWithKeys(static fn (array $matches, string|int $key) => yield $key => first($matches)) ->toArray(); } diff --git a/packages/support/src/Str/functions.php b/packages/support/src/Str/functions.php index 5a5a1188a4..ba9f657739 100644 --- a/packages/support/src/Str/functions.php +++ b/packages/support/src/Str/functions.php @@ -346,7 +346,7 @@ function starts_with(Stringable|string $string, Stringable|string|array $needles $needles = [$needles]; } - return array_any($needles, fn ($needle) => str_starts_with($string, (string) $needle)); + return array_any($needles, static fn ($needle) => str_starts_with($string, (string) $needle)); } /** @@ -597,7 +597,7 @@ function excerpt(Stringable|string $string, int $from, int $to, bool $asArray = if ($asArray) { return arr($lines) - ->mapWithKeys(fn (string $line, int $number) => yield $number + 1 => $line) + ->mapWithKeys(static fn (string $line, int $number) => yield $number + 1 => $line) ->toArray(); } @@ -658,7 +658,7 @@ function slice(Stringable|string $string, int $start, ?int $length = null): stri */ function contains(Stringable|string $string, Stringable|string|array $needle): bool { - return array_any(Arr\wrap($needle), fn ($item) => str_contains((string) $string, (string) $item)); + return array_any(Arr\wrap($needle), static fn ($item) => str_contains((string) $string, (string) $item)); } /** @@ -703,7 +703,7 @@ function strip_tags(Stringable|string $string, string|array|null $allowed = null $string = (string) $string; $allowed = arr($allowed) - ->map(fn (string $tag) => wrap($tag, '<', '>')) + ->map(static fn (string $tag) => wrap($tag, '<', '>')) ->toArray(); return php_strip_tags($string, $allowed); diff --git a/packages/support/src/Uri/Uri.php b/packages/support/src/Uri/Uri.php index d527a718c9..781bbac0c5 100644 --- a/packages/support/src/Uri/Uri.php +++ b/packages/support/src/Uri/Uri.php @@ -21,7 +21,7 @@ final class Uri implements Stringable return []; } - return array_values(array_filter(explode('/', $this->path), fn (string $segment) => $segment !== '')); + return array_values(array_filter(explode('/', $this->path), static fn (string $segment) => $segment !== '')); } } diff --git a/packages/upgrade/src/Tempest34/UpdateKernelDiscoveryPropertiesRector.php b/packages/upgrade/src/Tempest34/UpdateKernelDiscoveryPropertiesRector.php index 157c5ae64a..bb18929fec 100644 --- a/packages/upgrade/src/Tempest34/UpdateKernelDiscoveryPropertiesRector.php +++ b/packages/upgrade/src/Tempest34/UpdateKernelDiscoveryPropertiesRector.php @@ -53,6 +53,6 @@ private function isKernelType(Expr $expr): bool { $type = $this->nodeTypeResolver->getType($expr); - return array_any($type->getObjectClassNames(), fn ($className) => $className === 'Tempest\Core\Kernel' || is_subclass_of($className, 'Tempest\Core\Kernel')); + return array_any($type->getObjectClassNames(), static fn ($className) => $className === 'Tempest\Core\Kernel' || is_subclass_of($className, 'Tempest\Core\Kernel')); } } diff --git a/packages/validation/src/Validator.php b/packages/validation/src/Validator.php index 9ae3e1bbdb..587e1e75b8 100644 --- a/packages/validation/src/Validator.php +++ b/packages/validation/src/Validator.php @@ -161,7 +161,7 @@ public function validateValueForProperty(PropertyReflector $property, mixed $val return Arr\map( array: $this->validateValue($value, $rules), - map: fn (FailingRule $rule) => $rule->withField($field)->withKey($key), + map: static fn (FailingRule $rule) => $rule->withField($field)->withKey($key), ); } @@ -270,7 +270,7 @@ private function getTranslationKey(Rule|FailingRule $rule): string 'i_pv4' => 'ipv4', 'reg_ex' => 'regex', ]) - ->when($key !== '', fn ($s) => $s->append('.', $key)) + ->when($key !== '', static fn ($s) => $s->append('.', $key)) ->toString(); } diff --git a/packages/view/src/Components/x-icon.view.php b/packages/view/src/Components/x-icon.view.php index 8e1e46d474..05c8f9ea70 100644 --- a/packages/view/src/Components/x-icon.view.php +++ b/packages/view/src/Components/x-icon.view.php @@ -20,8 +20,8 @@ $svg = str(is_string($name) ? get(Icon::class)->render($name) : null) ->when( - fn (ImmutableString $s): bool => $s->toString() === '' && $environment->isLocal(), - fn (ImmutableString $s): ImmutableString => str(""), + static fn (ImmutableString $s): bool => $s->toString() === '' && $environment->isLocal(), + static fn (ImmutableString $s): ImmutableString => str(""), ) ->replace( search: ' width="1em" height="1em"', @@ -29,21 +29,21 @@ ) ->when( $style ?? null, - fn (ImmutableString $s): ImmutableString => $s->replace( + static fn (ImmutableString $s): ImmutableString => $s->replace( search: 'when( $class ?? null, - fn (ImmutableString $s): ImmutableString => $s->replace( + static fn (ImmutableString $s): ImmutableString => $s->replace( search: 'when( isset($width, $height), - fn (ImmutableString $s): ImmutableString => $s + static fn (ImmutableString $s): ImmutableString => $s ->replace( search: 'when( ! isset($width, $height) && ! isset($style) && ! isset($class), - fn (ImmutableString $s): ImmutableString => $s + static fn (ImmutableString $s): ImmutableString => $s ->replace( search: 'replaceRegex( regex: '/{{(?.*?)}}/', - replace: fn (array $matches): string => sprintf('escape(%s); ?>', $matches['match']), + replace: static fn (array $matches): string => sprintf('escape(%s); ?>', $matches['match']), ) // Render {!! ->replaceRegex( regex: '/{!!(?.*?)!!}/', - replace: fn (array $matches): string => sprintf('', $matches['match']), + replace: static fn (array $matches): string => sprintf('', $matches['match']), ) ->toString(); } diff --git a/packages/view/src/Elements/ViewComponentElement.php b/packages/view/src/Elements/ViewComponentElement.php index 539700e9b3..f767209e8e 100644 --- a/packages/view/src/Elements/ViewComponentElement.php +++ b/packages/view/src/Elements/ViewComponentElement.php @@ -51,16 +51,16 @@ public function __construct( $this->attributes = $attributes; $this->viewComponentAttributes = arr($attributes) - ->mapWithKeys(fn (string $value, string $key) => yield str($key)->ltrim(':')->toString() => $value); + ->mapWithKeys(static fn (string $value, string $key) => yield str($key)->ltrim(':')->toString() => $value); $this->dataAttributes = arr($attributes) - ->filter(fn (string $_, string $key) => ! str_starts_with($key, ':')) - ->mapWithKeys(fn (string $value, string $key) => yield str($key)->camel()->toString() => $value); + ->filter(static fn (string $_, string $key) => ! str_starts_with($key, ':')) + ->mapWithKeys(static fn (string $value, string $key) => yield str($key)->camel()->toString() => $value); $this->expressionAttributes = arr($attributes) - ->filter(fn (string $_, string $key) => str_starts_with($key, ':')) - ->filter(fn (string $_, string $key) => ! in_array($key, [':if', ':else', ':elseif', ':foreach', ':forelse'], strict: true)) - ->mapWithKeys(fn (string $value, string $key) => yield str($key)->camel()->ltrim(':')->toString() => $value === '' ? 'true' : $value); + ->filter(static fn (string $_, string $key) => str_starts_with($key, ':')) + ->filter(static fn (string $_, string $key) => ! in_array($key, [':if', ':else', ':elseif', ':foreach', ':forelse'], strict: true)) + ->mapWithKeys(static fn (string $value, string $key) => yield str($key)->camel()->ltrim(':')->toString() => $value === '' ? 'true' : $value); $this->scopedVariables = arr(); } @@ -148,9 +148,9 @@ public function compile(): string ->prepend( sprintf( '', - $this->dataAttributes->isNotEmpty() ? ', ' . $this->dataAttributes->map(fn (string $_value, string $key) => "\${$key}")->implode(', ') : '', - $this->expressionAttributes->isNotEmpty() ? ', ' . $this->expressionAttributes->map(fn (string $_value, string $key) => "\${$key}")->implode(', ') : '', - $this->scopedVariables->isNotEmpty() ? ', ' . $this->scopedVariables->map(fn (string $name) => "\${$name}")->implode(', ') : '', + $this->dataAttributes->isNotEmpty() ? ', ' . $this->dataAttributes->map(static fn (string $_value, string $key) => "\${$key}")->implode(', ') : '', + $this->expressionAttributes->isNotEmpty() ? ', ' . $this->expressionAttributes->map(static fn (string $_value, string $key) => "\${$key}")->implode(', ') : '', + $this->scopedVariables->isNotEmpty() ? ', ' . $this->scopedVariables->map(static fn (string $name) => "\${$name}")->implode(', ') : '', ), ) ->append('viewCache->getCachedViewPath( $cacheKey, - fn () => $compiledView->content, + static fn () => $compiledView->content, ); $this->viewCache->saveSourceMap($cachePath, $compiledView->sourcePath, $compiledView->lineMap); @@ -176,16 +176,16 @@ public function compile(): string $this->exportAttributesArray(), ViewObjectExporter::export($slots), $this->scopedVariables->isNotEmpty() - ? $this->scopedVariables->map(fn (string $name) => "'{$name}' => \${$name}")->implode(', ') + ? $this->scopedVariables->map(static fn (string $name) => "'{$name}' => \${$name}")->implode(', ') : '', $this->dataAttributes->isNotEmpty() - ? ', ' . $this->dataAttributes->map(fn (mixed $value, string $key) => "{$key}: " . ViewObjectExporter::exportValue($value))->implode(', ') + ? ', ' . $this->dataAttributes->map(static fn (mixed $value, string $key) => "{$key}: " . ViewObjectExporter::exportValue($value))->implode(', ') : '', $this->expressionAttributes->isNotEmpty() - ? ', ' . $this->expressionAttributes->map(fn (mixed $value, string $key) => "{$key}: " . $value)->implode(', ') + ? ', ' . $this->expressionAttributes->map(static fn (mixed $value, string $key) => "{$key}: " . $value)->implode(', ') : '', $this->scopedVariables->isNotEmpty() - ? ', ' . $this->scopedVariables->map(fn (string $name) => "{$name}: \${$name}")->implode(', ') + ? ', ' . $this->scopedVariables->map(static fn (string $name) => "{$name}: \${$name}")->implode(', ') : '', ); } @@ -231,7 +231,7 @@ private function compileComponent(): ImmutableString $fallthroughApplied = true; $attributes = arr($token->htmlAttributes) - ->map(fn (string $value) => new MutableString($value)); + ->map(static fn (string $value) => new MutableString($value)); foreach (['class', 'style', 'id'] as $name) { // If the root element already declares this attribute — in plain form (class="...") @@ -248,11 +248,11 @@ private function compileComponent(): ImmutableString } $attributeString = $attributes - ->map(fn (MutableString $value, string $key) => sprintf('%s="%s"', $key, $value->trim())) + ->map(static fn (MutableString $value, string $key) => sprintf('%s="%s"', $key, $value->trim())) ->implode(' ') ->when( - fn (ImmutableString $s) => $s->isNotEmpty(), - fn (ImmutableString $s) => $s->prepend(' '), + static fn (ImmutableString $s) => $s->isNotEmpty(), + static fn (ImmutableString $s) => $s->prepend(' '), ); if ($token->type === TokenType::SELF_CLOSING_TAG) { diff --git a/packages/view/src/Export/ViewObjectExporter.php b/packages/view/src/Export/ViewObjectExporter.php index 9d736e3f7b..6b4c588d04 100644 --- a/packages/view/src/Export/ViewObjectExporter.php +++ b/packages/view/src/Export/ViewObjectExporter.php @@ -17,7 +17,7 @@ public static function export(ExportableViewObject|ImmutableArray $object): stri $object::class, $object ->exportData - ->map(function (mixed $value, string $key) { + ->map(static function (mixed $value, string $key) { $value = self::exportValue($value); return "{$key} : {$value}"; @@ -33,7 +33,7 @@ public static function exportValue(mixed $value): string $value instanceof ImmutableArray => sprintf( 'new \%s([%s])', ImmutableArray::class, - $value->map(function (mixed $value, string|int $key) { + $value->map(static function (mixed $value, string|int $key) { $key = is_int($key) ? $key : "'{$key}'"; return $key . ' => ' . rtrim(self::exportValue($value), ';'); diff --git a/packages/view/src/Parser/TempestViewAst.php b/packages/view/src/Parser/TempestViewAst.php index 379e9564cc..34288937a4 100644 --- a/packages/view/src/Parser/TempestViewAst.php +++ b/packages/view/src/Parser/TempestViewAst.php @@ -28,7 +28,7 @@ public function add(Token $token): self public function compile(): string { return implode('', array_map( - fn (Token $token) => $token->compile(), + static fn (Token $token) => $token->compile(), iterator_to_array($this->tokens), )); } diff --git a/packages/view/src/Parser/TempestViewCompiler.php b/packages/view/src/Parser/TempestViewCompiler.php index 8cf85611c0..03ceacd375 100644 --- a/packages/view/src/Parser/TempestViewCompiler.php +++ b/packages/view/src/Parser/TempestViewCompiler.php @@ -119,7 +119,7 @@ private function retrieveTemplate(string|View $view): array $searchPathOptions = [ ...$searchPathOptions, ...arr($this->discoveryLocations) - ->map(fn (DiscoveryLocation $discoveryLocation) => path($discoveryLocation->path, $path)->toString()) + ->map(static fn (DiscoveryLocation $discoveryLocation) => path($discoveryLocation->path, $path)->toString()) ->toArray(), ]; @@ -277,7 +277,7 @@ private function cleanupCompiled(string $compiled, ?string $sourcePath, array $i $imports[$import] = $import; } - $compiled = $compiled->replaceRegex("/^\s*use (function )?.*;/m", function (array $matches) use (&$imports) { + $compiled = $compiled->replaceRegex("/^\s*use (function )?.*;/m", static function (array $matches) use (&$imports) { // The import contains escaped slashes, meaning it's a var_exported string; we can ignore those if (str_contains($matches[0], '\\\\')) { return $matches[0]; diff --git a/packages/view/src/Parser/TokenCollection.php b/packages/view/src/Parser/TokenCollection.php index c25679810b..6b36320c4d 100644 --- a/packages/view/src/Parser/TokenCollection.php +++ b/packages/view/src/Parser/TokenCollection.php @@ -33,7 +33,7 @@ public function __debugInfo(): array return [ implode( ', ' . PHP_EOL, - array_map(fn (Token $token) => $token->__debugInfo()[0], $this->tokens), + array_map(static fn (Token $token) => $token->__debugInfo()[0], $this->tokens), ), ]; } diff --git a/packages/view/src/ViewCachePool.php b/packages/view/src/ViewCachePool.php index de7f14bbf4..20fdc4054c 100644 --- a/packages/view/src/ViewCachePool.php +++ b/packages/view/src/ViewCachePool.php @@ -58,7 +58,7 @@ public function clear(): bool $path = path($this->directory); if ($path->isDirectory()) { - $path->glob('/*.php')->each(fn (string $file) => unlink($file)); + $path->glob('/*.php')->each(static fn (string $file) => unlink($file)); Filesystem\delete_directory($this->directory); } diff --git a/packages/vite/src/Installer/ViteInstaller.php b/packages/vite/src/Installer/ViteInstaller.php index bccfbc5065..5655693c9c 100644 --- a/packages/vite/src/Installer/ViteInstaller.php +++ b/packages/vite/src/Installer/ViteInstaller.php @@ -57,7 +57,7 @@ public function install( } // Installs package.json scripts - $this->updateJson(root_path('package.json'), function (array $json) { + $this->updateJson(root_path('package.json'), static function (array $json) { $json['type'] = 'module'; $json['scripts'] ??= []; $json['scripts'] = [ diff --git a/packages/vite/src/Manifest/Manifest.php b/packages/vite/src/Manifest/Manifest.php index 65dada92a4..42067a79fc 100644 --- a/packages/vite/src/Manifest/Manifest.php +++ b/packages/vite/src/Manifest/Manifest.php @@ -29,7 +29,7 @@ public static function fromArray(array $chunks): self return new self( chunks: $chunks, - entrypoints: $chunks->filter(fn (Chunk $entry) => $entry->isEntry), + entrypoints: $chunks->filter(static fn (Chunk $entry) => $entry->isEntry), ); } } diff --git a/packages/vite/src/TagsResolver/DevelopmentTagsResolver.php b/packages/vite/src/TagsResolver/DevelopmentTagsResolver.php index 9e86e52d10..be669c8a01 100644 --- a/packages/vite/src/TagsResolver/DevelopmentTagsResolver.php +++ b/packages/vite/src/TagsResolver/DevelopmentTagsResolver.php @@ -59,8 +59,8 @@ private function fileToAssetPath(string $file): string { return str($file) ->when( - condition: fn ($file) => $file->startsWith('./'), - callback: fn ($file) => str(Filesystem\normalize_path(root_path($file->toString()))), + condition: static fn ($file) => $file->startsWith('./'), + callback: static fn ($file) => str(Filesystem\normalize_path(root_path($file->toString()))), ) ->replace('\\', '/') // `realpath` makes slashes backwards, so replacements below wouldn't work ->replaceStart(root_path('public'), '') diff --git a/packages/vite/src/TagsResolver/ManifestTagsResolver.php b/packages/vite/src/TagsResolver/ManifestTagsResolver.php index 32cf77ce70..1d9d0d33ab 100644 --- a/packages/vite/src/TagsResolver/ManifestTagsResolver.php +++ b/packages/vite/src/TagsResolver/ManifestTagsResolver.php @@ -91,7 +91,7 @@ private function getStyleTags(Chunk $chunk): array return array_merge( $styleChunks, - array_map(fn (string $path) => ['file' => $path], $chunk->css), + array_map(static fn (string $path) => ['file' => $path], $chunk->css), ); }; @@ -179,7 +179,7 @@ private function resolvePrefetchingScript(Chunk $chunk): ?string }; $assets = array_values(array_map( - callback: fn (array $asset) => array_map(strval(...), $asset), + callback: static fn (array $asset) => array_map(strval(...), $asset), array: array_unique($findPrefetchableAssets($chunk), flags: SORT_REGULAR), )); @@ -253,8 +253,8 @@ private function fileToAssetPath(string $file): string { return str($file) ->when( - condition: fn ($file) => $file->startsWith('./'), - callback: fn ($file) => str(Filesystem\normalize_path(root_path($file->toString()))), + condition: static fn ($file) => $file->startsWith('./'), + callback: static fn ($file) => str(Filesystem\normalize_path(root_path($file->toString()))), ) ->replaceStart(root_path('public'), '') ->replaceStart(root_path(), '') diff --git a/src/Tempest/Framework/Commands/ConfigShowCommand.php b/src/Tempest/Framework/Commands/ConfigShowCommand.php index aba4447dba..90427dab7d 100644 --- a/src/Tempest/Framework/Commands/ConfigShowCommand.php +++ b/src/Tempest/Framework/Commands/ConfigShowCommand.php @@ -103,14 +103,14 @@ private function searchConfigFile(array $configs): string $return = $this->console->search( label: 'Which configuration file would you like to view?', - search: function (string $query) use ($data): array { + search: static function (string $query) use ($data): array { if ($query === '') { return $data; } return array_filter( array: $data, - callback: fn (string $path) => str_contains($path, $query), + callback: static fn (string $path) => str_contains($path, $query), ); }, default: $data[0], diff --git a/src/Tempest/Framework/Commands/MetaViewComponentCommand.php b/src/Tempest/Framework/Commands/MetaViewComponentCommand.php index ef9c5b0e14..661fbb4e97 100644 --- a/src/Tempest/Framework/Commands/MetaViewComponentCommand.php +++ b/src/Tempest/Framework/Commands/MetaViewComponentCommand.php @@ -62,7 +62,7 @@ private function resolveViewComponent(string $viewComponent): ?ViewComponent if (is_file($viewComponent)) { return array_find( array: $this->viewConfig->viewComponents, - callback: fn ($registeredViewComponent) => $registeredViewComponent->file === $viewComponent, + callback: static fn ($registeredViewComponent) => $registeredViewComponent->file === $viewComponent, ); } @@ -74,7 +74,7 @@ private function resolveSlots(ViewComponent $viewComponent): ImmutableArray preg_match_all('/[\w-]+)")?((\s*\/>)|>(?(.|\n)*?)<\/x-slot>)/', $viewComponent->contents, $matches); return arr($matches['name']) - ->mapWithKeys(fn (string $name) => yield $name => $name === '' ? Slot::DEFAULT : $name) + ->mapWithKeys(static fn (string $name) => yield $name => $name === '' ? Slot::DEFAULT : $name) ->values(); } @@ -82,19 +82,19 @@ private function resolveVariables(ViewComponent $viewComponent): ImmutableArray { return str($viewComponent->contents) ->matchAll('/^\s*\*\s*@var.*$/m') - ->map(fn (array $matches) => str($matches[0])) - ->map(fn (ImmutableString $line) => $line->replaceRegex('/^\s*\*\s*@var\s*/', '')) - ->map(fn (ImmutableString $line) => $line->trim()) - ->map(fn (ImmutableString $line) => $line->explode(limit: 3)) + ->map(static fn (array $matches) => str($matches[0])) + ->map(static fn (ImmutableString $line) => $line->replaceRegex('/^\s*\*\s*@var\s*/', '')) + ->map(static fn (ImmutableString $line) => $line->trim()) + ->map(static fn (ImmutableString $line) => $line->explode(limit: 3)) ->mapWithKeys( - fn (ImmutableArray $parts) => yield $parts[1] => [ + static fn (ImmutableArray $parts) => yield $parts[1] => [ 'type' => $parts[0], 'name' => $parts[1], 'attributeName' => str($parts[1])->kebab()->ltrim('$'), 'description' => $parts[2] ?? null, ], ) - ->filter(fn (array $parts) => ! in_array($parts['name'], ['$this', '$attributes', '$slots'], strict: true)) + ->filter(static fn (array $parts) => ! in_array($parts['name'], ['$this', '$attributes', '$slots'], strict: true)) ->values(); } } diff --git a/src/Tempest/Framework/Installers/ConfigInstaller.php b/src/Tempest/Framework/Installers/ConfigInstaller.php index efd001ae99..238c7caa43 100644 --- a/src/Tempest/Framework/Installers/ConfigInstaller.php +++ b/src/Tempest/Framework/Installers/ConfigInstaller.php @@ -25,9 +25,9 @@ public function __construct( public function install(): void { $searchOptions = arr($this->loadConfig->find()) - ->map(fn (string $path) => str($path)) - ->filter(fn (ImmutableString $path) => $path->contains(['/packages/', '/vendor/'])) - ->mapWithKeys(fn (ImmutableString $path) => yield $path->toString() => $path->afterLast('/')->toString()); + ->map(static fn (string $path) => str($path)) + ->filter(static fn (ImmutableString $path) => $path->contains(['/packages/', '/vendor/'])) + ->mapWithKeys(static fn (ImmutableString $path) => yield $path->toString() => $path->afterLast('/')->toString()); if ($searchOptions->isEmpty()) { $this->error('No installable config files found.'); diff --git a/src/Tempest/Framework/Installers/FrameworkInstaller.php b/src/Tempest/Framework/Installers/FrameworkInstaller.php index 82e8e70118..8b8d3ad759 100644 --- a/src/Tempest/Framework/Installers/FrameworkInstaller.php +++ b/src/Tempest/Framework/Installers/FrameworkInstaller.php @@ -36,7 +36,7 @@ public function install(): void $tempest = $this->publish( source: __DIR__ . '/tempest', destination: root_path('tempest'), - callback: function (string $_, string $destination): void { + callback: static function (string $_, string $destination): void { if (PHP_OS_FAMILY !== 'Windows') { /** @phpstan-ignore-next-line */ exec("chmod +x {$destination}"); @@ -47,7 +47,7 @@ public function install(): void $this->publish( source: __DIR__ . '/AGENTS.md', destination: root_path('AGENTS.md'), - callback: function (string $_, string $destination): void { + callback: static function (string $_, string $destination): void { $claude = root_path('CLAUDE.md'); if (PHP_OS_FAMILY !== 'Windows') { diff --git a/src/Tempest/Framework/Installers/ViewComponentsInstaller.php b/src/Tempest/Framework/Installers/ViewComponentsInstaller.php index 398571d7b9..c737cae5b7 100644 --- a/src/Tempest/Framework/Installers/ViewComponentsInstaller.php +++ b/src/Tempest/Framework/Installers/ViewComponentsInstaller.php @@ -24,7 +24,7 @@ public function __construct( public function install(): void { $searchOptions = arr($this->viewConfig->viewComponents) - ->filter(fn (ViewComponent $viewComponent) => $viewComponent->isVendorComponent); + ->filter(static fn (ViewComponent $viewComponent) => $viewComponent->isVendorComponent); if ($searchOptions->isEmpty()) { $this->error('No installable view vendor components found.'); diff --git a/src/Tempest/Framework/Testing/Http/HttpRouterTester.php b/src/Tempest/Framework/Testing/Http/HttpRouterTester.php index 15c636153c..0e027da0e8 100644 --- a/src/Tempest/Framework/Testing/Http/HttpRouterTester.php +++ b/src/Tempest/Framework/Testing/Http/HttpRouterTester.php @@ -323,7 +323,7 @@ private function createHeaders(array $headers = []): array { $key = array_find_key( array: $headers, - callback: fn (mixed $_, string $headerKey): bool => strcasecmp($headerKey, 'accept') === 0, + callback: static fn (mixed $_, string $headerKey): bool => strcasecmp($headerKey, 'accept') === 0, ); if ($this->contentType instanceof ContentType) { diff --git a/src/Tempest/Framework/Testing/Http/TestResponseHelper.php b/src/Tempest/Framework/Testing/Http/TestResponseHelper.php index b3e244d53b..6ab0e2aa27 100644 --- a/src/Tempest/Framework/Testing/Http/TestResponseHelper.php +++ b/src/Tempest/Framework/Testing/Http/TestResponseHelper.php @@ -214,7 +214,7 @@ public function assertHasCookie(string $key, string|Closure|null $value = null): /** @var array */ $cookies = Arr\map_with_keys( array: $this->response->getHeader('set-cookie')->values, - map: function (string $cookie) { + map: static function (string $cookie) { $cookie = Cookie::createFromString($cookie); yield $cookie->key => $cookie; }, @@ -247,7 +247,7 @@ public function assertDoesNotHaveCookie(string $key, string|Closure|null $value /** @var array */ $cookies = Arr\map_with_keys( array: $this->response->getHeader('set-cookie')->values ?? [], - map: function (string $cookie) { + map: static function (string $cookie) { $cookie = Cookie::createFromString($cookie); yield $cookie->key => $cookie; }, @@ -367,7 +367,7 @@ public function assertHasNoValidationsErrors(): self Assert::assertEmpty( actual: $validationErrors, message: arr($validationErrors) - ->map(fn (array $failingRules, string $key) => $key . ': ' . arr($failingRules)->map(fn (Rule $rule) => $rule::class)->implode(', ')) + ->map(static fn (array $failingRules, string $key) => $key . ': ' . arr($failingRules)->map(static fn (Rule $rule) => $rule::class)->implode(', ')) ->implode(', ') ->prepend('There should be no validation errors, but there were: ') ->toString(), diff --git a/src/Tempest/Framework/Testing/IntegrationTest.php b/src/Tempest/Framework/Testing/IntegrationTest.php index f755385332..514a15355b 100644 --- a/src/Tempest/Framework/Testing/IntegrationTest.php +++ b/src/Tempest/Framework/Testing/IntegrationTest.php @@ -176,8 +176,8 @@ protected function setupKernel(): self protected function setupConsole(): self { $this->console = new ConsoleTester($this->container); - $this->container->singleton(OutputBuffer::class, fn () => new MemoryOutputBuffer()); - $this->container->singleton(StdoutOutputBuffer::class, fn () => new MemoryOutputBuffer()); + $this->container->singleton(OutputBuffer::class, static fn () => new MemoryOutputBuffer()); + $this->container->singleton(StdoutOutputBuffer::class, static fn () => new MemoryOutputBuffer()); return $this; } @@ -212,8 +212,8 @@ protected function setupTesters(): self protected function setupBaseRequest(): self { $request = new GenericRequest(Method::GET, '/', []); - $this->container->singleton(Request::class, fn () => $request); - $this->container->singleton(GenericRequest::class, fn () => $request); + $this->container->singleton(Request::class, static fn () => $request); + $this->container->singleton(GenericRequest::class, static fn () => $request); return $this; } @@ -230,7 +230,7 @@ protected function clock(DateTimeInterface|string $now = 'now'): MockClock { $clock = new MockClock($now); - $this->container->singleton(Clock::class, fn () => $clock); + $this->container->singleton(Clock::class, static fn () => $clock); return $clock; } diff --git a/src/Tempest/Framework/Testing/ViteTester.php b/src/Tempest/Framework/Testing/ViteTester.php index cb9b5341c7..0d5868d874 100644 --- a/src/Tempest/Framework/Testing/ViteTester.php +++ b/src/Tempest/Framework/Testing/ViteTester.php @@ -54,7 +54,7 @@ public function clearCaches(): self */ public function preventTagResolution(): self { - $this->container->register(TagsResolver::class, fn () => new NullTagsResolver()); + $this->container->register(TagsResolver::class, static fn () => new NullTagsResolver()); return $this; } @@ -150,7 +150,7 @@ public function call(callable $callback, array $files, bool $manifest = false, ? $this->container->config($actualViteConfig); if ($tagsResolver) { - $this->container->register(TagsResolver::class, fn () => $tagsResolver); + $this->container->register(TagsResolver::class, static fn () => $tagsResolver); } delete_directory($temporaryRootDirectory); diff --git a/structarmed.php b/structarmed.php new file mode 100644 index 0000000000..d86a14494d --- /dev/null +++ b/structarmed.php @@ -0,0 +1,84 @@ +layer('Auth', 'packages/auth/src') + ->layer('Cache', 'packages/cache/src') + ->layer('Clock', 'packages/clock/src') + ->layer('CommandBus', 'packages/command-bus/src') + ->layer('Console', 'packages/console/src') + ->layer('Container', 'packages/container/src') + ->layer('Core', 'packages/core/src') + ->layer('Cryptography', 'packages/cryptography/src') + ->layer('Database', 'packages/database/src') + ->layer('DateTime', 'packages/datetime/src') + ->layer('Debug', 'packages/debug/src') + ->layer('Discovery', 'packages/discovery/src') + ->layer('EventBus', 'packages/event-bus/src') + ->layer('Framework', 'src/Tempest/Framework') + ->layer('Generation', 'packages/generation/src') + ->layer('Http', 'packages/http/src') + ->layer('HttpClient', 'packages/http-client/src') + ->layer('Icon', 'packages/icon/src') + ->layer('Idempotency', 'packages/idempotency/src') + ->layer('Intl', 'packages/intl/src') + ->layer('KeyValue', 'packages/kv-store/src') + ->layer('Log', 'packages/log/src') + ->layer('Mail', 'packages/mail/src') + ->layer('Mapper', 'packages/mapper/src') + ->layer('Mcp', 'packages/mcp/src') + ->layer('Process', 'packages/process/src') + ->layer('Reflection', 'packages/reflection/src') + ->layer('Router', 'packages/router/src') + ->layer('Storage', 'packages/storage/src') + ->layer('Support', 'packages/support/src') + ->layer('Upgrade', 'packages/upgrade/src') + ->layer('Validation', 'packages/validation/src') + ->layer('View', 'packages/view/src') + ->layer('Vite', 'packages/vite/src') + ->ruleset([ + 'Auth' => ['Container', 'Discovery', 'Http', 'Mapper', 'Reflection', 'Router', 'Support'], + 'Cache' => ['+Clock', 'Console', 'Core', 'Discovery', 'Icon', 'KeyValue', 'Reflection', 'View'], + 'Clock' => ['Container', 'DateTime'], + 'CommandBus' => ['+Clock', '+Container', 'Database', '+Generation', 'KeyValue'], + 'Console' => ['CommandBus', '+Discovery', '+EventBus', 'Http', 'Router'], + 'Container' => ['Console', 'Core', 'Discovery', 'Generation', 'Reflection', 'Support', 'Validation'], + 'Core' => ['+Discovery', '+Generation', '+Log', 'Router'], + 'Cryptography' => ['+Clock', 'Console', 'Core'], + 'Database' => ['+Container', 'Cryptography', '+EventBus', '+Generation', '+Mapper', 'Router'], + 'DateTime' => ['+Clock', 'Intl', 'Support'], + 'Debug' => ['Console', 'Container', 'EventBus'], + 'Discovery' => ['+Container', 'Process'], + 'EventBus' => ['Container', 'Core', 'Discovery', 'Reflection'], + 'Framework' => ['+Auth', '+Cryptography', '+Database', '+Discovery', '+Mail', '+Mcp', '+View', '+Vite'], + 'Generation' => ['Console', 'Container', 'DateTime', 'Discovery', 'Reflection', 'Support'], + 'Http' => ['+Cryptography', '+Database', '+KeyValue', 'View'], + 'HttpClient' => ['Container', 'Http'], + 'Icon' => ['DateTime', 'EventBus', '+HttpClient', 'Support'], + 'Idempotency' => ['Cache', 'CommandBus', 'Container', 'DateTime', 'Discovery', 'Http', 'Reflection', 'Router', 'Support', 'View'], + 'Intl' => ['DateTime', '+EventBus', 'Icon'], + 'KeyValue' => ['Container', 'Core', 'DateTime', 'EventBus', 'Support'], + 'Log' => ['Console', 'Container', 'Core', 'EventBus', 'Reflection'], + 'Mail' => ['Container', 'DateTime', 'EventBus', 'Mapper', 'Storage', 'View'], + 'Mapper' => ['Container', 'DateTime', 'Discovery', 'Reflection', 'Support', 'Validation'], + 'Mcp' => ['Console', 'Container', 'Core', 'Discovery', 'Http', 'Mapper', 'Reflection', 'Router', 'Validation'], + 'Process' => ['Container', 'Core', 'DateTime', 'Support'], + 'Reflection' => [], + 'Router' => ['Auth', 'Cryptography', '+EventBus', '+Generation', '+HttpClient', '+Support', '+Validation', 'View', '+Vite'], + 'Storage' => ['Container', 'Discovery', 'Reflection', 'Support'], + 'Support' => ['Console', 'Debug', 'Intl', 'Validation'], + 'Upgrade' => ['Core', 'Database', 'Router'], + 'Validation' => ['Container', 'Core', 'DateTime', 'Intl', 'Reflection', 'Support'], + 'View' => ['Cache', '+Container'], + 'Vite' => ['+Container'], + ]) + ->withPresets(Preset::PSR4(), Preset::CODEQUALITY()) + ->skip([ + 'packages/auth/src/Installer', + 'packages/**/tests', + __DIR__ . '/tests', + ]);