From 4d9e547e9851bb3158f1f9640b73d1bc5b53204e Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Mon, 6 Jan 2025 09:53:58 +0100 Subject: [PATCH 01/53] improve GetBySymfonyStringToConstructorInjectionRector with session, translator and security.token_storage --- ...ySymfonyStringToConstructorInjectionRector.php | 3 +++ src/Enum/SymfonyClass.php | 15 +++++++++++++++ .../Component/Translation/TranslatorInterface.php | 1 - 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/rules/DependencyInjection/Rector/Class_/GetBySymfonyStringToConstructorInjectionRector.php b/rules/DependencyInjection/Rector/Class_/GetBySymfonyStringToConstructorInjectionRector.php index bb9236cf..8901a040 100644 --- a/rules/DependencyInjection/Rector/Class_/GetBySymfonyStringToConstructorInjectionRector.php +++ b/rules/DependencyInjection/Rector/Class_/GetBySymfonyStringToConstructorInjectionRector.php @@ -32,6 +32,9 @@ final class GetBySymfonyStringToConstructorInjectionRector extends AbstractRecto 'event_dispatcher' => SymfonyClass::EVENT_DISPATCHER_INTERFACE, 'logger' => SymfonyClass::LOGGER_INTERFACE, 'jms_serializer' => SymfonyClass::SERIALIZER_INTERFACE, + 'translator' => SymfonyClass::TRANSLATOR_INTERFACE, + 'session' => SymfonyClass::SESSION, + 'security.token_storage' => SymfonyClass::TOKEN_STORAGE_INTERFACE, ]; public function __construct( diff --git a/src/Enum/SymfonyClass.php b/src/Enum/SymfonyClass.php index 1c845e65..9f5190cd 100644 --- a/src/Enum/SymfonyClass.php +++ b/src/Enum/SymfonyClass.php @@ -60,4 +60,19 @@ final class SymfonyClass * @var string */ public const EVENT_SUBSCRIBER_INTERFACE = 'Symfony\Component\EventDispatcher\EventSubscriberInterface'; + + /** + * @var string + */ + public const TRANSLATOR_INTERFACE = 'Symfony\Contracts\Translation\TranslatorInterface'; + + /** + * @var string + */ + public const SESSION = 'Symfony\Component\HttpFoundation\Session\Session'; + + /** + * @var string + */ + public const TOKEN_STORAGE_INTERFACE = 'Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface'; } diff --git a/stubs/Symfony/Component/Translation/TranslatorInterface.php b/stubs/Symfony/Component/Translation/TranslatorInterface.php index e2e06dad..a0fb6c83 100644 --- a/stubs/Symfony/Component/Translation/TranslatorInterface.php +++ b/stubs/Symfony/Component/Translation/TranslatorInterface.php @@ -10,5 +10,4 @@ interface TranslatorInterface { - } From 7b982875569dbbad9bbe943eca53253d60320bcb Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Mon, 6 Jan 2025 10:27:25 +0100 Subject: [PATCH 02/53] Add fixture that prefers required if found (#695) --- .../Fixture/prefer_required_setter.php.inc | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 rules-tests/DependencyInjection/Rector/Class_/GetBySymfonyStringToConstructorInjectionRector/Fixture/prefer_required_setter.php.inc diff --git a/rules-tests/DependencyInjection/Rector/Class_/GetBySymfonyStringToConstructorInjectionRector/Fixture/prefer_required_setter.php.inc b/rules-tests/DependencyInjection/Rector/Class_/GetBySymfonyStringToConstructorInjectionRector/Fixture/prefer_required_setter.php.inc new file mode 100644 index 00000000..d5965603 --- /dev/null +++ b/rules-tests/DependencyInjection/Rector/Class_/GetBySymfonyStringToConstructorInjectionRector/Fixture/prefer_required_setter.php.inc @@ -0,0 +1,62 @@ +eventDispatcher = $eventDispatcher; + } + + + public function configure() + { + $someType = $this->get('validator'); + } +} + +?> +----- +eventDispatcher = $eventDispatcher; + $this->validator = $validator; + } + + + public function configure() + { + $someType = $this->validator; + } +} + +?> From f14ec1ab84460a4ecc961bb69dc3c8c6c4122e60 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Mon, 6 Jan 2025 17:15:02 +0700 Subject: [PATCH 03/53] Update GetBySymfonyStringToConstructorInjectionRector fixture test to cover rector-srv:tv-readonly-add-ctor (#696) --- composer.json | 2 +- .../Fixture/prefer_required_setter.php.inc | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/composer.json b/composer.json index 5bfccf2e..38a9e9e5 100644 --- a/composer.json +++ b/composer.json @@ -12,7 +12,7 @@ "phpstan/phpstan": "^2.0", "phpstan/phpstan-webmozart-assert": "^2.0", "phpunit/phpunit": "^11.4", - "rector/rector-src": "dev-main", + "rector/rector-src": "dev-tv-readonly-add-ctor", "symfony/config": "^6.4", "symfony/dependency-injection": "^6.4", "symfony/http-kernel": "~6.3", diff --git a/rules-tests/DependencyInjection/Rector/Class_/GetBySymfonyStringToConstructorInjectionRector/Fixture/prefer_required_setter.php.inc b/rules-tests/DependencyInjection/Rector/Class_/GetBySymfonyStringToConstructorInjectionRector/Fixture/prefer_required_setter.php.inc index d5965603..56b71157 100644 --- a/rules-tests/DependencyInjection/Rector/Class_/GetBySymfonyStringToConstructorInjectionRector/Fixture/prefer_required_setter.php.inc +++ b/rules-tests/DependencyInjection/Rector/Class_/GetBySymfonyStringToConstructorInjectionRector/Fixture/prefer_required_setter.php.inc @@ -33,20 +33,17 @@ namespace Rector\Symfony\Tests\DependencyInjection\Rector\Class_\GetBySymfonyStr use Psr\EventDispatcher\EventDispatcherInterface; use Symfony\Bundle\FrameworkBundle\Controller\Controller; -use Symfony\Component\Validator\Validator\ValidatorInterface; class PreferRequiredSetter extends Controller { private EventDispatcherInterface $eventDispatcher; - - private ValidatorInterface $validator; + private \Symfony\Component\Validator\Validator\ValidatorInterface $validator; /** * @required */ public function autowire( - EventDispatcherInterface $eventDispatcher, - ValidatorInterface $validator + EventDispatcherInterface $eventDispatcher, \Symfony\Component\Validator\Validator\ValidatorInterface $validator ) { $this->eventDispatcher = $eventDispatcher; $this->validator = $validator; From a3253b4a96532357e8faf9e837e9be82237e2e80 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Mon, 6 Jan 2025 17:17:22 +0700 Subject: [PATCH 04/53] Back to require-dev rector-src:dev-main (#697) --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 38a9e9e5..5bfccf2e 100644 --- a/composer.json +++ b/composer.json @@ -12,7 +12,7 @@ "phpstan/phpstan": "^2.0", "phpstan/phpstan-webmozart-assert": "^2.0", "phpunit/phpunit": "^11.4", - "rector/rector-src": "dev-tv-readonly-add-ctor", + "rector/rector-src": "dev-main", "symfony/config": "^6.4", "symfony/dependency-injection": "^6.4", "symfony/http-kernel": "~6.3", From 4661c012e9eca57e9bd4c50d9c83bcb9e6917b8a Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Mon, 6 Jan 2025 13:21:26 +0100 Subject: [PATCH 05/53] extend list in GetBySymfonyStringToConstructorInjectionRector --- ...ymfonyStringToConstructorInjectionRector.php | 17 +++++++++++++++-- src/Enum/SymfonyClass.php | 4 ++-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/rules/DependencyInjection/Rector/Class_/GetBySymfonyStringToConstructorInjectionRector.php b/rules/DependencyInjection/Rector/Class_/GetBySymfonyStringToConstructorInjectionRector.php index 8901a040..769dcd86 100644 --- a/rules/DependencyInjection/Rector/Class_/GetBySymfonyStringToConstructorInjectionRector.php +++ b/rules/DependencyInjection/Rector/Class_/GetBySymfonyStringToConstructorInjectionRector.php @@ -31,10 +31,23 @@ final class GetBySymfonyStringToConstructorInjectionRector extends AbstractRecto 'validator' => SymfonyClass::VALIDATOR_INTERFACE, 'event_dispatcher' => SymfonyClass::EVENT_DISPATCHER_INTERFACE, 'logger' => SymfonyClass::LOGGER_INTERFACE, - 'jms_serializer' => SymfonyClass::SERIALIZER_INTERFACE, + 'jms_serializer' => SymfonyClass::JMS_SERIALIZER_INTERFACE, 'translator' => SymfonyClass::TRANSLATOR_INTERFACE, - 'session' => SymfonyClass::SESSION, + 'session' => SymfonyClass::SESSION_INTERFACRE, 'security.token_storage' => SymfonyClass::TOKEN_STORAGE_INTERFACE, + 'router' => 'Symfony\Component\Routing\RouterInterface', + 'request_stack' => 'Symfony\Component\HttpFoundation\RequestStack', + 'http_kernel' => 'Symfony\Component\HttpKernel\HttpKernelInterface', + 'serializer' => 'Symfony\Component\Serializer\SerializerInterface', + 'security.authorization_checker' => 'Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface', + 'templating' => 'Symfony\Component\Templating\EngineInterface', + 'twig' => 'Twig\Environment', + 'doctrine' => 'Doctrine\Persistence\ManagerRegistry', + 'form.factory' => 'Symfony\Component\Form\FormFactoryInterface', + 'security.csrf.token_manager' => 'Symfony\Component\Security\Core\Authorization\CsrfTokenManagerInterface', + 'parameter_bag' => 'Symfony\Component\DependencyInjection\ParameterBag\ContainerBagInterface', + 'message_bus' => 'Symfony\Component\Messenger\MessageBusInterface', + 'messenger.default_bus' => 'Symfony\Component\Messenger\MessageBusInterface', ]; public function __construct( diff --git a/src/Enum/SymfonyClass.php b/src/Enum/SymfonyClass.php index 9f5190cd..d79bafad 100644 --- a/src/Enum/SymfonyClass.php +++ b/src/Enum/SymfonyClass.php @@ -44,7 +44,7 @@ final class SymfonyClass /** * @var string */ - public const SERIALIZER_INTERFACE = 'JMS\Serializer\SerializerInterface'; + public const JMS_SERIALIZER_INTERFACE = 'JMS\Serializer\SerializerInterface'; /** * @var string @@ -69,7 +69,7 @@ final class SymfonyClass /** * @var string */ - public const SESSION = 'Symfony\Component\HttpFoundation\Session\Session'; + public const SESSION_INTERFACRE = 'Symfony\Component\HttpFoundation\Session\SessionInterface'; /** * @var string From 3fb51717851c36174357fe97dc77afb233e42654 Mon Sep 17 00:00:00 2001 From: Carlos Granados Date: Fri, 14 Feb 2025 14:03:53 +0100 Subject: [PATCH 06/53] Do not change method if name does not need to change (#700) --- .../Rector/ClassMethod/ActionSuffixRemoverRector.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/rules/CodeQuality/Rector/ClassMethod/ActionSuffixRemoverRector.php b/rules/CodeQuality/Rector/ClassMethod/ActionSuffixRemoverRector.php index ec85c9fe..dc652cad 100644 --- a/rules/CodeQuality/Rector/ClassMethod/ActionSuffixRemoverRector.php +++ b/rules/CodeQuality/Rector/ClassMethod/ActionSuffixRemoverRector.php @@ -72,16 +72,18 @@ public function refactor(Node $node): ?Node return null; } - $this->removeSuffix($node, 'Action'); - - return $node; + return $this->removeSuffix($node, 'Action'); } - private function removeSuffix(ClassMethod $classMethod, string $suffixToRemove): void + private function removeSuffix(ClassMethod $classMethod, string $suffixToRemove): ?ClassMethod { $name = $this->nodeNameResolver->getName($classMethod); $newName = Strings::replace($name, sprintf('#%s$#', $suffixToRemove), ''); + if ($newName === $name) { + return null; + } $classMethod->name = new Identifier($newName); + return $classMethod; } } From 2eb7139cd4f4482bc210f013964589dac734349a Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Sat, 15 Feb 2025 22:04:28 +0100 Subject: [PATCH 07/53] [code-quality] Add InlineClassRoutePrefixRector (#701) --- config/sets/symfony/symfony-code-quality.php | 4 + .../Fixture/explicit_silent_mix.php.inc | 40 ++++ .../inversed_explicit_silent_mix.php.inc | 40 ++++ .../Fixture/skip_no_controller.php.inc | 18 ++ .../Fixture/some_routing_class.php.inc | 40 ++++ .../InlineClassRoutePrefixRectorTest.php | 28 +++ .../config/configured_rule.php | 10 + .../Class_/InlineClassRoutePrefixRector.php | 207 ++++++++++++++++++ .../ListenerServiceDefinitionProvider.php | 12 +- src/Enum/FosAnnotation.php | 23 ++ 10 files changed, 415 insertions(+), 7 deletions(-) create mode 100644 rules-tests/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector/Fixture/explicit_silent_mix.php.inc create mode 100644 rules-tests/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector/Fixture/inversed_explicit_silent_mix.php.inc create mode 100644 rules-tests/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector/Fixture/skip_no_controller.php.inc create mode 100644 rules-tests/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector/Fixture/some_routing_class.php.inc create mode 100644 rules-tests/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector/InlineClassRoutePrefixRectorTest.php create mode 100644 rules-tests/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector/config/configured_rule.php create mode 100644 rules/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector.php create mode 100644 src/Enum/FosAnnotation.php diff --git a/config/sets/symfony/symfony-code-quality.php b/config/sets/symfony/symfony-code-quality.php index 330a73ba..809ea40e 100644 --- a/config/sets/symfony/symfony-code-quality.php +++ b/config/sets/symfony/symfony-code-quality.php @@ -5,6 +5,7 @@ use Rector\Config\RectorConfig; use Rector\Symfony\CodeQuality\Rector\BinaryOp\ResponseStatusCodeRector; use Rector\Symfony\CodeQuality\Rector\Class_\EventListenerToEventSubscriberRector; +use Rector\Symfony\CodeQuality\Rector\Class_\InlineClassRoutePrefixRector; use Rector\Symfony\CodeQuality\Rector\Class_\LoadValidatorMetadataToAnnotationRector; use Rector\Symfony\CodeQuality\Rector\ClassMethod\ActionSuffixRemoverRector; use Rector\Symfony\CodeQuality\Rector\ClassMethod\ParamTypeFromRouteRequiredRegexRector; @@ -30,5 +31,8 @@ // tests AssertSameResponseCodeWithDebugContentsRector::class, + + // routing + InlineClassRoutePrefixRector::class, ]); }; diff --git a/rules-tests/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector/Fixture/explicit_silent_mix.php.inc b/rules-tests/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector/Fixture/explicit_silent_mix.php.inc new file mode 100644 index 00000000..1d110132 --- /dev/null +++ b/rules-tests/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector/Fixture/explicit_silent_mix.php.inc @@ -0,0 +1,40 @@ + +----- + diff --git a/rules-tests/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector/Fixture/inversed_explicit_silent_mix.php.inc b/rules-tests/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector/Fixture/inversed_explicit_silent_mix.php.inc new file mode 100644 index 00000000..e2ac7f1b --- /dev/null +++ b/rules-tests/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector/Fixture/inversed_explicit_silent_mix.php.inc @@ -0,0 +1,40 @@ + +----- + diff --git a/rules-tests/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector/Fixture/skip_no_controller.php.inc b/rules-tests/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector/Fixture/skip_no_controller.php.inc new file mode 100644 index 00000000..2ce30425 --- /dev/null +++ b/rules-tests/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector/Fixture/skip_no_controller.php.inc @@ -0,0 +1,18 @@ + +----- + diff --git a/rules-tests/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector/InlineClassRoutePrefixRectorTest.php b/rules-tests/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector/InlineClassRoutePrefixRectorTest.php new file mode 100644 index 00000000..ee362781 --- /dev/null +++ b/rules-tests/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector/InlineClassRoutePrefixRectorTest.php @@ -0,0 +1,28 @@ +doTestFile($filePath); + } + + public static function provideData(): Iterator + { + return self::yieldFilesFromDirectory(__DIR__ . '/Fixture'); + } + + public function provideConfigFilePath(): string + { + return __DIR__ . '/config/configured_rule.php'; + } +} diff --git a/rules-tests/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector/config/configured_rule.php b/rules-tests/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector/config/configured_rule.php new file mode 100644 index 00000000..5044168a --- /dev/null +++ b/rules-tests/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector/config/configured_rule.php @@ -0,0 +1,10 @@ +rule(InlineClassRoutePrefixRector::class); +}; diff --git a/rules/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector.php b/rules/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector.php new file mode 100644 index 00000000..7f6ac1b0 --- /dev/null +++ b/rules/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector.php @@ -0,0 +1,207 @@ +shouldSkipClass($node)) { + return null; + } + + // 1. detect and remove class-level Route annotation + $classPhpDocInfo = $this->phpDocInfoFactory->createFromNode($node); + if (! $classPhpDocInfo instanceof PhpDocInfo) { + return null; + } + + $classRouteTagValueNode = $classPhpDocInfo->getByAnnotationClass(SymfonyAnnotation::ROUTE); + if (! $classRouteTagValueNode instanceof DoctrineAnnotationTagValueNode) { + return null; + } + + $classRoutePathNode = $classRouteTagValueNode->getSilentValue() ?: $classRouteTagValueNode->getValue('path'); + if (! $classRoutePathNode instanceof ArrayItemNode) { + return null; + } + + if (! $classRoutePathNode->value instanceof StringNode) { + return null; + } + + $classRoutePath = $classRoutePathNode->value->value; + + // 2. inline prefix to all method routes + $hasChanged = false; + + foreach ($node->getMethods() as $classMethod) { + if (! $classMethod->isPublic()) { + continue; + } + + if ($classMethod->isMagic()) { + continue; + } + + // can be route method + $methodPhpDocInfo = $this->phpDocInfoFactory->createFromNode($classMethod); + if (! $methodPhpDocInfo instanceof PhpDocInfo) { + continue; + } + + $methodRouteTagValueNodes = $methodPhpDocInfo->findByAnnotationClass(SymfonyAnnotation::ROUTE); + foreach ($methodRouteTagValueNodes as $methodRouteTagValueNode) { + $routePathArrayItemNode = $methodRouteTagValueNode->getSilentValue() ?? $methodRouteTagValueNode->getValue( + 'path' + ); + if (! $routePathArrayItemNode instanceof ArrayItemNode) { + continue; + } + + if (! $routePathArrayItemNode->value instanceof StringNode) { + continue; + } + + $methodPrefix = $routePathArrayItemNode->value; + $newMethodPath = $classRoutePath . $methodPrefix->value; + + $routePathArrayItemNode->value = new StringNode($newMethodPath); + $this->docBlockUpdater->updateRefactoredNodeWithPhpDocInfo($classMethod); + + $hasChanged = true; + } + } + + if (! $hasChanged) { + return null; + } + + $this->phpDocTagRemover->removeTagValueFromNode($classPhpDocInfo, $classRouteTagValueNode); + $this->docBlockUpdater->updateRefactoredNodeWithPhpDocInfo($node); + + return $node; + } + + private function shouldSkipClass(Class_ $class): bool + { + if (! $class->extends instanceof Name) { + return true; + } + + if (! $this->controllerAnalyzer->isController($class)) { + return true; + } + + foreach ($class->getMethods() as $classMethod) { + if (! $classMethod->isPublic()) { + continue; + } + + if ($classMethod->isMagic()) { + continue; + } + + $classMethodPhpDocInfo = $this->phpDocInfoFactory->createFromNode($classMethod); + if (! $classMethodPhpDocInfo instanceof PhpDocInfo) { + continue; + } + + // special cases for FOS rest that should be skipped + if ($classMethodPhpDocInfo->hasByAnnotationClasses(self::SKIPPED_ANNOTATIONS)) { + return true; + } + } + + return false; + } +} diff --git a/src/ApplicationMetadata/ListenerServiceDefinitionProvider.php b/src/ApplicationMetadata/ListenerServiceDefinitionProvider.php index 8da9a2ae..47ea57f4 100644 --- a/src/ApplicationMetadata/ListenerServiceDefinitionProvider.php +++ b/src/ApplicationMetadata/ListenerServiceDefinitionProvider.php @@ -54,13 +54,11 @@ public function extract(): array $eventName = $tag->getEvent(); - if ($tag->getMethod() === '') { - // fill method based on the event - if (str_starts_with($tag->getEvent(), 'kernel.')) { - [, $event] = explode('.', $tag->getEvent()); - $methodName = 'onKernel' . ucfirst($event); - $tag->changeMethod($methodName); - } + // fill method based on the event + if ($tag->getMethod() === '' && str_starts_with($tag->getEvent(), 'kernel.')) { + [, $event] = explode('.', $tag->getEvent()); + $methodName = 'onKernel' . ucfirst($event); + $tag->changeMethod($methodName); } $this->listenerClassesToEvents[$eventListener->getClass()][$eventName][] = $eventListener; diff --git a/src/Enum/FosAnnotation.php b/src/Enum/FosAnnotation.php new file mode 100644 index 00000000..9679e587 --- /dev/null +++ b/src/Enum/FosAnnotation.php @@ -0,0 +1,23 @@ + Date: Sat, 15 Feb 2025 23:01:39 +0100 Subject: [PATCH 08/53] [code-quality] Add attribute support (#702) --- .../Fixture/attribute_routing_class.php.inc | 34 ++++ .../Class_/InlineClassRoutePrefixRector.php | 178 +++++++++++------- src/Enum/SymfonyAttribute.php | 5 + 3 files changed, 152 insertions(+), 65 deletions(-) create mode 100644 rules-tests/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector/Fixture/attribute_routing_class.php.inc diff --git a/rules-tests/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector/Fixture/attribute_routing_class.php.inc b/rules-tests/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector/Fixture/attribute_routing_class.php.inc new file mode 100644 index 00000000..767a0e81 --- /dev/null +++ b/rules-tests/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector/Fixture/attribute_routing_class.php.inc @@ -0,0 +1,34 @@ + +----- + diff --git a/rules/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector.php b/rules/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector.php index 7f6ac1b0..5053afd9 100644 --- a/rules/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector.php +++ b/rules/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector.php @@ -5,18 +5,20 @@ namespace Rector\Symfony\CodeQuality\Rector\Class_; use PhpParser\Node; -use PhpParser\Node\Name; +use PhpParser\Node\Attribute; +use PhpParser\Node\Scalar\String_; use PhpParser\Node\Stmt\Class_; use Rector\BetterPhpDocParser\PhpDoc\ArrayItemNode; use Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode; use Rector\BetterPhpDocParser\PhpDoc\StringNode; -use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo; use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory; use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTagRemover; use Rector\Comments\NodeDocBlock\DocBlockUpdater; +use Rector\Doctrine\NodeAnalyzer\AttrinationFinder; use Rector\Rector\AbstractRector; use Rector\Symfony\Enum\FosAnnotation; use Rector\Symfony\Enum\SymfonyAnnotation; +use Rector\Symfony\Enum\SymfonyAttribute; use Rector\Symfony\TypeAnalyzer\ControllerAnalyzer; use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; @@ -29,17 +31,23 @@ final class InlineClassRoutePrefixRector extends AbstractRector /** * @var string[] */ - private const SKIPPED_ANNOTATIONS = [ + private const FOS_REST_ANNOTATIONS = [ FosAnnotation::REST_POST, FosAnnotation::REST_GET, FosAnnotation::REST_ROUTE, ]; + /** + * @var string + */ + private const PATH = 'path'; + public function __construct( private readonly PhpDocInfoFactory $phpDocInfoFactory, private readonly PhpDocTagRemover $phpDocTagRemover, private readonly DocBlockUpdater $docBlockUpdater, private readonly ControllerAnalyzer $controllerAnalyzer, + private readonly AttrinationFinder $attrinationFinder ) { } @@ -80,7 +88,6 @@ public function action() } CODE_SAMPLE ), - ] ); } @@ -99,66 +106,76 @@ public function refactor(Node $node): ?Class_ return null; } - // 1. detect and remove class-level Route annotation - $classPhpDocInfo = $this->phpDocInfoFactory->createFromNode($node); - if (! $classPhpDocInfo instanceof PhpDocInfo) { - return null; - } + $classRoutePath = null; - $classRouteTagValueNode = $classPhpDocInfo->getByAnnotationClass(SymfonyAnnotation::ROUTE); - if (! $classRouteTagValueNode instanceof DoctrineAnnotationTagValueNode) { - return null; - } + // 1. detect attribute + $routeAttributeOrAnnotation = $this->attrinationFinder->getByMany( + $node, + [SymfonyAttribute::ROUTE, SymfonyAnnotation::ROUTE] + ); - $classRoutePathNode = $classRouteTagValueNode->getSilentValue() ?: $classRouteTagValueNode->getValue('path'); - if (! $classRoutePathNode instanceof ArrayItemNode) { - return null; + if ($routeAttributeOrAnnotation instanceof DoctrineAnnotationTagValueNode) { + $classRoutePath = $this->resolveRoutePath($routeAttributeOrAnnotation); + } elseif ($routeAttributeOrAnnotation instanceof Attribute) { + $classRoutePath = $this->resolveRoutePathFromAttribute($routeAttributeOrAnnotation); } - if (! $classRoutePathNode->value instanceof StringNode) { + if ($classRoutePath === null) { return null; } - $classRoutePath = $classRoutePathNode->value->value; - // 2. inline prefix to all method routes $hasChanged = false; foreach ($node->getMethods() as $classMethod) { - if (! $classMethod->isPublic()) { - continue; - } - - if ($classMethod->isMagic()) { + if (! $classMethod->isPublic() || $classMethod->isMagic()) { continue; } // can be route method - $methodPhpDocInfo = $this->phpDocInfoFactory->createFromNode($classMethod); - if (! $methodPhpDocInfo instanceof PhpDocInfo) { - continue; - } - - $methodRouteTagValueNodes = $methodPhpDocInfo->findByAnnotationClass(SymfonyAnnotation::ROUTE); - foreach ($methodRouteTagValueNodes as $methodRouteTagValueNode) { - $routePathArrayItemNode = $methodRouteTagValueNode->getSilentValue() ?? $methodRouteTagValueNode->getValue( - 'path' - ); - if (! $routePathArrayItemNode instanceof ArrayItemNode) { - continue; - } - - if (! $routePathArrayItemNode->value instanceof StringNode) { - continue; + $methodRouteAnnotationOrAttributes = $this->attrinationFinder->findManyByMany( + $classMethod, + [SymfonyAttribute::ROUTE, SymfonyAnnotation::ROUTE] + ); + + foreach ($methodRouteAnnotationOrAttributes as $methodRouteAnnotationOrAttribute) { + if ($methodRouteAnnotationOrAttribute instanceof DoctrineAnnotationTagValueNode) { + $routePathArrayItemNode = $methodRouteAnnotationOrAttribute->getSilentValue() ?? $methodRouteAnnotationOrAttribute->getValue( + self::PATH + ); + if (! $routePathArrayItemNode instanceof ArrayItemNode) { + continue; + } + + if (! $routePathArrayItemNode->value instanceof StringNode) { + continue; + } + + $methodPrefix = $routePathArrayItemNode->value; + $newMethodPath = $classRoutePath . $methodPrefix->value; + + $routePathArrayItemNode->value = new StringNode($newMethodPath); + $this->docBlockUpdater->updateRefactoredNodeWithPhpDocInfo($classMethod); + + $hasChanged = true; + } elseif ($methodRouteAnnotationOrAttribute instanceof Attribute) { + foreach ($methodRouteAnnotationOrAttribute->args as $methodRouteArg) { + if ($methodRouteArg->name === null || $methodRouteArg->name->toString() === self::PATH) { + if (! $methodRouteArg->value instanceof String_) { + continue; + } + + $methodRouteString = $methodRouteArg->value; + $methodRouteArg->value = new String_(sprintf( + '%s%s', + $classRoutePath, + $methodRouteString->value + )); + + $hasChanged = true; + } + } } - - $methodPrefix = $routePathArrayItemNode->value; - $newMethodPath = $classRoutePath . $methodPrefix->value; - - $routePathArrayItemNode->value = new StringNode($newMethodPath); - $this->docBlockUpdater->updateRefactoredNodeWithPhpDocInfo($classMethod); - - $hasChanged = true; } } @@ -166,42 +183,73 @@ public function refactor(Node $node): ?Class_ return null; } - $this->phpDocTagRemover->removeTagValueFromNode($classPhpDocInfo, $classRouteTagValueNode); - $this->docBlockUpdater->updateRefactoredNodeWithPhpDocInfo($node); + if ($routeAttributeOrAnnotation instanceof DoctrineAnnotationTagValueNode) { + $classPhpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($node); + + $this->phpDocTagRemover->removeTagValueFromNode($classPhpDocInfo, $routeAttributeOrAnnotation); + $this->docBlockUpdater->updateRefactoredNodeWithPhpDocInfo($node); + } else { + foreach ($node->attrGroups as $attrGroupKey => $attrGroup) { + foreach ($attrGroup->attrs as $attribute) { + if ($attribute === $routeAttributeOrAnnotation) { + unset($node->attrGroups[$attrGroupKey]); + } + } + } + } return $node; } private function shouldSkipClass(Class_ $class): bool { - if (! $class->extends instanceof Name) { - return true; - } - if (! $this->controllerAnalyzer->isController($class)) { return true; } foreach ($class->getMethods() as $classMethod) { - if (! $classMethod->isPublic()) { - continue; - } - - if ($classMethod->isMagic()) { - continue; - } - - $classMethodPhpDocInfo = $this->phpDocInfoFactory->createFromNode($classMethod); - if (! $classMethodPhpDocInfo instanceof PhpDocInfo) { + if (! $classMethod->isPublic() || $classMethod->isMagic()) { continue; } // special cases for FOS rest that should be skipped - if ($classMethodPhpDocInfo->hasByAnnotationClasses(self::SKIPPED_ANNOTATIONS)) { + if ($this->attrinationFinder->hasByMany($class, self::FOS_REST_ANNOTATIONS)) { return true; } } return false; } + + private function resolveRoutePath(DoctrineAnnotationTagValueNode $doctrineAnnotationTagValueNode): ?string + { + $classRoutePathNode = $doctrineAnnotationTagValueNode->getSilentValue() ?: $doctrineAnnotationTagValueNode->getValue( + self::PATH + ); + + if (! $classRoutePathNode instanceof ArrayItemNode) { + return null; + } + + if (! $classRoutePathNode->value instanceof StringNode) { + return null; + } + + return $classRoutePathNode->value->value; + } + + private function resolveRoutePathFromAttribute(Attribute $attribute): ?string + { + foreach ($attribute->args as $arg) { + // silent or "path" + if ($arg->name === null || $arg->name->toString() === self::PATH) { + $routeExpr = $arg->value; + if ($routeExpr instanceof String_) { + return $routeExpr->value; + } + } + } + + return null; + } } diff --git a/src/Enum/SymfonyAttribute.php b/src/Enum/SymfonyAttribute.php index 6e4404f5..5f698524 100644 --- a/src/Enum/SymfonyAttribute.php +++ b/src/Enum/SymfonyAttribute.php @@ -15,4 +15,9 @@ final class SymfonyAttribute * @var string */ public const EVENT_LISTENER_ATTRIBUTE = 'Symfony\Component\EventDispatcher\Attribute\AsEventListener'; + + /** + * @var string + */ + public const ROUTE = 'Symfony\Component\Routing\Attribute\Route'; } From d2bdae4017d5d18267f79120201b05120a8b8c03 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sun, 16 Feb 2025 16:40:01 +0700 Subject: [PATCH 09/53] [Symfony] Add attribute routing with mix other annotation (#703) * [Symfony] Add attribute routing with mix other annotation * Trigger CI --- ...outing_class_with_other_annotation.php.inc | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 rules-tests/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector/Fixture/attribute_routing_class_with_other_annotation.php.inc diff --git a/rules-tests/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector/Fixture/attribute_routing_class_with_other_annotation.php.inc b/rules-tests/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector/Fixture/attribute_routing_class_with_other_annotation.php.inc new file mode 100644 index 00000000..110bd414 --- /dev/null +++ b/rules-tests/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector/Fixture/attribute_routing_class_with_other_annotation.php.inc @@ -0,0 +1,40 @@ + +----- + From c02c2554e1f0a0b2fef936a9bbba07243416f784 Mon Sep 17 00:00:00 2001 From: Johan Vlaar Date: Mon, 17 Feb 2025 11:10:24 +0100 Subject: [PATCH 10/53] [SYMFONY 5 & 6] Security add missing param (#699) --- config/sets/symfony/symfony50.php | 30 ++++++++++++++++++++++++++++++ config/sets/symfony/symfony60.php | 14 +++++++++++++- 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/config/sets/symfony/symfony50.php b/config/sets/symfony/symfony50.php index e1aeef38..6f06b45c 100644 --- a/config/sets/symfony/symfony50.php +++ b/config/sets/symfony/symfony50.php @@ -2,16 +2,46 @@ declare(strict_types=1); +use PHPStan\Type\StringType; use Rector\Config\RectorConfig; use Rector\Renaming\Rector\MethodCall\RenameMethodRector; use Rector\Renaming\Rector\Name\RenameClassRector; use Rector\Renaming\ValueObject\MethodCallRename; +use Rector\TypeDeclaration\Rector\ClassMethod\AddParamTypeDeclarationRector; +use Rector\TypeDeclaration\ValueObject\AddParamTypeDeclaration; # https://github.com/symfony/symfony/blob/5.0/UPGRADE-5.0.md return static function (RectorConfig $rectorConfig): void { $rectorConfig->import(__DIR__ . '/symfony50-types.php'); + $rectorConfig->ruleWithConfiguration(AddParamTypeDeclarationRector::class, [ + new AddParamTypeDeclaration( + 'Symfony\Component\Security\Core\User\UserProviderInterface', + 'loadUserByUsername', + 0, + new StringType(), + ), + new AddParamTypeDeclaration( + 'Symfony\Component\Security\Core\User\UserProviderInterface', + 'supportsClass', + 0, + new StringType(), + ), + new AddParamTypeDeclaration( + 'Symfony\Bridge\Doctrine\Security\User\EntityUserProvider', + 'loadUserByUsername', + 0, + new StringType(), + ), + new AddParamTypeDeclaration( + 'Symfony\Bridge\Doctrine\Security\User\EntityUserProvider', + 'supportsClass', + 0, + new StringType(), + ), + ]); + $rectorConfig->ruleWithConfiguration(RenameClassRector::class, [ 'Symfony\Component\Debug\Debug' => 'Symfony\Component\ErrorHandler\Debug', ]); diff --git a/config/sets/symfony/symfony60.php b/config/sets/symfony/symfony60.php index 49d9c810..e8bba0c0 100644 --- a/config/sets/symfony/symfony60.php +++ b/config/sets/symfony/symfony60.php @@ -5,6 +5,7 @@ use PhpParser\Node\Scalar\String_; use PHPStan\Type\MixedType; use PHPStan\Type\ObjectType; +use PHPStan\Type\StringType; use Rector\Config\RectorConfig; use Rector\Renaming\Rector\MethodCall\RenameMethodRector; use Rector\Renaming\Rector\Name\RenameClassRector; @@ -36,7 +37,18 @@ ]); $rectorConfig->ruleWithConfiguration(AddParamTypeDeclarationRector::class, [ - new AddParamTypeDeclaration('Symfony\Component\Config\Loader\LoaderInterface', 'load', 0, new MixedType(true)), + new AddParamTypeDeclaration( + 'Symfony\Component\Config\Loader\LoaderInterface', + 'load', + 0, + new MixedType(true) + ), + new AddParamTypeDeclaration( + 'Symfony\Component\Config\Loader\LoaderInterface', + 'supports', + 0, + new MixedType(true) + ), new AddParamTypeDeclaration( 'Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait', 'configureRoutes', From dcb8a8896bf6c5cd220c84dd9dac66293fc985e3 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Thu, 6 Mar 2025 21:38:21 +0700 Subject: [PATCH 11/53] [CodeQuality] Concat name annotation/attribute on InlineClassRoutePrefixRector (#704) --- config/sets/symfony/symfony60.php | 1 - .../Fixture/with_existing_name.php.inc | 40 ++++++++++++ .../Fixture/with_existing_name2.php.inc | 34 ++++++++++ .../Class_/InlineClassRoutePrefixRector.php | 62 +++++++++++++++++++ 4 files changed, 136 insertions(+), 1 deletion(-) create mode 100644 rules-tests/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector/Fixture/with_existing_name.php.inc create mode 100644 rules-tests/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector/Fixture/with_existing_name2.php.inc diff --git a/config/sets/symfony/symfony60.php b/config/sets/symfony/symfony60.php index e8bba0c0..b578bd31 100644 --- a/config/sets/symfony/symfony60.php +++ b/config/sets/symfony/symfony60.php @@ -5,7 +5,6 @@ use PhpParser\Node\Scalar\String_; use PHPStan\Type\MixedType; use PHPStan\Type\ObjectType; -use PHPStan\Type\StringType; use Rector\Config\RectorConfig; use Rector\Renaming\Rector\MethodCall\RenameMethodRector; use Rector\Renaming\Rector\Name\RenameClassRector; diff --git a/rules-tests/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector/Fixture/with_existing_name.php.inc b/rules-tests/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector/Fixture/with_existing_name.php.inc new file mode 100644 index 00000000..040bd10e --- /dev/null +++ b/rules-tests/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector/Fixture/with_existing_name.php.inc @@ -0,0 +1,40 @@ + +----- + diff --git a/rules-tests/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector/Fixture/with_existing_name2.php.inc b/rules-tests/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector/Fixture/with_existing_name2.php.inc new file mode 100644 index 00000000..1191d193 --- /dev/null +++ b/rules-tests/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector/Fixture/with_existing_name2.php.inc @@ -0,0 +1,34 @@ + +----- + diff --git a/rules/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector.php b/rules/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector.php index 5053afd9..3b53c7ee 100644 --- a/rules/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector.php +++ b/rules/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector.php @@ -107,6 +107,7 @@ public function refactor(Node $node): ?Class_ } $classRoutePath = null; + $classRouteName = null; // 1. detect attribute $routeAttributeOrAnnotation = $this->attrinationFinder->getByMany( @@ -116,8 +117,10 @@ public function refactor(Node $node): ?Class_ if ($routeAttributeOrAnnotation instanceof DoctrineAnnotationTagValueNode) { $classRoutePath = $this->resolveRoutePath($routeAttributeOrAnnotation); + $classRouteName = $this->resolveRouteName($routeAttributeOrAnnotation); } elseif ($routeAttributeOrAnnotation instanceof Attribute) { $classRoutePath = $this->resolveRoutePathFromAttribute($routeAttributeOrAnnotation); + $classRouteName = $this->resolveRouteNameFromAttribute($routeAttributeOrAnnotation); } if ($classRoutePath === null) { @@ -155,6 +158,15 @@ public function refactor(Node $node): ?Class_ $newMethodPath = $classRoutePath . $methodPrefix->value; $routePathArrayItemNode->value = new StringNode($newMethodPath); + + foreach ($methodRouteAnnotationOrAttribute->values as $value) { + if ($value->key === 'name' && $value->value instanceof StringNode && is_string( + $classRouteName + )) { + $value->value->value = $classRouteName . $value->value->value; + } + } + $this->docBlockUpdater->updateRefactoredNodeWithPhpDocInfo($classMethod); $hasChanged = true; @@ -173,6 +185,23 @@ public function refactor(Node $node): ?Class_ )); $hasChanged = true; + + continue; + } + + if ($methodRouteArg->name->toString() === 'name') { + if (! $methodRouteArg->value instanceof String_) { + continue; + } + + $methodRouteString = $methodRouteArg->value; + $methodRouteArg->value = new String_(sprintf( + '%s%s', + $classRouteName, + $methodRouteString->value + )); + + $hasChanged = true; } } } @@ -238,6 +267,21 @@ private function resolveRoutePath(DoctrineAnnotationTagValueNode $doctrineAnnota return $classRoutePathNode->value->value; } + private function resolveRouteName(DoctrineAnnotationTagValueNode $doctrineAnnotationTagValueNode): ?string + { + $classRouteNameNode = $doctrineAnnotationTagValueNode->getValue('name'); + + if (! $classRouteNameNode instanceof ArrayItemNode) { + return null; + } + + if (! $classRouteNameNode->value instanceof StringNode) { + return null; + } + + return $classRouteNameNode->value->value; + } + private function resolveRoutePathFromAttribute(Attribute $attribute): ?string { foreach ($attribute->args as $arg) { @@ -252,4 +296,22 @@ private function resolveRoutePathFromAttribute(Attribute $attribute): ?string return null; } + + private function resolveRouteNameFromAttribute(Attribute $attribute): ?string + { + foreach ($attribute->args as $arg) { + if ($arg->name === null) { + continue; + } + + if ($arg->name->toString() === 'name') { + $routeExpr = $arg->value; + if ($routeExpr instanceof String_) { + return $routeExpr->value; + } + } + } + + return null; + } } From 578d314f0cfdf7289f4e73b82cdf7809da73c250 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Mon, 10 Mar 2025 03:50:15 +0700 Subject: [PATCH 12/53] Change deprecated ClassReflection::isSubClassOf() to ClassReflection::is() for PHPStan ^2.1.8 (#706) * Change deprecated ClassReflection::isSubClassOf() to ClassReflection::is() for PHPStan ^2.1.8 * bump --- composer.json | 2 +- .../Class_/CommandGetByTypeToConstructorInjectionRector.php | 2 +- .../ControllerGetByTypeToConstructorInjectionRector.php | 2 +- .../Class_/GetBySymfonyStringToConstructorInjectionRector.php | 4 ++-- .../Rector/Class_/DowngradeSymfonyCommandAttributeRector.php | 2 +- .../ClassMethod/EventDispatcherParentConstructRector.php | 2 +- .../Rector/ClassMethod/CommandConstantReturnCodeRector.php | 2 +- .../ErrorNamesPropertyToConstantRector.php | 2 +- .../Twig134/Rector/Return_/SimpleFunctionAndFilterRector.php | 2 +- src/NodeAnalyzer/SymfonyTestCaseAnalyzer.php | 4 ++-- src/TypeAnalyzer/ControllerAnalyzer.php | 4 ++-- 11 files changed, 14 insertions(+), 14 deletions(-) diff --git a/composer.json b/composer.json index 5bfccf2e..6c7c26dc 100644 --- a/composer.json +++ b/composer.json @@ -9,7 +9,7 @@ }, "require-dev": { "phpstan/extension-installer": "^1.4", - "phpstan/phpstan": "^2.0", + "phpstan/phpstan": "^2.1.8", "phpstan/phpstan-webmozart-assert": "^2.0", "phpunit/phpunit": "^11.4", "rector/rector-src": "dev-main", diff --git a/rules/DependencyInjection/Rector/Class_/CommandGetByTypeToConstructorInjectionRector.php b/rules/DependencyInjection/Rector/Class_/CommandGetByTypeToConstructorInjectionRector.php index ba303b87..86a5ba6a 100644 --- a/rules/DependencyInjection/Rector/Class_/CommandGetByTypeToConstructorInjectionRector.php +++ b/rules/DependencyInjection/Rector/Class_/CommandGetByTypeToConstructorInjectionRector.php @@ -134,6 +134,6 @@ private function shouldSkipClass(Class_ $class): bool return true; } - return ! $classReflection->isSubclassOf(SymfonyClass::CONTAINER_AWARE_COMMAND); + return ! $classReflection->is(SymfonyClass::CONTAINER_AWARE_COMMAND); } } diff --git a/rules/DependencyInjection/Rector/Class_/ControllerGetByTypeToConstructorInjectionRector.php b/rules/DependencyInjection/Rector/Class_/ControllerGetByTypeToConstructorInjectionRector.php index 3147ee9f..b1aedc02 100644 --- a/rules/DependencyInjection/Rector/Class_/ControllerGetByTypeToConstructorInjectionRector.php +++ b/rules/DependencyInjection/Rector/Class_/ControllerGetByTypeToConstructorInjectionRector.php @@ -130,6 +130,6 @@ private function shouldSkipClass(Class_ $class): bool return true; } - return ! $classReflection->isSubclassOf(SymfonyClass::CONTROLLER); + return ! $classReflection->is(SymfonyClass::CONTROLLER); } } diff --git a/rules/DependencyInjection/Rector/Class_/GetBySymfonyStringToConstructorInjectionRector.php b/rules/DependencyInjection/Rector/Class_/GetBySymfonyStringToConstructorInjectionRector.php index 769dcd86..0a2ced0a 100644 --- a/rules/DependencyInjection/Rector/Class_/GetBySymfonyStringToConstructorInjectionRector.php +++ b/rules/DependencyInjection/Rector/Class_/GetBySymfonyStringToConstructorInjectionRector.php @@ -155,10 +155,10 @@ private function shouldSkipClass(Class_ $class): bool return true; } - if ($classReflection->isSubclassOf(SymfonyClass::CONTAINER_AWARE_COMMAND)) { + if ($classReflection->is(SymfonyClass::CONTAINER_AWARE_COMMAND)) { return false; } - return ! $classReflection->isSubclassOf(SymfonyClass::CONTROLLER); + return ! $classReflection->is(SymfonyClass::CONTROLLER); } } diff --git a/rules/DowngradeSymfony70/Rector/Class_/DowngradeSymfonyCommandAttributeRector.php b/rules/DowngradeSymfony70/Rector/Class_/DowngradeSymfonyCommandAttributeRector.php index 3552074d..d0753f95 100644 --- a/rules/DowngradeSymfony70/Rector/Class_/DowngradeSymfonyCommandAttributeRector.php +++ b/rules/DowngradeSymfony70/Rector/Class_/DowngradeSymfonyCommandAttributeRector.php @@ -77,7 +77,7 @@ public function refactor(Node $node): ?Node return null; } - if (! $classReflection->isSubClassOf('Symfony\Component\Console\Command\Command')) { + if (! $classReflection->is('Symfony\Component\Console\Command\Command')) { return null; } diff --git a/rules/Symfony43/Rector/ClassMethod/EventDispatcherParentConstructRector.php b/rules/Symfony43/Rector/ClassMethod/EventDispatcherParentConstructRector.php index 81d6d0ed..341b4409 100644 --- a/rules/Symfony43/Rector/ClassMethod/EventDispatcherParentConstructRector.php +++ b/rules/Symfony43/Rector/ClassMethod/EventDispatcherParentConstructRector.php @@ -86,7 +86,7 @@ public function refactor(Node $node): ?Node } $classReflection = $scope->getClassReflection(); - if (! $classReflection->isSubclassOf('Symfony\Contracts\EventDispatcher\EventDispatcherInterface')) { + if (! $classReflection->is('Symfony\Contracts\EventDispatcher\EventDispatcherInterface')) { return null; } diff --git a/rules/Symfony51/Rector/ClassMethod/CommandConstantReturnCodeRector.php b/rules/Symfony51/Rector/ClassMethod/CommandConstantReturnCodeRector.php index 4ce8cc17..96ebf6f0 100644 --- a/rules/Symfony51/Rector/ClassMethod/CommandConstantReturnCodeRector.php +++ b/rules/Symfony51/Rector/ClassMethod/CommandConstantReturnCodeRector.php @@ -80,7 +80,7 @@ public function refactor(Node $node): ?Node return null; } - if (! $classReflection->isSubclassOf('Symfony\Component\Console\Command\Command')) { + if (! $classReflection->is('Symfony\Component\Console\Command\Command')) { return null; } diff --git a/rules/Symfony61/Rector/StaticPropertyFetch/ErrorNamesPropertyToConstantRector.php b/rules/Symfony61/Rector/StaticPropertyFetch/ErrorNamesPropertyToConstantRector.php index 0e8e6b88..a9671a38 100644 --- a/rules/Symfony61/Rector/StaticPropertyFetch/ErrorNamesPropertyToConstantRector.php +++ b/rules/Symfony61/Rector/StaticPropertyFetch/ErrorNamesPropertyToConstantRector.php @@ -73,7 +73,7 @@ public function refactor(Node $node): ?Node if (! $classReflection instanceof ClassReflection) { return null; } - if (! $classReflection->isSubclassOf('Symfony\Component\Validator\Constraint')) { + if (! $classReflection->is('Symfony\Component\Validator\Constraint')) { return null; } if (! $this->nodeNameResolver->isName($node->name, 'errorNames')) { diff --git a/rules/Twig134/Rector/Return_/SimpleFunctionAndFilterRector.php b/rules/Twig134/Rector/Return_/SimpleFunctionAndFilterRector.php index bea17abc..0fe25901 100644 --- a/rules/Twig134/Rector/Return_/SimpleFunctionAndFilterRector.php +++ b/rules/Twig134/Rector/Return_/SimpleFunctionAndFilterRector.php @@ -151,7 +151,7 @@ private function shouldSkip(ClassMethod $classMethod): bool return true; } - if (! $classReflection->isSubclassOf('Twig_Extension')) { + if (! $classReflection->is('Twig_Extension')) { return true; } diff --git a/src/NodeAnalyzer/SymfonyTestCaseAnalyzer.php b/src/NodeAnalyzer/SymfonyTestCaseAnalyzer.php index 7e1a211e..645efbc6 100644 --- a/src/NodeAnalyzer/SymfonyTestCaseAnalyzer.php +++ b/src/NodeAnalyzer/SymfonyTestCaseAnalyzer.php @@ -22,7 +22,7 @@ public function isInWebTestCase(Node $node): bool return false; } - return $classReflection->isSubclassOf('Symfony\Bundle\FrameworkBundle\Test\WebTestCase'); + return $classReflection->is('Symfony\Bundle\FrameworkBundle\Test\WebTestCase'); } /** @@ -35,6 +35,6 @@ public function isInKernelTestCase(Node $node): bool return false; } - return $classReflection->isSubclassOf('Symfony\Bundle\FrameworkBundle\Test\KernelTestCase'); + return $classReflection->is('Symfony\Bundle\FrameworkBundle\Test\KernelTestCase'); } } diff --git a/src/TypeAnalyzer/ControllerAnalyzer.php b/src/TypeAnalyzer/ControllerAnalyzer.php index a452e5ff..e24ecde4 100644 --- a/src/TypeAnalyzer/ControllerAnalyzer.php +++ b/src/TypeAnalyzer/ControllerAnalyzer.php @@ -68,11 +68,11 @@ public function isInsideController(Node $node): bool private function isControllerClassReflection(ClassReflection $classReflection): bool { - if ($classReflection->isSubclassOf('Symfony\Bundle\FrameworkBundle\Controller\Controller')) { + if ($classReflection->is('Symfony\Bundle\FrameworkBundle\Controller\Controller')) { return true; } - return $classReflection->isSubclassOf('Symfony\Bundle\FrameworkBundle\Controller\AbstractController'); + return $classReflection->is('Symfony\Bundle\FrameworkBundle\Controller\AbstractController'); } private function isControllerClass(Class_ $class): bool From d4e5a0f5ca731659f5d7761c3133e176fa78cdef Mon Sep 17 00:00:00 2001 From: Duncan de Boer Date: Tue, 11 Mar 2025 11:18:32 +0100 Subject: [PATCH 13/53] feat: add flysystem key (#705) * feat: add flysystem key * docs: add link for reference --- .../Rector/Closure/StringExtensionToConfigBuilderRector.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rules/CodeQuality/Rector/Closure/StringExtensionToConfigBuilderRector.php b/rules/CodeQuality/Rector/Closure/StringExtensionToConfigBuilderRector.php index 58b905d3..e4253930 100644 --- a/rules/CodeQuality/Rector/Closure/StringExtensionToConfigBuilderRector.php +++ b/rules/CodeQuality/Rector/Closure/StringExtensionToConfigBuilderRector.php @@ -51,6 +51,8 @@ final class StringExtensionToConfigBuilderRector extends AbstractRector 'maker' => 'Symfony\Config\MakerConfig', 'nelmio_cors' => 'Symfony\Config\NelmioCorsConfig', 'api_platform' => 'Symfony\Config\ApiPlatformConfig', + // @see https://github.com/thephpleague/flysystem-bundle/blob/3.x/src/DependencyInjection/Configuration.php + 'flysystem' => 'Symfony\Config\FlysystemConfig', ]; public function __construct( From 00c1f259413b81b5075df372d56446f3e41d7891 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Fri, 21 Mar 2025 11:27:25 +0100 Subject: [PATCH 14/53] [symfony 7.3] Add InvokableCommandRector - kick off (#707) * [symfony 7.3] Add InvokableCommandRector * phsptan fixes --- composer.json | 9 +- config/sets/symfony/symfony73.php | 11 + phpstan.neon | 38 ++- .../Fixture/some_command.php.inc | 61 +++++ .../InvokableCommandRectorTest.php | 28 +++ .../config/configured_rule.php | 10 + .../CommandConfigureToAttributeRector.php | 13 +- .../CommandPropertyToAttributeRector.php | 8 +- .../CommandArgumentsAndOptionsResolver.php | 90 +++++++ .../CommandInvokeParamsFactory.php | 78 ++++++ .../Rector/Class_/InvokableCommandRector.php | 222 ++++++++++++++++++ .../Symfony73/ValueObject/CommandArgument.php | 20 ++ rules/Symfony73/ValueObject/CommandOption.php | 20 ++ src/Enum/CommandMethodName.php | 16 ++ src/Enum/SymfonyAnnotation.php | 5 - src/Enum/SymfonyAttribute.php | 15 ++ 16 files changed, 604 insertions(+), 40 deletions(-) create mode 100644 config/sets/symfony/symfony73.php create mode 100644 rules-tests/Symfony73/Rector/Class_/InvokableCommandRector/Fixture/some_command.php.inc create mode 100644 rules-tests/Symfony73/Rector/Class_/InvokableCommandRector/InvokableCommandRectorTest.php create mode 100644 rules-tests/Symfony73/Rector/Class_/InvokableCommandRector/config/configured_rule.php create mode 100644 rules/Symfony73/NodeAnalyzer/CommandArgumentsAndOptionsResolver.php create mode 100644 rules/Symfony73/NodeFactory/CommandInvokeParamsFactory.php create mode 100644 rules/Symfony73/Rector/Class_/InvokableCommandRector.php create mode 100644 rules/Symfony73/ValueObject/CommandArgument.php create mode 100644 rules/Symfony73/ValueObject/CommandOption.php create mode 100644 src/Enum/CommandMethodName.php diff --git a/composer.json b/composer.json index 6c7c26dc..b3b44cfe 100644 --- a/composer.json +++ b/composer.json @@ -8,21 +8,24 @@ "ext-xml": "*" }, "require-dev": { + "phpecs/phpecs": "^2.0.1", "phpstan/extension-installer": "^1.4", "phpstan/phpstan": "^2.1.8", "phpstan/phpstan-webmozart-assert": "^2.0", "phpunit/phpunit": "^11.4", "rector/rector-src": "dev-main", + "rector/type-perfect": "^2.0", "symfony/config": "^6.4", "symfony/dependency-injection": "^6.4", - "symfony/http-kernel": "~6.3", + "symfony/http-kernel": "^6.4", "symfony/routing": "^6.4", "symfony/security-core": "^6.4", "symfony/security-http": "^6.4", "symfony/validator": "^6.4", - "symplify/easy-coding-standard": "^12.3", "symplify/vendor-patches": "^11.3", - "tomasvotruba/class-leak": "^1.0", + "tomasvotruba/class-leak": "^2.0", + "tomasvotruba/type-coverage": "^2.0", + "tomasvotruba/unused-public": "^2.0", "tracy/tracy": "^2.10" }, "autoload": { diff --git a/config/sets/symfony/symfony73.php b/config/sets/symfony/symfony73.php new file mode 100644 index 00000000..0d87fd60 --- /dev/null +++ b/config/sets/symfony/symfony73.php @@ -0,0 +1,11 @@ +withRules([InvokableCommandRector::class]); diff --git a/phpstan.neon b/phpstan.neon index 1c88c994..38b98277 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -2,7 +2,6 @@ parameters: level: 8 reportUnmatchedIgnoredErrors: false - treatPhpDocTypesAsCertain: false paths: @@ -12,18 +11,17 @@ parameters: - rules - rules-tests -# to be enabled later once rector upgraded to use phpstan v2 -# # https://github.com/rectorphp/type-perfect/ -# type_perfect: -# no_mixed: true -# null_over_false: true -# narrow_param: true -# narrow_return: true + # https://github.com/rectorphp/type-perfect/ + type_perfect: + no_mixed: true + null_over_false: true + narrow_param: true + narrow_return: true -# unused_public: -# constants: true -# methods: true -# properties: true + unused_public: + constants: true + methods: true + properties: true scanDirectories: - stubs @@ -54,16 +52,12 @@ parameters: - '#Doing instanceof PHPStan\\Type\\.+ is error\-prone and deprecated#' # phpstan instanceof - - - identifier: phpstanApi.instanceofAssumption - - - - identifier: phpstanApi.varTagAssumption + - identifier: argument.type + - identifier: assign.propertyType - - - identifier: argument.type + - '#::provideMinPhpVersion\(\) never returns \d+ so it can be removed from the return type#' + # node finder - - identifier: assign.propertyType - - - '#::provideMinPhpVersion\(\) never returns \d+ so it can be removed from the return type#' + identifier: return.type + path: rules/Symfony73/NodeAnalyzer/CommandArgumentsAndOptionsResolver.php diff --git a/rules-tests/Symfony73/Rector/Class_/InvokableCommandRector/Fixture/some_command.php.inc b/rules-tests/Symfony73/Rector/Class_/InvokableCommandRector/Fixture/some_command.php.inc new file mode 100644 index 00000000..700d41aa --- /dev/null +++ b/rules-tests/Symfony73/Rector/Class_/InvokableCommandRector/Fixture/some_command.php.inc @@ -0,0 +1,61 @@ +addArgument('argument', InputArgument::REQUIRED, 'Argument description'); + $this->addOption('option', 'o', InputOption::VALUE_NONE, 'Option description'); + } + + public function execute(InputInterface $input, OutputInterface $output): int + { + $someArgument = $input->getArgument('argument'); + $someOption = $input->getOption('option'); + + // ... + + return 1; + } +} + +?> +----- + diff --git a/rules-tests/Symfony73/Rector/Class_/InvokableCommandRector/InvokableCommandRectorTest.php b/rules-tests/Symfony73/Rector/Class_/InvokableCommandRector/InvokableCommandRectorTest.php new file mode 100644 index 00000000..f10fe23e --- /dev/null +++ b/rules-tests/Symfony73/Rector/Class_/InvokableCommandRector/InvokableCommandRectorTest.php @@ -0,0 +1,28 @@ +doTestFile($filePath); + } + + public static function provideData(): Iterator + { + return self::yieldFilesFromDirectory(__DIR__ . '/Fixture'); + } + + public function provideConfigFilePath(): string + { + return __DIR__ . '/config/configured_rule.php'; + } +} diff --git a/rules-tests/Symfony73/Rector/Class_/InvokableCommandRector/config/configured_rule.php b/rules-tests/Symfony73/Rector/Class_/InvokableCommandRector/config/configured_rule.php new file mode 100644 index 00000000..a96cce4b --- /dev/null +++ b/rules-tests/Symfony73/Rector/Class_/InvokableCommandRector/config/configured_rule.php @@ -0,0 +1,10 @@ +rule(InvokableCommandRector::class); +}; diff --git a/rules/Symfony61/Rector/Class_/CommandConfigureToAttributeRector.php b/rules/Symfony61/Rector/Class_/CommandConfigureToAttributeRector.php index c37df3dd..6025824b 100644 --- a/rules/Symfony61/Rector/Class_/CommandConfigureToAttributeRector.php +++ b/rules/Symfony61/Rector/Class_/CommandConfigureToAttributeRector.php @@ -19,14 +19,15 @@ use PHPStan\Type\ObjectType; use Rector\PhpAttribute\NodeFactory\PhpAttributeGroupFactory; use Rector\Rector\AbstractRector; -use Rector\Symfony\Enum\SymfonyAnnotation; +use Rector\Symfony\Enum\SymfonyAttribute; +use Rector\Symfony\Enum\SymfonyClass; use Rector\ValueObject\PhpVersionFeature; use Rector\VersionBonding\Contract\MinPhpVersionInterface; use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; /** - * @changelog https://symfony.com/doc/current/console.html#registering-the-command + * @see https://symfony.com/doc/current/console.html#registering-the-command * * @see \Rector\Symfony\Tests\Symfony61\Rector\Class_\CommandConfigureToAttributeRector\CommandConfigureToAttributeRectorTest */ @@ -102,11 +103,11 @@ public function refactor(Node $node): ?Node return null; } - if (! $this->reflectionProvider->hasClass(SymfonyAnnotation::AS_COMMAND)) { + if (! $this->reflectionProvider->hasClass(SymfonyAttribute::AS_COMMAND)) { return null; } - if (! $this->isObjectType($node, new ObjectType('Symfony\\Component\\Console\\Command\\Command'))) { + if (! $this->isObjectType($node, new ObjectType(SymfonyClass::COMMAND))) { return null; } @@ -120,7 +121,7 @@ public function refactor(Node $node): ?Node $attributeArgs = []; foreach ($node->attrGroups as $attrGroup) { foreach ($attrGroup->attrs as $attribute) { - if (! $this->nodeNameResolver->isName($attribute->name, SymfonyAnnotation::AS_COMMAND)) { + if (! $this->nodeNameResolver->isName($attribute->name, SymfonyAttribute::AS_COMMAND)) { continue; } @@ -139,7 +140,7 @@ public function refactor(Node $node): ?Node } if (! $asCommandAttribute instanceof Attribute) { - $asCommandAttributeGroup = $this->phpAttributeGroupFactory->createFromClass(SymfonyAnnotation::AS_COMMAND); + $asCommandAttributeGroup = $this->phpAttributeGroupFactory->createFromClass(SymfonyAttribute::AS_COMMAND); $asCommandAttribute = $asCommandAttributeGroup->attrs[0]; diff --git a/rules/Symfony61/Rector/Class_/CommandPropertyToAttributeRector.php b/rules/Symfony61/Rector/Class_/CommandPropertyToAttributeRector.php index 5c1a0fce..879fcd57 100644 --- a/rules/Symfony61/Rector/Class_/CommandPropertyToAttributeRector.php +++ b/rules/Symfony61/Rector/Class_/CommandPropertyToAttributeRector.php @@ -17,7 +17,7 @@ use Rector\Doctrine\NodeAnalyzer\AttributeFinder; use Rector\PhpAttribute\NodeFactory\PhpAttributeGroupFactory; use Rector\Rector\AbstractRector; -use Rector\Symfony\Enum\SymfonyAnnotation; +use Rector\Symfony\Enum\SymfonyAttribute; use Rector\Symfony\Enum\SymfonyClass; use Rector\ValueObject\PhpVersionFeature; use Rector\VersionBonding\Contract\MinPhpVersionInterface; @@ -91,7 +91,7 @@ public function refactor(Node $node): ?Node } // does attribute already exist? - if (! $this->reflectionProvider->hasClass(SymfonyAnnotation::AS_COMMAND)) { + if (! $this->reflectionProvider->hasClass(SymfonyAttribute::AS_COMMAND)) { return null; } @@ -104,7 +104,7 @@ public function refactor(Node $node): ?Node $existingAsCommandAttribute = $this->attributeFinder->findAttributeByClass( $node, - SymfonyAnnotation::AS_COMMAND + SymfonyAttribute::AS_COMMAND ); $attributeArgs = $this->createAttributeArgs($defaultNameExpr, $defaultDescriptionExpr); @@ -126,7 +126,7 @@ private function createAttributeGroupAsCommand(array $args): AttributeGroup { Assert::allIsInstanceOf($args, Arg::class); - $attributeGroup = $this->phpAttributeGroupFactory->createFromClass(SymfonyAnnotation::AS_COMMAND); + $attributeGroup = $this->phpAttributeGroupFactory->createFromClass(SymfonyAttribute::AS_COMMAND); $attributeGroup->attrs[0]->args = $args; return $attributeGroup; diff --git a/rules/Symfony73/NodeAnalyzer/CommandArgumentsAndOptionsResolver.php b/rules/Symfony73/NodeAnalyzer/CommandArgumentsAndOptionsResolver.php new file mode 100644 index 00000000..dd13bce2 --- /dev/null +++ b/rules/Symfony73/NodeAnalyzer/CommandArgumentsAndOptionsResolver.php @@ -0,0 +1,90 @@ +findMethodCallsByName($configureClassMethod, 'addArgument'); + + $commandArguments = []; + foreach ($addArgumentMethodCalls as $addArgumentMethodCall) { + // @todo extract name, type and requirements + $addArgumentArgs = $addArgumentMethodCall->getArgs(); + + $nameArgValue = $addArgumentArgs[0]->value; + if (! $nameArgValue instanceof String_) { + // we need string value, otherwise param will not have a name + throw new ShouldNotHappenException('Argument name is required'); + } + + $optionName = $nameArgValue->value; + + $commandArguments[] = new CommandArgument($optionName); + } + + return $commandArguments; + } + + /** + * @return CommandOption[] + */ + public function collectCommandOptions(ClassMethod $configureClassMethod): array + { + $addOptionMethodCalls = $this->findMethodCallsByName($configureClassMethod, 'addOption'); + + $commandOptionMetadatas = []; + foreach ($addOptionMethodCalls as $addOptionMethodCall) { + // @todo extract name, type and requirements + $addOptionArgs = $addOptionMethodCall->getArgs(); + + $nameArgValue = $addOptionArgs[0]->value; + if (! $nameArgValue instanceof String_) { + // we need string value, otherwise param will not have a name + throw new ShouldNotHappenException('Option name is required'); + } + + $optionName = $nameArgValue->value; + + $commandOptionMetadatas[] = new CommandOption($optionName); + } + + return $commandOptionMetadatas; + } + + /** + * @return MethodCall[] + */ + private function findMethodCallsByName(ClassMethod $classMethod, string $desiredMethodName): array + { + $nodeFinder = new NodeFinder(); + + return $nodeFinder->find($classMethod, function (Node $node) use ($desiredMethodName): bool { + if (! $node instanceof MethodCall) { + return false; + } + + if (! $node->name instanceof Identifier) { + return false; + } + + return $node->name->toString() === $desiredMethodName; + }); + } +} diff --git a/rules/Symfony73/NodeFactory/CommandInvokeParamsFactory.php b/rules/Symfony73/NodeFactory/CommandInvokeParamsFactory.php new file mode 100644 index 00000000..08537f15 --- /dev/null +++ b/rules/Symfony73/NodeFactory/CommandInvokeParamsFactory.php @@ -0,0 +1,78 @@ +createArgumentParams($commandArguments); + $optionParams = $this->createOptionParams($commandOptions); + + return array_merge($argumentParams, $optionParams); + } + + /** + * @param CommandArgument[] $commandArguments + * @return Param[] + */ + private function createArgumentParams(array $commandArguments): array + { + $argumentParams = []; + + foreach ($commandArguments as $commandArgument) { + $argumentParam = new Param(new Variable($commandArgument->getName())); + + $argumentParam->type = new Identifier('string'); + // @todo fill type or default value + // @todo default string, multiple values array + + $argumentParam->attrGroups[] = new AttributeGroup([ + new Attribute(new FullyQualified(SymfonyAttribute::COMMAND_ARGUMENT)), + ]); + + $argumentParams[] = $argumentParam; + } + + return $argumentParams; + } + + /** + * @param CommandOption[] $commandOptions + * @return Param[] + */ + private function createOptionParams(array $commandOptions): array + { + $optionParams = []; + + foreach ($commandOptions as $commandOption) { + $optionParam = new Param(new Variable($commandOption->getName())); + + // @todo fill type or default value + $optionParam->attrGroups[] = new AttributeGroup([ + new Attribute(new FullyQualified(SymfonyAttribute::COMMAND_OPTION)), + ]); + + $optionParams[] = $optionParam; + } + + return $optionParams; + } +} diff --git a/rules/Symfony73/Rector/Class_/InvokableCommandRector.php b/rules/Symfony73/Rector/Class_/InvokableCommandRector.php new file mode 100644 index 00000000..a1ba97bd --- /dev/null +++ b/rules/Symfony73/Rector/Class_/InvokableCommandRector.php @@ -0,0 +1,222 @@ +addArgument('argument', InputArgument::REQUIRED, 'Argument description'); + $this->addOption('option', 'o', InputOption::VALUE_NONE, 'Option description'); + } + + public function execute(InputInterface $input, OutputInterface $output) + { + $someArgument = $input->getArgument('argument'); + $someOption = $input->getOption('option'); + + // ... + + return 1; + } +} +CODE_SAMPLE + , + <<<'CODE_SAMPLE' +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Command\Argument; +use Symfony\Component\Console\Command\Option; + +final class SomeCommand +{ + public function __invoke( + #[Argument] + string $argument, + #[Option] + bool $option = false, + ) { + $someArgument = $argument; + $someOption = $option; + + // ... + + return 1; + } +} +CODE_SAMPLE + ), + ]); + } + + public function getNodeTypes(): array + { + return [Class_::class]; + } + + /** + * @param Class_ $node + */ + public function refactor(Node $node): ?Class_ + { + if (! $node->extends instanceof Name) { + return null; + } + + // handle only direct child classes, to keep safe + if (! $this->isName($node->extends, SymfonyClass::COMMAND)) { + return null; + } + + if ($this->isComplexCommand($node)) { + return null; + } + + // as command attribute is required, its handled by previous symfony versions + // @todo possibly to add it here to handle multiple cases + if (! $this->attributeFinder->findAttributeByClass($node, SymfonyAttribute::AS_COMMAND) instanceof Attribute) { + return null; + } + + // 1. fetch configure method to get arguments and options metadata + $configureClassMethod = $node->getMethod(CommandMethodName::CONFIGURE); + if (! $configureClassMethod instanceof ClassMethod) { + return null; + } + + // 2. rename execute to __invoke + $executeClassMethod = $node->getMethod(CommandMethodName::EXECUTE); + if (! $executeClassMethod instanceof ClassMethod) { + return null; + } + + $executeClassMethod->name = new Identifier('__invoke'); + + // 3. create arguments and options parameters + // @todo + $commandArguments = $this->commandArgumentsAndOptionsResolver->collectCommandArguments( + $configureClassMethod + ); + + $commandOptions = $this->commandArgumentsAndOptionsResolver->collectCommandOptions($configureClassMethod); + + // 4. remove configure() method + $this->removeConfigureClassMethod($node); + + // 5. decorate __invoke method with attributes + $invokeParams = $this->commandInvokeParamsFactory->createParams($commandArguments, $commandOptions); + $executeClassMethod->params = $invokeParams; + + // 6. remove parent class + $node->extends = null; + + // 7. replace input->getArgument() and input->getOption() calls with direct variable access + $this->replaceInputArgumentOptionFetchWithVariables($executeClassMethod); + + return $node; + } + + /** + * Skip commands with interact() or initialize() methods as modify the argument/option values + */ + private function isComplexCommand(Class_ $class): bool + { + if ($class->getMethod(CommandMethodName::INTERACT) instanceof ClassMethod) { + return true; + } + + return $class->getMethod(CommandMethodName::INITIALIZE) instanceof ClassMethod; + } + + private function removeConfigureClassMethod(Class_ $class): void + { + foreach ($class->stmts as $key => $stmt) { + if (! $stmt instanceof ClassMethod) { + continue; + } + + if (! $this->isName($stmt->name, CommandMethodName::CONFIGURE)) { + continue; + } + + unset($class->stmts[$key]); + return; + } + } + + private function replaceInputArgumentOptionFetchWithVariables(ClassMethod $executeClassMethod): void + { + $this->traverseNodesWithCallable($executeClassMethod->stmts, function (Node $node): ?Variable { + if (! $node instanceof MethodCall) { + return null; + } + + if (! $this->isName($node->var, 'input')) { + return null; + } + + if (! $this->isNames($node->name, ['getOption', 'getArgument'])) { + return null; + } + + $firstArgValue = $node->getArgs()[0] + ->value; + + if (! $firstArgValue instanceof String_) { + // unable to resolve argument/option name + throw new ShouldNotHappenException(); + } + + return new Variable($firstArgValue->value); + }); + } +} diff --git a/rules/Symfony73/ValueObject/CommandArgument.php b/rules/Symfony73/ValueObject/CommandArgument.php new file mode 100644 index 00000000..33bfc873 --- /dev/null +++ b/rules/Symfony73/ValueObject/CommandArgument.php @@ -0,0 +1,20 @@ +name; + } +} diff --git a/rules/Symfony73/ValueObject/CommandOption.php b/rules/Symfony73/ValueObject/CommandOption.php new file mode 100644 index 00000000..b6880612 --- /dev/null +++ b/rules/Symfony73/ValueObject/CommandOption.php @@ -0,0 +1,20 @@ +name; + } +} diff --git a/src/Enum/CommandMethodName.php b/src/Enum/CommandMethodName.php new file mode 100644 index 00000000..e276426c --- /dev/null +++ b/src/Enum/CommandMethodName.php @@ -0,0 +1,16 @@ + Date: Mon, 24 Mar 2025 15:14:08 +0100 Subject: [PATCH 15/53] [code-quality] Add RequestIsMasterRector (#708) --- config/sets/symfony/symfony-code-quality.php | 4 + .../Fixture/fixture.php.inc | 43 +++++++ .../Fixture/skip_different_type.php.inc | 13 ++ .../RequestIsMainRectorTest.php | 28 +++++ .../config/configured_rule.php | 10 ++ .../Rector/BinaryOp/RequestIsMainRector.php | 115 ++++++++++++++++++ src/Enum/SymfonyClass.php | 15 +++ .../Component/HttpFoundation/Request.php | 11 ++ 8 files changed, 239 insertions(+) create mode 100644 rules-tests/CodeQuality/Rector/BinaryOp/RequestIsMainRector/Fixture/fixture.php.inc create mode 100644 rules-tests/CodeQuality/Rector/BinaryOp/RequestIsMainRector/Fixture/skip_different_type.php.inc create mode 100644 rules-tests/CodeQuality/Rector/BinaryOp/RequestIsMainRector/RequestIsMainRectorTest.php create mode 100644 rules-tests/CodeQuality/Rector/BinaryOp/RequestIsMainRector/config/configured_rule.php create mode 100644 rules/CodeQuality/Rector/BinaryOp/RequestIsMainRector.php diff --git a/config/sets/symfony/symfony-code-quality.php b/config/sets/symfony/symfony-code-quality.php index 809ea40e..d43c20a5 100644 --- a/config/sets/symfony/symfony-code-quality.php +++ b/config/sets/symfony/symfony-code-quality.php @@ -3,6 +3,7 @@ declare(strict_types=1); use Rector\Config\RectorConfig; +use Rector\Symfony\CodeQuality\Rector\BinaryOp\RequestIsMainRector; use Rector\Symfony\CodeQuality\Rector\BinaryOp\ResponseStatusCodeRector; use Rector\Symfony\CodeQuality\Rector\Class_\EventListenerToEventSubscriberRector; use Rector\Symfony\CodeQuality\Rector\Class_\InlineClassRoutePrefixRector; @@ -29,6 +30,9 @@ ActionSuffixRemoverRector::class, LoadValidatorMetadataToAnnotationRector::class, + // request method + RequestIsMainRector::class, + // tests AssertSameResponseCodeWithDebugContentsRector::class, diff --git a/rules-tests/CodeQuality/Rector/BinaryOp/RequestIsMainRector/Fixture/fixture.php.inc b/rules-tests/CodeQuality/Rector/BinaryOp/RequestIsMainRector/Fixture/fixture.php.inc new file mode 100644 index 00000000..ce8e5b20 --- /dev/null +++ b/rules-tests/CodeQuality/Rector/BinaryOp/RequestIsMainRector/Fixture/fixture.php.inc @@ -0,0 +1,43 @@ +getRequestType() === HttpKernel::MASTER_REQUEST; + } + + public function second(Request $request) + { + return $request->getRequestType() === HttpKernel::MAIN_REQUEST; + } +} + +?> +----- +isMainRequest(); + } + + public function second(Request $request) + { + return $request->isMainRequest(); + } +} + +?> diff --git a/rules-tests/CodeQuality/Rector/BinaryOp/RequestIsMainRector/Fixture/skip_different_type.php.inc b/rules-tests/CodeQuality/Rector/BinaryOp/RequestIsMainRector/Fixture/skip_different_type.php.inc new file mode 100644 index 00000000..30f007e8 --- /dev/null +++ b/rules-tests/CodeQuality/Rector/BinaryOp/RequestIsMainRector/Fixture/skip_different_type.php.inc @@ -0,0 +1,13 @@ +getRequestType() === HttpKernel::MASTER_REQUEST; + } +} diff --git a/rules-tests/CodeQuality/Rector/BinaryOp/RequestIsMainRector/RequestIsMainRectorTest.php b/rules-tests/CodeQuality/Rector/BinaryOp/RequestIsMainRector/RequestIsMainRectorTest.php new file mode 100644 index 00000000..5bfe32e5 --- /dev/null +++ b/rules-tests/CodeQuality/Rector/BinaryOp/RequestIsMainRector/RequestIsMainRectorTest.php @@ -0,0 +1,28 @@ +doTestFile($filePath); + } + + public static function provideData(): Iterator + { + return self::yieldFilesFromDirectory(__DIR__ . '/Fixture'); + } + + public function provideConfigFilePath(): string + { + return __DIR__ . '/config/configured_rule.php'; + } +} diff --git a/rules-tests/CodeQuality/Rector/BinaryOp/RequestIsMainRector/config/configured_rule.php b/rules-tests/CodeQuality/Rector/BinaryOp/RequestIsMainRector/config/configured_rule.php new file mode 100644 index 00000000..bdd6c9fb --- /dev/null +++ b/rules-tests/CodeQuality/Rector/BinaryOp/RequestIsMainRector/config/configured_rule.php @@ -0,0 +1,10 @@ +rule(RequestIsMainRector::class); +}; diff --git a/rules/CodeQuality/Rector/BinaryOp/RequestIsMainRector.php b/rules/CodeQuality/Rector/BinaryOp/RequestIsMainRector.php new file mode 100644 index 00000000..0347e0a9 --- /dev/null +++ b/rules/CodeQuality/Rector/BinaryOp/RequestIsMainRector.php @@ -0,0 +1,115 @@ +getRequestType() === HttpKernel::MASTER_REQUEST; + } +} +CODE_SAMPLE + , + <<<'CODE_SAMPLE' +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\HttpKernel; + +class SomeController +{ + public function index(Request $request): bool + { + return $request->isMasterRequestType(); + } +} +CODE_SAMPLE + ), + ]); + } + + /** + * @return array> + */ + public function getNodeTypes(): array + { + return [BinaryOp::class]; + } + + /** + * @param BinaryOp $node + */ + public function refactor(Node $node): ?Node + { + if (! $node->left instanceof MethodCall) { + return null; + } + + $methodCall = $node->left; + if (! $this->isRequestGetRequestType($methodCall)) { + return null; + } + + if (! $this->isHttpKernelMainRequestClassConstFetch($node->right)) { + return null; + } + + $requestClassReflection = $this->reflectionProvider->getClass(SymfonyClass::REQUEST); + $methodName = $requestClassReflection->hasMethod('isMainRequest') ? 'isMainRequest' : 'isMasterRequest'; + + return new MethodCall($methodCall->var, $methodName); + } + + private function isRequestGetRequestType(MethodCall $methodCall): bool + { + if (! $this->isName($methodCall->name, 'getRequestType')) { + return false; + } + + return $this->isObjectType($methodCall->var, new ObjectType(SymfonyClass::REQUEST)); + } + + private function isHttpKernelMainRequestClassConstFetch(Expr $expr): bool + { + if (! $expr instanceof ClassConstFetch) { + return false; + } + + if (! $this->isNames($expr->class, [SymfonyClass::HTTP_KERNEL_INTERFACE, SymfonyClass::HTTP_KERNEL])) { + return false; + } + + return $this->isNames($expr->name, ['MASTER_REQUEST', 'MAIN_REQUEST']); + } +} diff --git a/src/Enum/SymfonyClass.php b/src/Enum/SymfonyClass.php index d79bafad..9d705f94 100644 --- a/src/Enum/SymfonyClass.php +++ b/src/Enum/SymfonyClass.php @@ -75,4 +75,19 @@ final class SymfonyClass * @var string */ public const TOKEN_STORAGE_INTERFACE = 'Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface'; + + /** + * @var string + */ + public const HTTP_KERNEL_INTERFACE = 'Symfony\Component\HttpKernel\HttpKernelInterface'; + + /** + * @var string + */ + public const HTTP_KERNEL = 'Symfony\Component\HttpKernel\HttpKernel'; + + /** + * @var string + */ + public const REQUEST = 'Symfony\Component\HttpFoundation\Request'; } diff --git a/stubs/Symfony/Component/HttpFoundation/Request.php b/stubs/Symfony/Component/HttpFoundation/Request.php index 2007c895..0bdb8947 100644 --- a/stubs/Symfony/Component/HttpFoundation/Request.php +++ b/stubs/Symfony/Component/HttpFoundation/Request.php @@ -10,5 +10,16 @@ final class Request { + public function getRequestType() + { + } + // newer version + public function isMainRequest() + { + } + + public function isMasterRequest() + { + } } From 49e65e62edb5b7b9be3880aff170f73431db1b9a Mon Sep 17 00:00:00 2001 From: Myks92 <31630905+Myks92@users.noreply.github.com> Date: Fri, 28 Mar 2025 13:37:55 +0300 Subject: [PATCH 16/53] Skip excluded tag in container (#710) --- .../Fixture/skip_excluded_tag.php.inc | 12 ++++++++++++ .../Source/ExcludedService.php | 9 +++++++++ .../xml/services.xml | 3 +++ src/ValueObjectFactory/ServiceMapFactory.php | 4 ++++ 4 files changed, 28 insertions(+) create mode 100644 rules-tests/Configs/Rector/Closure/ServiceSetStringNameToClassNameRector/Fixture/skip_excluded_tag.php.inc create mode 100644 rules-tests/Configs/Rector/Closure/ServiceSetStringNameToClassNameRector/Source/ExcludedService.php diff --git a/rules-tests/Configs/Rector/Closure/ServiceSetStringNameToClassNameRector/Fixture/skip_excluded_tag.php.inc b/rules-tests/Configs/Rector/Closure/ServiceSetStringNameToClassNameRector/Fixture/skip_excluded_tag.php.inc new file mode 100644 index 00000000..bd958fc2 --- /dev/null +++ b/rules-tests/Configs/Rector/Closure/ServiceSetStringNameToClassNameRector/Fixture/skip_excluded_tag.php.inc @@ -0,0 +1,12 @@ +services(); + + $services->set('excluded', ExcludedService::class); +}; diff --git a/rules-tests/Configs/Rector/Closure/ServiceSetStringNameToClassNameRector/Source/ExcludedService.php b/rules-tests/Configs/Rector/Closure/ServiceSetStringNameToClassNameRector/Source/ExcludedService.php new file mode 100644 index 00000000..1446bb3e --- /dev/null +++ b/rules-tests/Configs/Rector/Closure/ServiceSetStringNameToClassNameRector/Source/ExcludedService.php @@ -0,0 +1,9 @@ + + + + diff --git a/src/ValueObjectFactory/ServiceMapFactory.php b/src/ValueObjectFactory/ServiceMapFactory.php index 76ea7096..c110bbbd 100644 --- a/src/ValueObjectFactory/ServiceMapFactory.php +++ b/src/ValueObjectFactory/ServiceMapFactory.php @@ -47,6 +47,10 @@ public function createFromFileContent(string $configFilePath): ServiceMap $def = $this->convertXmlToArray($def); $tags = $this->createTagFromXmlElement($def); + if (in_array('container.excluded', array_column($tags, 'name'), true)) { + continue; + } + $service = $this->createServiceFromXmlAndTagsData($attrs, $tags); if ($service->getAlias() !== null) { $aliases[] = $service; From d446023054c0bbc776c80eb25298707af1bac580 Mon Sep 17 00:00:00 2001 From: Carlos Granados Date: Mon, 31 Mar 2025 14:25:33 +0200 Subject: [PATCH 17/53] Fix cases where rule was applied even when no code changed (#711) --- .../TemplateAnnotationToThisRenderRector.php | 33 +++++++++++-------- ...ypeOptionNameFromTypeToEntryTypeRector.php | 10 ++++-- .../StringToArrayArgumentProcessRector.php | 14 ++++++-- .../ConsoleExecuteReturnIntRector.php | 2 ++ 4 files changed, 41 insertions(+), 18 deletions(-) diff --git a/rules/CodeQuality/Rector/ClassMethod/TemplateAnnotationToThisRenderRector.php b/rules/CodeQuality/Rector/ClassMethod/TemplateAnnotationToThisRenderRector.php index 77835565..bffc75da 100644 --- a/rules/CodeQuality/Rector/ClassMethod/TemplateAnnotationToThisRenderRector.php +++ b/rules/CodeQuality/Rector/ClassMethod/TemplateAnnotationToThisRenderRector.php @@ -204,14 +204,15 @@ private function refactorClassMethod( return null; } - $this->refactorStmtsAwareNode( + $hasChangedNode = $this->refactorStmtsAwareNode( $node, $templateDoctrineAnnotationTagValueNode, $hasThisRenderOrReturnsResponse, $classMethod ); - - $hasChanged = true; + if ($hasChangedNode) { + $hasChanged = true; + } return null; }); @@ -256,10 +257,10 @@ private function refactorReturn( DoctrineAnnotationTagValueNode $templateDoctrineAnnotationTagValueNode, bool $hasThisRenderOrReturnsResponse, ClassMethod $classMethod - ): void { + ): bool { // nothing we can do if (! $return->expr instanceof Expr) { - return; + return false; } // create "$this->render('template.file.twig.html', ['key' => 'value']);" method call @@ -269,7 +270,7 @@ private function refactorReturn( $classMethod ); - $this->refactorReturnWithValue( + return $this->refactorReturnWithValue( $return, $hasThisRenderOrReturnsResponse, $thisRenderMethodCall, @@ -295,7 +296,7 @@ private function refactorReturnWithValue( MethodCall $thisRenderMethodCall, ClassMethod $classMethod, DoctrineAnnotationTagValueNode $doctrineAnnotationTagValueNode - ): void { + ): bool { /** @var Expr $lastReturnExpr */ $lastReturnExpr = $return->expr; @@ -309,7 +310,7 @@ private function refactorReturnWithValue( $return->expr = $thisRenderMethodCall; } elseif ($returnStaticType instanceof MixedType) { // nothing we can do - return; + return false; } $isArrayOrResponseType = $this->arrayUnionResponseTypeAnalyzer->isArrayUnionResponseType( @@ -319,12 +320,13 @@ private function refactorReturnWithValue( // skip as the original class method has to change first if ($isArrayOrResponseType) { - return; + return false; } // already response $this->removeDoctrineAnnotationTagValueNode($classMethod, $doctrineAnnotationTagValueNode); $this->returnTypeDeclarationUpdater->updateClassMethod($classMethod, SymfonyClass::RESPONSE); + return true; } private function removeDoctrineAnnotationTagValueNode( @@ -342,11 +344,12 @@ private function refactorStmtsAwareNode( DoctrineAnnotationTagValueNode $templateDoctrineAnnotationTagValueNode, bool $hasThisRenderOrReturnsResponse, ClassMethod $classMethod - ): void { + ): bool { if ($stmtsAware->stmts === null) { - return; + return false; } + $hasChanged = false; foreach ($stmtsAware->stmts as $stmt) { if (! $stmt instanceof Return_) { continue; @@ -354,15 +357,19 @@ private function refactorStmtsAwareNode( // just created node, skip it if ($stmt->getAttributes() === []) { - return; + return false; } - $this->refactorReturn( + $hasChangedReturn = $this->refactorReturn( $stmt, $templateDoctrineAnnotationTagValueNode, $hasThisRenderOrReturnsResponse, $classMethod ); + if ($hasChangedReturn) { + $hasChanged = true; + } } + return $hasChanged; } } diff --git a/rules/Symfony27/Rector/MethodCall/ChangeCollectionTypeOptionNameFromTypeToEntryTypeRector.php b/rules/Symfony27/Rector/MethodCall/ChangeCollectionTypeOptionNameFromTypeToEntryTypeRector.php index c13e2167..71db08a8 100644 --- a/rules/Symfony27/Rector/MethodCall/ChangeCollectionTypeOptionNameFromTypeToEntryTypeRector.php +++ b/rules/Symfony27/Rector/MethodCall/ChangeCollectionTypeOptionNameFromTypeToEntryTypeRector.php @@ -113,13 +113,17 @@ public function refactor(Node $node): ?Node return null; } - $this->refactorOptionsArray($optionsArray); + $hasChanged = $this->refactorOptionsArray($optionsArray); + if (! $hasChanged) { + return null; + } return $node; } - private function refactorOptionsArray(Array_ $optionsArray): void + private function refactorOptionsArray(Array_ $optionsArray): bool { + $hasChanged = false; foreach ($optionsArray->items as $arrayItem) { if (! $arrayItem instanceof ArrayItem) { continue; @@ -135,7 +139,9 @@ private function refactorOptionsArray(Array_ $optionsArray): void } $arrayItem->key = new String_($newName); + $hasChanged = true; } } + return $hasChanged; } } diff --git a/rules/Symfony42/Rector/New_/StringToArrayArgumentProcessRector.php b/rules/Symfony42/Rector/New_/StringToArrayArgumentProcessRector.php index 90868180..6963de2c 100644 --- a/rules/Symfony42/Rector/New_/StringToArrayArgumentProcessRector.php +++ b/rules/Symfony42/Rector/New_/StringToArrayArgumentProcessRector.php @@ -111,7 +111,11 @@ private function processArgumentPosition(New_|MethodCall $node, int $argumentPos return null; } - $this->processStringType($node, $argumentPosition, $activeArgValue); + $hasChanged = $this->processStringType($node, $argumentPosition, $activeArgValue); + + if (! $hasChanged) { + return null; + } return $node; } @@ -121,25 +125,29 @@ private function shouldSkipProcessMethodCall(MethodCall $methodCall): bool return in_array($methodName, self::EXCLUDED_PROCESS_METHOD_CALLS, true); } - private function processStringType(New_|MethodCall $expr, int $argumentPosition, Expr $firstArgumentExpr): void + private function processStringType(New_|MethodCall $expr, int $argumentPosition, Expr $firstArgumentExpr): bool { if ($firstArgumentExpr instanceof Concat) { $arrayNode = $this->nodeTransformer->transformConcatToStringArray($firstArgumentExpr); $expr->args[$argumentPosition] = new Arg($arrayNode); - return; + return true; } $args = $expr->getArgs(); + $hasChanged = false; if ($firstArgumentExpr instanceof FuncCall && $this->isName($firstArgumentExpr, 'sprintf')) { $arrayNode = $this->nodeTransformer->transformSprintfToArray($firstArgumentExpr); if ($arrayNode instanceof Array_) { $args[$argumentPosition]->value = $arrayNode; + $hasChanged = true; } } elseif ($firstArgumentExpr instanceof String_) { $parts = $this->splitProcessCommandToItems($firstArgumentExpr->value); $args[$argumentPosition]->value = $this->nodeFactory->createArray($parts); + $hasChanged = true; } + return $hasChanged; } /** diff --git a/rules/Symfony44/Rector/ClassMethod/ConsoleExecuteReturnIntRector.php b/rules/Symfony44/Rector/ClassMethod/ConsoleExecuteReturnIntRector.php index f46e7441..3e88640c 100644 --- a/rules/Symfony44/Rector/ClassMethod/ConsoleExecuteReturnIntRector.php +++ b/rules/Symfony44/Rector/ClassMethod/ConsoleExecuteReturnIntRector.php @@ -90,6 +90,8 @@ public function refactor(Node $node): ?Node return null; } + $this->hasChanged = false; + $this->refactorReturnTypeDeclaration($executeClassMethod); $this->addReturn0ToExecuteClassMethod($executeClassMethod); From 19521bd56e8115afad190e3d680eaed20ef35dea Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Tue, 8 Apr 2025 10:01:06 +0200 Subject: [PATCH 18/53] [code-quality] Add attribute-existance check to SecurityAttributeToIsGrantedAttributeRector, add to code-quality set (#713) --- config/sets/symfony/symfony-code-quality.php | 4 ++ .../EventListenerToEventSubscriberRector.php | 4 +- ...ityAttributeToIsGrantedAttributeRector.php | 50 +++++++++++++++---- src/Enum/SensioAttribute.php | 10 ++++ src/Enum/SymfonyAttribute.php | 7 ++- .../Configuration/Security.php | 1 + 6 files changed, 62 insertions(+), 14 deletions(-) diff --git a/config/sets/symfony/symfony-code-quality.php b/config/sets/symfony/symfony-code-quality.php index d43c20a5..b122b817 100644 --- a/config/sets/symfony/symfony-code-quality.php +++ b/config/sets/symfony/symfony-code-quality.php @@ -2,6 +2,7 @@ declare(strict_types=1); +use Rector\Symfony\Symfony62\Rector\Class_\SecurityAttributeToIsGrantedAttributeRector; use Rector\Config\RectorConfig; use Rector\Symfony\CodeQuality\Rector\BinaryOp\RequestIsMainRector; use Rector\Symfony\CodeQuality\Rector\BinaryOp\ResponseStatusCodeRector; @@ -38,5 +39,8 @@ // routing InlineClassRoutePrefixRector::class, + + // narrow attributes + SecurityAttributeToIsGrantedAttributeRector::class, ]); }; diff --git a/rules/CodeQuality/Rector/Class_/EventListenerToEventSubscriberRector.php b/rules/CodeQuality/Rector/Class_/EventListenerToEventSubscriberRector.php index cae412d0..58b6410b 100644 --- a/rules/CodeQuality/Rector/Class_/EventListenerToEventSubscriberRector.php +++ b/rules/CodeQuality/Rector/Class_/EventListenerToEventSubscriberRector.php @@ -170,7 +170,7 @@ private function changeListenerToSubscriberWithMethods(Class_ $class, array $eve */ private function hasAsListenerAttribute(Class_ $class): bool { - if ($this->phpAttributeAnalyzer->hasPhpAttribute($class, SymfonyAttribute::EVENT_LISTENER_ATTRIBUTE)) { + if ($this->phpAttributeAnalyzer->hasPhpAttribute($class, SymfonyAttribute::AS_EVENT_LISTENER)) { return true; } @@ -181,7 +181,7 @@ private function hasAsListenerAttribute(Class_ $class): bool if ($this->phpAttributeAnalyzer->hasPhpAttribute( $classMethod, - SymfonyAttribute::EVENT_LISTENER_ATTRIBUTE + SymfonyAttribute::AS_EVENT_LISTENER )) { return true; } diff --git a/rules/Symfony62/Rector/Class_/SecurityAttributeToIsGrantedAttributeRector.php b/rules/Symfony62/Rector/Class_/SecurityAttributeToIsGrantedAttributeRector.php index 3f3748a2..6676790f 100644 --- a/rules/Symfony62/Rector/Class_/SecurityAttributeToIsGrantedAttributeRector.php +++ b/rules/Symfony62/Rector/Class_/SecurityAttributeToIsGrantedAttributeRector.php @@ -14,7 +14,10 @@ use PhpParser\Node\Scalar\String_; use PhpParser\Node\Stmt\Class_; use PhpParser\Node\Stmt\ClassMethod; +use PHPStan\Reflection\ReflectionProvider; use Rector\Rector\AbstractRector; +use Rector\Symfony\Enum\SensioAttribute; +use Rector\Symfony\Enum\SymfonyAttribute; use Rector\ValueObject\PhpVersionFeature; use Rector\VersionBonding\Contract\MinPhpVersionInterface; use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; @@ -28,15 +31,6 @@ */ final class SecurityAttributeToIsGrantedAttributeRector extends AbstractRector implements MinPhpVersionInterface { - /** - * @var string - */ - private const SECURITY_ATTRIBUTE = 'Sensio\Bundle\FrameworkExtraBundle\Configuration\Security'; - - /** - * @var string - */ - private const IS_GRANTED_ATTRIBUTE = 'Symfony\Component\Security\Http\Attribute\IsGranted'; /** * @var string @@ -50,6 +44,11 @@ final class SecurityAttributeToIsGrantedAttributeRector extends AbstractRector i */ private const IS_GRANTED_AND_SUBJECT_REGEX = '#^is_granted\((\"|\')(?[\w]+)(\"|\'),\s+(?\w+)\)$#'; + public function __construct( + private readonly ReflectionProvider $reflectionProvider + ) { + } + public function provideMinPhpVersion(): int { return PhpVersionFeature::ATTRIBUTES; @@ -113,15 +112,22 @@ public function getNodeTypes(): array */ public function refactor(Node $node): ?Node { + if (! $this->hasSymfonySecurityAttribute()) { + return null; + } + $hasChanged = false; foreach ($node->attrGroups as $attrGroup) { foreach ($attrGroup->attrs as $attribute) { - if (! $this->isName($attribute->name, self::SECURITY_ATTRIBUTE)) { + if (! $this->isName($attribute->name, SensioAttribute::SECURITY)) { continue; } - $attribute->name = new FullyQualified(self::IS_GRANTED_ATTRIBUTE); + // 1. resolve closest existing name of IsGranted + $isGrantedName = $this->resolveIsGrantedAttributeName(); + + $attribute->name = new FullyQualified($isGrantedName); $firstArg = $attribute->args[0]; $firstArg->name = new Identifier('attribute'); @@ -179,4 +185,26 @@ private function wrapToNewExpression(Expr $expr): New_|String_ return new New_(new FullyQualified('Symfony\Component\ExpressionLanguage\Expression'), $args); } + + private function resolveIsGrantedAttributeName(): string + { + if ($this->reflectionProvider->hasClass(SymfonyAttribute::IS_GRANTED)) { + return SymfonyAttribute::IS_GRANTED; + } + + // fallback to sensio, if available + return SensioAttribute::IS_GRANTED; + } + + private function hasSymfonySecurityAttribute(): bool + { + // run only if the sensio attribute is available + if (! $this->reflectionProvider->hasClass(SensioAttribute::SECURITY)) { + return false; + } + + // must be attribute, not just annotation + $securityClassReflection = $this->reflectionProvider->getClass(SensioAttribute::SECURITY); + return $securityClassReflection->isAttributeClass(); + } } diff --git a/src/Enum/SensioAttribute.php b/src/Enum/SensioAttribute.php index 86d57361..033216dd 100644 --- a/src/Enum/SensioAttribute.php +++ b/src/Enum/SensioAttribute.php @@ -25,4 +25,14 @@ final class SensioAttribute * @var string */ public const TEMPLATE = 'Sensio\Bundle\FrameworkExtraBundle\Configuration\Template'; + + /** + * @var string + */ + public const IS_GRANTED = 'Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted'; + + /** + * @var string + */ + public const SECURITY = 'Sensio\Bundle\FrameworkExtraBundle\Configuration\Security'; } diff --git a/src/Enum/SymfonyAttribute.php b/src/Enum/SymfonyAttribute.php index 9d276771..e4f79afb 100644 --- a/src/Enum/SymfonyAttribute.php +++ b/src/Enum/SymfonyAttribute.php @@ -29,10 +29,15 @@ final class SymfonyAttribute /** * @var string */ - public const EVENT_LISTENER_ATTRIBUTE = 'Symfony\Component\EventDispatcher\Attribute\AsEventListener'; + public const AS_EVENT_LISTENER = 'Symfony\Component\EventDispatcher\Attribute\AsEventListener'; /** * @var string */ public const ROUTE = 'Symfony\Component\Routing\Attribute\Route'; + + /** + * @var string + */ + public const IS_GRANTED = 'Symfony\Component\Security\Http\Attribute\IsGranted'; } diff --git a/stubs/Symfony/Bundle/FrameworkExtraBundle/Configuration/Security.php b/stubs/Symfony/Bundle/FrameworkExtraBundle/Configuration/Security.php index ebb0fddd..46838f4e 100644 --- a/stubs/Symfony/Bundle/FrameworkExtraBundle/Configuration/Security.php +++ b/stubs/Symfony/Bundle/FrameworkExtraBundle/Configuration/Security.php @@ -2,6 +2,7 @@ namespace Sensio\Bundle\FrameworkExtraBundle\Configuration; +#[\Attribute] class Security { } From 23b69dc2b71236195536332fc31db63b45315156 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Tue, 8 Apr 2025 10:24:40 +0200 Subject: [PATCH 19/53] [code-quality] Add SecurityAttributeToIsGrantedRector (#714) --- config/sets/symfony/symfony-code-quality.php | 5 +- ...controller_with_security_attribute.php.inc | 31 ++++++ .../Fixture/skip_multiples.php.inc | 13 +++ .../Fixture/with_is_granted.php.inc | 31 ++++++ ...SecurityAttributeToIsGrantedRectorTest.php | 28 ++++++ .../config/configured_rule.php | 10 ++ .../AttributePresenceDetector.php | 28 ++++++ ...tionSecurityAttributeToIsGrantedRector.php | 96 +++++++++++++++++++ .../EventListenerToEventSubscriberRector.php | 5 +- ...ityAttributeToIsGrantedAttributeRector.php | 26 ++--- .../Configuration/Security.php | 3 + 11 files changed, 251 insertions(+), 25 deletions(-) create mode 100644 rules-tests/CodeQuality/Rector/AttributeGroup/SingleConditionSecurityAttributeToIsGrantedRector/Fixture/controller_with_security_attribute.php.inc create mode 100644 rules-tests/CodeQuality/Rector/AttributeGroup/SingleConditionSecurityAttributeToIsGrantedRector/Fixture/skip_multiples.php.inc create mode 100644 rules-tests/CodeQuality/Rector/AttributeGroup/SingleConditionSecurityAttributeToIsGrantedRector/Fixture/with_is_granted.php.inc create mode 100644 rules-tests/CodeQuality/Rector/AttributeGroup/SingleConditionSecurityAttributeToIsGrantedRector/SingleConditionSecurityAttributeToIsGrantedRectorTest.php create mode 100644 rules-tests/CodeQuality/Rector/AttributeGroup/SingleConditionSecurityAttributeToIsGrantedRector/config/configured_rule.php create mode 100644 rules/CodeQuality/NodeAnalyzer/AttributePresenceDetector.php create mode 100644 rules/CodeQuality/Rector/AttributeGroup/SingleConditionSecurityAttributeToIsGrantedRector.php diff --git a/config/sets/symfony/symfony-code-quality.php b/config/sets/symfony/symfony-code-quality.php index b122b817..9f0171f0 100644 --- a/config/sets/symfony/symfony-code-quality.php +++ b/config/sets/symfony/symfony-code-quality.php @@ -2,8 +2,8 @@ declare(strict_types=1); -use Rector\Symfony\Symfony62\Rector\Class_\SecurityAttributeToIsGrantedAttributeRector; use Rector\Config\RectorConfig; +use Rector\Symfony\CodeQuality\Rector\AttributeGroup\SingleConditionSecurityAttributeToIsGrantedRector; use Rector\Symfony\CodeQuality\Rector\BinaryOp\RequestIsMainRector; use Rector\Symfony\CodeQuality\Rector\BinaryOp\ResponseStatusCodeRector; use Rector\Symfony\CodeQuality\Rector\Class_\EventListenerToEventSubscriberRector; @@ -16,6 +16,7 @@ use Rector\Symfony\CodeQuality\Rector\MethodCall\AssertSameResponseCodeWithDebugContentsRector; use Rector\Symfony\CodeQuality\Rector\MethodCall\LiteralGetToRequestClassConstantRector; use Rector\Symfony\Symfony26\Rector\MethodCall\RedirectToRouteRector; +use Rector\Symfony\Symfony62\Rector\Class_\SecurityAttributeToIsGrantedAttributeRector; return static function (RectorConfig $rectorConfig): void { $rectorConfig->rules([ @@ -41,6 +42,6 @@ InlineClassRoutePrefixRector::class, // narrow attributes - SecurityAttributeToIsGrantedAttributeRector::class, + SingleConditionSecurityAttributeToIsGrantedRector::class, ]); }; diff --git a/rules-tests/CodeQuality/Rector/AttributeGroup/SingleConditionSecurityAttributeToIsGrantedRector/Fixture/controller_with_security_attribute.php.inc b/rules-tests/CodeQuality/Rector/AttributeGroup/SingleConditionSecurityAttributeToIsGrantedRector/Fixture/controller_with_security_attribute.php.inc new file mode 100644 index 00000000..ae5d8251 --- /dev/null +++ b/rules-tests/CodeQuality/Rector/AttributeGroup/SingleConditionSecurityAttributeToIsGrantedRector/Fixture/controller_with_security_attribute.php.inc @@ -0,0 +1,31 @@ + +----- + diff --git a/rules-tests/CodeQuality/Rector/AttributeGroup/SingleConditionSecurityAttributeToIsGrantedRector/Fixture/skip_multiples.php.inc b/rules-tests/CodeQuality/Rector/AttributeGroup/SingleConditionSecurityAttributeToIsGrantedRector/Fixture/skip_multiples.php.inc new file mode 100644 index 00000000..4a9f01cb --- /dev/null +++ b/rules-tests/CodeQuality/Rector/AttributeGroup/SingleConditionSecurityAttributeToIsGrantedRector/Fixture/skip_multiples.php.inc @@ -0,0 +1,13 @@ + +----- + diff --git a/rules-tests/CodeQuality/Rector/AttributeGroup/SingleConditionSecurityAttributeToIsGrantedRector/SingleConditionSecurityAttributeToIsGrantedRectorTest.php b/rules-tests/CodeQuality/Rector/AttributeGroup/SingleConditionSecurityAttributeToIsGrantedRector/SingleConditionSecurityAttributeToIsGrantedRectorTest.php new file mode 100644 index 00000000..1e3a6f3a --- /dev/null +++ b/rules-tests/CodeQuality/Rector/AttributeGroup/SingleConditionSecurityAttributeToIsGrantedRector/SingleConditionSecurityAttributeToIsGrantedRectorTest.php @@ -0,0 +1,28 @@ +doTestFile($filePath); + } + + public static function provideData(): Iterator + { + return self::yieldFilesFromDirectory(__DIR__ . '/Fixture'); + } + + public function provideConfigFilePath(): string + { + return __DIR__ . '/config/configured_rule.php'; + } +} diff --git a/rules-tests/CodeQuality/Rector/AttributeGroup/SingleConditionSecurityAttributeToIsGrantedRector/config/configured_rule.php b/rules-tests/CodeQuality/Rector/AttributeGroup/SingleConditionSecurityAttributeToIsGrantedRector/config/configured_rule.php new file mode 100644 index 00000000..c6217805 --- /dev/null +++ b/rules-tests/CodeQuality/Rector/AttributeGroup/SingleConditionSecurityAttributeToIsGrantedRector/config/configured_rule.php @@ -0,0 +1,10 @@ +rule(SingleConditionSecurityAttributeToIsGrantedRector::class); +}; diff --git a/rules/CodeQuality/NodeAnalyzer/AttributePresenceDetector.php b/rules/CodeQuality/NodeAnalyzer/AttributePresenceDetector.php new file mode 100644 index 00000000..69ee1eb2 --- /dev/null +++ b/rules/CodeQuality/NodeAnalyzer/AttributePresenceDetector.php @@ -0,0 +1,28 @@ +reflectionProvider->hasClass($attributeClass)) { + return false; + } + + // must be attribute, not just annotation + $securityClassReflection = $this->reflectionProvider->getClass($attributeClass); + + return $securityClassReflection->isAttributeClass(); + } +} diff --git a/rules/CodeQuality/Rector/AttributeGroup/SingleConditionSecurityAttributeToIsGrantedRector.php b/rules/CodeQuality/Rector/AttributeGroup/SingleConditionSecurityAttributeToIsGrantedRector.php new file mode 100644 index 00000000..cf756686 --- /dev/null +++ b/rules/CodeQuality/Rector/AttributeGroup/SingleConditionSecurityAttributeToIsGrantedRector.php @@ -0,0 +1,96 @@ +attributePresenceDetector->detect(SensioAttribute::SECURITY)) { + return null; + } + + foreach ($node->attrs as $attr) { + if (! $this->isName($attr->name, SensioAttribute::SECURITY)) { + continue; + } + + $firstArgValue = $attr->args[0]->value; + if (! $firstArgValue instanceof String_) { + continue; + } + + $matches = Strings::match( + $firstArgValue->value, + '#^(is_granted|has_role)\(\'(?[A-Za-z_]+)\'\)$#' + ); + if (! isset($matches['access_right'])) { + continue; + } + + $attr->name = new FullyQualified(SensioAttribute::IS_GRANTED); + $attr->args = [new Arg(new String_($matches['access_right']))]; + + return $node; + } + + return null; + } +} diff --git a/rules/CodeQuality/Rector/Class_/EventListenerToEventSubscriberRector.php b/rules/CodeQuality/Rector/Class_/EventListenerToEventSubscriberRector.php index 58b6410b..b0c9b5db 100644 --- a/rules/CodeQuality/Rector/Class_/EventListenerToEventSubscriberRector.php +++ b/rules/CodeQuality/Rector/Class_/EventListenerToEventSubscriberRector.php @@ -179,10 +179,7 @@ private function hasAsListenerAttribute(Class_ $class): bool continue; } - if ($this->phpAttributeAnalyzer->hasPhpAttribute( - $classMethod, - SymfonyAttribute::AS_EVENT_LISTENER - )) { + if ($this->phpAttributeAnalyzer->hasPhpAttribute($classMethod, SymfonyAttribute::AS_EVENT_LISTENER)) { return true; } } diff --git a/rules/Symfony62/Rector/Class_/SecurityAttributeToIsGrantedAttributeRector.php b/rules/Symfony62/Rector/Class_/SecurityAttributeToIsGrantedAttributeRector.php index 6676790f..48c2a5d8 100644 --- a/rules/Symfony62/Rector/Class_/SecurityAttributeToIsGrantedAttributeRector.php +++ b/rules/Symfony62/Rector/Class_/SecurityAttributeToIsGrantedAttributeRector.php @@ -16,6 +16,7 @@ use PhpParser\Node\Stmt\ClassMethod; use PHPStan\Reflection\ReflectionProvider; use Rector\Rector\AbstractRector; +use Rector\Symfony\CodeQuality\NodeAnalyzer\AttributePresenceDetector; use Rector\Symfony\Enum\SensioAttribute; use Rector\Symfony\Enum\SymfonyAttribute; use Rector\ValueObject\PhpVersionFeature; @@ -31,7 +32,6 @@ */ final class SecurityAttributeToIsGrantedAttributeRector extends AbstractRector implements MinPhpVersionInterface { - /** * @var string * @see https://regex101.com/r/Si1sDz/1 @@ -45,7 +45,8 @@ final class SecurityAttributeToIsGrantedAttributeRector extends AbstractRector i private const IS_GRANTED_AND_SUBJECT_REGEX = '#^is_granted\((\"|\')(?[\w]+)(\"|\'),\s+(?\w+)\)$#'; public function __construct( - private readonly ReflectionProvider $reflectionProvider + private readonly ReflectionProvider $reflectionProvider, + private readonly AttributePresenceDetector $attributePresenceDetector, ) { } @@ -83,12 +84,12 @@ public function list() class PostController extends Controller { - #[IsGranted('ROLE_ADMIN')] + #[IsGranted(attribute: 'ROLE_ADMIN')] public function index() { } - #[IsGranted(new Expression("is_granted('ROLE_ADMIN') and is_granted('ROLE_FRIENDLY_USER')"))] + #[IsGranted(attribute: new Expression("is_granted('ROLE_ADMIN') and is_granted('ROLE_FRIENDLY_USER')"))] public function list() { } @@ -112,7 +113,7 @@ public function getNodeTypes(): array */ public function refactor(Node $node): ?Node { - if (! $this->hasSymfonySecurityAttribute()) { + if (! $this->attributePresenceDetector->detect(SensioAttribute::SECURITY)) { return null; } @@ -126,7 +127,6 @@ public function refactor(Node $node): ?Node // 1. resolve closest existing name of IsGranted $isGrantedName = $this->resolveIsGrantedAttributeName(); - $attribute->name = new FullyQualified($isGrantedName); $firstArg = $attribute->args[0]; @@ -192,19 +192,7 @@ private function resolveIsGrantedAttributeName(): string return SymfonyAttribute::IS_GRANTED; } - // fallback to sensio, if available + // fallback to "sensio" return SensioAttribute::IS_GRANTED; } - - private function hasSymfonySecurityAttribute(): bool - { - // run only if the sensio attribute is available - if (! $this->reflectionProvider->hasClass(SensioAttribute::SECURITY)) { - return false; - } - - // must be attribute, not just annotation - $securityClassReflection = $this->reflectionProvider->getClass(SensioAttribute::SECURITY); - return $securityClassReflection->isAttributeClass(); - } } diff --git a/stubs/Symfony/Bundle/FrameworkExtraBundle/Configuration/Security.php b/stubs/Symfony/Bundle/FrameworkExtraBundle/Configuration/Security.php index 46838f4e..ee3376d6 100644 --- a/stubs/Symfony/Bundle/FrameworkExtraBundle/Configuration/Security.php +++ b/stubs/Symfony/Bundle/FrameworkExtraBundle/Configuration/Security.php @@ -5,4 +5,7 @@ #[\Attribute] class Security { + public function __construct(string $expression) + { + } } From 41c4a5d4b2df2cfa42297aa57244b4db1b37278e Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Tue, 8 Apr 2025 10:25:50 +0200 Subject: [PATCH 20/53] note --- .../SingleConditionSecurityAttributeToIsGrantedRectorTest.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/rules-tests/CodeQuality/Rector/AttributeGroup/SingleConditionSecurityAttributeToIsGrantedRector/SingleConditionSecurityAttributeToIsGrantedRectorTest.php b/rules-tests/CodeQuality/Rector/AttributeGroup/SingleConditionSecurityAttributeToIsGrantedRector/SingleConditionSecurityAttributeToIsGrantedRectorTest.php index 1e3a6f3a..aabfdd70 100644 --- a/rules-tests/CodeQuality/Rector/AttributeGroup/SingleConditionSecurityAttributeToIsGrantedRector/SingleConditionSecurityAttributeToIsGrantedRectorTest.php +++ b/rules-tests/CodeQuality/Rector/AttributeGroup/SingleConditionSecurityAttributeToIsGrantedRector/SingleConditionSecurityAttributeToIsGrantedRectorTest.php @@ -8,6 +8,9 @@ use PHPUnit\Framework\Attributes\DataProvider; use Rector\Testing\PHPUnit\AbstractRectorTestCase; +/** + * @see https://github.com/symfony/symfony/pull/27305/ + */ final class SingleConditionSecurityAttributeToIsGrantedRectorTest extends AbstractRectorTestCase { #[DataProvider('provideData')] From 24414a6761c6ccf6d719e7fc9d0caaef3cf59e2c Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Tue, 8 Apr 2025 10:29:00 +0200 Subject: [PATCH 21/53] note 2 --- .../SingleConditionSecurityAttributeToIsGrantedRectorTest.php | 3 --- .../SingleConditionSecurityAttributeToIsGrantedRector.php | 4 ++++ 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/rules-tests/CodeQuality/Rector/AttributeGroup/SingleConditionSecurityAttributeToIsGrantedRector/SingleConditionSecurityAttributeToIsGrantedRectorTest.php b/rules-tests/CodeQuality/Rector/AttributeGroup/SingleConditionSecurityAttributeToIsGrantedRector/SingleConditionSecurityAttributeToIsGrantedRectorTest.php index aabfdd70..1e3a6f3a 100644 --- a/rules-tests/CodeQuality/Rector/AttributeGroup/SingleConditionSecurityAttributeToIsGrantedRector/SingleConditionSecurityAttributeToIsGrantedRectorTest.php +++ b/rules-tests/CodeQuality/Rector/AttributeGroup/SingleConditionSecurityAttributeToIsGrantedRector/SingleConditionSecurityAttributeToIsGrantedRectorTest.php @@ -8,9 +8,6 @@ use PHPUnit\Framework\Attributes\DataProvider; use Rector\Testing\PHPUnit\AbstractRectorTestCase; -/** - * @see https://github.com/symfony/symfony/pull/27305/ - */ final class SingleConditionSecurityAttributeToIsGrantedRectorTest extends AbstractRectorTestCase { #[DataProvider('provideData')] diff --git a/rules/CodeQuality/Rector/AttributeGroup/SingleConditionSecurityAttributeToIsGrantedRector.php b/rules/CodeQuality/Rector/AttributeGroup/SingleConditionSecurityAttributeToIsGrantedRector.php index cf756686..5e3f5653 100644 --- a/rules/CodeQuality/Rector/AttributeGroup/SingleConditionSecurityAttributeToIsGrantedRector.php +++ b/rules/CodeQuality/Rector/AttributeGroup/SingleConditionSecurityAttributeToIsGrantedRector.php @@ -16,6 +16,10 @@ use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; +/** + * @see https://github.com/symfony/symfony/pull/27305/ + * @see https://stackoverflow.com/a/65439590/1348344 + */ final class SingleConditionSecurityAttributeToIsGrantedRector extends AbstractRector { public function __construct( From 456b20adfbece1197062abec5d9c0593cf1629e0 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Tue, 8 Apr 2025 20:40:56 +0200 Subject: [PATCH 22/53] [code-quality] Add SplitAndSecurityAttributeToIsGrantedRector (#715) --- config/sets/symfony/symfony-code-quality.php | 3 +- .../Fixture/skip_single_or.php.inc | 11 ++ .../Fixture/two_security_attributes.php.inc | 27 ++++ ...SecurityAttributeToIsGrantedRectorTest.php | 28 ++++ .../config/configured_rule.php | 10 ++ ...tionSecurityAttributeToIsGrantedRector.php | 2 + ...tAndSecurityAttributeToIsGrantedRector.php | 125 ++++++++++++++++++ 7 files changed, 205 insertions(+), 1 deletion(-) create mode 100644 rules-tests/CodeQuality/Rector/Class_/SplitAndSecurityAttributeToIsGrantedRector/Fixture/skip_single_or.php.inc create mode 100644 rules-tests/CodeQuality/Rector/Class_/SplitAndSecurityAttributeToIsGrantedRector/Fixture/two_security_attributes.php.inc create mode 100644 rules-tests/CodeQuality/Rector/Class_/SplitAndSecurityAttributeToIsGrantedRector/SplitAndSecurityAttributeToIsGrantedRectorTest.php create mode 100644 rules-tests/CodeQuality/Rector/Class_/SplitAndSecurityAttributeToIsGrantedRector/config/configured_rule.php create mode 100644 rules/CodeQuality/Rector/Class_/SplitAndSecurityAttributeToIsGrantedRector.php diff --git a/config/sets/symfony/symfony-code-quality.php b/config/sets/symfony/symfony-code-quality.php index 9f0171f0..1255e98f 100644 --- a/config/sets/symfony/symfony-code-quality.php +++ b/config/sets/symfony/symfony-code-quality.php @@ -9,6 +9,7 @@ use Rector\Symfony\CodeQuality\Rector\Class_\EventListenerToEventSubscriberRector; use Rector\Symfony\CodeQuality\Rector\Class_\InlineClassRoutePrefixRector; use Rector\Symfony\CodeQuality\Rector\Class_\LoadValidatorMetadataToAnnotationRector; +use Rector\Symfony\CodeQuality\Rector\Class_\SplitAndSecurityAttributeToIsGrantedRector; use Rector\Symfony\CodeQuality\Rector\ClassMethod\ActionSuffixRemoverRector; use Rector\Symfony\CodeQuality\Rector\ClassMethod\ParamTypeFromRouteRequiredRegexRector; use Rector\Symfony\CodeQuality\Rector\ClassMethod\RemoveUnusedRequestParamRector; @@ -16,7 +17,6 @@ use Rector\Symfony\CodeQuality\Rector\MethodCall\AssertSameResponseCodeWithDebugContentsRector; use Rector\Symfony\CodeQuality\Rector\MethodCall\LiteralGetToRequestClassConstantRector; use Rector\Symfony\Symfony26\Rector\MethodCall\RedirectToRouteRector; -use Rector\Symfony\Symfony62\Rector\Class_\SecurityAttributeToIsGrantedAttributeRector; return static function (RectorConfig $rectorConfig): void { $rectorConfig->rules([ @@ -43,5 +43,6 @@ // narrow attributes SingleConditionSecurityAttributeToIsGrantedRector::class, + SplitAndSecurityAttributeToIsGrantedRector::class, ]); }; diff --git a/rules-tests/CodeQuality/Rector/Class_/SplitAndSecurityAttributeToIsGrantedRector/Fixture/skip_single_or.php.inc b/rules-tests/CodeQuality/Rector/Class_/SplitAndSecurityAttributeToIsGrantedRector/Fixture/skip_single_or.php.inc new file mode 100644 index 00000000..a51b83fb --- /dev/null +++ b/rules-tests/CodeQuality/Rector/Class_/SplitAndSecurityAttributeToIsGrantedRector/Fixture/skip_single_or.php.inc @@ -0,0 +1,11 @@ + +----- + diff --git a/rules-tests/CodeQuality/Rector/Class_/SplitAndSecurityAttributeToIsGrantedRector/SplitAndSecurityAttributeToIsGrantedRectorTest.php b/rules-tests/CodeQuality/Rector/Class_/SplitAndSecurityAttributeToIsGrantedRector/SplitAndSecurityAttributeToIsGrantedRectorTest.php new file mode 100644 index 00000000..244e8f5c --- /dev/null +++ b/rules-tests/CodeQuality/Rector/Class_/SplitAndSecurityAttributeToIsGrantedRector/SplitAndSecurityAttributeToIsGrantedRectorTest.php @@ -0,0 +1,28 @@ +doTestFile($filePath); + } + + public static function provideData(): Iterator + { + return self::yieldFilesFromDirectory(__DIR__ . '/Fixture'); + } + + public function provideConfigFilePath(): string + { + return __DIR__ . '/config/configured_rule.php'; + } +} diff --git a/rules-tests/CodeQuality/Rector/Class_/SplitAndSecurityAttributeToIsGrantedRector/config/configured_rule.php b/rules-tests/CodeQuality/Rector/Class_/SplitAndSecurityAttributeToIsGrantedRector/config/configured_rule.php new file mode 100644 index 00000000..99695fc3 --- /dev/null +++ b/rules-tests/CodeQuality/Rector/Class_/SplitAndSecurityAttributeToIsGrantedRector/config/configured_rule.php @@ -0,0 +1,10 @@ +rule(SplitAndSecurityAttributeToIsGrantedRector::class); +}; diff --git a/rules/CodeQuality/Rector/AttributeGroup/SingleConditionSecurityAttributeToIsGrantedRector.php b/rules/CodeQuality/Rector/AttributeGroup/SingleConditionSecurityAttributeToIsGrantedRector.php index 5e3f5653..e956e95e 100644 --- a/rules/CodeQuality/Rector/AttributeGroup/SingleConditionSecurityAttributeToIsGrantedRector.php +++ b/rules/CodeQuality/Rector/AttributeGroup/SingleConditionSecurityAttributeToIsGrantedRector.php @@ -19,6 +19,8 @@ /** * @see https://github.com/symfony/symfony/pull/27305/ * @see https://stackoverflow.com/a/65439590/1348344 + * + * @see \Rector\Symfony\Tests\CodeQuality\Rector\AttributeGroup\SingleConditionSecurityAttributeToIsGrantedRector\SingleConditionSecurityAttributeToIsGrantedRectorTest */ final class SingleConditionSecurityAttributeToIsGrantedRector extends AbstractRector { diff --git a/rules/CodeQuality/Rector/Class_/SplitAndSecurityAttributeToIsGrantedRector.php b/rules/CodeQuality/Rector/Class_/SplitAndSecurityAttributeToIsGrantedRector.php new file mode 100644 index 00000000..34695110 --- /dev/null +++ b/rules/CodeQuality/Rector/Class_/SplitAndSecurityAttributeToIsGrantedRector.php @@ -0,0 +1,125 @@ +attrGroups as $key => $attrGroup) { + foreach ($attrGroup->attrs as $attr) { + if (! $this->isName($attr->name, Security::class)) { + continue; + } + + $firstArgValue = $attr->args[0]->value; + if (! $firstArgValue instanceof String_) { + continue; + } + + $content = $firstArgValue->value; + + // unable to resolve with pure attributes + if (str_contains($content, ' or ')) { + continue; + } + + // we look for "and"s + if (! str_contains($content, ' and')) { + continue; + } + + $andItems = explode(' and ', $content); + + $accessRights = []; + + foreach ($andItems as $andItem) { + $matches = Strings::match($andItem, '#^(is_granted|has_role)\(\'(?[A-Za-z_]+)\'\)$#'); + if (! isset($matches['access_right'])) { + // all or nothing + return null; + } + + $accessRights[] = $matches['access_right']; + } + + unset($node->attrGroups[$key]); + + $hasChanged = true; + + foreach ($accessRights as $accessRight) { + $attributeGroup = new AttributeGroup([ + new Attribute(new FullyQualified(IsGranted::class), [ + new Arg(new String_($accessRight)), + ]), + ]); + + $node->attrGroups[] = $attributeGroup; + } + } + } + + if ($hasChanged) { + return $node; + } + + return null; + } +} From b5f953a3bc2502ff5baaf0a43e6428573f563ff7 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Wed, 9 Apr 2025 14:28:07 +0200 Subject: [PATCH 23/53] add ampersand support (#716) --- .../Fixture/with_ampersand_attributes.php.inc | 26 +++++++++++++++++++ ...tAndSecurityAttributeToIsGrantedRector.php | 15 ++++++----- 2 files changed, 35 insertions(+), 6 deletions(-) create mode 100644 rules-tests/CodeQuality/Rector/Class_/SplitAndSecurityAttributeToIsGrantedRector/Fixture/with_ampersand_attributes.php.inc diff --git a/rules-tests/CodeQuality/Rector/Class_/SplitAndSecurityAttributeToIsGrantedRector/Fixture/with_ampersand_attributes.php.inc b/rules-tests/CodeQuality/Rector/Class_/SplitAndSecurityAttributeToIsGrantedRector/Fixture/with_ampersand_attributes.php.inc new file mode 100644 index 00000000..8ef6db8c --- /dev/null +++ b/rules-tests/CodeQuality/Rector/Class_/SplitAndSecurityAttributeToIsGrantedRector/Fixture/with_ampersand_attributes.php.inc @@ -0,0 +1,26 @@ + +----- + diff --git a/rules/CodeQuality/Rector/Class_/SplitAndSecurityAttributeToIsGrantedRector.php b/rules/CodeQuality/Rector/Class_/SplitAndSecurityAttributeToIsGrantedRector.php index 34695110..12e0895c 100644 --- a/rules/CodeQuality/Rector/Class_/SplitAndSecurityAttributeToIsGrantedRector.php +++ b/rules/CodeQuality/Rector/Class_/SplitAndSecurityAttributeToIsGrantedRector.php @@ -4,12 +4,12 @@ namespace Rector\Symfony\CodeQuality\Rector\Class_; -use PhpParser\Node\Name\FullyQualified; use Nette\Utils\Strings; use PhpParser\Node; use PhpParser\Node\Arg; use PhpParser\Node\Attribute; use PhpParser\Node\AttributeGroup; +use PhpParser\Node\Name\FullyQualified; use PhpParser\Node\Scalar\String_; use PhpParser\Node\Stmt\Class_; use PhpParser\Node\Stmt\ClassMethod; @@ -82,11 +82,16 @@ public function refactor(Node $node): ?Node } // we look for "and"s - if (! str_contains($content, ' and')) { + if (! str_contains($content, ' and ') && ! str_contains($content, ' && ')) { continue; } - $andItems = explode(' and ', $content); + // split by && and "and" + if (str_contains($content, ' && ')) { + $andItems = explode(' && ', $content); + } else { + $andItems = explode(' and ', $content); + } $accessRights = []; @@ -106,9 +111,7 @@ public function refactor(Node $node): ?Node foreach ($accessRights as $accessRight) { $attributeGroup = new AttributeGroup([ - new Attribute(new FullyQualified(IsGranted::class), [ - new Arg(new String_($accessRight)), - ]), + new Attribute(new FullyQualified(IsGranted::class), [new Arg(new String_($accessRight))]), ]); $node->attrGroups[] = $attributeGroup; From 3681411a79a40459a9e8beb49bd855878fb5f2a7 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Thu, 10 Apr 2025 17:07:43 +0700 Subject: [PATCH 24/53] [CodeQuality] Handle crash on no extensions on StringExtensionToConfigBuilderRector (#717) --- .../Fixture/skip_no_extension.php.inc | 31 +++++++++++++++++++ .../SymfonyClosureExtensionMatcher.php | 4 +++ 2 files changed, 35 insertions(+) create mode 100644 rules-tests/CodeQuality/Rector/Closure/StringExtensionToConfigBuilderRector/Fixture/skip_no_extension.php.inc diff --git a/rules-tests/CodeQuality/Rector/Closure/StringExtensionToConfigBuilderRector/Fixture/skip_no_extension.php.inc b/rules-tests/CodeQuality/Rector/Closure/StringExtensionToConfigBuilderRector/Fixture/skip_no_extension.php.inc new file mode 100644 index 00000000..bd0f0e5b --- /dev/null +++ b/rules-tests/CodeQuality/Rector/Closure/StringExtensionToConfigBuilderRector/Fixture/skip_no_extension.php.inc @@ -0,0 +1,31 @@ +services(); + + $services->alias(RequestFactoryInterface::class, 'http_discovery.psr17_factory'); + + $services->alias(ResponseFactoryInterface::class, 'http_discovery.psr17_factory'); + + $services->alias(ServerRequestFactoryInterface::class, 'http_discovery.psr17_factory'); + + $services->alias(StreamFactoryInterface::class, 'http_discovery.psr17_factory'); + + $services->alias(UploadedFileFactoryInterface::class, 'http_discovery.psr17_factory'); + + $services->alias(UriFactoryInterface::class, 'http_discovery.psr17_factory'); + + $services->set('http_discovery.psr17_factory', Psr17Factory::class); +}; \ No newline at end of file diff --git a/src/NodeAnalyzer/SymfonyClosureExtensionMatcher.php b/src/NodeAnalyzer/SymfonyClosureExtensionMatcher.php index 6ce0a972..3ad58af7 100644 --- a/src/NodeAnalyzer/SymfonyClosureExtensionMatcher.php +++ b/src/NodeAnalyzer/SymfonyClosureExtensionMatcher.php @@ -29,6 +29,10 @@ public function match(Closure $closure): ?ExtensionKeyAndConfiguration return null; } + if ($extensionNames === []) { + return null; + } + // warn use early about it, to avoid silent skip $errorMessage = sprintf( 'Split extensions "%s" to multiple separated files first', From 9b807485a017c4becf5b7d6f93e05a1597700b0a Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Tue, 22 Apr 2025 17:14:14 +0700 Subject: [PATCH 25/53] Update fixture on parent construct empty usage (#719) --- composer.json | 2 +- .../CommandGetByTypeToConstructorInjectionRectorTest.php | 2 ++ .../Fixture/command_validator.php.inc | 1 + .../GetBySymfonyStringToConstructorInjectionRectorTest.php | 2 ++ 4 files changed, 6 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index b3b44cfe..6f40fb6c 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,7 @@ "phpstan/phpstan": "^2.1.8", "phpstan/phpstan-webmozart-assert": "^2.0", "phpunit/phpunit": "^11.4", - "rector/rector-src": "dev-main", + "rector/rector-src": "dev-follow-empty-param", "rector/type-perfect": "^2.0", "symfony/config": "^6.4", "symfony/dependency-injection": "^6.4", diff --git a/rules-tests/DependencyInjection/Rector/Class_/CommandGetByTypeToConstructorInjectionRector/CommandGetByTypeToConstructorInjectionRectorTest.php b/rules-tests/DependencyInjection/Rector/Class_/CommandGetByTypeToConstructorInjectionRector/CommandGetByTypeToConstructorInjectionRectorTest.php index 85c3f7e6..91bfa77b 100644 --- a/rules-tests/DependencyInjection/Rector/Class_/CommandGetByTypeToConstructorInjectionRector/CommandGetByTypeToConstructorInjectionRectorTest.php +++ b/rules-tests/DependencyInjection/Rector/Class_/CommandGetByTypeToConstructorInjectionRector/CommandGetByTypeToConstructorInjectionRectorTest.php @@ -6,8 +6,10 @@ use Iterator; use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\RunClassInSeparateProcess; use Rector\Testing\PHPUnit\AbstractRectorTestCase; +#[RunClassInSeparateProcess] final class CommandGetByTypeToConstructorInjectionRectorTest extends AbstractRectorTestCase { #[DataProvider('provideData')] diff --git a/rules-tests/DependencyInjection/Rector/Class_/GetBySymfonyStringToConstructorInjectionRector/Fixture/command_validator.php.inc b/rules-tests/DependencyInjection/Rector/Class_/GetBySymfonyStringToConstructorInjectionRector/Fixture/command_validator.php.inc index eee09ad6..adb8d006 100644 --- a/rules-tests/DependencyInjection/Rector/Class_/GetBySymfonyStringToConstructorInjectionRector/Fixture/command_validator.php.inc +++ b/rules-tests/DependencyInjection/Rector/Class_/GetBySymfonyStringToConstructorInjectionRector/Fixture/command_validator.php.inc @@ -24,6 +24,7 @@ final class CommandValidator extends ContainerAwareCommand { public function __construct(private readonly \Symfony\Component\Validator\Validator\ValidatorInterface $validator) { + parent::__construct(); } public function configure() { diff --git a/rules-tests/DependencyInjection/Rector/Class_/GetBySymfonyStringToConstructorInjectionRector/GetBySymfonyStringToConstructorInjectionRectorTest.php b/rules-tests/DependencyInjection/Rector/Class_/GetBySymfonyStringToConstructorInjectionRector/GetBySymfonyStringToConstructorInjectionRectorTest.php index 5b22c570..99e7dbfa 100644 --- a/rules-tests/DependencyInjection/Rector/Class_/GetBySymfonyStringToConstructorInjectionRector/GetBySymfonyStringToConstructorInjectionRectorTest.php +++ b/rules-tests/DependencyInjection/Rector/Class_/GetBySymfonyStringToConstructorInjectionRector/GetBySymfonyStringToConstructorInjectionRectorTest.php @@ -6,8 +6,10 @@ use Iterator; use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\RunClassInSeparateProcess; use Rector\Testing\PHPUnit\AbstractRectorTestCase; +#[RunClassInSeparateProcess] final class GetBySymfonyStringToConstructorInjectionRectorTest extends AbstractRectorTestCase { #[DataProvider('provideData')] From fc00253be624ef24a4f3ad7df177dfa4af28a476 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Tue, 22 Apr 2025 17:16:52 +0700 Subject: [PATCH 26/53] Back to use rector-src dev-main (#720) --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 6f40fb6c..b3b44cfe 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,7 @@ "phpstan/phpstan": "^2.1.8", "phpstan/phpstan-webmozart-assert": "^2.0", "phpunit/phpunit": "^11.4", - "rector/rector-src": "dev-follow-empty-param", + "rector/rector-src": "dev-main", "rector/type-perfect": "^2.0", "symfony/config": "^6.4", "symfony/dependency-injection": "^6.4", From 9a4e2c8f07b227da7df27987f4ab13503abd8b86 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Tue, 22 Apr 2025 18:25:39 +0700 Subject: [PATCH 27/53] Clean up #[RunClassInSeparateProcess] tweak (#721) --- .../CommandGetByTypeToConstructorInjectionRectorTest.php | 2 -- .../GetBySymfonyStringToConstructorInjectionRectorTest.php | 2 -- 2 files changed, 4 deletions(-) diff --git a/rules-tests/DependencyInjection/Rector/Class_/CommandGetByTypeToConstructorInjectionRector/CommandGetByTypeToConstructorInjectionRectorTest.php b/rules-tests/DependencyInjection/Rector/Class_/CommandGetByTypeToConstructorInjectionRector/CommandGetByTypeToConstructorInjectionRectorTest.php index 91bfa77b..85c3f7e6 100644 --- a/rules-tests/DependencyInjection/Rector/Class_/CommandGetByTypeToConstructorInjectionRector/CommandGetByTypeToConstructorInjectionRectorTest.php +++ b/rules-tests/DependencyInjection/Rector/Class_/CommandGetByTypeToConstructorInjectionRector/CommandGetByTypeToConstructorInjectionRectorTest.php @@ -6,10 +6,8 @@ use Iterator; use PHPUnit\Framework\Attributes\DataProvider; -use PHPUnit\Framework\Attributes\RunClassInSeparateProcess; use Rector\Testing\PHPUnit\AbstractRectorTestCase; -#[RunClassInSeparateProcess] final class CommandGetByTypeToConstructorInjectionRectorTest extends AbstractRectorTestCase { #[DataProvider('provideData')] diff --git a/rules-tests/DependencyInjection/Rector/Class_/GetBySymfonyStringToConstructorInjectionRector/GetBySymfonyStringToConstructorInjectionRectorTest.php b/rules-tests/DependencyInjection/Rector/Class_/GetBySymfonyStringToConstructorInjectionRector/GetBySymfonyStringToConstructorInjectionRectorTest.php index 99e7dbfa..5b22c570 100644 --- a/rules-tests/DependencyInjection/Rector/Class_/GetBySymfonyStringToConstructorInjectionRector/GetBySymfonyStringToConstructorInjectionRectorTest.php +++ b/rules-tests/DependencyInjection/Rector/Class_/GetBySymfonyStringToConstructorInjectionRector/GetBySymfonyStringToConstructorInjectionRectorTest.php @@ -6,10 +6,8 @@ use Iterator; use PHPUnit\Framework\Attributes\DataProvider; -use PHPUnit\Framework\Attributes\RunClassInSeparateProcess; use Rector\Testing\PHPUnit\AbstractRectorTestCase; -#[RunClassInSeparateProcess] final class GetBySymfonyStringToConstructorInjectionRectorTest extends AbstractRectorTestCase { #[DataProvider('provideData')] From b3a4192e97a4ea787becb19929902897a5d6e4d6 Mon Sep 17 00:00:00 2001 From: Johan Vlaar Date: Thu, 24 Apr 2025 12:45:36 +0200 Subject: [PATCH 28/53] [Symfony 7.3] add 7.3 constant and test for 7.3 and support method chaining and test help to attribute (#722) --- config/sets/symfony/symfony73.php | 3 +- .../Fixture/call_all_option.php.inc | 43 ++++ .../Fixture/other-calls-middle.php.inc | 31 --- .../CommandHelpToAttributeRectorTest.php | 28 +++ .../add_help_to_attribute_command.php.inc | 36 +++ .../all_attribute_set_also_add_help.php.inc | 42 ++++ .../skip_has_help_attribute_command.php.inc | 32 +++ ...mand_attribute_and_no_help_command.php.inc | 16 ++ .../config/configured_rule.php | 10 + .../some_command_with_method_chaining.php.inc | 62 +++++ .../some_command_with_set_help.php.inc | 67 ++++++ .../Class_/CommandHelpToAttributeRector.php | 220 ++++++++++++++++++ .../Rector/Class_/InvokableCommandRector.php | 47 +++- src/Set/SymfonySetList.php | 5 + .../Component/console/attribute/AsCommand.php | 53 +++++ .../Fixture/command_remove_config.php.inc | 72 ++++++ tests/Set/Symfony73/Symfony73Test.php | 28 +++ tests/Set/Symfony73/config/symfony73.php | 10 + 18 files changed, 772 insertions(+), 33 deletions(-) create mode 100644 rules-tests/Symfony61/Rector/Class_/CommandConfigureToAttributeRector/Fixture/call_all_option.php.inc delete mode 100644 rules-tests/Symfony61/Rector/Class_/CommandConfigureToAttributeRector/Fixture/other-calls-middle.php.inc create mode 100644 rules-tests/Symfony73/Rector/Class_/CommandHelpToAttributeRector/CommandHelpToAttributeRectorTest.php create mode 100644 rules-tests/Symfony73/Rector/Class_/CommandHelpToAttributeRector/Fixture/add_help_to_attribute_command.php.inc create mode 100644 rules-tests/Symfony73/Rector/Class_/CommandHelpToAttributeRector/Fixture/all_attribute_set_also_add_help.php.inc create mode 100644 rules-tests/Symfony73/Rector/Class_/CommandHelpToAttributeRector/Fixture/skip_has_help_attribute_command.php.inc create mode 100644 rules-tests/Symfony73/Rector/Class_/CommandHelpToAttributeRector/Fixture/skip_no_as_command_attribute_and_no_help_command.php.inc create mode 100644 rules-tests/Symfony73/Rector/Class_/CommandHelpToAttributeRector/config/configured_rule.php create mode 100644 rules-tests/Symfony73/Rector/Class_/InvokableCommandRector/Fixture/some_command_with_method_chaining.php.inc create mode 100644 rules-tests/Symfony73/Rector/Class_/InvokableCommandRector/Fixture/some_command_with_set_help.php.inc create mode 100644 rules/Symfony73/Rector/Class_/CommandHelpToAttributeRector.php create mode 100644 stubs/Symfony/Component/console/attribute/AsCommand.php create mode 100644 tests/Set/Symfony73/Fixture/command_remove_config.php.inc create mode 100644 tests/Set/Symfony73/Symfony73Test.php create mode 100644 tests/Set/Symfony73/config/symfony73.php diff --git a/config/sets/symfony/symfony73.php b/config/sets/symfony/symfony73.php index 0d87fd60..1896a5e3 100644 --- a/config/sets/symfony/symfony73.php +++ b/config/sets/symfony/symfony73.php @@ -3,9 +3,10 @@ declare(strict_types=1); use Rector\Config\RectorConfig; +use Rector\Symfony\Symfony73\Rector\Class_\CommandHelpToAttributeRector; use Rector\Symfony\Symfony73\Rector\Class_\InvokableCommandRector; // @see https://github.com/symfony/symfony/blame/7.3/UPGRADE-7.3.md return RectorConfig::configure() - ->withRules([InvokableCommandRector::class]); + ->withRules([CommandHelpToAttributeRector::class, InvokableCommandRector::class]); diff --git a/rules-tests/Symfony61/Rector/Class_/CommandConfigureToAttributeRector/Fixture/call_all_option.php.inc b/rules-tests/Symfony61/Rector/Class_/CommandConfigureToAttributeRector/Fixture/call_all_option.php.inc new file mode 100644 index 00000000..8a8360c2 --- /dev/null +++ b/rules-tests/Symfony61/Rector/Class_/CommandConfigureToAttributeRector/Fixture/call_all_option.php.inc @@ -0,0 +1,43 @@ +setName('sunshine') + ->setDescription('Some description') + ->setHidden(false) + ->setHelp('Some help text') + ->addArgument('argument name') + ->addOption('option', 'o', InputOption::VALUE_NONE, 'Option description') + ->setAliases(['first', 'second']); + } +} + +?> +----- +setHelp('Some help text') + ->addArgument('argument name') + ->addOption('option', 'o', InputOption::VALUE_NONE, 'Option description'); + } +} + +?> diff --git a/rules-tests/Symfony61/Rector/Class_/CommandConfigureToAttributeRector/Fixture/other-calls-middle.php.inc b/rules-tests/Symfony61/Rector/Class_/CommandConfigureToAttributeRector/Fixture/other-calls-middle.php.inc deleted file mode 100644 index f5bad67f..00000000 --- a/rules-tests/Symfony61/Rector/Class_/CommandConfigureToAttributeRector/Fixture/other-calls-middle.php.inc +++ /dev/null @@ -1,31 +0,0 @@ -setName('sunshine') - ->addArgument('argument name') - ->setAliases(['first', 'second']); - } -} - -?> ------ -addArgument('argument name'); - } -} - -?> diff --git a/rules-tests/Symfony73/Rector/Class_/CommandHelpToAttributeRector/CommandHelpToAttributeRectorTest.php b/rules-tests/Symfony73/Rector/Class_/CommandHelpToAttributeRector/CommandHelpToAttributeRectorTest.php new file mode 100644 index 00000000..415f405f --- /dev/null +++ b/rules-tests/Symfony73/Rector/Class_/CommandHelpToAttributeRector/CommandHelpToAttributeRectorTest.php @@ -0,0 +1,28 @@ +doTestFile($filePath); + } + + public static function provideData(): Iterator + { + return self::yieldFilesFromDirectory(__DIR__ . '/Fixture'); + } + + public function provideConfigFilePath(): string + { + return __DIR__ . '/config/configured_rule.php'; + } +} diff --git a/rules-tests/Symfony73/Rector/Class_/CommandHelpToAttributeRector/Fixture/add_help_to_attribute_command.php.inc b/rules-tests/Symfony73/Rector/Class_/CommandHelpToAttributeRector/Fixture/add_help_to_attribute_command.php.inc new file mode 100644 index 00000000..f84d1421 --- /dev/null +++ b/rules-tests/Symfony73/Rector/Class_/CommandHelpToAttributeRector/Fixture/add_help_to_attribute_command.php.inc @@ -0,0 +1,36 @@ +setHelp('Some help text'); + } +} + +?> +----- + diff --git a/rules-tests/Symfony73/Rector/Class_/CommandHelpToAttributeRector/Fixture/all_attribute_set_also_add_help.php.inc b/rules-tests/Symfony73/Rector/Class_/CommandHelpToAttributeRector/Fixture/all_attribute_set_also_add_help.php.inc new file mode 100644 index 00000000..46fce7e7 --- /dev/null +++ b/rules-tests/Symfony73/Rector/Class_/CommandHelpToAttributeRector/Fixture/all_attribute_set_also_add_help.php.inc @@ -0,0 +1,42 @@ +setHelp('Some help text') + ->addArgument('argument name') + ->addOption('option', 'o', InputOption::VALUE_NONE, 'Option description'); + } +} + +?> +----- +addArgument('argument name') + ->addOption('option', 'o', InputOption::VALUE_NONE, 'Option description'); + } +} + +?> diff --git a/rules-tests/Symfony73/Rector/Class_/CommandHelpToAttributeRector/Fixture/skip_has_help_attribute_command.php.inc b/rules-tests/Symfony73/Rector/Class_/CommandHelpToAttributeRector/Fixture/skip_has_help_attribute_command.php.inc new file mode 100644 index 00000000..e559f801 --- /dev/null +++ b/rules-tests/Symfony73/Rector/Class_/CommandHelpToAttributeRector/Fixture/skip_has_help_attribute_command.php.inc @@ -0,0 +1,32 @@ +addArgument('argument', InputArgument::REQUIRED, 'Argument description'); + $this->addOption('option', 'o', InputOption::VALUE_NONE, 'Option description'); + } + + public function execute(InputInterface $input, OutputInterface $output): int + { + $someArgument = $input->getArgument('argument'); + $someOption = $input->getOption('option'); + + // ... + + return 1; + } +} + +?> diff --git a/rules-tests/Symfony73/Rector/Class_/CommandHelpToAttributeRector/Fixture/skip_no_as_command_attribute_and_no_help_command.php.inc b/rules-tests/Symfony73/Rector/Class_/CommandHelpToAttributeRector/Fixture/skip_no_as_command_attribute_and_no_help_command.php.inc new file mode 100644 index 00000000..2be9b2e7 --- /dev/null +++ b/rules-tests/Symfony73/Rector/Class_/CommandHelpToAttributeRector/Fixture/skip_no_as_command_attribute_and_no_help_command.php.inc @@ -0,0 +1,16 @@ +setName('Some command'); + } +} + +?> diff --git a/rules-tests/Symfony73/Rector/Class_/CommandHelpToAttributeRector/config/configured_rule.php b/rules-tests/Symfony73/Rector/Class_/CommandHelpToAttributeRector/config/configured_rule.php new file mode 100644 index 00000000..e5cd37d4 --- /dev/null +++ b/rules-tests/Symfony73/Rector/Class_/CommandHelpToAttributeRector/config/configured_rule.php @@ -0,0 +1,10 @@ +rule(CommandHelpToAttributeRector::class); +}; diff --git a/rules-tests/Symfony73/Rector/Class_/InvokableCommandRector/Fixture/some_command_with_method_chaining.php.inc b/rules-tests/Symfony73/Rector/Class_/InvokableCommandRector/Fixture/some_command_with_method_chaining.php.inc new file mode 100644 index 00000000..5c6f04c7 --- /dev/null +++ b/rules-tests/Symfony73/Rector/Class_/InvokableCommandRector/Fixture/some_command_with_method_chaining.php.inc @@ -0,0 +1,62 @@ +addArgument('argument', InputArgument::REQUIRED, 'Argument description') + ->addOption('option', 'o', InputOption::VALUE_NONE, 'Option description'); + } + + public function execute(InputInterface $input, OutputInterface $output): int + { + $someArgument = $input->getArgument('argument'); + $someOption = $input->getOption('option'); + + // ... + + return 1; + } +} + +?> +----- + diff --git a/rules-tests/Symfony73/Rector/Class_/InvokableCommandRector/Fixture/some_command_with_set_help.php.inc b/rules-tests/Symfony73/Rector/Class_/InvokableCommandRector/Fixture/some_command_with_set_help.php.inc new file mode 100644 index 00000000..35490226 --- /dev/null +++ b/rules-tests/Symfony73/Rector/Class_/InvokableCommandRector/Fixture/some_command_with_set_help.php.inc @@ -0,0 +1,67 @@ +setHelp('argument'); + $this->addArgument('argument', InputArgument::REQUIRED, 'Argument description'); + $this->addOption('option', 'o', InputOption::VALUE_NONE, 'Option description'); + } + + public function execute(InputInterface $input, OutputInterface $output): int + { + $someArgument = $input->getArgument('argument'); + $someOption = $input->getOption('option'); + + // ... + + return 1; + } +} + +?> +----- +setHelp('argument'); + } + + public function __invoke(#[\Symfony\Component\Console\Attribute\Command\Argument] + string $argument, #[\Symfony\Component\Console\Attribute\Command\Option] + $option): int + { + $someArgument = $argument; + $someOption = $option; + + // ... + + return 1; + } +} + +?> diff --git a/rules/Symfony73/Rector/Class_/CommandHelpToAttributeRector.php b/rules/Symfony73/Rector/Class_/CommandHelpToAttributeRector.php new file mode 100644 index 00000000..d9a67618 --- /dev/null +++ b/rules/Symfony73/Rector/Class_/CommandHelpToAttributeRector.php @@ -0,0 +1,220 @@ +setHelp() to the "help" named argument of #[AsCommand]', + [ + new CodeSample( + <<<'CODE_SAMPLE' +use Symfony\Component\Console\Command\Command; + +final class SomeCommand extends Command +{ + protected function configure(): void + { + $this->setHelp('Some help text'); + } +} +CODE_SAMPLE + , + <<<'CODE_SAMPLE' +use Symfony\Component\Console\Attribute\AsCommand; +use Symfony\Component\Console\Command\Command; + +#[AsCommand(name: 'app:some', help: <<<'TXT' +Some help text +TXT)] +final class SomeCommand extends Command +{ +} +CODE_SAMPLE + ), + ] + ); + } + + /** + * @return array> + */ + public function getNodeTypes(): array + { + return [Class_::class]; + } + + /** + * @param Class_ $node + */ + public function refactor(Node $node): ?Node + { + if ($node->isAbstract()) { + return null; + } + + if (! $this->reflectionProvider->hasClass(SymfonyAttribute::AS_COMMAND)) { + return null; + } + + if (! $this->isObjectType($node, new ObjectType(SymfonyClass::COMMAND))) { + return null; + } + + $asCommandAttribute = $this->getAsCommandAttribute($node); + if ($asCommandAttribute === null) { + return null; + } + + foreach ($asCommandAttribute->args as $arg) { + if ($arg->name?->toString() === 'help') { + return null; + } + } + + $configureClassMethod = $node->getMethod(CommandMethodName::CONFIGURE); + if (! $configureClassMethod instanceof ClassMethod) { + return null; + } + + $helpExpr = $this->findAndRemoveSetHelpExpr($configureClassMethod); + if (! $helpExpr instanceof String_) { + return null; + } + + $wrappedHelp = new String_( + $helpExpr->value, + [ + Attributekey::KIND => String_::KIND_NOWDOC, + AttributeKey::DOC_LABEL => 'TXT', + ] + ); + + $asCommandAttribute->args[] = new Arg($wrappedHelp, false, false, [], new Identifier('help')); + + if ($configureClassMethod->stmts === []) { + unset($configureClassMethod); + } + + return $node; + } + + private function getAsCommandAttribute(Class_ $class): ?Attribute + { + foreach ($class->attrGroups as $attrGroup) { + foreach ($attrGroup->attrs as $attribute) { + if ($this->nodeNameResolver->isName($attribute->name, SymfonyAttribute::AS_COMMAND)) { + return $attribute; + } + } + } + + return null; + } + + /** + * Returns the argument passed to setHelp() and removes the MethodCall node. + */ + private function findAndRemoveSetHelpExpr(ClassMethod $configureMethod): ?String_ + { + $helpString = null; + + $this->traverseNodesWithCallable( + (array) $configureMethod->stmts, + function (Node $node) use (&$helpString) { + if ($node instanceof Class_ || $node instanceof Function_) { + return NodeVisitor::DONT_TRAVERSE_CURRENT_AND_CHILDREN; + } + if (! $node instanceof MethodCall) { + return null; + } + + if (! $this->isName($node->name, 'setHelp')) { + return null; + } + + if ($node->isFirstClassCallable() || ! isset($node->getArgs()[0])) { + return null; + } + + $argExpr = $node->getArgs()[0] + ->value; + if ($argExpr instanceof String_) { + $helpString = $argExpr; + } + + $parent = $node->getAttribute('parent'); + if ($parent instanceof Expression) { + unset($parent); + } + + return $node->var; + } + ); + + foreach ((array) $configureMethod->stmts as $key => $stmt) { + if ($this->isExpressionVariableThis($stmt)) { + unset($configureMethod->stmts[$key]); + } + } + + return $helpString; + } + + private function isExpressionVariableThis(Stmt $stmt): bool + { + if (! $stmt instanceof Expression) { + return false; + } + + if (! $stmt->expr instanceof Variable) { + return false; + } + + return $this->isName($stmt->expr, 'this'); + } +} diff --git a/rules/Symfony73/Rector/Class_/InvokableCommandRector.php b/rules/Symfony73/Rector/Class_/InvokableCommandRector.php index a1ba97bd..bb004162 100644 --- a/rules/Symfony73/Rector/Class_/InvokableCommandRector.php +++ b/rules/Symfony73/Rector/Class_/InvokableCommandRector.php @@ -13,6 +13,7 @@ use PhpParser\Node\Scalar\String_; use PhpParser\Node\Stmt\Class_; use PhpParser\Node\Stmt\ClassMethod; +use PhpParser\Node\Stmt\Expression; use Rector\Doctrine\NodeAnalyzer\AttributeFinder; use Rector\Exception\ShouldNotHappenException; use Rector\Rector\AbstractRector; @@ -32,6 +33,8 @@ */ final class InvokableCommandRector extends AbstractRector { + private const MIGRATED_CONFIGURE_CALLS = ['addArgument', 'addOption']; + public function __construct( private readonly AttributeFinder $attributeFinder, private readonly CommandArgumentsAndOptionsResolver $commandArgumentsAndOptionsResolver, @@ -188,7 +191,32 @@ private function removeConfigureClassMethod(Class_ $class): void continue; } - unset($class->stmts[$key]); + foreach ((array) $stmt->stmts as $innerKey => $innerStmt) { + if (! $innerStmt instanceof Expression) { + continue; + } + + $expr = $innerStmt->expr; + if (! $expr instanceof MethodCall) { + continue; + } + + if ($this->isFluentArgumentOptionChain($expr)) { + unset($stmt->stmts[$innerKey]); + continue; + } + + if ($this->isName($expr->var, 'this') + && $this->isNames($expr->name, self::MIGRATED_CONFIGURE_CALLS)) { + unset($stmt->stmts[$innerKey]); + } + } + + // 2. if configure() has become empty → remove the method itself + if ($stmt->stmts === [] || $stmt->stmts === null) { + unset($class->stmts[$key]); + } + return; } } @@ -219,4 +247,21 @@ private function replaceInputArgumentOptionFetchWithVariables(ClassMethod $execu return new Variable($firstArgValue->value); }); } + + private function isFluentArgumentOptionChain(MethodCall $call): bool + { + $current = $call; + + while ($current instanceof MethodCall) { + // every link must be addArgument() or addOption() + if (! $this->isNames($current->name, self::MIGRATED_CONFIGURE_CALLS)) { + return false; + } + + $current = $current->var; // go one step left + } + + // the left-most var must be $this + return $current instanceof Variable && $this->isName($current, 'this'); + } } diff --git a/src/Set/SymfonySetList.php b/src/Set/SymfonySetList.php index c62aa0e9..7d8017fe 100644 --- a/src/Set/SymfonySetList.php +++ b/src/Set/SymfonySetList.php @@ -160,6 +160,11 @@ final class SymfonySetList */ final public const SYMFONY_72 = __DIR__ . '/../../config/sets/symfony/symfony72.php'; + /** + * @var string + */ + final public const SYMFONY_73 = __DIR__ . '/../../config/sets/symfony/symfony73.php'; + /** * @var string */ diff --git a/stubs/Symfony/Component/console/attribute/AsCommand.php b/stubs/Symfony/Component/console/attribute/AsCommand.php new file mode 100644 index 00000000..25442894 --- /dev/null +++ b/stubs/Symfony/Component/console/attribute/AsCommand.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Attribute; + +if (class_exists('Symfony\Component\Console\Attribute\AsCommand')) { + return; +} + +/** + * Service tag to autoconfigure commands. + * + * @final since Symfony 7.3 + */ +#[\Attribute(\Attribute::TARGET_CLASS)] +class AsCommand +{ + /** + * @param string $name The name of the command, used when calling it (i.e. "cache:clear") + * @param string|null $description The description of the command, displayed with the help page + * @param string[] $aliases The list of aliases of the command. The command will be executed when using one of them (i.e. "cache:clean") + * @param bool $hidden If true, the command won't be shown when listing all the available commands, but it can still be run as any other command + * @param string|null $help The help content of the command, displayed with the help page + */ + public function __construct( + public string $name, + public ?string $description = null, + array $aliases = [], + bool $hidden = false, + public ?string $help = null, + ) { + if (!$hidden && !$aliases) { + return; + } + + $name = explode('|', $name); + $name = array_merge($name, $aliases); + + if ($hidden && '' !== $name[0]) { + array_unshift($name, ''); + } + + $this->name = implode('|', $name); + } +} diff --git a/tests/Set/Symfony73/Fixture/command_remove_config.php.inc b/tests/Set/Symfony73/Fixture/command_remove_config.php.inc new file mode 100644 index 00000000..e46999d5 --- /dev/null +++ b/tests/Set/Symfony73/Fixture/command_remove_config.php.inc @@ -0,0 +1,72 @@ +setHelp( + 'The %command.name% command will do some + argument passed to it: + + php %command.full_name% argument' + ); + $this->addArgument('argument', InputArgument::REQUIRED, 'Argument description'); + $this->addOption('option', 'o', InputOption::VALUE_NONE, 'Option description'); + } + + public function execute(InputInterface $input, OutputInterface $output): int + { + $someArgument = $input->getArgument('argument'); + $someOption = $input->getOption('option'); + + // ... + + return 1; + } +} + +?> +----- +%command.name% command will do some + argument passed to it: + + php %command.full_name% argument +TXT)] +final class SomeCommand +{ + public function __invoke(#[\Symfony\Component\Console\Attribute\Command\Argument] + string $argument, #[\Symfony\Component\Console\Attribute\Command\Option] + $option): int + { + $someArgument = $argument; + $someOption = $option; + + // ... + + return 1; + } +} + +?> diff --git a/tests/Set/Symfony73/Symfony73Test.php b/tests/Set/Symfony73/Symfony73Test.php new file mode 100644 index 00000000..a4da7392 --- /dev/null +++ b/tests/Set/Symfony73/Symfony73Test.php @@ -0,0 +1,28 @@ +doTestFile($filePath); + } + + public static function provideData(): Iterator + { + return self::yieldFilesFromDirectory(__DIR__ . '/Fixture'); + } + + public function provideConfigFilePath(): string + { + return __DIR__ . '/config/symfony73.php'; + } +} diff --git a/tests/Set/Symfony73/config/symfony73.php b/tests/Set/Symfony73/config/symfony73.php new file mode 100644 index 00000000..219b3986 --- /dev/null +++ b/tests/Set/Symfony73/config/symfony73.php @@ -0,0 +1,10 @@ +sets([SymfonySetList::SYMFONY_73]); +}; From d623cf211ffe859808cde1452e1b974a98817559 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Sat, 3 May 2025 01:24:23 +0200 Subject: [PATCH 29/53] [symfony 6.2] Fix attribute adding on abstract class in MessageHandlerInterfaceToAttributeRector (#724) --- ...tact_class_that_implements_handler.php.inc | 24 +++++++++++++++++++ ...move_interface_from_abstract_class.php.inc | 23 ++++++++++++++++++ .../AbstractClassWithHandlerInterface.php | 9 +++++++ ...ssageHandlerInterfaceToAttributeRector.php | 20 +++++++++++++--- src/Helper/MessengerHelper.php | 15 +++++++++++- .../Messenger/Attribute/AsMessageHandler.php | 8 +++++++ .../Handler/MessageHandlerInterface.php | 7 ++++++ 7 files changed, 102 insertions(+), 4 deletions(-) create mode 100644 rules-tests/Symfony62/Rector/Class_/MessageHandlerInterfaceToAttributeRector/Fixture/class_that_extends_abstact_class_that_implements_handler.php.inc create mode 100644 rules-tests/Symfony62/Rector/Class_/MessageHandlerInterfaceToAttributeRector/Fixture/only_remove_interface_from_abstract_class.php.inc create mode 100644 rules-tests/Symfony62/Rector/Class_/MessageHandlerInterfaceToAttributeRector/Source/AbstractClassWithHandlerInterface.php create mode 100644 stubs/Symfony/Component/Messenger/Attribute/AsMessageHandler.php create mode 100644 stubs/Symfony/Component/Messenger/Handler/MessageHandlerInterface.php diff --git a/rules-tests/Symfony62/Rector/Class_/MessageHandlerInterfaceToAttributeRector/Fixture/class_that_extends_abstact_class_that_implements_handler.php.inc b/rules-tests/Symfony62/Rector/Class_/MessageHandlerInterfaceToAttributeRector/Fixture/class_that_extends_abstact_class_that_implements_handler.php.inc new file mode 100644 index 00000000..c4413e61 --- /dev/null +++ b/rules-tests/Symfony62/Rector/Class_/MessageHandlerInterfaceToAttributeRector/Fixture/class_that_extends_abstact_class_that_implements_handler.php.inc @@ -0,0 +1,24 @@ + +----- + diff --git a/rules-tests/Symfony62/Rector/Class_/MessageHandlerInterfaceToAttributeRector/Fixture/only_remove_interface_from_abstract_class.php.inc b/rules-tests/Symfony62/Rector/Class_/MessageHandlerInterfaceToAttributeRector/Fixture/only_remove_interface_from_abstract_class.php.inc new file mode 100644 index 00000000..f2d70532 --- /dev/null +++ b/rules-tests/Symfony62/Rector/Class_/MessageHandlerInterfaceToAttributeRector/Fixture/only_remove_interface_from_abstract_class.php.inc @@ -0,0 +1,23 @@ + +----- + diff --git a/rules-tests/Symfony62/Rector/Class_/MessageHandlerInterfaceToAttributeRector/Source/AbstractClassWithHandlerInterface.php b/rules-tests/Symfony62/Rector/Class_/MessageHandlerInterfaceToAttributeRector/Source/AbstractClassWithHandlerInterface.php new file mode 100644 index 00000000..8ac71dfe --- /dev/null +++ b/rules-tests/Symfony62/Rector/Class_/MessageHandlerInterfaceToAttributeRector/Source/AbstractClassWithHandlerInterface.php @@ -0,0 +1,9 @@ +reflectionProvider->hasClass(MessengerHelper::AS_MESSAGE_HANDLER_ATTRIBUTE)) { + return null; + } + if ($this->phpAttributeAnalyzer->hasPhpAttribute($node, MessengerHelper::AS_MESSAGE_HANDLER_ATTRIBUTE)) { return null; } - if (! $this->classAnalyzer->hasImplements($node, MessengerHelper::MESSAGE_HANDLER_INTERFACE)) { + $classType = $this->getType($node); + + $messageHandlerObjectType = new ObjectType(MessengerHelper::MESSAGE_HANDLER_INTERFACE); + + if (! $messageHandlerObjectType->isSuperTypeOf($classType)->yes()) { $handlers = $this->messengerHelper->getHandlersFromServices(); if ($handlers === []) { return null; @@ -99,6 +108,11 @@ public function refactor(Node $node): ?Node $this->classManipulator->removeImplements($node, [MessengerHelper::MESSAGE_HANDLER_INTERFACE]); + // no need to add the attribute + if ($node->isAbstract()) { + return $node; + } + return $this->messengerHelper->addAttribute($node); } diff --git a/src/Helper/MessengerHelper.php b/src/Helper/MessengerHelper.php index 9fa18949..44613bba 100644 --- a/src/Helper/MessengerHelper.php +++ b/src/Helper/MessengerHelper.php @@ -24,6 +24,11 @@ final class MessengerHelper private string $messengerTagName = 'messenger.message_handler'; + /** + * @var ServiceDefinition[] + */ + private array $handlersFromServices = []; + public function __construct( private readonly PhpAttributeGroupFactory $phpAttributeGroupFactory, private readonly AttributeArrayNameInliner $attributeArrayNameInliner, @@ -42,6 +47,7 @@ public function extractOptionsFromServiceDefinition(ServiceDefinition $serviceDe $options = $tag->getData(); } } + if ($options['from_transport']) { $options['fromTransport'] = $options['from_transport']; unset($options['from_transport']); @@ -54,8 +60,15 @@ public function extractOptionsFromServiceDefinition(ServiceDefinition $serviceDe */ public function getHandlersFromServices(): array { + if ($this->handlersFromServices !== []) { + return $this->handlersFromServices; + } + $serviceMap = $this->serviceMapProvider->provide(); - return $serviceMap->getServicesByTag($this->messengerTagName); + + $this->handlersFromServices = $serviceMap->getServicesByTag($this->messengerTagName); + + return $this->handlersFromServices; } /** diff --git a/stubs/Symfony/Component/Messenger/Attribute/AsMessageHandler.php b/stubs/Symfony/Component/Messenger/Attribute/AsMessageHandler.php new file mode 100644 index 00000000..083014dd --- /dev/null +++ b/stubs/Symfony/Component/Messenger/Attribute/AsMessageHandler.php @@ -0,0 +1,8 @@ + Date: Sun, 4 May 2025 00:36:18 +0200 Subject: [PATCH 30/53] [depre] Hard deprecated ContainerGetToConstructorInjectionRector (#725) --- ...ntainerGetToConstructorInjectionRector.php | 77 ++----------------- 1 file changed, 5 insertions(+), 72 deletions(-) diff --git a/rules/Symfony42/Rector/MethodCall/ContainerGetToConstructorInjectionRector.php b/rules/Symfony42/Rector/MethodCall/ContainerGetToConstructorInjectionRector.php index df14f03c..35f26067 100644 --- a/rules/Symfony42/Rector/MethodCall/ContainerGetToConstructorInjectionRector.php +++ b/rules/Symfony42/Rector/MethodCall/ContainerGetToConstructorInjectionRector.php @@ -5,17 +5,10 @@ namespace Rector\Symfony\Symfony42\Rector\MethodCall; use PhpParser\Node; -use PhpParser\Node\Expr\ClassConstFetch; -use PhpParser\Node\Expr\MethodCall; use PhpParser\Node\Stmt\Class_; -use PHPStan\Type\ObjectType; use Rector\Configuration\Deprecation\Contract\DeprecatedInterface; -use Rector\NodeManipulator\ClassDependencyManipulator; -use Rector\PHPUnit\NodeAnalyzer\TestsNodeAnalyzer; -use Rector\PostRector\ValueObject\PropertyMetadata; +use Rector\Exception\ShouldNotHappenException; use Rector\Rector\AbstractRector; -use Rector\Symfony\DependencyInjection\NodeDecorator\CommandConstructorDecorator; -use Rector\Symfony\NodeAnalyzer\DependencyInjectionMethodCallAnalyzer; use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; @@ -26,14 +19,6 @@ */ final class ContainerGetToConstructorInjectionRector extends AbstractRector implements DeprecatedInterface { - public function __construct( - private readonly DependencyInjectionMethodCallAnalyzer $dependencyInjectionMethodCallAnalyzer, - private readonly TestsNodeAnalyzer $testsNodeAnalyzer, - private readonly ClassDependencyManipulator $classDependencyManipulator, - private readonly CommandConstructorDecorator $commandConstructorDecorator, - ) { - } - public function getRuleDefinition(): RuleDefinition { return new RuleDefinition( @@ -86,61 +71,9 @@ public function getNodeTypes(): array */ public function refactor(Node $node): ?Node { - if ($this->testsNodeAnalyzer->isInTestClass($node)) { - return null; - } - - $class = $node; - $propertyMetadatas = []; - - $this->traverseNodesWithCallable($class, function (Node $node) use ($class, &$propertyMetadatas): ?Node { - if (! $node instanceof MethodCall) { - return null; - } - - if (! $this->isName($node->name, 'get')) { - return null; - } - - if (! $this->isObjectType( - $node->var, - new ObjectType('Symfony\Component\DependencyInjection\ContainerInterface') - )) { - return null; - } - - if ($node->isFirstClassCallable()) { - return null; - } - - $args = $node->getArgs(); - if (count($args) === 1 && $args[0]->value instanceof ClassConstFetch) { - return null; - } - - $propertyMetadata = $this->dependencyInjectionMethodCallAnalyzer->replaceMethodCallWithPropertyFetchAndDependency( - $class, - $node - ); - - if (! $propertyMetadata instanceof PropertyMetadata) { - return null; - } - - $propertyMetadatas[] = $propertyMetadata; - return $this->nodeFactory->createPropertyFetch('this', $propertyMetadata->getName()); - }); - - if ($propertyMetadatas === []) { - return null; - } - - foreach ($propertyMetadatas as $propertyMetadata) { - $this->classDependencyManipulator->addConstructorDependency($class, $propertyMetadata); - } - - $this->commandConstructorDecorator->decorate($class); - - return $node; + throw new ShouldNotHappenException(sprintf( + 'The %s rule is deprecated. Use more reliable set \Rector\Symfony\Set\SymfonySetList::SYMFONY_CONSTRUCTOR_INJECTION instead', + self::class + )); } } From 7e678dcd5a189c308ac5381f54cf8d09b87ebb26 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Sun, 4 May 2025 15:59:14 +0200 Subject: [PATCH 31/53] [config] Split off set to set provider for Symfony 3.0 (#726) * [config] Prepare per package sets for symfony/* split packages * nest symfony3x configs to symfony3 direcory * [config] split off class-loader and http-foundation * add to set provider * [config] split of http-kernel and validator config * [config] split of console, process, property-access and security configs * [config] split of translation and bridge monolog * [config] split of twig and swift mailer configs --- config/sets/symfony/symfony3/symfony30.php | 24 ++ .../symfony30/symfony30-bridge-monolog.php | 22 ++ .../symfony30-bridge-swift-mailer.php | 13 ++ .../symfony30/symfony30-class-loader.php | 52 +++++ .../symfony3/symfony30/symfony30-console.php | 13 ++ .../symfony3/symfony30/symfony30-forms.php | 80 +++++++ .../symfony30/symfony30-http-foundation.php | 10 + .../symfony30/symfony30-http-kernel.php | 31 +++ .../symfony3/symfony30/symfony30-process.php | 14 ++ .../symfony30/symfony30-property-access.php | 17 ++ .../symfony3/symfony30/symfony30-security.php | 12 + .../symfony30/symfony30-translation.php | 14 ++ .../symfony30/symfony30-twig-bundle.php | 12 + .../symfony30/symfony30-validator.php | 46 ++++ .../sets/symfony/{ => symfony3}/symfony31.php | 0 .../sets/symfony/{ => symfony3}/symfony32.php | 0 .../sets/symfony/{ => symfony3}/symfony33.php | 0 .../sets/symfony/{ => symfony3}/symfony34.php | 0 config/sets/symfony/symfony30.php | 210 ------------------ .../Rector/MethodCall/OptionNameRector.php | 12 +- src/Set/SetProvider/SymfonySetProvider.php | 97 +++++++- 21 files changed, 461 insertions(+), 218 deletions(-) create mode 100644 config/sets/symfony/symfony3/symfony30.php create mode 100644 config/sets/symfony/symfony3/symfony30/symfony30-bridge-monolog.php create mode 100644 config/sets/symfony/symfony3/symfony30/symfony30-bridge-swift-mailer.php create mode 100644 config/sets/symfony/symfony3/symfony30/symfony30-class-loader.php create mode 100644 config/sets/symfony/symfony3/symfony30/symfony30-console.php create mode 100644 config/sets/symfony/symfony3/symfony30/symfony30-forms.php create mode 100644 config/sets/symfony/symfony3/symfony30/symfony30-http-foundation.php create mode 100644 config/sets/symfony/symfony3/symfony30/symfony30-http-kernel.php create mode 100644 config/sets/symfony/symfony3/symfony30/symfony30-process.php create mode 100644 config/sets/symfony/symfony3/symfony30/symfony30-property-access.php create mode 100644 config/sets/symfony/symfony3/symfony30/symfony30-security.php create mode 100644 config/sets/symfony/symfony3/symfony30/symfony30-translation.php create mode 100644 config/sets/symfony/symfony3/symfony30/symfony30-twig-bundle.php create mode 100644 config/sets/symfony/symfony3/symfony30/symfony30-validator.php rename config/sets/symfony/{ => symfony3}/symfony31.php (100%) rename config/sets/symfony/{ => symfony3}/symfony32.php (100%) rename config/sets/symfony/{ => symfony3}/symfony33.php (100%) rename config/sets/symfony/{ => symfony3}/symfony34.php (100%) delete mode 100644 config/sets/symfony/symfony30.php diff --git a/config/sets/symfony/symfony3/symfony30.php b/config/sets/symfony/symfony3/symfony30.php new file mode 100644 index 00000000..dd527cd4 --- /dev/null +++ b/config/sets/symfony/symfony3/symfony30.php @@ -0,0 +1,24 @@ +import(__DIR__ . '/symfony30/symfony30-class-loader.php'); + $rectorConfig->import(__DIR__ . '/symfony30/symfony30-console.php'); + $rectorConfig->import(__DIR__ . '/symfony30/symfony30-forms.php'); + $rectorConfig->import(__DIR__ . '/symfony30/symfony30-security.php'); + $rectorConfig->import(__DIR__ . '/symfony30/symfony30-process.php'); + $rectorConfig->import(__DIR__ . '/symfony30/symfony30-property-access.php'); + $rectorConfig->import(__DIR__ . '/symfony30/symfony30-http-foundation.php'); + $rectorConfig->import(__DIR__ . '/symfony30/symfony30-http-kernel.php'); + $rectorConfig->import(__DIR__ . '/symfony30/symfony30-validator.php'); + $rectorConfig->import(__DIR__ . '/symfony30/symfony30-translation.php'); + $rectorConfig->import(__DIR__ . '/symfony30/symfony30-bridge-monolog.php'); + $rectorConfig->import(__DIR__ . '/symfony30/symfony30-twig-bundle.php'); + $rectorConfig->import(__DIR__ . '/symfony30/symfony30-bridge-swift-mailer.php'); +}; diff --git a/config/sets/symfony/symfony3/symfony30/symfony30-bridge-monolog.php b/config/sets/symfony/symfony3/symfony30/symfony30-bridge-monolog.php new file mode 100644 index 00000000..e6fb1eb7 --- /dev/null +++ b/config/sets/symfony/symfony3/symfony30/symfony30-bridge-monolog.php @@ -0,0 +1,22 @@ +ruleWithConfiguration(RenameClassRector::class, [ + 'Symfony\Bridge\Monolog\Logger' => 'Psr\Log\LoggerInterface', + ]); + + $rectorConfig->ruleWithConfiguration(RenameMethodRector::class, [ + new MethodCallRename('Symfony\Bridge\Monolog\Logger', 'emerg', 'emergency'), + new MethodCallRename('Symfony\Bridge\Monolog\Logger', 'crit', 'critical'), + new MethodCallRename('Symfony\Bridge\Monolog\Logger', 'err', 'error'), + new MethodCallRename('Symfony\Bridge\Monolog\Logger', 'warn', 'warning'), + ]); + +}; diff --git a/config/sets/symfony/symfony3/symfony30/symfony30-bridge-swift-mailer.php b/config/sets/symfony/symfony3/symfony30/symfony30-bridge-swift-mailer.php new file mode 100644 index 00000000..16d254c2 --- /dev/null +++ b/config/sets/symfony/symfony3/symfony30/symfony30-bridge-swift-mailer.php @@ -0,0 +1,13 @@ +ruleWithConfiguration(RenameClassRector::class, [ + // swift mailer + 'Symfony\Bridge\Swiftmailer\DataCollector\MessageDataCollector' => 'Symfony\Bundle\SwiftmailerBundle\DataCollector\MessageDataCollector', + ]); +}; diff --git a/config/sets/symfony/symfony3/symfony30/symfony30-class-loader.php b/config/sets/symfony/symfony3/symfony30/symfony30-class-loader.php new file mode 100644 index 00000000..24b78640 --- /dev/null +++ b/config/sets/symfony/symfony3/symfony30/symfony30-class-loader.php @@ -0,0 +1,52 @@ +ruleWithConfiguration(RenameMethodRector::class, [ + new MethodCallRename( + 'Symfony\Component\ClassLoader\UniversalClassLoader\UniversalClassLoader', + 'registerNamespaces', + 'addPrefixes' + ), + new MethodCallRename( + 'Symfony\Component\ClassLoader\UniversalClassLoader\UniversalClassLoader', + 'registerPrefixes', + 'addPrefixes' + ), + new MethodCallRename( + 'Symfony\Component\ClassLoader\UniversalClassLoader\UniversalClassLoader', + 'registerNamespace', + 'addPrefix' + ), + new MethodCallRename( + 'Symfony\Component\ClassLoader\UniversalClassLoader\UniversalClassLoader', + 'registerPrefix', + 'addPrefix' + ), + new MethodCallRename( + 'Symfony\Component\ClassLoader\UniversalClassLoader\UniversalClassLoader', + 'getNamespaces', + 'getPrefixes' + ), + new MethodCallRename( + 'Symfony\Component\ClassLoader\UniversalClassLoader\UniversalClassLoader', + 'getNamespaceFallbacks', + 'getFallbackDirs' + ), + new MethodCallRename( + 'Symfony\Component\ClassLoader\UniversalClassLoader\UniversalClassLoader', + 'getPrefixFallbacks', + 'getFallbackDirs' + ), + ]); + + $rectorConfig->ruleWithConfiguration(RenameClassRector::class, [ + 'Symfony\Component\ClassLoader\UniversalClassLoader\UniversalClassLoader' => 'Symfony\Component\ClassLoader\ClassLoader', + ]); +}; diff --git a/config/sets/symfony/symfony3/symfony30/symfony30-console.php b/config/sets/symfony/symfony3/symfony30/symfony30-console.php new file mode 100644 index 00000000..bdac3bf3 --- /dev/null +++ b/config/sets/symfony/symfony3/symfony30/symfony30-console.php @@ -0,0 +1,13 @@ +ruleWithConfiguration(RenameClassRector::class, [ + // console + 'Symfony\Component\Console\Helper\ProgressHelper' => 'Symfony\Component\Console\Helper\ProgressBar', + ]); +}; diff --git a/config/sets/symfony/symfony3/symfony30/symfony30-forms.php b/config/sets/symfony/symfony3/symfony30/symfony30-forms.php new file mode 100644 index 00000000..82dd1652 --- /dev/null +++ b/config/sets/symfony/symfony3/symfony30/symfony30-forms.php @@ -0,0 +1,80 @@ +rules([ + FormTypeInstanceToClassConstRector::class, + StringFormTypeToClassRector::class, + RemoveDefaultGetBlockPrefixRector::class, + FormTypeGetParentRector::class, + OptionNameRector::class, + ReadOnlyOptionToAttributeRector::class, + ChangeStringCollectionOptionToConstantRector::class, + ]); + + $rectorConfig->ruleWithConfiguration(RenameClassConstFetchRector::class, [ + new RenameClassConstFetch('Symfony\Component\Form\FormEvents', 'PRE_BIND', 'PRE_SUBMIT'), + new RenameClassConstFetch('Symfony\Component\Form\FormEvents', 'BIND', 'SUBMIT'), + new RenameClassConstFetch('Symfony\Component\Form\FormEvents', 'POST_BIND', 'POST_SUBMIT'), + new RenameClassConstFetch( + 'Symfony\Component\Form\Extension\Core\DataTransformer', + 'ROUND_HALFEVEN', + 'ROUND_HALF_EVEN' + ), + new RenameClassConstFetch( + 'Symfony\Component\Form\Extension\Core\DataTransformer', + 'ROUND_HALFUP', + 'ROUND_HALF_UP' + ), + new RenameClassConstFetch( + 'Symfony\Component\Form\Extension\Core\DataTransformer', + 'ROUND_HALFDOWN', + 'ROUND_HALF_DOWN' + ), + ]); + + $rectorConfig->ruleWithConfiguration(RenameMethodRector::class, [ + new MethodCallRename('Symfony\Component\Form\AbstractType', 'getName', 'getBlockPrefix'), + new MethodCallRename('Symfony\Component\Form\FormTypeInterface', 'getName', 'getBlockPrefix'), + + new MethodCallRename('Symfony\Component\Form\FormTypeInterface', 'setDefaultOptions', 'configureOptions'), + new MethodCallRename('Symfony\Component\Form\ResolvedFormTypeInterface', 'getName', 'getBlockPrefix'), + new MethodCallRename( + 'Symfony\Component\Form\AbstractTypeExtension', + 'setDefaultOptions', + 'configureOptions' + ), + new MethodCallRename('Symfony\Component\Form\Form', 'bind', 'submit'), + new MethodCallRename('Symfony\Component\Form\Form', 'isBound', 'isSubmitted'), + ]); + + $rectorConfig->ruleWithConfiguration(RenameClassRector::class, [ + 'Symfony\Component\Form\Util\VirtualFormAwareIterator' => 'Symfony\Component\Form\Util\InheritDataAwareIterator', + 'Symfony\Component\Form\Tests\Extension\Core\Type\TypeTestCase' => 'Symfony\Component\Form\Test\TypeTestCase', + 'Symfony\Component\Form\Tests\FormIntegrationTestCase' => 'Symfony\Component\Form\Test\FormIntegrationTestCase', + 'Symfony\Component\Form\Tests\FormPerformanceTestCase' => 'Symfony\Component\Form\Test\FormPerformanceTestCase', + 'Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface' => 'Symfony\Component\Form\ChoiceList\ChoiceListInterface', + 'Symfony\Component\Form\Extension\Core\View\ChoiceView' => 'Symfony\Component\Form\ChoiceList\View\ChoiceView', + 'Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface' => 'Symfony\Component\Security\Csrf\CsrfTokenManagerInterface', + 'Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceList' => 'Symfony\Component\Form\ChoiceList\ArrayChoiceList', + 'Symfony\Component\Form\Extension\Core\ChoiceList\LazyChoiceList' => 'Symfony\Component\Form\ChoiceList\LazyChoiceList', + 'Symfony\Component\Form\Extension\Core\ChoiceList\ObjectChoiceList' => 'Symfony\Component\Form\ChoiceList\ArrayChoiceList', + 'Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList' => 'Symfony\Component\Form\ChoiceList\ArrayChoiceList', + 'Symfony\Component\Form\ChoiceList\ArrayKeyChoiceList' => 'Symfony\Component\Form\ChoiceList\ArrayChoiceList', + ]); +}; diff --git a/config/sets/symfony/symfony3/symfony30/symfony30-http-foundation.php b/config/sets/symfony/symfony3/symfony30/symfony30-http-foundation.php new file mode 100644 index 00000000..a1e80d19 --- /dev/null +++ b/config/sets/symfony/symfony3/symfony30/symfony30-http-foundation.php @@ -0,0 +1,10 @@ +rules([GetRequestRector::class]); +}; diff --git a/config/sets/symfony/symfony3/symfony30/symfony30-http-kernel.php b/config/sets/symfony/symfony3/symfony30/symfony30-http-kernel.php new file mode 100644 index 00000000..62b2b223 --- /dev/null +++ b/config/sets/symfony/symfony3/symfony30/symfony30-http-kernel.php @@ -0,0 +1,31 @@ +ruleWithConfiguration(RenameMethodRector::class, [ + new MethodCallRename('Symfony\Component\HttpKernel\Log\LoggerInterface', 'emerg', 'emergency'), + new MethodCallRename('Symfony\Component\HttpKernel\Log\LoggerInterface', 'crit', 'critical'), + new MethodCallRename('Symfony\Component\HttpKernel\Log\LoggerInterface', 'err', 'error'), + new MethodCallRename('Symfony\Component\HttpKernel\Log\LoggerInterface', 'warn', 'warning'), + new MethodCallRename('Symfony\Component\HttpKernel\Log\NullLogger', 'emerg', 'emergency'), + new MethodCallRename('Symfony\Component\HttpKernel\Log\NullLogger', 'crit', 'critical'), + new MethodCallRename('Symfony\Component\HttpKernel\Log\NullLogger', 'err', 'error'), + new MethodCallRename('Symfony\Component\HttpKernel\Log\NullLogger', 'warn', 'warning'), + ]); + + $rectorConfig->ruleWithConfiguration(RenameClassRector::class, [ + 'Symfony\Component\HttpKernel\Debug\ErrorHandler' => 'Symfony\Component\Debug\ErrorHandler', + 'Symfony\Component\HttpKernel\Debug\ExceptionHandler' => 'Symfony\Component\Debug\ExceptionHandler', + 'Symfony\Component\HttpKernel\Exception\FatalErrorException' => 'Symfony\Component\Debug\Exception\FatalErrorException', + 'Symfony\Component\HttpKernel\Exception\FlattenException' => 'Symfony\Component\Debug\Exception\FlattenException', + 'Symfony\Component\HttpKernel\Log\LoggerInterface' => 'Psr\Log\LoggerInterface', + 'Symfony\Component\HttpKernel\DependencyInjection\RegisterListenersPass' => 'Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass', + 'Symfony\Component\HttpKernel\Log\NullLogger' => 'Psr\Log\LoggerInterface', + ]); +}; diff --git a/config/sets/symfony/symfony3/symfony30/symfony30-process.php b/config/sets/symfony/symfony3/symfony30/symfony30-process.php new file mode 100644 index 00000000..d82c0352 --- /dev/null +++ b/config/sets/symfony/symfony3/symfony30/symfony30-process.php @@ -0,0 +1,14 @@ +ruleWithConfiguration(RenameMethodRector::class, [ + new MethodCallRename('Symfony\Component\Process\Process', 'setStdin', 'setInput'), + new MethodCallRename('Symfony\Component\Process\Process', 'getStdin', 'getInput'), + ]); +}; diff --git a/config/sets/symfony/symfony3/symfony30/symfony30-property-access.php b/config/sets/symfony/symfony3/symfony30/symfony30-property-access.php new file mode 100644 index 00000000..eec3421c --- /dev/null +++ b/config/sets/symfony/symfony3/symfony30/symfony30-property-access.php @@ -0,0 +1,17 @@ +ruleWithConfiguration(RenameMethodRector::class, [ + new MethodCallRename( + 'Symfony\Component\PropertyAccess\PropertyAccess', + 'getPropertyAccessor', + 'createPropertyAccessor' + ), + ]); +}; diff --git a/config/sets/symfony/symfony3/symfony30/symfony30-security.php b/config/sets/symfony/symfony3/symfony30/symfony30-security.php new file mode 100644 index 00000000..9f97bee6 --- /dev/null +++ b/config/sets/symfony/symfony3/symfony30/symfony30-security.php @@ -0,0 +1,12 @@ +ruleWithConfiguration(RenameClassRector::class, [ + 'Symfony\Component\Security\Core\Authorization\Voter\AbstractVoter' => 'Symfony\Component\Security\Core\Authorization\Voter\Voter', + ]); +}; diff --git a/config/sets/symfony/symfony3/symfony30/symfony30-translation.php b/config/sets/symfony/symfony3/symfony30/symfony30-translation.php new file mode 100644 index 00000000..ba64fc1a --- /dev/null +++ b/config/sets/symfony/symfony3/symfony30/symfony30-translation.php @@ -0,0 +1,14 @@ +ruleWithConfiguration(RenameMethodRector::class, [ + new MethodCallRename('Symfony\Component\Translation\Dumper\FileDumper', 'format', 'formatCatalogue'), + new MethodCallRename('Symfony\Component\Translation\Translator', 'getMessages', 'getCatalogue'), + ]); +}; diff --git a/config/sets/symfony/symfony3/symfony30/symfony30-twig-bundle.php b/config/sets/symfony/symfony3/symfony30/symfony30-twig-bundle.php new file mode 100644 index 00000000..d51460ec --- /dev/null +++ b/config/sets/symfony/symfony3/symfony30/symfony30-twig-bundle.php @@ -0,0 +1,12 @@ +ruleWithConfiguration(RenameClassRector::class, [ + 'Symfony\Bundle\TwigBundle\TwigDefaultEscapingStrategy' => 'Twig_FileExtensionEscapingStrategy', + ]); +}; diff --git a/config/sets/symfony/symfony3/symfony30/symfony30-validator.php b/config/sets/symfony/symfony3/symfony30/symfony30-validator.php new file mode 100644 index 00000000..fda92eef --- /dev/null +++ b/config/sets/symfony/symfony3/symfony30/symfony30-validator.php @@ -0,0 +1,46 @@ +ruleWithConfiguration(RenameClassRector::class, [ + 'Symfony\Component\Validator\Constraints\Collection\Optional' => 'Symfony\Component\Validator\Constraints\Optional', + 'Symfony\Component\Validator\Constraints\Collection\Required' => 'Symfony\Component\Validator\Constraints\Required', + 'Symfony\Component\Validator\MetadataInterface' => 'Symfony\Component\Validator\Mapping\MetadataInterface', + 'Symfony\Component\Validator\PropertyMetadataInterface' => 'Symfony\Component\Validator\Mapping\PropertyMetadataInterface', + 'Symfony\Component\Validator\PropertyMetadataContainerInterface' => 'Symfony\Component\Validator\Mapping\ClassMetadataInterface', + 'Symfony\Component\Validator\ClassBasedInterface' => 'Symfony\Component\Validator\Mapping\ClassMetadataInterface', + 'Symfony\Component\Validator\Mapping\ElementMetadata' => 'Symfony\Component\Validator\Mapping\GenericMetadata', + 'Symfony\Component\Validator\ExecutionContextInterface' => 'Symfony\Component\Validator\Context\ExecutionContextInterface', + 'Symfony\Component\Validator\Mapping\ClassMetadataFactory' => 'Symfony\Component\Validator\Mapping\Factory\LazyLoadingMetadataFactory', + 'Symfony\Component\Validator\Mapping\MetadataFactoryInterface' => 'Symfony\Component\Validator\Mapping\Factory\MetadataFactoryInterface', + ]); + + $rectorConfig->ruleWithConfiguration(RenameMethodRector::class, [ + new MethodCallRename( + 'Symfony\Component\Validator\ConstraintViolationInterface', + 'getMessageParameters', + 'getParameters' + ), + new MethodCallRename( + 'Symfony\Component\Validator\ConstraintViolationInterface', + 'getMessagePluralization', + 'getPlural' + ), + new MethodCallRename( + 'Symfony\Component\Validator\ConstraintViolation', + 'getMessageParameters', + 'getParameters' + ), + new MethodCallRename( + 'Symfony\Component\Validator\ConstraintViolation', + 'getMessagePluralization', + 'getPlural' + ), + ]); +}; diff --git a/config/sets/symfony/symfony31.php b/config/sets/symfony/symfony3/symfony31.php similarity index 100% rename from config/sets/symfony/symfony31.php rename to config/sets/symfony/symfony3/symfony31.php diff --git a/config/sets/symfony/symfony32.php b/config/sets/symfony/symfony3/symfony32.php similarity index 100% rename from config/sets/symfony/symfony32.php rename to config/sets/symfony/symfony3/symfony32.php diff --git a/config/sets/symfony/symfony33.php b/config/sets/symfony/symfony3/symfony33.php similarity index 100% rename from config/sets/symfony/symfony33.php rename to config/sets/symfony/symfony3/symfony33.php diff --git a/config/sets/symfony/symfony34.php b/config/sets/symfony/symfony3/symfony34.php similarity index 100% rename from config/sets/symfony/symfony34.php rename to config/sets/symfony/symfony3/symfony34.php diff --git a/config/sets/symfony/symfony30.php b/config/sets/symfony/symfony30.php deleted file mode 100644 index 0aa8c6ee..00000000 --- a/config/sets/symfony/symfony30.php +++ /dev/null @@ -1,210 +0,0 @@ -rules([ - // php - GetRequestRector::class, - FormTypeGetParentRector::class, - OptionNameRector::class, - ReadOnlyOptionToAttributeRector::class, - - // forms - FormTypeInstanceToClassConstRector::class, - StringFormTypeToClassRector::class, - RemoveDefaultGetBlockPrefixRector::class, - - // forms - collection - ChangeStringCollectionOptionToConstantRector::class, - ]); - - $rectorConfig->ruleWithConfiguration(RenameClassConstFetchRector::class, [ - new RenameClassConstFetch('Symfony\Component\Form\FormEvents', 'PRE_BIND', 'PRE_SUBMIT'), - new RenameClassConstFetch('Symfony\Component\Form\FormEvents', 'BIND', 'SUBMIT'), - new RenameClassConstFetch('Symfony\Component\Form\FormEvents', 'POST_BIND', 'POST_SUBMIT'), - new RenameClassConstFetch( - 'Symfony\Component\Form\Extension\Core\DataTransformer', - 'ROUND_HALFEVEN', - 'ROUND_HALF_EVEN' - ), - new RenameClassConstFetch( - 'Symfony\Component\Form\Extension\Core\DataTransformer', - 'ROUND_HALFUP', - 'ROUND_HALF_UP' - ), - new RenameClassConstFetch( - 'Symfony\Component\Form\Extension\Core\DataTransformer', - 'ROUND_HALFDOWN', - 'ROUND_HALF_DOWN' - ), - ]); - - $rectorConfig->ruleWithConfiguration(RenameMethodRector::class, [ - new MethodCallRename( - 'Symfony\Component\ClassLoader\UniversalClassLoader\UniversalClassLoader', - 'registerNamespaces', - 'addPrefixes' - ), - new MethodCallRename( - 'Symfony\Component\ClassLoader\UniversalClassLoader\UniversalClassLoader', - 'registerPrefixes', - 'addPrefixes' - ), - new MethodCallRename( - 'Symfony\Component\ClassLoader\UniversalClassLoader\UniversalClassLoader', - 'registerNamespace', - 'addPrefix' - ), - new MethodCallRename( - 'Symfony\Component\ClassLoader\UniversalClassLoader\UniversalClassLoader', - 'registerPrefix', - 'addPrefix' - ), - new MethodCallRename( - 'Symfony\Component\ClassLoader\UniversalClassLoader\UniversalClassLoader', - 'getNamespaces', - 'getPrefixes' - ), - new MethodCallRename( - 'Symfony\Component\ClassLoader\UniversalClassLoader\UniversalClassLoader', - 'getNamespaceFallbacks', - 'getFallbackDirs' - ), - new MethodCallRename( - 'Symfony\Component\ClassLoader\UniversalClassLoader\UniversalClassLoader', - 'getPrefixFallbacks', - 'getFallbackDirs' - ), - // form - new MethodCallRename('Symfony\Component\Form\AbstractType', 'getName', 'getBlockPrefix'), - new MethodCallRename('Symfony\Component\Form\FormTypeInterface', 'getName', 'getBlockPrefix'), - - new MethodCallRename('Symfony\Component\Form\FormTypeInterface', 'setDefaultOptions', 'configureOptions'), - new MethodCallRename('Symfony\Component\Form\ResolvedFormTypeInterface', 'getName', 'getBlockPrefix'), - new MethodCallRename( - 'Symfony\Component\Form\AbstractTypeExtension', - 'setDefaultOptions', - 'configureOptions' - ), - new MethodCallRename('Symfony\Component\Form\Form', 'bind', 'submit'), - new MethodCallRename('Symfony\Component\Form\Form', 'isBound', 'isSubmitted'), - // process - new MethodCallRename('Symfony\Component\Process\Process', 'setStdin', 'setInput'), - new MethodCallRename('Symfony\Component\Process\Process', 'getStdin', 'getInput'), - // monolog - new MethodCallRename('Symfony\Bridge\Monolog\Logger', 'emerg', 'emergency'), - new MethodCallRename('Symfony\Bridge\Monolog\Logger', 'crit', 'critical'), - new MethodCallRename('Symfony\Bridge\Monolog\Logger', 'err', 'error'), - new MethodCallRename('Symfony\Bridge\Monolog\Logger', 'warn', 'warning'), - # http kernel - new MethodCallRename('Symfony\Component\HttpKernel\Log\LoggerInterface', 'emerg', 'emergency'), - new MethodCallRename('Symfony\Component\HttpKernel\Log\LoggerInterface', 'crit', 'critical'), - new MethodCallRename('Symfony\Component\HttpKernel\Log\LoggerInterface', 'err', 'error'), - new MethodCallRename('Symfony\Component\HttpKernel\Log\LoggerInterface', 'warn', 'warning'), - new MethodCallRename('Symfony\Component\HttpKernel\Log\NullLogger', 'emerg', 'emergency'), - new MethodCallRename('Symfony\Component\HttpKernel\Log\NullLogger', 'crit', 'critical'), - new MethodCallRename('Symfony\Component\HttpKernel\Log\NullLogger', 'err', 'error'), - new MethodCallRename('Symfony\Component\HttpKernel\Log\NullLogger', 'warn', 'warning'), - // property access - new MethodCallRename( - 'Symfony\Component\PropertyAccess\PropertyAccess', - 'getPropertyAccessor', - 'createPropertyAccessor' - ), - // translator - new MethodCallRename('Symfony\Component\Translation\Dumper\FileDumper', 'format', 'formatCatalogue'), - new MethodCallRename('Symfony\Component\Translation\Translator', 'getMessages', 'getCatalogue'), - // validator - new MethodCallRename( - 'Symfony\Component\Validator\ConstraintViolationInterface', - 'getMessageParameters', - 'getParameters' - ), - new MethodCallRename( - 'Symfony\Component\Validator\ConstraintViolationInterface', - 'getMessagePluralization', - 'getPlural' - ), - new MethodCallRename( - 'Symfony\Component\Validator\ConstraintViolation', - 'getMessageParameters', - 'getParameters' - ), - new MethodCallRename( - 'Symfony\Component\Validator\ConstraintViolation', - 'getMessagePluralization', - 'getPlural' - ), - ]); - - $rectorConfig->ruleWithConfiguration(RenameClassRector::class, [ - # class loader - # partial with method rename - 'Symfony\Component\ClassLoader\UniversalClassLoader\UniversalClassLoader' => 'Symfony\Component\ClassLoader\ClassLoader', - # console - 'Symfony\Component\Console\Helper\ProgressHelper' => 'Symfony\Component\Console\Helper\ProgressBar', - # form - 'Symfony\Component\Form\Util\VirtualFormAwareIterator' => 'Symfony\Component\Form\Util\InheritDataAwareIterator', - 'Symfony\Component\Form\Tests\Extension\Core\Type\TypeTestCase' => 'Symfony\Component\Form\Test\TypeTestCase', - 'Symfony\Component\Form\Tests\FormIntegrationTestCase' => 'Symfony\Component\Form\Test\FormIntegrationTestCase', - 'Symfony\Component\Form\Tests\FormPerformanceTestCase' => 'Symfony\Component\Form\Test\FormPerformanceTestCase', - 'Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface' => 'Symfony\Component\Form\ChoiceList\ChoiceListInterface', - 'Symfony\Component\Form\Extension\Core\View\ChoiceView' => 'Symfony\Component\Form\ChoiceList\View\ChoiceView', - 'Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface' => 'Symfony\Component\Security\Csrf\CsrfTokenManagerInterface', - 'Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceList' => 'Symfony\Component\Form\ChoiceList\ArrayChoiceList', - 'Symfony\Component\Form\Extension\Core\ChoiceList\LazyChoiceList' => 'Symfony\Component\Form\ChoiceList\LazyChoiceList', - 'Symfony\Component\Form\Extension\Core\ChoiceList\ObjectChoiceList' => 'Symfony\Component\Form\ChoiceList\ArrayChoiceList', - 'Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList' => 'Symfony\Component\Form\ChoiceList\ArrayChoiceList', - 'Symfony\Component\Form\ChoiceList\ArrayKeyChoiceList' => 'Symfony\Component\Form\ChoiceList\ArrayChoiceList', - # http kernel - 'Symfony\Component\HttpKernel\Debug\ErrorHandler' => 'Symfony\Component\Debug\ErrorHandler', - 'Symfony\Component\HttpKernel\Debug\ExceptionHandler' => 'Symfony\Component\Debug\ExceptionHandler', - 'Symfony\Component\HttpKernel\Exception\FatalErrorException' => 'Symfony\Component\Debug\Exception\FatalErrorException', - 'Symfony\Component\HttpKernel\Exception\FlattenException' => 'Symfony\Component\Debug\Exception\FlattenException', - # partial with method rename - 'Symfony\Component\HttpKernel\Log\LoggerInterface' => 'Psr\Log\LoggerInterface', - # event disptacher - 'Symfony\Component\HttpKernel\DependencyInjection\RegisterListenersPass' => 'Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass', - # partial with methor rename - 'Symfony\Component\HttpKernel\Log\NullLogger' => 'Psr\Log\LoggerInterface', - # monolog - # partial with method rename - 'Symfony\Bridge\Monolog\Logger' => 'Psr\Log\LoggerInterface', - # security - 'Symfony\Component\Security\Core\Authorization\Voter\AbstractVoter' => 'Symfony\Component\Security\Core\Authorization\Voter\Voter', - # twig - 'Symfony\Bundle\TwigBundle\TwigDefaultEscapingStrategy' => 'Twig_FileExtensionEscapingStrategy', - # validator - 'Symfony\Component\Validator\Constraints\Collection\Optional' => 'Symfony\Component\Validator\Constraints\Optional', - 'Symfony\Component\Validator\Constraints\Collection\Required' => 'Symfony\Component\Validator\Constraints\Required', - 'Symfony\Component\Validator\MetadataInterface' => 'Symfony\Component\Validator\Mapping\MetadataInterface', - 'Symfony\Component\Validator\PropertyMetadataInterface' => 'Symfony\Component\Validator\Mapping\PropertyMetadataInterface', - 'Symfony\Component\Validator\PropertyMetadataContainerInterface' => 'Symfony\Component\Validator\Mapping\ClassMetadataInterface', - 'Symfony\Component\Validator\ClassBasedInterface' => 'Symfony\Component\Validator\Mapping\ClassMetadataInterface', - 'Symfony\Component\Validator\Mapping\ElementMetadata' => 'Symfony\Component\Validator\Mapping\GenericMetadata', - 'Symfony\Component\Validator\ExecutionContextInterface' => 'Symfony\Component\Validator\Context\ExecutionContextInterface', - 'Symfony\Component\Validator\Mapping\ClassMetadataFactory' => 'Symfony\Component\Validator\Mapping\Factory\LazyLoadingMetadataFactory', - 'Symfony\Component\Validator\Mapping\MetadataFactoryInterface' => 'Symfony\Component\Validator\Mapping\Factory\MetadataFactoryInterface', - # swift mailer - 'Symfony\Bridge\Swiftmailer\DataCollector\MessageDataCollector' => 'Symfony\Bundle\SwiftmailerBundle\DataCollector\MessageDataCollector', - ]); -}; diff --git a/rules/Symfony30/Rector/MethodCall/OptionNameRector.php b/rules/Symfony30/Rector/MethodCall/OptionNameRector.php index d1eecd54..5b691890 100644 --- a/rules/Symfony30/Rector/MethodCall/OptionNameRector.php +++ b/rules/Symfony30/Rector/MethodCall/OptionNameRector.php @@ -41,13 +41,17 @@ public function getRuleDefinition(): RuleDefinition [ new CodeSample( <<<'CODE_SAMPLE' -$builder = new FormBuilder; -$builder->add("...", ["precision" => "...", "virtual" => "..."]; +use Symfony\Component\Form\FormBuilder; + +$formBuilder = new FormBuilder; +$formBuilder->add("...", ["precision" => "...", "virtual" => "..."]; CODE_SAMPLE , <<<'CODE_SAMPLE' -$builder = new FormBuilder; -$builder->add("...", ["scale" => "...", "inherit_data" => "..."]; +use Symfony\Component\Form\FormBuilder; + +$formBuilder = new FormBuilder; +$formBuilder->add("...", ["scale" => "...", "inherit_data" => "..."]; CODE_SAMPLE ), ] diff --git a/src/Set/SetProvider/SymfonySetProvider.php b/src/Set/SetProvider/SymfonySetProvider.php index ba19ba59..a5950ee8 100644 --- a/src/Set/SetProvider/SymfonySetProvider.php +++ b/src/Set/SetProvider/SymfonySetProvider.php @@ -20,28 +20,117 @@ public function provide(): array return [ new ComposerTriggeredSet( SetGroup::SYMFONY, - 'symfony/*', + 'symfony/symfony', '2.5', __DIR__ . '/../../../config/sets/symfony/symfony25.php' ), new ComposerTriggeredSet( SetGroup::SYMFONY, - 'symfony/*', + 'symfony/symfony', '2.6', __DIR__ . '/../../../config/sets/symfony/symfony26.php' ), new ComposerTriggeredSet( SetGroup::SYMFONY, - 'symfony/*', + 'symfony/symfony', '2.7', __DIR__ . '/../../../config/sets/symfony/symfony27.php' ), + + // symfony 3.0 new ComposerTriggeredSet( SetGroup::SYMFONY, - 'symfony/*', + 'symfony/symfony', '3.0', __DIR__ . '/../../../config/sets/symfony/symfony30.php' ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/bridge-swift-mailer', + '3.0', + __DIR__ . '/../../../config/sets/symfony/symfony30/symfony30-bridge-swift-mailer.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/class-loader', + '3.0', + __DIR__ . '/../../../config/sets/symfony/symfony30/symfony30-class-loader.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/console', + '3.0', + __DIR__ . '/../../../config/sets/symfony/symfony30/symfony30-console.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/forms', + '3.0', + __DIR__ . '/../../../config/sets/symfony/symfony30/symfony30-forms.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/http-foundation', + '3.0', + __DIR__ . '/../../../config/sets/symfony/symfony30/symfony30-http-foundation.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/http-kernel', + '3.0', + __DIR__ . '/../../../config/sets/symfony/symfony30/symfony30-http-kernel.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/process', + '3.0', + __DIR__ . '/../../../config/sets/symfony/symfony30/symfony30-process.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/property-access', + '3.0', + __DIR__ . '/../../../config/sets/symfony/symfony30/symfony30-property-access.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/security', + '3.0', + __DIR__ . '/../../../config/sets/symfony/symfony30/symfony30-security.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/translation', + '3.0', + __DIR__ . '/../../../config/sets/symfony/symfony30/symfony30-translation.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/twig-bundle', + '3.0', + __DIR__ . '/../../../config/sets/symfony/symfony30/symfony30-twig-bundle.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/validator', + '3.0', + __DIR__ . '/../../../config/sets/symfony/symfony30/symfony30-validator.php' + ), + + // @todo split rest + new ComposerTriggeredSet( SetGroup::SYMFONY, 'symfony/*', From 98d18cc4a459e1114a213744a0dbdc1768d5b943 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Sun, 4 May 2025 16:48:19 +0200 Subject: [PATCH 32/53] [symfony 3.1] split of yaml config (#727) --- config/sets/symfony/symfony3/symfony31.php | 34 +-------------- .../symfony3/symfony31/symfony31-yaml.php | 43 +++++++++++++++++++ src/Set/SetProvider/SymfonySetProvider.php | 13 +++++- 3 files changed, 55 insertions(+), 35 deletions(-) create mode 100644 config/sets/symfony/symfony3/symfony31/symfony31-yaml.php diff --git a/config/sets/symfony/symfony3/symfony31.php b/config/sets/symfony/symfony3/symfony31.php index e59c2eb7..9da51487 100644 --- a/config/sets/symfony/symfony3/symfony31.php +++ b/config/sets/symfony/symfony3/symfony31.php @@ -7,37 +7,5 @@ use Rector\Config\RectorConfig; return static function (RectorConfig $rectorConfig): void { - $rectorConfig->ruleWithConfiguration(ReplaceArgumentDefaultValueRector::class, [ - new ReplaceArgumentDefaultValue('Symfony\Component\Yaml\Yaml', 'parse', 1, [ - false, - false, - true, - ], 'Symfony\Component\Yaml\Yaml::PARSE_OBJECT_FOR_MAP'), - new ReplaceArgumentDefaultValue('Symfony\Component\Yaml\Yaml', 'parse', 1, [ - false, - true, - ], 'Symfony\Component\Yaml\Yaml::PARSE_OBJECT'), - new ReplaceArgumentDefaultValue( - 'Symfony\Component\Yaml\Yaml', - 'parse', - 1, - true, - 'Symfony\Component\Yaml\Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE' - ), - new ReplaceArgumentDefaultValue('Symfony\Component\Yaml\Yaml', 'parse', 1, false, 0), - new ReplaceArgumentDefaultValue( - 'Symfony\Component\Yaml\Yaml', - 'dump', - 3, - [false, true], - 'Symfony\Component\Yaml\Yaml::DUMP_OBJECT' - ), - new ReplaceArgumentDefaultValue( - 'Symfony\Component\Yaml\Yaml', - 'dump', - 3, - true, - 'Symfony\Component\Yaml\Yaml::DUMP_EXCEPTION_ON_INVALID_TYPE' - ), - ]); + $rectorConfig->import(__DIR__ . '/symfony30/symfony31-yaml.php'); }; diff --git a/config/sets/symfony/symfony3/symfony31/symfony31-yaml.php b/config/sets/symfony/symfony3/symfony31/symfony31-yaml.php new file mode 100644 index 00000000..e59c2eb7 --- /dev/null +++ b/config/sets/symfony/symfony3/symfony31/symfony31-yaml.php @@ -0,0 +1,43 @@ +ruleWithConfiguration(ReplaceArgumentDefaultValueRector::class, [ + new ReplaceArgumentDefaultValue('Symfony\Component\Yaml\Yaml', 'parse', 1, [ + false, + false, + true, + ], 'Symfony\Component\Yaml\Yaml::PARSE_OBJECT_FOR_MAP'), + new ReplaceArgumentDefaultValue('Symfony\Component\Yaml\Yaml', 'parse', 1, [ + false, + true, + ], 'Symfony\Component\Yaml\Yaml::PARSE_OBJECT'), + new ReplaceArgumentDefaultValue( + 'Symfony\Component\Yaml\Yaml', + 'parse', + 1, + true, + 'Symfony\Component\Yaml\Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE' + ), + new ReplaceArgumentDefaultValue('Symfony\Component\Yaml\Yaml', 'parse', 1, false, 0), + new ReplaceArgumentDefaultValue( + 'Symfony\Component\Yaml\Yaml', + 'dump', + 3, + [false, true], + 'Symfony\Component\Yaml\Yaml::DUMP_OBJECT' + ), + new ReplaceArgumentDefaultValue( + 'Symfony\Component\Yaml\Yaml', + 'dump', + 3, + true, + 'Symfony\Component\Yaml\Yaml::DUMP_EXCEPTION_ON_INVALID_TYPE' + ), + ]); +}; diff --git a/src/Set/SetProvider/SymfonySetProvider.php b/src/Set/SetProvider/SymfonySetProvider.php index a5950ee8..6c280de9 100644 --- a/src/Set/SetProvider/SymfonySetProvider.php +++ b/src/Set/SetProvider/SymfonySetProvider.php @@ -129,14 +129,23 @@ public function provide(): array __DIR__ . '/../../../config/sets/symfony/symfony30/symfony30-validator.php' ), - // @todo split rest new ComposerTriggeredSet( SetGroup::SYMFONY, - 'symfony/*', + 'symfony/symfony', '3.1', __DIR__ . '/../../../config/sets/symfony/symfony31.php' ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/yaml', + '3.1', + __DIR__ . '/../../../config/sets/symfony/symfony31-yaml.php' + ), + + // @todo split rest + new ComposerTriggeredSet( SetGroup::SYMFONY, 'symfony/*', From bdbdc160dc56d84ea86527309c5d42c9a0e41792 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Sun, 4 May 2025 16:59:25 +0200 Subject: [PATCH 33/53] [phpstan] add symplify phpstan rules + fix static errors (#728) * [phpstan] add symplify phpstan rules * fix path * static fixes * cleanup --- composer.json | 1 + config/sets/symfony/symfony3/symfony31.php | 4 +- phpstan.neon | 3 ++ ...tAndSecurityAttributeToIsGrantedRector.php | 6 +-- .../Class_/CommandHelpToAttributeRector.php | 36 +++++++----------- .../Rector/Class_/InvokableCommandRector.php | 4 +- src/Set/SetProvider/SymfonySetProvider.php | 37 +++++++++---------- src/Set/SymfonySetList.php | 12 +++--- .../config/configured_rule.php | 12 ------ 9 files changed, 47 insertions(+), 68 deletions(-) delete mode 100644 tests/Rector/ClassMethod/ArgumentValueResolverToValueResolverRector/config/configured_rule.php diff --git a/composer.json b/composer.json index b3b44cfe..2de1eaa9 100644 --- a/composer.json +++ b/composer.json @@ -22,6 +22,7 @@ "symfony/security-core": "^6.4", "symfony/security-http": "^6.4", "symfony/validator": "^6.4", + "symplify/phpstan-rules": "^14.6", "symplify/vendor-patches": "^11.3", "tomasvotruba/class-leak": "^2.0", "tomasvotruba/type-coverage": "^2.0", diff --git a/config/sets/symfony/symfony3/symfony31.php b/config/sets/symfony/symfony3/symfony31.php index 9da51487..7aa92b7f 100644 --- a/config/sets/symfony/symfony3/symfony31.php +++ b/config/sets/symfony/symfony3/symfony31.php @@ -2,10 +2,8 @@ declare(strict_types=1); -use Rector\Arguments\Rector\ClassMethod\ReplaceArgumentDefaultValueRector; -use Rector\Arguments\ValueObject\ReplaceArgumentDefaultValue; use Rector\Config\RectorConfig; return static function (RectorConfig $rectorConfig): void { - $rectorConfig->import(__DIR__ . '/symfony30/symfony31-yaml.php'); + $rectorConfig->import(__DIR__ . '/symfony31/symfony31-yaml.php'); }; diff --git a/phpstan.neon b/phpstan.neon index 38b98277..39fa6b84 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,3 +1,6 @@ +rules: + - Symplify\PHPStanRules\Rules\StringFileAbsolutePathExistsRule + parameters: level: 8 diff --git a/rules/CodeQuality/Rector/Class_/SplitAndSecurityAttributeToIsGrantedRector.php b/rules/CodeQuality/Rector/Class_/SplitAndSecurityAttributeToIsGrantedRector.php index 12e0895c..ffb81bc0 100644 --- a/rules/CodeQuality/Rector/Class_/SplitAndSecurityAttributeToIsGrantedRector.php +++ b/rules/CodeQuality/Rector/Class_/SplitAndSecurityAttributeToIsGrantedRector.php @@ -87,11 +87,7 @@ public function refactor(Node $node): ?Node } // split by && and "and" - if (str_contains($content, ' && ')) { - $andItems = explode(' && ', $content); - } else { - $andItems = explode(' and ', $content); - } + $andItems = str_contains($content, ' && ') ? explode(' && ', $content) : explode(' and ', $content); $accessRights = []; diff --git a/rules/Symfony73/Rector/Class_/CommandHelpToAttributeRector.php b/rules/Symfony73/Rector/Class_/CommandHelpToAttributeRector.php index d9a67618..5f503401 100644 --- a/rules/Symfony73/Rector/Class_/CommandHelpToAttributeRector.php +++ b/rules/Symfony73/Rector/Class_/CommandHelpToAttributeRector.php @@ -7,6 +7,7 @@ use PhpParser\Node; use PhpParser\Node\Arg; use PhpParser\Node\Attribute; +use PhpParser\Node\Expr; use PhpParser\Node\Expr\MethodCall; use PhpParser\Node\Expr\Variable; use PhpParser\Node\Identifier; @@ -19,6 +20,7 @@ use PhpParser\NodeVisitor; use PHPStan\Reflection\ReflectionProvider; use PHPStan\Type\ObjectType; +use Rector\Doctrine\NodeAnalyzer\AttributeFinder; use Rector\NodeTypeResolver\Node\AttributeKey; use Rector\Rector\AbstractRector; use Rector\Symfony\Enum\CommandMethodName; @@ -38,6 +40,7 @@ final class CommandHelpToAttributeRector extends AbstractRector implements MinPh { public function __construct( private readonly ReflectionProvider $reflectionProvider, + private readonly AttributeFinder $attributeFinder ) { } @@ -53,8 +56,10 @@ public function getRuleDefinition(): RuleDefinition [ new CodeSample( <<<'CODE_SAMPLE' +use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Command\Command; +#[AsCommand(name: 'app:some')] final class SomeCommand extends Command { protected function configure(): void @@ -105,8 +110,8 @@ public function refactor(Node $node): ?Node return null; } - $asCommandAttribute = $this->getAsCommandAttribute($node); - if ($asCommandAttribute === null) { + $asCommandAttribute = $this->attributeFinder->findAttributeByClass($node, SymfonyAttribute::AS_COMMAND); + if (! $asCommandAttribute instanceof Attribute) { return null; } @@ -126,7 +131,7 @@ public function refactor(Node $node): ?Node return null; } - $wrappedHelp = new String_( + $wrappedHelpString = new String_( $helpExpr->value, [ Attributekey::KIND => String_::KIND_NOWDOC, @@ -134,7 +139,7 @@ public function refactor(Node $node): ?Node ] ); - $asCommandAttribute->args[] = new Arg($wrappedHelp, false, false, [], new Identifier('help')); + $asCommandAttribute->args[] = new Arg($wrappedHelpString, false, false, [], new Identifier('help')); if ($configureClassMethod->stmts === []) { unset($configureClassMethod); @@ -143,29 +148,16 @@ public function refactor(Node $node): ?Node return $node; } - private function getAsCommandAttribute(Class_ $class): ?Attribute - { - foreach ($class->attrGroups as $attrGroup) { - foreach ($attrGroup->attrs as $attribute) { - if ($this->nodeNameResolver->isName($attribute->name, SymfonyAttribute::AS_COMMAND)) { - return $attribute; - } - } - } - - return null; - } - /** * Returns the argument passed to setHelp() and removes the MethodCall node. */ - private function findAndRemoveSetHelpExpr(ClassMethod $configureMethod): ?String_ + private function findAndRemoveSetHelpExpr(ClassMethod $configureClassMethod): ?String_ { $helpString = null; $this->traverseNodesWithCallable( - (array) $configureMethod->stmts, - function (Node $node) use (&$helpString) { + (array) $configureClassMethod->stmts, + function (Node $node) use (&$helpString): int|null|Expr { if ($node instanceof Class_ || $node instanceof Function_) { return NodeVisitor::DONT_TRAVERSE_CURRENT_AND_CHILDREN; } @@ -196,9 +188,9 @@ function (Node $node) use (&$helpString) { } ); - foreach ((array) $configureMethod->stmts as $key => $stmt) { + foreach ((array) $configureClassMethod->stmts as $key => $stmt) { if ($this->isExpressionVariableThis($stmt)) { - unset($configureMethod->stmts[$key]); + unset($configureClassMethod->stmts[$key]); } } diff --git a/rules/Symfony73/Rector/Class_/InvokableCommandRector.php b/rules/Symfony73/Rector/Class_/InvokableCommandRector.php index bb004162..fb8abe30 100644 --- a/rules/Symfony73/Rector/Class_/InvokableCommandRector.php +++ b/rules/Symfony73/Rector/Class_/InvokableCommandRector.php @@ -248,9 +248,9 @@ private function replaceInputArgumentOptionFetchWithVariables(ClassMethod $execu }); } - private function isFluentArgumentOptionChain(MethodCall $call): bool + private function isFluentArgumentOptionChain(MethodCall $methodCall): bool { - $current = $call; + $current = $methodCall; while ($current instanceof MethodCall) { // every link must be addArgument() or addOption() diff --git a/src/Set/SetProvider/SymfonySetProvider.php b/src/Set/SetProvider/SymfonySetProvider.php index 6c280de9..4aa78dfb 100644 --- a/src/Set/SetProvider/SymfonySetProvider.php +++ b/src/Set/SetProvider/SymfonySetProvider.php @@ -42,106 +42,105 @@ public function provide(): array SetGroup::SYMFONY, 'symfony/symfony', '3.0', - __DIR__ . '/../../../config/sets/symfony/symfony30.php' + __DIR__ . '/../../../config/sets/symfony/symfony3/symfony30.php' ), new ComposerTriggeredSet( SetGroup::SYMFONY, 'symfony/bridge-swift-mailer', '3.0', - __DIR__ . '/../../../config/sets/symfony/symfony30/symfony30-bridge-swift-mailer.php' + __DIR__ . '/../../../config/sets/symfony/symfony3/symfony30/symfony30-bridge-swift-mailer.php' ), new ComposerTriggeredSet( SetGroup::SYMFONY, 'symfony/class-loader', '3.0', - __DIR__ . '/../../../config/sets/symfony/symfony30/symfony30-class-loader.php' + __DIR__ . '/../../../config/sets/symfony/symfony3/symfony30/symfony30-class-loader.php' ), new ComposerTriggeredSet( SetGroup::SYMFONY, 'symfony/console', '3.0', - __DIR__ . '/../../../config/sets/symfony/symfony30/symfony30-console.php' + __DIR__ . '/../../../config/sets/symfony/symfony3/symfony30/symfony30-console.php' ), new ComposerTriggeredSet( SetGroup::SYMFONY, 'symfony/forms', '3.0', - __DIR__ . '/../../../config/sets/symfony/symfony30/symfony30-forms.php' + __DIR__ . '/../../../config/sets/symfony/symfony3/symfony30/symfony30-forms.php' ), new ComposerTriggeredSet( SetGroup::SYMFONY, 'symfony/http-foundation', '3.0', - __DIR__ . '/../../../config/sets/symfony/symfony30/symfony30-http-foundation.php' + __DIR__ . '/../../../config/sets/symfony/symfony3/symfony30/symfony30-http-foundation.php' ), new ComposerTriggeredSet( SetGroup::SYMFONY, 'symfony/http-kernel', '3.0', - __DIR__ . '/../../../config/sets/symfony/symfony30/symfony30-http-kernel.php' + __DIR__ . '/../../../config/sets/symfony/symfony3/symfony30/symfony30-http-kernel.php' ), new ComposerTriggeredSet( SetGroup::SYMFONY, 'symfony/process', '3.0', - __DIR__ . '/../../../config/sets/symfony/symfony30/symfony30-process.php' + __DIR__ . '/../../../config/sets/symfony/symfony3/symfony30/symfony30-process.php' ), new ComposerTriggeredSet( SetGroup::SYMFONY, 'symfony/property-access', '3.0', - __DIR__ . '/../../../config/sets/symfony/symfony30/symfony30-property-access.php' + __DIR__ . '/../../../config/sets/symfony/symfony3/symfony30/symfony30-property-access.php' ), new ComposerTriggeredSet( SetGroup::SYMFONY, 'symfony/security', '3.0', - __DIR__ . '/../../../config/sets/symfony/symfony30/symfony30-security.php' + __DIR__ . '/../../../config/sets/symfony/symfony3/symfony30/symfony30-security.php' ), new ComposerTriggeredSet( SetGroup::SYMFONY, 'symfony/translation', '3.0', - __DIR__ . '/../../../config/sets/symfony/symfony30/symfony30-translation.php' + __DIR__ . '/../../../config/sets/symfony/symfony3/symfony30/symfony30-translation.php' ), new ComposerTriggeredSet( SetGroup::SYMFONY, 'symfony/twig-bundle', '3.0', - __DIR__ . '/../../../config/sets/symfony/symfony30/symfony30-twig-bundle.php' + __DIR__ . '/../../../config/sets/symfony/symfony3/symfony30/symfony30-twig-bundle.php' ), new ComposerTriggeredSet( SetGroup::SYMFONY, 'symfony/validator', '3.0', - __DIR__ . '/../../../config/sets/symfony/symfony30/symfony30-validator.php' + __DIR__ . '/../../../config/sets/symfony/symfony3/symfony30/symfony30-validator.php' ), - new ComposerTriggeredSet( SetGroup::SYMFONY, 'symfony/symfony', '3.1', - __DIR__ . '/../../../config/sets/symfony/symfony31.php' + __DIR__ . '/../../../config/sets/symfony/symfony3/symfony31.php' ), new ComposerTriggeredSet( SetGroup::SYMFONY, 'symfony/yaml', '3.1', - __DIR__ . '/../../../config/sets/symfony/symfony31-yaml.php' + __DIR__ . '/../../../config/sets/symfony/symfony3/symfony31/symfony31-yaml.php' ), // @todo split rest @@ -150,19 +149,19 @@ public function provide(): array SetGroup::SYMFONY, 'symfony/*', '3.2', - __DIR__ . '/../../../config/sets/symfony/symfony32.php' + __DIR__ . '/../../../config/sets/symfony/symfony3/symfony32.php' ), new ComposerTriggeredSet( SetGroup::SYMFONY, 'symfony/*', '3.3', - __DIR__ . '/../../../config/sets/symfony/symfony33.php' + __DIR__ . '/../../../config/sets/symfony/symfony3/symfony33.php' ), new ComposerTriggeredSet( SetGroup::SYMFONY, 'symfony/*', '3.4', - __DIR__ . '/../../../config/sets/symfony/symfony34.php' + __DIR__ . '/../../../config/sets/symfony/symfony3/symfony34.php' ), new ComposerTriggeredSet( SetGroup::SYMFONY, diff --git a/src/Set/SymfonySetList.php b/src/Set/SymfonySetList.php index 7d8017fe..ff80f8ce 100644 --- a/src/Set/SymfonySetList.php +++ b/src/Set/SymfonySetList.php @@ -5,6 +5,8 @@ namespace Rector\Symfony\Set; /** + * @deprecated Set list are too generic and do not handle package differences. Use ->withComposerBased(symfony: true) instead + * * @api */ final class SymfonySetList @@ -37,27 +39,27 @@ final class SymfonySetList /** * @var string */ - final public const SYMFONY_30 = __DIR__ . '/../../config/sets/symfony/symfony30.php'; + final public const SYMFONY_30 = __DIR__ . '/../../config/sets/symfony/symfony3/symfony30.php'; /** * @var string */ - final public const SYMFONY_31 = __DIR__ . '/../../config/sets/symfony/symfony31.php'; + final public const SYMFONY_31 = __DIR__ . '/../../config/sets/symfony/symfony3/symfony31.php'; /** * @var string */ - final public const SYMFONY_32 = __DIR__ . '/../../config/sets/symfony/symfony32.php'; + final public const SYMFONY_32 = __DIR__ . '/../../config/sets/symfony/symfony3/symfony32.php'; /** * @var string */ - final public const SYMFONY_33 = __DIR__ . '/../../config/sets/symfony/symfony33.php'; + final public const SYMFONY_33 = __DIR__ . '/../../config/sets/symfony/symfony3/symfony33.php'; /** * @var string */ - final public const SYMFONY_34 = __DIR__ . '/../../config/sets/symfony/symfony34.php'; + final public const SYMFONY_34 = __DIR__ . '/../../config/sets/symfony/symfony3/symfony34.php'; /** * @var string diff --git a/tests/Rector/ClassMethod/ArgumentValueResolverToValueResolverRector/config/configured_rule.php b/tests/Rector/ClassMethod/ArgumentValueResolverToValueResolverRector/config/configured_rule.php deleted file mode 100644 index 846ce4e4..00000000 --- a/tests/Rector/ClassMethod/ArgumentValueResolverToValueResolverRector/config/configured_rule.php +++ /dev/null @@ -1,12 +0,0 @@ -import(__DIR__ . '/../../../../../config/config.php'); - - $rectorConfig->rule(ArgumentValueResolverToValueResolverRector::class); -}; From e3f9449259f5dc3502c641248589df038eb3cf42 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Sun, 4 May 2025 17:06:28 +0200 Subject: [PATCH 34/53] [symfony 4.0] split of particular configs, improve SetListProvider (#729) --- config/sets/symfony/symfony4/symfony40.php | 13 +++++ .../symfony40-dependency-injection.php | 10 ++++ .../symfony4/symfony40/symfony40-forms.php | 10 ++++ .../symfony4/symfony40/symfony40-process.php | 12 +++++ .../symfony40/symfony40-validator.php | 15 ++++++ .../symfony40/symfony40-var-dumper.php | 10 ++++ config/sets/symfony/symfony40.php | 24 --------- src/Set/SetProvider/SymfonySetProvider.php | 51 ++++++++++++++++--- src/Set/SymfonySetList.php | 2 +- 9 files changed, 115 insertions(+), 32 deletions(-) create mode 100644 config/sets/symfony/symfony4/symfony40.php create mode 100644 config/sets/symfony/symfony4/symfony40/symfony40-dependency-injection.php create mode 100644 config/sets/symfony/symfony4/symfony40/symfony40-forms.php create mode 100644 config/sets/symfony/symfony4/symfony40/symfony40-process.php create mode 100644 config/sets/symfony/symfony4/symfony40/symfony40-validator.php create mode 100644 config/sets/symfony/symfony4/symfony40/symfony40-var-dumper.php delete mode 100644 config/sets/symfony/symfony40.php diff --git a/config/sets/symfony/symfony4/symfony40.php b/config/sets/symfony/symfony4/symfony40.php new file mode 100644 index 00000000..19e2cf46 --- /dev/null +++ b/config/sets/symfony/symfony4/symfony40.php @@ -0,0 +1,13 @@ +import(__DIR__ . '/symfony40/symfony40-validator.php'); + $rectorConfig->import(__DIR__ . '/symfony40/symfony40-dependency-injection.php'); + $rectorConfig->import(__DIR__ . '/symfony40/symfony40-process.php'); + $rectorConfig->import(__DIR__ . '/symfony40/symfony40-forms.php'); + $rectorConfig->import(__DIR__ . '/symfony40/symfony40-var-dumper.php'); +}; diff --git a/config/sets/symfony/symfony4/symfony40/symfony40-dependency-injection.php b/config/sets/symfony/symfony4/symfony40/symfony40-dependency-injection.php new file mode 100644 index 00000000..d029830b --- /dev/null +++ b/config/sets/symfony/symfony4/symfony40/symfony40-dependency-injection.php @@ -0,0 +1,10 @@ +rules([ContainerBuilderCompileEnvArgumentRector::class]); +}; diff --git a/config/sets/symfony/symfony4/symfony40/symfony40-forms.php b/config/sets/symfony/symfony4/symfony40/symfony40-forms.php new file mode 100644 index 00000000..f54ea651 --- /dev/null +++ b/config/sets/symfony/symfony4/symfony40/symfony40-forms.php @@ -0,0 +1,10 @@ +rules([FormIsValidRector::class]); +}; diff --git a/config/sets/symfony/symfony4/symfony40/symfony40-process.php b/config/sets/symfony/symfony4/symfony40/symfony40-process.php new file mode 100644 index 00000000..02a69337 --- /dev/null +++ b/config/sets/symfony/symfony4/symfony40/symfony40-process.php @@ -0,0 +1,12 @@ +ruleWithConfiguration(RenameClassRector::class, [ + 'Symfony\Component\Process\ProcessBuilder' => 'Symfony\Component\Process\Process', + ]); +}; diff --git a/config/sets/symfony/symfony4/symfony40/symfony40-validator.php b/config/sets/symfony/symfony4/symfony40/symfony40-validator.php new file mode 100644 index 00000000..9475e864 --- /dev/null +++ b/config/sets/symfony/symfony4/symfony40/symfony40-validator.php @@ -0,0 +1,15 @@ +rules([ConstraintUrlOptionRector::class]); + + $rectorConfig->ruleWithConfiguration(RenameClassRector::class, [ + 'Symfony\Component\Validator\Tests\Constraints\AbstractConstraintValidatorTest' => 'Symfony\Component\Validator\Test\ConstraintValidatorTestCase', + ]); +}; diff --git a/config/sets/symfony/symfony4/symfony40/symfony40-var-dumper.php b/config/sets/symfony/symfony4/symfony40/symfony40-var-dumper.php new file mode 100644 index 00000000..b676c11b --- /dev/null +++ b/config/sets/symfony/symfony4/symfony40/symfony40-var-dumper.php @@ -0,0 +1,10 @@ +rules([VarDumperTestTraitMethodArgsRector::class]); +}; diff --git a/config/sets/symfony/symfony40.php b/config/sets/symfony/symfony40.php deleted file mode 100644 index 61e4afaa..00000000 --- a/config/sets/symfony/symfony40.php +++ /dev/null @@ -1,24 +0,0 @@ -rules([ - ConstraintUrlOptionRector::class, - FormIsValidRector::class, - VarDumperTestTraitMethodArgsRector::class, - ContainerBuilderCompileEnvArgumentRector::class, - ]); - - $rectorConfig->ruleWithConfiguration(RenameClassRector::class, [ - 'Symfony\Component\Validator\Tests\Constraints\AbstractConstraintValidatorTest' => 'Symfony\Component\Validator\Test\ConstraintValidatorTestCase', - 'Symfony\Component\Process\ProcessBuilder' => 'Symfony\Component\Process\Process', - ]); -}; diff --git a/src/Set/SetProvider/SymfonySetProvider.php b/src/Set/SetProvider/SymfonySetProvider.php index 4aa78dfb..97e7a3e9 100644 --- a/src/Set/SetProvider/SymfonySetProvider.php +++ b/src/Set/SetProvider/SymfonySetProvider.php @@ -143,32 +143,69 @@ public function provide(): array __DIR__ . '/../../../config/sets/symfony/symfony3/symfony31/symfony31-yaml.php' ), - // @todo split rest - new ComposerTriggeredSet( SetGroup::SYMFONY, - 'symfony/*', + 'symfony/symfony', '3.2', __DIR__ . '/../../../config/sets/symfony/symfony3/symfony32.php' ), new ComposerTriggeredSet( SetGroup::SYMFONY, - 'symfony/*', + 'symfony/symfony', '3.3', __DIR__ . '/../../../config/sets/symfony/symfony3/symfony33.php' ), new ComposerTriggeredSet( SetGroup::SYMFONY, - 'symfony/*', + 'symfony/symfony', '3.4', __DIR__ . '/../../../config/sets/symfony/symfony3/symfony34.php' ), + new ComposerTriggeredSet( SetGroup::SYMFONY, - 'symfony/*', + 'symfony/symfony', + '4.0', + __DIR__ . '/../../../config/sets/symfony/symfony4/symfony40.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/dependency-injection', + '4.0', + __DIR__ . '/../../../config/sets/symfony/symfony4/symfony40/symfony40-dependency-injection.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/process', '4.0', - __DIR__ . '/../../../config/sets/symfony/symfony40.php' + __DIR__ . '/../../../config/sets/symfony/symfony4/symfony40/symfony40-process.php' ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/validator', + '4.0', + __DIR__ . '/../../../config/sets/symfony/symfony4/symfony40/symfony40-validator.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/var-dumper', + '4.0', + __DIR__ . '/../../../config/sets/symfony/symfony4/symfony40/symfony40-var-dumper.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/forms', + '4.0', + __DIR__ . '/../../../config/sets/symfony/symfony4/symfony40/symfony40-forms.php' + ), + + // @todo split rest + new ComposerTriggeredSet( SetGroup::SYMFONY, 'symfony/*', diff --git a/src/Set/SymfonySetList.php b/src/Set/SymfonySetList.php index ff80f8ce..daca1196 100644 --- a/src/Set/SymfonySetList.php +++ b/src/Set/SymfonySetList.php @@ -64,7 +64,7 @@ final class SymfonySetList /** * @var string */ - final public const SYMFONY_40 = __DIR__ . '/../../config/sets/symfony/symfony40.php'; + final public const SYMFONY_40 = __DIR__ . '/../../config/sets/symfony/symfony4/symfony40.php'; /** * @var string From 9cc7ebdfa05fb0466aefcad0746c486088a99ecb Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Sun, 4 May 2025 17:17:33 +0200 Subject: [PATCH 35/53] [symfony 4.1] split to particular configs (#730) * move * [symfony 4.1] split to particular configs --- config/sets/symfony/symfony4/symfony41.php | 14 +++++++ .../symfony41/symfony41-console.php} | 13 +----- .../symfony41/symfony41-framework-bundle.php | 13 ++++++ .../symfony41/symfony41-http-foundation.php | 13 ++++++ .../symfony4/symfony41/symfony41-workflow.php | 20 +++++++++ .../sets/symfony/{ => symfony4}/symfony42.php | 0 .../sets/symfony/{ => symfony4}/symfony43.php | 0 .../sets/symfony/{ => symfony4}/symfony44.php | 0 src/Set/SetProvider/SymfonySetProvider.php | 41 ++++++++++++++++--- src/Set/SymfonySetList.php | 8 ++-- 10 files changed, 100 insertions(+), 22 deletions(-) create mode 100644 config/sets/symfony/symfony4/symfony41.php rename config/sets/symfony/{symfony41.php => symfony4/symfony41/symfony41-console.php} (63%) create mode 100644 config/sets/symfony/symfony4/symfony41/symfony41-framework-bundle.php create mode 100644 config/sets/symfony/symfony4/symfony41/symfony41-http-foundation.php create mode 100644 config/sets/symfony/symfony4/symfony41/symfony41-workflow.php rename config/sets/symfony/{ => symfony4}/symfony42.php (100%) rename config/sets/symfony/{ => symfony4}/symfony43.php (100%) rename config/sets/symfony/{ => symfony4}/symfony44.php (100%) diff --git a/config/sets/symfony/symfony4/symfony41.php b/config/sets/symfony/symfony4/symfony41.php new file mode 100644 index 00000000..58ab6251 --- /dev/null +++ b/config/sets/symfony/symfony4/symfony41.php @@ -0,0 +1,14 @@ +import(__DIR__ . '/symfony41/symfony41-console.php'); + $rectorConfig->import(__DIR__ . '/symfony41/symfony41-http-foundation.php'); + $rectorConfig->import(__DIR__ . '/symfony41/symfony41-workflow.php'); + $rectorConfig->import(__DIR__ . '/symfony41/symfony41-framework-bundle.php'); + +}; diff --git a/config/sets/symfony/symfony41.php b/config/sets/symfony/symfony4/symfony41/symfony41-console.php similarity index 63% rename from config/sets/symfony/symfony41.php rename to config/sets/symfony/symfony4/symfony41/symfony41-console.php index 326b4c2f..54d00edd 100644 --- a/config/sets/symfony/symfony41.php +++ b/config/sets/symfony/symfony4/symfony41/symfony41-console.php @@ -4,11 +4,9 @@ use Rector\Config\RectorConfig; use Rector\Renaming\Rector\MethodCall\RenameMethodRector; -use Rector\Renaming\Rector\Name\RenameClassRector; use Rector\Renaming\ValueObject\MethodCallRename; use Rector\Renaming\ValueObject\MethodCallRenameWithArrayKey; -# https://github.com/symfony/symfony/blob/master/UPGRADE-4.1.md return static function (RectorConfig $rectorConfig): void { $rectorConfig->ruleWithConfiguration(RenameMethodRector::class, [ # https://github.com/symfony/symfony/commit/463f986c28a497571967e37c1314e9911f1ef6ba @@ -29,9 +27,7 @@ 'setCrossingChar', 'setDefaultCrossingChar' ), - new MethodCallRename('Symfony\Component\HttpFoundation\File\UploadedFile', 'getClientSize', 'getSize'), - new MethodCallRename('Symfony\Component\Workflow\DefinitionBuilder', 'reset', 'clear'), - new MethodCallRename('Symfony\Component\Workflow\DefinitionBuilder', 'add', 'addWorkflow'), + # https://github.com/symfony/symfony/commit/463f986c28a497571967e37c1314e9911f1ef6ba new MethodCallRenameWithArrayKey( 'Symfony\Component\Console\Helper\TableStyle', @@ -48,11 +44,4 @@ 2 ), ]); - - $rectorConfig->ruleWithConfiguration(RenameClassRector::class, [ - # https://github.com/symfony/symfony/commit/07dd09db59e2f2a86a291d00d978169d9059e307 - 'Symfony\Bundle\FrameworkBundle\DataCollector\RequestDataCollector' => 'Symfony\Component\HttpKernel\DataCollector\RequestDataCollector', - 'Symfony\Component\Workflow\SupportStrategy\SupportStrategyInterface' => 'Symfony\Component\Workflow\SupportStrategy\WorkflowSupportStrategyInterface', - 'Symfony\Component\Workflow\SupportStrategy\ClassInstanceSupportStrategy' => 'Symfony\Component\Workflow\SupportStrategy\InstanceOfSupportStrategy', - ]); }; diff --git a/config/sets/symfony/symfony4/symfony41/symfony41-framework-bundle.php b/config/sets/symfony/symfony4/symfony41/symfony41-framework-bundle.php new file mode 100644 index 00000000..26559523 --- /dev/null +++ b/config/sets/symfony/symfony4/symfony41/symfony41-framework-bundle.php @@ -0,0 +1,13 @@ +ruleWithConfiguration(RenameClassRector::class, [ + # https://github.com/symfony/symfony/commit/07dd09db59e2f2a86a291d00d978169d9059e307 + 'Symfony\Bundle\FrameworkBundle\DataCollector\RequestDataCollector' => 'Symfony\Component\HttpKernel\DataCollector\RequestDataCollector', + ]); +}; diff --git a/config/sets/symfony/symfony4/symfony41/symfony41-http-foundation.php b/config/sets/symfony/symfony4/symfony41/symfony41-http-foundation.php new file mode 100644 index 00000000..78e7376c --- /dev/null +++ b/config/sets/symfony/symfony4/symfony41/symfony41-http-foundation.php @@ -0,0 +1,13 @@ +ruleWithConfiguration(RenameMethodRector::class, [ + new MethodCallRename('Symfony\Component\HttpFoundation\File\UploadedFile', 'getClientSize', 'getSize'), + ]); +}; diff --git a/config/sets/symfony/symfony4/symfony41/symfony41-workflow.php b/config/sets/symfony/symfony4/symfony41/symfony41-workflow.php new file mode 100644 index 00000000..5f519315 --- /dev/null +++ b/config/sets/symfony/symfony4/symfony41/symfony41-workflow.php @@ -0,0 +1,20 @@ +ruleWithConfiguration(RenameMethodRector::class, [ + new MethodCallRename('Symfony\Component\Workflow\DefinitionBuilder', 'reset', 'clear'), + new MethodCallRename('Symfony\Component\Workflow\DefinitionBuilder', 'add', 'addWorkflow'), + ]); + + $rectorConfig->ruleWithConfiguration(RenameClassRector::class, [ + 'Symfony\Component\Workflow\SupportStrategy\SupportStrategyInterface' => 'Symfony\Component\Workflow\SupportStrategy\WorkflowSupportStrategyInterface', + 'Symfony\Component\Workflow\SupportStrategy\ClassInstanceSupportStrategy' => 'Symfony\Component\Workflow\SupportStrategy\InstanceOfSupportStrategy', + ]); +}; diff --git a/config/sets/symfony/symfony42.php b/config/sets/symfony/symfony4/symfony42.php similarity index 100% rename from config/sets/symfony/symfony42.php rename to config/sets/symfony/symfony4/symfony42.php diff --git a/config/sets/symfony/symfony43.php b/config/sets/symfony/symfony4/symfony43.php similarity index 100% rename from config/sets/symfony/symfony43.php rename to config/sets/symfony/symfony4/symfony43.php diff --git a/config/sets/symfony/symfony44.php b/config/sets/symfony/symfony4/symfony44.php similarity index 100% rename from config/sets/symfony/symfony44.php rename to config/sets/symfony/symfony4/symfony44.php diff --git a/src/Set/SetProvider/SymfonySetProvider.php b/src/Set/SetProvider/SymfonySetProvider.php index 97e7a3e9..db07ae4b 100644 --- a/src/Set/SetProvider/SymfonySetProvider.php +++ b/src/Set/SetProvider/SymfonySetProvider.php @@ -204,31 +204,60 @@ public function provide(): array __DIR__ . '/../../../config/sets/symfony/symfony4/symfony40/symfony40-forms.php' ), - // @todo split rest + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/symfony', + '4.1', + __DIR__ . '/../../../config/sets/symfony/symfony4/symfony41.php' + ), new ComposerTriggeredSet( SetGroup::SYMFONY, - 'symfony/*', + 'symfony/console', '4.1', - __DIR__ . '/../../../config/sets/symfony/symfony41.php' + __DIR__ . '/../../../config/sets/symfony/symfony4/symfony41/symfony41-console.php' ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/framework-bundle', + '4.1', + __DIR__ . '/../../../config/sets/symfony/symfony4/symfony41/symfony41-framework-bundle.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/http-foundation', + '4.1', + __DIR__ . '/../../../config/sets/symfony/symfony4/symfony41/symfony41-http-foundation.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/workflow', + '4.1', + __DIR__ . '/../../../config/sets/symfony/symfony4/symfony41/symfony41-workflow.php' + ), + + // @todo split rest + new ComposerTriggeredSet( SetGroup::SYMFONY, 'symfony/*', '4.2', - __DIR__ . '/../../../config/sets/symfony/symfony42.php' + __DIR__ . '/../../../config/sets/symfony/symfony4/symfony42.php' ), new ComposerTriggeredSet( SetGroup::SYMFONY, 'symfony/*', '4.3', - __DIR__ . '/../../../config/sets/symfony/symfony43.php' + __DIR__ . '/../../../config/sets/symfony/symfony4/symfony43.php' ), new ComposerTriggeredSet( SetGroup::SYMFONY, 'symfony/*', '4.4', - __DIR__ . '/../../../config/sets/symfony/symfony44.php' + __DIR__ . '/../../../config/sets/symfony/symfony4/symfony44.php' ), new ComposerTriggeredSet( SetGroup::SYMFONY, diff --git a/src/Set/SymfonySetList.php b/src/Set/SymfonySetList.php index daca1196..a028f274 100644 --- a/src/Set/SymfonySetList.php +++ b/src/Set/SymfonySetList.php @@ -69,22 +69,22 @@ final class SymfonySetList /** * @var string */ - final public const SYMFONY_41 = __DIR__ . '/../../config/sets/symfony/symfony41.php'; + final public const SYMFONY_41 = __DIR__ . '/../../config/sets/symfony/symfony4/symfony41.php'; /** * @var string */ - final public const SYMFONY_42 = __DIR__ . '/../../config/sets/symfony/symfony42.php'; + final public const SYMFONY_42 = __DIR__ . '/../../config/sets/symfony/symfony4/symfony42.php'; /** * @var string */ - final public const SYMFONY_43 = __DIR__ . '/../../config/sets/symfony/symfony43.php'; + final public const SYMFONY_43 = __DIR__ . '/../../config/sets/symfony/symfony4/symfony43.php'; /** * @var string */ - final public const SYMFONY_44 = __DIR__ . '/../../config/sets/symfony/symfony44.php'; + final public const SYMFONY_44 = __DIR__ . '/../../config/sets/symfony/symfony4/symfony44.php'; /** * @var string From 5b36ba6768bc15ef6868927e84aebef841355860 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Sun, 4 May 2025 17:34:21 +0200 Subject: [PATCH 36/53] [symfony 4.2] split to particular configs (#731) * move * [symfony 4.1] split to particular configs * [symfony 4.2] Split off to per package configs * improve symfony set provider --- config/sets/symfony/symfony4/symfony41.php | 1 - config/sets/symfony/symfony4/symfony42.php | 193 ++---------------- .../symfony4/symfony42/symfony42-cache.php | 13 ++ .../symfony4/symfony42/symfony42-config.php | 13 ++ .../symfony42/symfony42-dom-crawler.php | 22 ++ .../symfony4/symfony42/symfony42-finder.php | 21 ++ .../symfony4/symfony42/symfony42-forms.php | 48 +++++ .../symfony42/symfony42-framework-bundle.php | 14 ++ .../symfony42/symfony42-http-foundation.php | 38 ++++ .../symfony42/symfony42-http-kernel.php | 27 +++ .../symfony42/symfony42-monolog-bridge.php | 49 +++++ .../symfony4/symfony42/symfony42-process.php | 13 ++ .../symfony42/symfony42-serializer.php | 31 +++ .../symfony42/symfony42-translation.php | 12 ++ src/Set/SetProvider/SymfonySetProvider.php | 98 ++++++++- 15 files changed, 408 insertions(+), 185 deletions(-) create mode 100644 config/sets/symfony/symfony4/symfony42/symfony42-cache.php create mode 100644 config/sets/symfony/symfony4/symfony42/symfony42-config.php create mode 100644 config/sets/symfony/symfony4/symfony42/symfony42-dom-crawler.php create mode 100644 config/sets/symfony/symfony4/symfony42/symfony42-finder.php create mode 100644 config/sets/symfony/symfony4/symfony42/symfony42-forms.php create mode 100644 config/sets/symfony/symfony4/symfony42/symfony42-framework-bundle.php create mode 100644 config/sets/symfony/symfony4/symfony42/symfony42-http-foundation.php create mode 100644 config/sets/symfony/symfony4/symfony42/symfony42-http-kernel.php create mode 100644 config/sets/symfony/symfony4/symfony42/symfony42-monolog-bridge.php create mode 100644 config/sets/symfony/symfony4/symfony42/symfony42-process.php create mode 100644 config/sets/symfony/symfony4/symfony42/symfony42-serializer.php create mode 100644 config/sets/symfony/symfony4/symfony42/symfony42-translation.php diff --git a/config/sets/symfony/symfony4/symfony41.php b/config/sets/symfony/symfony4/symfony41.php index 58ab6251..ee504d83 100644 --- a/config/sets/symfony/symfony4/symfony41.php +++ b/config/sets/symfony/symfony4/symfony41.php @@ -10,5 +10,4 @@ $rectorConfig->import(__DIR__ . '/symfony41/symfony41-http-foundation.php'); $rectorConfig->import(__DIR__ . '/symfony41/symfony41-workflow.php'); $rectorConfig->import(__DIR__ . '/symfony41/symfony41-framework-bundle.php'); - }; diff --git a/config/sets/symfony/symfony4/symfony42.php b/config/sets/symfony/symfony4/symfony42.php index 541301f0..2425a8a3 100644 --- a/config/sets/symfony/symfony4/symfony42.php +++ b/config/sets/symfony/symfony4/symfony42.php @@ -2,190 +2,21 @@ declare(strict_types=1); -use PHPStan\Type\IterableType; -use PHPStan\Type\MixedType; -use Rector\Arguments\NodeAnalyzer\ArgumentAddingScope; -use Rector\Arguments\Rector\ClassMethod\ArgumentAdderRector; -use Rector\Arguments\Rector\ClassMethod\ReplaceArgumentDefaultValueRector; -use Rector\Arguments\ValueObject\ArgumentAdder; -use Rector\Arguments\ValueObject\ReplaceArgumentDefaultValue; use Rector\Config\RectorConfig; -use Rector\Removing\Rector\ClassMethod\ArgumentRemoverRector; -use Rector\Removing\ValueObject\ArgumentRemover; -use Rector\Renaming\Rector\MethodCall\RenameMethodRector; -use Rector\Renaming\Rector\Name\RenameClassRector; -use Rector\Renaming\ValueObject\MethodCallRename; -use Rector\Symfony\Symfony42\Rector\New_\RootNodeTreeBuilderRector; -use Rector\Symfony\Symfony42\Rector\New_\StringToArrayArgumentProcessRector; -use Rector\Transform\Rector\ClassMethod\WrapReturnRector; -use Rector\Transform\Rector\New_\NewToStaticCallRector; -use Rector\Transform\ValueObject\NewToStaticCall; -use Rector\Transform\ValueObject\WrapReturn; -use Rector\TypeDeclaration\Rector\ClassMethod\AddReturnTypeDeclarationRector; -use Rector\TypeDeclaration\ValueObject\AddReturnTypeDeclaration; -use Rector\ValueObject\MethodName; -use Rector\ValueObject\Visibility; -use Rector\Visibility\Rector\ClassMethod\ChangeMethodVisibilityRector; -use Rector\Visibility\ValueObject\ChangeMethodVisibility; # https://github.com/symfony/symfony/pull/28447 return static function (RectorConfig $rectorConfig): void { - $rectorConfig->ruleWithConfiguration(NewToStaticCallRector::class, [ - new NewToStaticCall( - 'Symfony\Component\HttpFoundation\Cookie', - 'Symfony\Component\HttpFoundation\Cookie', - 'create' - ), - ]); - - $rectorConfig->ruleWithConfiguration(RenameClassRector::class, [ - # https://github.com/symfony/symfony/commit/a7e319d9e1316e2e18843f8ce15b67a8693e5bf9 - 'Symfony\Bundle\FrameworkBundle\Controller\Controller' => 'Symfony\Bundle\FrameworkBundle\Controller\AbstractController', - # https://github.com/symfony/symfony/commit/744bf0e7ac3ecf240d0bf055cc58f881bb0b3ec0 - 'Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand' => 'Symfony\Component\Console\Command\Command', - 'Symfony\Component\Translation\TranslatorInterface' => 'Symfony\Contracts\Translation\TranslatorInterface', - ]); - - $rectorConfig->rules([ - # https://symfony.com/blog/new-in-symfony-4-2-important-deprecations - StringToArrayArgumentProcessRector::class, - RootNodeTreeBuilderRector::class, - ]); - - $rectorConfig->ruleWithConfiguration(ArgumentAdderRector::class, [ - new ArgumentAdder( - 'Symfony\Component\DomCrawler\Crawler', - 'children', - 0, - null, - null, - null, - ArgumentAddingScope::SCOPE_METHOD_CALL - ), - new ArgumentAdder( - 'Symfony\Component\Finder\Finder', - 'sortByName', - 0, - null, - false, - null, - ArgumentAddingScope::SCOPE_METHOD_CALL - ), - new ArgumentAdder( - 'Symfony\Bridge\Monolog\Processor\DebugProcessor', - 'getLogs', - 0, - null, - null, - null, - ArgumentAddingScope::SCOPE_METHOD_CALL - ), - new ArgumentAdder( - 'Symfony\Bridge\Monolog\Processor\DebugProcessor', - 'countErrors', - 0, - 'default_value', - null, - null, - ArgumentAddingScope::SCOPE_METHOD_CALL - ), - new ArgumentAdder( - 'Symfony\Bridge\Monolog\Logger', - 'getLogs', - 0, - 'default_value', - null, - null, - ArgumentAddingScope::SCOPE_METHOD_CALL - ), - new ArgumentAdder( - 'Symfony\Bridge\Monolog\Logger', - 'countErrors', - 0, - 'default_value', - null, - null, - ArgumentAddingScope::SCOPE_METHOD_CALL - ), - new ArgumentAdder( - 'Symfony\Component\Serializer\Normalizer', - 'handleCircularReference', - 1, - null, - null, - null, - ArgumentAddingScope::SCOPE_METHOD_CALL - ), - new ArgumentAdder( - 'Symfony\Component\Serializer\Normalizer', - 'handleCircularReference', - 2, - null, - null, - null, - ArgumentAddingScope::SCOPE_METHOD_CALL - ), - ]); - - $rectorConfig->ruleWithConfiguration(RenameMethodRector::class, [ - new MethodCallRename('Symfony\Component\Cache\CacheItem', 'getPreviousTags', 'getMetadata'), - new MethodCallRename('Symfony\Component\Form\AbstractTypeExtension', 'getExtendedType', 'getExtendedTypes'), - ]); - - $iterableType = new IterableType(new MixedType(), new MixedType()); - - $rectorConfig->ruleWithConfiguration(AddReturnTypeDeclarationRector::class, [ - new AddReturnTypeDeclaration( - 'Symfony\Component\Form\AbstractTypeExtension', - 'getExtendedTypes', - $iterableType - ), - ]); - - $rectorConfig->ruleWithConfiguration(ChangeMethodVisibilityRector::class, [new ChangeMethodVisibility( - 'Symfony\Component\Form\AbstractTypeExtension', - 'getExtendedTypes', - Visibility::STATIC - ), - ]); - - $rectorConfig->ruleWithConfiguration( - WrapReturnRector::class, - [new WrapReturn('Symfony\Component\Form\AbstractTypeExtension', 'getExtendedTypes', true)] - ); - - // https://github.com/symfony/symfony/commit/9493cfd5f2366dab19bbdde0d0291d0575454567 - $rectorConfig->ruleWithConfiguration(ReplaceArgumentDefaultValueRector::class, [ - new ReplaceArgumentDefaultValue( - 'Symfony\Component\HttpFoundation\Cookie', - MethodName::CONSTRUCT, - 5, - false, - null - ), - new ReplaceArgumentDefaultValue( - 'Symfony\Component\HttpFoundation\Cookie', - MethodName::CONSTRUCT, - 8, - null, - 'lax' - ), - ]); - - # https://github.com/symfony/symfony/commit/f5c355e1ba399a1b3512367647d902148bdaf09f - $rectorConfig->ruleWithConfiguration(ArgumentRemoverRector::class, [ - new ArgumentRemover( - 'Symfony\Component\HttpKernel\DataCollector\ConfigDataCollector', - MethodName::CONSTRUCT, - 0, - null - ), - new ArgumentRemover( - 'Symfony\Component\HttpKernel\DataCollector\ConfigDataCollector', - MethodName::CONSTRUCT, - 1, - null - ), - ]); + $rectorConfig->import(__DIR__ . '/symfony42/symfony42-http-foundation.php'); + $rectorConfig->import(__DIR__ . '/symfony42/symfony42-http-kernel.php'); + $rectorConfig->import(__DIR__ . '/symfony42/symfony42-framework-bundle.php'); + $rectorConfig->import(__DIR__ . '/symfony42/symfony42-translation.php'); + $rectorConfig->import(__DIR__ . '/symfony42/symfony42-process.php'); + $rectorConfig->import(__DIR__ . '/symfony42/symfony42-config.php'); + $rectorConfig->import(__DIR__ . '/symfony42/symfony42-dom-crawler.php'); + $rectorConfig->import(__DIR__ . '/symfony42/symfony42-finder.php'); + $rectorConfig->import(__DIR__ . '/symfony42/symfony42-monolog-bridge.php'); + $rectorConfig->import(__DIR__ . '/symfony42/symfony42-serializer.php'); + $rectorConfig->import(__DIR__ . '/symfony42/symfony42-forms.php'); + $rectorConfig->import(__DIR__ . '/symfony42/symfony42-cache.php'); }; diff --git a/config/sets/symfony/symfony4/symfony42/symfony42-cache.php b/config/sets/symfony/symfony4/symfony42/symfony42-cache.php new file mode 100644 index 00000000..e8fd3ea2 --- /dev/null +++ b/config/sets/symfony/symfony4/symfony42/symfony42-cache.php @@ -0,0 +1,13 @@ +ruleWithConfiguration(RenameMethodRector::class, [ + new MethodCallRename('Symfony\Component\Cache\CacheItem', 'getPreviousTags', 'getMetadata'), + ]); +}; diff --git a/config/sets/symfony/symfony4/symfony42/symfony42-config.php b/config/sets/symfony/symfony4/symfony42/symfony42-config.php new file mode 100644 index 00000000..349c4168 --- /dev/null +++ b/config/sets/symfony/symfony4/symfony42/symfony42-config.php @@ -0,0 +1,13 @@ +rules([ + // https://symfony.com/blog/new-in-symfony-4-2-important-deprecations + RootNodeTreeBuilderRector::class, + ]); +}; diff --git a/config/sets/symfony/symfony4/symfony42/symfony42-dom-crawler.php b/config/sets/symfony/symfony4/symfony42/symfony42-dom-crawler.php new file mode 100644 index 00000000..f6196ca2 --- /dev/null +++ b/config/sets/symfony/symfony4/symfony42/symfony42-dom-crawler.php @@ -0,0 +1,22 @@ +ruleWithConfiguration(ArgumentAdderRector::class, [ + new ArgumentAdder( + 'Symfony\Component\DomCrawler\Crawler', + 'children', + 0, + null, + null, + null, + ArgumentAddingScope::SCOPE_METHOD_CALL + ), + ]); +}; diff --git a/config/sets/symfony/symfony4/symfony42/symfony42-finder.php b/config/sets/symfony/symfony4/symfony42/symfony42-finder.php new file mode 100644 index 00000000..d813abd7 --- /dev/null +++ b/config/sets/symfony/symfony4/symfony42/symfony42-finder.php @@ -0,0 +1,21 @@ +ruleWithConfiguration(ArgumentAdderRector::class, [ + new ArgumentAdder( + 'Symfony\Component\Finder\Finder', + 'sortByName', + 0, + null, + false, + null, + \Rector\Arguments\NodeAnalyzer\ArgumentAddingScope::SCOPE_METHOD_CALL + ), + ]); +}; diff --git a/config/sets/symfony/symfony4/symfony42/symfony42-forms.php b/config/sets/symfony/symfony4/symfony42/symfony42-forms.php new file mode 100644 index 00000000..9c7f4527 --- /dev/null +++ b/config/sets/symfony/symfony4/symfony42/symfony42-forms.php @@ -0,0 +1,48 @@ +ruleWithConfiguration(RenameMethodRector::class, [ + new MethodCallRename('Symfony\Component\Form\AbstractTypeExtension', 'getExtendedType', 'getExtendedTypes'), + ]); + + $iterableType = new \PHPStan\Type\IterableType(new MixedType(), new MixedType()); + + $rectorConfig->ruleWithConfiguration( + \Rector\TypeDeclaration\Rector\ClassMethod\AddReturnTypeDeclarationRector::class, + [ + new \Rector\TypeDeclaration\ValueObject\AddReturnTypeDeclaration( + 'Symfony\Component\Form\AbstractTypeExtension', + 'getExtendedTypes', + $iterableType + ), + ] + ); + + $rectorConfig->ruleWithConfiguration( + \Rector\Visibility\Rector\ClassMethod\ChangeMethodVisibilityRector::class, + [new \Rector\Visibility\ValueObject\ChangeMethodVisibility( + 'Symfony\Component\Form\AbstractTypeExtension', + 'getExtendedTypes', + \Rector\ValueObject\Visibility::STATIC + ), + ] + ); + + $rectorConfig->ruleWithConfiguration( + \Rector\Transform\Rector\ClassMethod\WrapReturnRector::class, + [ + new \Rector\Transform\ValueObject\WrapReturn( + 'Symfony\Component\Form\AbstractTypeExtension', + 'getExtendedTypes', + true + ), + ] + ); +}; diff --git a/config/sets/symfony/symfony4/symfony42/symfony42-framework-bundle.php b/config/sets/symfony/symfony4/symfony42/symfony42-framework-bundle.php new file mode 100644 index 00000000..da1e0ad1 --- /dev/null +++ b/config/sets/symfony/symfony4/symfony42/symfony42-framework-bundle.php @@ -0,0 +1,14 @@ +ruleWithConfiguration(RenameClassRector::class, [ + # https://github.com/symfony/symfony/commit/a7e319d9e1316e2e18843f8ce15b67a8693e5bf9 + 'Symfony\Bundle\FrameworkBundle\Controller\Controller' => 'Symfony\Bundle\FrameworkBundle\Controller\AbstractController', + # https://github.com/symfony/symfony/commit/744bf0e7ac3ecf240d0bf055cc58f881bb0b3ec0 + ]); +}; diff --git a/config/sets/symfony/symfony4/symfony42/symfony42-http-foundation.php b/config/sets/symfony/symfony4/symfony42/symfony42-http-foundation.php new file mode 100644 index 00000000..cf74f67b --- /dev/null +++ b/config/sets/symfony/symfony4/symfony42/symfony42-http-foundation.php @@ -0,0 +1,38 @@ +ruleWithConfiguration(NewToStaticCallRector::class, [ + new NewToStaticCall( + 'Symfony\Component\HttpFoundation\Cookie', + 'Symfony\Component\HttpFoundation\Cookie', + 'create' + ), + ]); + + // https://github.com/symfony/symfony/commit/9493cfd5f2366dab19bbdde0d0291d0575454567 + $rectorConfig->ruleWithConfiguration(ReplaceArgumentDefaultValueRector::class, [ + new ReplaceArgumentDefaultValue( + 'Symfony\Component\HttpFoundation\Cookie', + MethodName::CONSTRUCT, + 5, + false, + null + ), + new ReplaceArgumentDefaultValue( + 'Symfony\Component\HttpFoundation\Cookie', + MethodName::CONSTRUCT, + 8, + null, + 'lax' + ), + ]); +}; diff --git a/config/sets/symfony/symfony4/symfony42/symfony42-http-kernel.php b/config/sets/symfony/symfony4/symfony42/symfony42-http-kernel.php new file mode 100644 index 00000000..42643b8b --- /dev/null +++ b/config/sets/symfony/symfony4/symfony42/symfony42-http-kernel.php @@ -0,0 +1,27 @@ +ruleWithConfiguration(ArgumentRemoverRector::class, [ + new ArgumentRemover( + 'Symfony\Component\HttpKernel\DataCollector\ConfigDataCollector', + MethodName::CONSTRUCT, + 0, + null + ), + new ArgumentRemover( + 'Symfony\Component\HttpKernel\DataCollector\ConfigDataCollector', + MethodName::CONSTRUCT, + 1, + null + ), + ]); +}; diff --git a/config/sets/symfony/symfony4/symfony42/symfony42-monolog-bridge.php b/config/sets/symfony/symfony4/symfony42/symfony42-monolog-bridge.php new file mode 100644 index 00000000..3cd972ef --- /dev/null +++ b/config/sets/symfony/symfony4/symfony42/symfony42-monolog-bridge.php @@ -0,0 +1,49 @@ +ruleWithConfiguration(ArgumentAdderRector::class, [ + new ArgumentAdder( + 'Symfony\Bridge\Monolog\Processor\DebugProcessor', + 'getLogs', + 0, + null, + null, + null, + ArgumentAddingScope::SCOPE_METHOD_CALL + ), + new ArgumentAdder( + 'Symfony\Bridge\Monolog\Processor\DebugProcessor', + 'countErrors', + 0, + 'default_value', + null, + null, + ArgumentAddingScope::SCOPE_METHOD_CALL + ), + new ArgumentAdder( + 'Symfony\Bridge\Monolog\Logger', + 'getLogs', + 0, + 'default_value', + null, + null, + ArgumentAddingScope::SCOPE_METHOD_CALL + ), + new ArgumentAdder( + 'Symfony\Bridge\Monolog\Logger', + 'countErrors', + 0, + 'default_value', + null, + null, + ArgumentAddingScope::SCOPE_METHOD_CALL + ), + ]); +}; diff --git a/config/sets/symfony/symfony4/symfony42/symfony42-process.php b/config/sets/symfony/symfony4/symfony42/symfony42-process.php new file mode 100644 index 00000000..4abe48e0 --- /dev/null +++ b/config/sets/symfony/symfony4/symfony42/symfony42-process.php @@ -0,0 +1,13 @@ +rules([ + // https://symfony.com/blog/new-in-symfony-4-2-important-deprecations + StringToArrayArgumentProcessRector::class, + ]); +}; diff --git a/config/sets/symfony/symfony4/symfony42/symfony42-serializer.php b/config/sets/symfony/symfony4/symfony42/symfony42-serializer.php new file mode 100644 index 00000000..5627f0b3 --- /dev/null +++ b/config/sets/symfony/symfony4/symfony42/symfony42-serializer.php @@ -0,0 +1,31 @@ +ruleWithConfiguration(ArgumentAdderRector::class, [ + new ArgumentAdder( + 'Symfony\Component\Serializer\Normalizer', + 'handleCircularReference', + 1, + null, + null, + null, + ArgumentAddingScope::SCOPE_METHOD_CALL + ), + new ArgumentAdder( + 'Symfony\Component\Serializer\Normalizer', + 'handleCircularReference', + 2, + null, + null, + null, + ArgumentAddingScope::SCOPE_METHOD_CALL + ), + ]); +}; diff --git a/config/sets/symfony/symfony4/symfony42/symfony42-translation.php b/config/sets/symfony/symfony4/symfony42/symfony42-translation.php new file mode 100644 index 00000000..331446f5 --- /dev/null +++ b/config/sets/symfony/symfony4/symfony42/symfony42-translation.php @@ -0,0 +1,12 @@ +ruleWithConfiguration(RenameClassRector::class, [ + 'Symfony\Component\Translation\TranslatorInterface' => 'Symfony\Contracts\Translation\TranslatorInterface', + ]); +}; diff --git a/src/Set/SetProvider/SymfonySetProvider.php b/src/Set/SetProvider/SymfonySetProvider.php index db07ae4b..b79a1b23 100644 --- a/src/Set/SetProvider/SymfonySetProvider.php +++ b/src/Set/SetProvider/SymfonySetProvider.php @@ -239,14 +239,106 @@ public function provide(): array __DIR__ . '/../../../config/sets/symfony/symfony4/symfony41/symfony41-workflow.php' ), - // @todo split rest - new ComposerTriggeredSet( SetGroup::SYMFONY, - 'symfony/*', + 'symfony/symfony', '4.2', __DIR__ . '/../../../config/sets/symfony/symfony4/symfony42.php' ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/framework-bundle', + '4.2', + __DIR__ . '/../../../config/sets/symfony/symfony4/symfony42/symfony42-framework-bundle.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/http-foundation', + '4.2', + __DIR__ . '/../../../config/sets/symfony/symfony4/symfony42/symfony42-http-foundation.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/http-kernel', + '4.2', + __DIR__ . '/../../../config/sets/symfony/symfony4/symfony42/symfony42-http-kernel.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/monolog-bridge', + '4.2', + __DIR__ . '/../../../config/sets/symfony/symfony4/symfony42/symfony42-monolog-bridge.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/cache', + '4.2', + __DIR__ . '/../../../config/sets/symfony/symfony4/symfony42/symfony42-cache.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/config', + '4.2', + __DIR__ . '/../../../config/sets/symfony/symfony4/symfony42/symfony42-config.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/dom-crawler', + '4.2', + __DIR__ . '/../../../config/sets/symfony/symfony4/symfony42/symfony42-dom-crawler.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/forms', + '4.2', + __DIR__ . '/../../../config/sets/symfony/symfony4/symfony42/symfony42-forms.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/finder', + '4.2', + __DIR__ . '/../../../config/sets/symfony/symfony4/symfony42/symfony42-finder.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/framework-bundle', + '4.2', + __DIR__ . '/../../../config/sets/symfony/symfony4/symfony42/symfony42-framework-bundle.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/process', + '4.2', + __DIR__ . '/../../../config/sets/symfony/symfony4/symfony42/symfony42-process.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/serializer', + '4.2', + __DIR__ . '/../../../config/sets/symfony/symfony4/symfony42/symfony42-serializer.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/translation', + '4.2', + __DIR__ . '/../../../config/sets/symfony/symfony4/symfony42/symfony42-translation.php' + ), + + // @todo split rest + new ComposerTriggeredSet( SetGroup::SYMFONY, 'symfony/*', From e1a00877bbd3ed0a4e24a1d2450ddfa4caee2032 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Sun, 4 May 2025 18:44:37 +0200 Subject: [PATCH 37/53] [symfony 4.3] split of symfony configs per package (#732) --- config/sets/symfony/symfony4/symfony43.php | 99 +++---------------- .../symfony43/symfony43-browser-kit.php | 18 ++++ .../symfony4/symfony43/symfony43-cache.php | 26 +++++ .../symfony43/symfony43-event-dispatcher.php | 13 +++ .../symfony43/symfony43-framework-bundle.php | 24 +++++ .../symfony43/symfony43-http-foundation.php | 17 ++++ .../symfony43/symfony43-http-kernel.php | 22 +++++ .../symfony4/symfony43/symfony43-intl.php | 10 ++ .../symfony43/symfony43-security-core.php | 14 +++ .../symfony43/symfony43-security-http.php | 13 +++ .../symfony43/symfony43-twig-bundle.php | 11 +++ .../symfony4/symfony43/symfony43-workflow.php | 20 ++++ .../TemplateAnnotationToThisRenderRector.php | 2 +- ...plateShortNotationToBundleSyntaxRector.php | 4 +- src/Enum/SymfonyClass.php | 5 + src/Set/SetProvider/SymfonySetProvider.php | 89 ++++++++++++++++- src/TypeAnalyzer/ContainerAwareAnalyzer.php | 5 +- src/TypeAnalyzer/ControllerAnalyzer.php | 5 +- 18 files changed, 301 insertions(+), 96 deletions(-) create mode 100644 config/sets/symfony/symfony4/symfony43/symfony43-browser-kit.php create mode 100644 config/sets/symfony/symfony4/symfony43/symfony43-cache.php create mode 100644 config/sets/symfony/symfony4/symfony43/symfony43-event-dispatcher.php create mode 100644 config/sets/symfony/symfony4/symfony43/symfony43-framework-bundle.php create mode 100644 config/sets/symfony/symfony4/symfony43/symfony43-http-foundation.php create mode 100644 config/sets/symfony/symfony4/symfony43/symfony43-http-kernel.php create mode 100644 config/sets/symfony/symfony4/symfony43/symfony43-intl.php create mode 100644 config/sets/symfony/symfony4/symfony43/symfony43-security-core.php create mode 100644 config/sets/symfony/symfony4/symfony43/symfony43-security-http.php create mode 100644 config/sets/symfony/symfony4/symfony43/symfony43-twig-bundle.php create mode 100644 config/sets/symfony/symfony4/symfony43/symfony43-workflow.php diff --git a/config/sets/symfony/symfony4/symfony43.php b/config/sets/symfony/symfony4/symfony43.php index e71f91fe..b977b86a 100644 --- a/config/sets/symfony/symfony4/symfony43.php +++ b/config/sets/symfony/symfony4/symfony43.php @@ -2,96 +2,19 @@ declare(strict_types=1); -use Rector\Arguments\Rector\ClassMethod\ArgumentAdderRector; -use Rector\Arguments\ValueObject\ArgumentAdder; use Rector\Config\RectorConfig; -use Rector\Renaming\Rector\MethodCall\RenameMethodRector; -use Rector\Renaming\Rector\Name\RenameClassRector; -use Rector\Renaming\ValueObject\MethodCallRename; -use Rector\Symfony\Symfony43\Rector\ClassMethod\EventDispatcherParentConstructRector; -use Rector\Symfony\Symfony43\Rector\MethodCall\ConvertRenderTemplateShortNotationToBundleSyntaxRector; -use Rector\Symfony\Symfony43\Rector\MethodCall\GetCurrencyBundleMethodCallsToIntlRector; -use Rector\Symfony\Symfony43\Rector\MethodCall\MakeDispatchFirstArgumentEventRector; -use Rector\Symfony\Symfony43\Rector\MethodCall\WebTestCaseAssertIsSuccessfulRector; -use Rector\Symfony\Symfony43\Rector\MethodCall\WebTestCaseAssertResponseCodeRector; -use Rector\Symfony\Symfony43\Rector\StmtsAwareInterface\TwigBundleFilesystemLoaderToTwigRector; # https://github.com/symfony/symfony/blob/4.4/UPGRADE-4.3.md return static function (RectorConfig $rectorConfig): void { - # https://symfony.com/blog/new-in-symfony-4-3-better-test-assertions - $rectorConfig->rules([ - WebTestCaseAssertIsSuccessfulRector::class, - WebTestCaseAssertResponseCodeRector::class, - TwigBundleFilesystemLoaderToTwigRector::class, - MakeDispatchFirstArgumentEventRector::class, - GetCurrencyBundleMethodCallsToIntlRector::class, - ConvertRenderTemplateShortNotationToBundleSyntaxRector::class, - EventDispatcherParentConstructRector::class, - ]); - - $rectorConfig->ruleWithConfiguration(RenameMethodRector::class, [ - new MethodCallRename('Symfony\Component\BrowserKit\Response', 'getStatus', 'getStatusCode'), - new MethodCallRename('Symfony\Component\Security\Http\Firewall', 'handleRequest', 'callListeners'), - ]); - - $rectorConfig->ruleWithConfiguration(RenameClassRector::class, [ - // assets deprecation - 'Symfony\Bundle\FrameworkBundle\Templating\Helper\AssetsHelper' => 'Symfony\Component\Asset\Packages', - - // templating - 'Symfony\Bundle\FrameworkBundle\Templating\EngineInterface' => 'Symfony\Component\Templating\EngineInterface', - - # https://symfony.com/blog/new-in-symfony-4-3-simpler-event-dispatching - # Browser Kit - 'Symfony\Component\BrowserKit\Client' => 'Symfony\Component\BrowserKit\AbstractBrowser', - # Cache - # https://github.com/symfony/symfony/pull/29236 - 'Symfony\Component\Cache\Traits\ApcuTrait\ApcuCache' => 'Symfony\Component\Cache\Traits\ApcuTrait\ApcuAdapter', - 'Symfony\Component\Cache\Adapter\SimpleCacheAdapter' => 'Symfony\Component\Cache\Adapter\Psr16Adapter', - 'Symfony\Component\Cache\Simple\ArrayCache' => 'Symfony\Component\Cache\Adapter\ArrayAdapter', - 'Symfony\Component\Cache\Simple\ChainCache' => 'Symfony\Component\Cache\Adapter\ChainAdapter', - 'Symfony\Component\Cache\Simple\DoctrineCache' => 'Symfony\Component\Cache\Adapter\DoctrineAdapter', - 'Symfony\Component\Cache\Simple\FilesystemCache' => 'Symfony\Component\Cache\Adapter\FilesystemAdapter', - 'Symfony\Component\Cache\Simple\MemcachedCache' => 'Symfony\Component\Cache\Adapter\MemcachedAdapter', - 'Symfony\Component\Cache\Simple\NullCache' => 'Symfony\Component\Cache\Adapter\NullAdapter', - 'Symfony\Component\Cache\Simple\PdoCache' => 'Symfony\Component\Cache\Adapter\PdoAdapter', - 'Symfony\Component\Cache\Simple\PhpArrayCache' => 'Symfony\Component\Cache\Adapter\PhpArrayAdapter', - 'Symfony\Component\Cache\Simple\PhpFilesCache' => 'Symfony\Component\Cache\Adapter\PhpFilesAdapter', - 'Symfony\Component\Cache\Simple\RedisCache' => 'Symfony\Component\Cache\Adapter\RedisAdapter', - 'Symfony\Component\Cache\Simple\TraceableCache' => 'Symfony\Component\Cache\Adapter\TraceableAdapterCache', - 'Symfony\Component\Cache\Simple\Psr6Cache' => 'Symfony\Component\Cache\Psr16Cache', - # EventDispatcher - 'Symfony\Component\HttpKernel\Event\FilterControllerArgumentsEvent' => 'Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent', - 'Symfony\Component\HttpKernel\Event\FilterControllerEvent' => 'Symfony\Component\HttpKernel\Event\ControllerEvent', - 'Symfony\Component\HttpKernel\Event\FilterResponseEvent' => 'Symfony\Component\HttpKernel\Event\ResponseEvent', - 'Symfony\Component\HttpKernel\Event\GetResponseEvent' => 'Symfony\Component\HttpKernel\Event\RequestEvent', - 'Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent' => 'Symfony\Component\HttpKernel\Event\ViewEvent', - 'Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent' => 'Symfony\Component\HttpKernel\Event\ExceptionEvent', - 'Symfony\Component\HttpKernel\Event\PostResponseEvent' => 'Symfony\Component\HttpKernel\Event\TerminateEvent', - # has lowest priority, have to be last - 'Symfony\Component\EventDispatcher\Event' => 'Symfony\Contracts\EventDispatcher\Event', - # MimeType - 'Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesserInterface' => 'Symfony\Component\Mime\MimeTypesInterface', - 'Symfony\Component\HttpFoundation\File\MimeType\ExtensionGuesserInterface' => 'Symfony\Component\Mime\MimeTypesInterface', - 'Symfony\Component\HttpFoundation\File\MimeType\MimeTypeExtensionGuesser' => 'Symfony\Component\Mime\MimeTypes', - 'Symfony\Component\HttpFoundation\File\MimeType\FileBinaryMimeTypeGuesser' => 'Symfony\Component\Mime\FileBinaryMimeTypeGuesser', - 'Symfony\Component\HttpFoundation\File\MimeType\FileinfoMimeTypeGuesser' => 'Symfony\Component\Mime\FileinfoMimeTypeGuesser', - # HttpKernel - # @todo unpack after YAML to PHP migration, Symfony\Component\HttpKernel\Client: Symfony\Component\HttpKernel\HttpKernelBrowser - 'Symfony\Component\HttpKernel\EventListener\TranslatorListener' => 'Symfony\Component\HttpKernel\EventListener\LocaleAwareListener', - # Security - 'Symfony\Component\Security\Core\Encoder\Argon2iPasswordEncoder' => 'Symfony\Component\Security\Core\Encoder\SodiumPasswordEncoder', - 'Symfony\Component\Security\Core\Encoder\BCryptPasswordEncoder' => 'Symfony\Component\Security\Core\Encoder\NativePasswordEncoder', - ]); - - # https://github.com/symfony/symfony/blob/4.4/UPGRADE-4.3.md#workflow - $rectorConfig->ruleWithConfiguration(ArgumentAdderRector::class, [ - new ArgumentAdder( - 'Symfony\Component\Workflow\MarkingStore\MarkingStoreInterface', - 'setMarking', - 2, - 'context', - [] - ), - ]); + $rectorConfig->import(__DIR__ . '/symfony43/symfony43-browser-kit.php'); + $rectorConfig->import(__DIR__ . '/symfony43/symfony43-cache.php'); + $rectorConfig->import(__DIR__ . '/symfony43/symfony43-event-dispatcher.php'); + $rectorConfig->import(__DIR__ . '/symfony43/symfony43-framework-bundle.php'); + $rectorConfig->import(__DIR__ . '/symfony43/symfony43-http-foundation.php'); + $rectorConfig->import(__DIR__ . '/symfony43/symfony43-http-kernel.php'); + $rectorConfig->import(__DIR__ . '/symfony43/symfony43-intl.php'); + $rectorConfig->import(__DIR__ . '/symfony43/symfony43-security-core.php'); + $rectorConfig->import(__DIR__ . '/symfony43/symfony43-security-http.php'); + $rectorConfig->import(__DIR__ . '/symfony43/symfony43-twig-bundle.php'); + $rectorConfig->import(__DIR__ . '/symfony43/symfony43-workflow.php'); }; diff --git a/config/sets/symfony/symfony4/symfony43/symfony43-browser-kit.php b/config/sets/symfony/symfony4/symfony43/symfony43-browser-kit.php new file mode 100644 index 00000000..0fac5a6f --- /dev/null +++ b/config/sets/symfony/symfony4/symfony43/symfony43-browser-kit.php @@ -0,0 +1,18 @@ +ruleWithConfiguration(RenameMethodRector::class, [ + new MethodCallRename('Symfony\Component\BrowserKit\Response', 'getStatus', 'getStatusCode'), + ]); + + $rectorConfig->ruleWithConfiguration(RenameClassRector::class, [ + 'Symfony\Component\BrowserKit\Client' => 'Symfony\Component\BrowserKit\AbstractBrowser', + ]); +}; diff --git a/config/sets/symfony/symfony4/symfony43/symfony43-cache.php b/config/sets/symfony/symfony4/symfony43/symfony43-cache.php new file mode 100644 index 00000000..5dfb98a6 --- /dev/null +++ b/config/sets/symfony/symfony4/symfony43/symfony43-cache.php @@ -0,0 +1,26 @@ +ruleWithConfiguration(RenameClassRector::class, [ + # https://github.com/symfony/symfony/pull/29236 + 'Symfony\Component\Cache\Traits\ApcuTrait\ApcuCache' => 'Symfony\Component\Cache\Traits\ApcuTrait\ApcuAdapter', + 'Symfony\Component\Cache\Adapter\SimpleCacheAdapter' => 'Symfony\Component\Cache\Adapter\Psr16Adapter', + 'Symfony\Component\Cache\Simple\ArrayCache' => 'Symfony\Component\Cache\Adapter\ArrayAdapter', + 'Symfony\Component\Cache\Simple\ChainCache' => 'Symfony\Component\Cache\Adapter\ChainAdapter', + 'Symfony\Component\Cache\Simple\DoctrineCache' => 'Symfony\Component\Cache\Adapter\DoctrineAdapter', + 'Symfony\Component\Cache\Simple\FilesystemCache' => 'Symfony\Component\Cache\Adapter\FilesystemAdapter', + 'Symfony\Component\Cache\Simple\MemcachedCache' => 'Symfony\Component\Cache\Adapter\MemcachedAdapter', + 'Symfony\Component\Cache\Simple\NullCache' => 'Symfony\Component\Cache\Adapter\NullAdapter', + 'Symfony\Component\Cache\Simple\PdoCache' => 'Symfony\Component\Cache\Adapter\PdoAdapter', + 'Symfony\Component\Cache\Simple\PhpArrayCache' => 'Symfony\Component\Cache\Adapter\PhpArrayAdapter', + 'Symfony\Component\Cache\Simple\PhpFilesCache' => 'Symfony\Component\Cache\Adapter\PhpFilesAdapter', + 'Symfony\Component\Cache\Simple\RedisCache' => 'Symfony\Component\Cache\Adapter\RedisAdapter', + 'Symfony\Component\Cache\Simple\TraceableCache' => 'Symfony\Component\Cache\Adapter\TraceableAdapterCache', + 'Symfony\Component\Cache\Simple\Psr6Cache' => 'Symfony\Component\Cache\Psr16Cache', + ]); +}; diff --git a/config/sets/symfony/symfony4/symfony43/symfony43-event-dispatcher.php b/config/sets/symfony/symfony4/symfony43/symfony43-event-dispatcher.php new file mode 100644 index 00000000..a23ef4e6 --- /dev/null +++ b/config/sets/symfony/symfony4/symfony43/symfony43-event-dispatcher.php @@ -0,0 +1,13 @@ +ruleWithConfiguration(RenameClassRector::class, [ + // has lowest priority, have to be last + 'Symfony\Component\EventDispatcher\Event' => 'Symfony\Contracts\EventDispatcher\Event', + ]); +}; diff --git a/config/sets/symfony/symfony4/symfony43/symfony43-framework-bundle.php b/config/sets/symfony/symfony4/symfony43/symfony43-framework-bundle.php new file mode 100644 index 00000000..82844996 --- /dev/null +++ b/config/sets/symfony/symfony4/symfony43/symfony43-framework-bundle.php @@ -0,0 +1,24 @@ +ruleWithConfiguration(RenameClassRector::class, [ + // assets deprecation + 'Symfony\Bundle\FrameworkBundle\Templating\Helper\AssetsHelper' => 'Symfony\Component\Asset\Packages', + + // templating + 'Symfony\Bundle\FrameworkBundle\Templating\EngineInterface' => 'Symfony\Component\Templating\EngineInterface', + ]); + + $rectorConfig->rules([ + \Rector\Symfony\Symfony43\Rector\MethodCall\ConvertRenderTemplateShortNotationToBundleSyntaxRector::class, + # https://symfony.com/blog/new-in-symfony-4-3-better-test-assertions + // + \Rector\Symfony\Symfony43\Rector\MethodCall\WebTestCaseAssertIsSuccessfulRector::class, + \Rector\Symfony\Symfony43\Rector\MethodCall\WebTestCaseAssertResponseCodeRector::class, + ]); +}; diff --git a/config/sets/symfony/symfony4/symfony43/symfony43-http-foundation.php b/config/sets/symfony/symfony4/symfony43/symfony43-http-foundation.php new file mode 100644 index 00000000..7f5f9b7d --- /dev/null +++ b/config/sets/symfony/symfony4/symfony43/symfony43-http-foundation.php @@ -0,0 +1,17 @@ +ruleWithConfiguration(RenameClassRector::class, [ + // MimeType + 'Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesserInterface' => 'Symfony\Component\Mime\MimeTypesInterface', + 'Symfony\Component\HttpFoundation\File\MimeType\ExtensionGuesserInterface' => 'Symfony\Component\Mime\MimeTypesInterface', + 'Symfony\Component\HttpFoundation\File\MimeType\MimeTypeExtensionGuesser' => 'Symfony\Component\Mime\MimeTypes', + 'Symfony\Component\HttpFoundation\File\MimeType\FileBinaryMimeTypeGuesser' => 'Symfony\Component\Mime\FileBinaryMimeTypeGuesser', + 'Symfony\Component\HttpFoundation\File\MimeType\FileinfoMimeTypeGuesser' => 'Symfony\Component\Mime\FileinfoMimeTypeGuesser', + ]); +}; diff --git a/config/sets/symfony/symfony4/symfony43/symfony43-http-kernel.php b/config/sets/symfony/symfony4/symfony43/symfony43-http-kernel.php new file mode 100644 index 00000000..bdd0d7d6 --- /dev/null +++ b/config/sets/symfony/symfony4/symfony43/symfony43-http-kernel.php @@ -0,0 +1,22 @@ +ruleWithConfiguration(RenameClassRector::class, [ + // EventDispatcher + 'Symfony\Component\HttpKernel\Event\FilterControllerArgumentsEvent' => 'Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent', + 'Symfony\Component\HttpKernel\Event\FilterControllerEvent' => 'Symfony\Component\HttpKernel\Event\ControllerEvent', + 'Symfony\Component\HttpKernel\Event\FilterResponseEvent' => 'Symfony\Component\HttpKernel\Event\ResponseEvent', + 'Symfony\Component\HttpKernel\Event\GetResponseEvent' => 'Symfony\Component\HttpKernel\Event\RequestEvent', + 'Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent' => 'Symfony\Component\HttpKernel\Event\ViewEvent', + 'Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent' => 'Symfony\Component\HttpKernel\Event\ExceptionEvent', + 'Symfony\Component\HttpKernel\Event\PostResponseEvent' => 'Symfony\Component\HttpKernel\Event\TerminateEvent', + + // @todo unpack after YAML to PHP migration, Symfony\Component\HttpKernel\Client: Symfony\Component\HttpKernel\HttpKernelBrowser + 'Symfony\Component\HttpKernel\EventListener\TranslatorListener' => 'Symfony\Component\HttpKernel\EventListener\LocaleAwareListener', + ]); +}; diff --git a/config/sets/symfony/symfony4/symfony43/symfony43-intl.php b/config/sets/symfony/symfony4/symfony43/symfony43-intl.php new file mode 100644 index 00000000..e9382013 --- /dev/null +++ b/config/sets/symfony/symfony4/symfony43/symfony43-intl.php @@ -0,0 +1,10 @@ +rules([GetCurrencyBundleMethodCallsToIntlRector::class]); +}; diff --git a/config/sets/symfony/symfony4/symfony43/symfony43-security-core.php b/config/sets/symfony/symfony4/symfony43/symfony43-security-core.php new file mode 100644 index 00000000..29e8c128 --- /dev/null +++ b/config/sets/symfony/symfony4/symfony43/symfony43-security-core.php @@ -0,0 +1,14 @@ +ruleWithConfiguration(RenameClassRector::class, [ + # Security + 'Symfony\Component\Security\Core\Encoder\Argon2iPasswordEncoder' => 'Symfony\Component\Security\Core\Encoder\SodiumPasswordEncoder', + 'Symfony\Component\Security\Core\Encoder\BCryptPasswordEncoder' => 'Symfony\Component\Security\Core\Encoder\NativePasswordEncoder', + ]); +}; diff --git a/config/sets/symfony/symfony4/symfony43/symfony43-security-http.php b/config/sets/symfony/symfony4/symfony43/symfony43-security-http.php new file mode 100644 index 00000000..fbd04252 --- /dev/null +++ b/config/sets/symfony/symfony4/symfony43/symfony43-security-http.php @@ -0,0 +1,13 @@ +ruleWithConfiguration(RenameMethodRector::class, [ + new MethodCallRename('Symfony\Component\Security\Http\Firewall', 'handleRequest', 'callListeners'), + ]); +}; diff --git a/config/sets/symfony/symfony4/symfony43/symfony43-twig-bundle.php b/config/sets/symfony/symfony4/symfony43/symfony43-twig-bundle.php new file mode 100644 index 00000000..1b8399a5 --- /dev/null +++ b/config/sets/symfony/symfony4/symfony43/symfony43-twig-bundle.php @@ -0,0 +1,11 @@ +rules([ + \Rector\Symfony\Symfony43\Rector\StmtsAwareInterface\TwigBundleFilesystemLoaderToTwigRector::class, + ]); +}; diff --git a/config/sets/symfony/symfony4/symfony43/symfony43-workflow.php b/config/sets/symfony/symfony4/symfony43/symfony43-workflow.php new file mode 100644 index 00000000..709cd652 --- /dev/null +++ b/config/sets/symfony/symfony4/symfony43/symfony43-workflow.php @@ -0,0 +1,20 @@ +ruleWithConfiguration(ArgumentAdderRector::class, [ + new ArgumentAdder( + 'Symfony\Component\Workflow\MarkingStore\MarkingStoreInterface', + 'setMarking', + 2, + 'context', + [] + ), + ]); +}; diff --git a/rules/CodeQuality/Rector/ClassMethod/TemplateAnnotationToThisRenderRector.php b/rules/CodeQuality/Rector/ClassMethod/TemplateAnnotationToThisRenderRector.php index bffc75da..64905ed9 100644 --- a/rules/CodeQuality/Rector/ClassMethod/TemplateAnnotationToThisRenderRector.php +++ b/rules/CodeQuality/Rector/ClassMethod/TemplateAnnotationToThisRenderRector.php @@ -152,7 +152,7 @@ private function decorateAbstractControllerParentClass(Class_ $class): void } // this will make $this->render() method available - $class->extends = new FullyQualified('Symfony\Bundle\FrameworkBundle\Controller\AbstractController'); + $class->extends = new FullyQualified(SymfonyClass::ABSTRACT_CONTROLLER); } private function replaceTemplateAnnotation( diff --git a/rules/Symfony43/Rector/MethodCall/ConvertRenderTemplateShortNotationToBundleSyntaxRector.php b/rules/Symfony43/Rector/MethodCall/ConvertRenderTemplateShortNotationToBundleSyntaxRector.php index 21086ab0..cf74da80 100644 --- a/rules/Symfony43/Rector/MethodCall/ConvertRenderTemplateShortNotationToBundleSyntaxRector.php +++ b/rules/Symfony43/Rector/MethodCall/ConvertRenderTemplateShortNotationToBundleSyntaxRector.php @@ -13,12 +13,14 @@ use PHPStan\Type\ThisType; use Rector\PhpParser\Node\Value\ValueResolver; use Rector\Rector\AbstractRector; +use Rector\Symfony\Enum\SymfonyClass; use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; /** * @changelog https://github.com/symfony/symfony/pull/21035 * @changelog https://github.com/symfony/symfony/blob/4.4/src/Symfony/Bundle/FrameworkBundle/Templating/TemplateNameParser.php + * * @changelog https://symfony.com/doc/4.4/templates.html#bundle-templates * * @see \Rector\Symfony\Tests\Symfony43\Rector\MethodCall\ConvertRenderTemplateShortNotationToBundleSyntaxRector\ConvertRenderTemplateShortNotationToBundleSyntaxRectorTest @@ -83,7 +85,7 @@ public function refactor(Node $node): ?Node } $objectType = $this->nodeTypeResolver->getType($node->var); - $controllerType = new ObjectType('Symfony\Bundle\FrameworkBundle\Controller\Controller'); + $controllerType = new ObjectType(SymfonyClass::CONTROLLER); if (! $controllerType->isSuperTypeOf($objectType)->yes()) { return null; } diff --git a/src/Enum/SymfonyClass.php b/src/Enum/SymfonyClass.php index 9d705f94..5492c9d8 100644 --- a/src/Enum/SymfonyClass.php +++ b/src/Enum/SymfonyClass.php @@ -90,4 +90,9 @@ final class SymfonyClass * @var string */ public const REQUEST = 'Symfony\Component\HttpFoundation\Request'; + + /** + * @var string + */ + public const ABSTRACT_CONTROLLER = 'Symfony\Bundle\FrameworkBundle\Controller\AbstractController'; } diff --git a/src/Set/SetProvider/SymfonySetProvider.php b/src/Set/SetProvider/SymfonySetProvider.php index b79a1b23..3d8e3505 100644 --- a/src/Set/SetProvider/SymfonySetProvider.php +++ b/src/Set/SetProvider/SymfonySetProvider.php @@ -337,14 +337,99 @@ public function provide(): array __DIR__ . '/../../../config/sets/symfony/symfony4/symfony42/symfony42-translation.php' ), - // @todo split rest + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/workflow', + '4.3', + __DIR__ . '/../../../config/sets/symfony/symfony4/symfony43/symfony43-workflow.php' + ), new ComposerTriggeredSet( SetGroup::SYMFONY, - 'symfony/*', + 'symfony/browser-kit', + '4.3', + __DIR__ . '/../../../config/sets/symfony/symfony4/symfony43/symfony43-browser-kit.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/cache', + '4.3', + __DIR__ . '/../../../config/sets/symfony/symfony4/symfony43/symfony43-cache.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/event-dispatcher', + '4.3', + __DIR__ . '/../../../config/sets/symfony/symfony4/symfony43/symfony43-event-dispatcher.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/framework-bundle', + '4.3', + __DIR__ . '/../../../config/sets/symfony/symfony4/symfony43/symfony43-framework-bundle.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/http-foundation', + '4.3', + __DIR__ . '/../../../config/sets/symfony/symfony4/symfony43/symfony43-http-foundation.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/http-kernel', + '4.3', + __DIR__ . '/../../../config/sets/symfony/symfony4/symfony43/symfony43-http-kernel.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/intl', + '4.3', + __DIR__ . '/../../../config/sets/symfony/symfony4/symfony43/symfony43-intl.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/security-core', + '4.3', + __DIR__ . '/../../../config/sets/symfony/symfony4/symfony43/symfony43-security-core.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/security-http', + '4.3', + __DIR__ . '/../../../config/sets/symfony/symfony4/symfony43/symfony43-security-http.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/twig-bundle', + '4.3', + __DIR__ . '/../../../config/sets/symfony/symfony4/symfony43/symfony43-twig-bundle.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/workflow', + '4.3', + __DIR__ . '/../../../config/sets/symfony/symfony4/symfony43/symfony43-workflow.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/symfony', '4.3', __DIR__ . '/../../../config/sets/symfony/symfony4/symfony43.php' ), + + // ... + new ComposerTriggeredSet( SetGroup::SYMFONY, 'symfony/*', diff --git a/src/TypeAnalyzer/ContainerAwareAnalyzer.php b/src/TypeAnalyzer/ContainerAwareAnalyzer.php index 3d05e094..351bb4b0 100644 --- a/src/TypeAnalyzer/ContainerAwareAnalyzer.php +++ b/src/TypeAnalyzer/ContainerAwareAnalyzer.php @@ -7,6 +7,7 @@ use PhpParser\Node\Expr; use PHPStan\Type\ObjectType; use Rector\NodeTypeResolver\NodeTypeResolver; +use Rector\Symfony\Enum\SymfonyClass; final class ContainerAwareAnalyzer { @@ -19,8 +20,8 @@ public function __construct( private readonly NodeTypeResolver $nodeTypeResolver, ) { $this->getMethodAwareObjectTypes = [ - new ObjectType('Symfony\Bundle\FrameworkBundle\Controller\AbstractController'), - new ObjectType('Symfony\Bundle\FrameworkBundle\Controller\Controller'), + new ObjectType(SymfonyClass::ABSTRACT_CONTROLLER), + new ObjectType(SymfonyClass::CONTROLLER), new ObjectType('Symfony\Bundle\FrameworkBundle\Controller\ControllerTrait'), ]; } diff --git a/src/TypeAnalyzer/ControllerAnalyzer.php b/src/TypeAnalyzer/ControllerAnalyzer.php index e24ecde4..4081c83b 100644 --- a/src/TypeAnalyzer/ControllerAnalyzer.php +++ b/src/TypeAnalyzer/ControllerAnalyzer.php @@ -14,6 +14,7 @@ use PHPStan\Type\TypeWithClassName; use Rector\NodeTypeResolver\Node\AttributeKey; use Rector\Reflection\ReflectionResolver; +use Rector\Symfony\Enum\SymfonyClass; final readonly class ControllerAnalyzer { @@ -68,11 +69,11 @@ public function isInsideController(Node $node): bool private function isControllerClassReflection(ClassReflection $classReflection): bool { - if ($classReflection->is('Symfony\Bundle\FrameworkBundle\Controller\Controller')) { + if ($classReflection->is(SymfonyClass::CONTROLLER)) { return true; } - return $classReflection->is('Symfony\Bundle\FrameworkBundle\Controller\AbstractController'); + return $classReflection->is(SymfonyClass::ABSTRACT_CONTROLLER); } private function isControllerClass(Class_ $class): bool From 1734da9172d3ba3f1c96e51168173cab5ae95235 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Sun, 4 May 2025 18:45:37 +0200 Subject: [PATCH 38/53] enum --- src/Enum/SymfonyClass.php | 5 +++++ src/TypeAnalyzer/ContainerAwareAnalyzer.php | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Enum/SymfonyClass.php b/src/Enum/SymfonyClass.php index 5492c9d8..f3822834 100644 --- a/src/Enum/SymfonyClass.php +++ b/src/Enum/SymfonyClass.php @@ -95,4 +95,9 @@ final class SymfonyClass * @var string */ public const ABSTRACT_CONTROLLER = 'Symfony\Bundle\FrameworkBundle\Controller\AbstractController'; + + /** + * @var string + */ + public const CONTROLLER_TRAIT = 'Symfony\Bundle\FrameworkBundle\Controller\ControllerTrait'; } diff --git a/src/TypeAnalyzer/ContainerAwareAnalyzer.php b/src/TypeAnalyzer/ContainerAwareAnalyzer.php index 351bb4b0..17490134 100644 --- a/src/TypeAnalyzer/ContainerAwareAnalyzer.php +++ b/src/TypeAnalyzer/ContainerAwareAnalyzer.php @@ -22,7 +22,7 @@ public function __construct( $this->getMethodAwareObjectTypes = [ new ObjectType(SymfonyClass::ABSTRACT_CONTROLLER), new ObjectType(SymfonyClass::CONTROLLER), - new ObjectType('Symfony\Bundle\FrameworkBundle\Controller\ControllerTrait'), + new ObjectType(SymfonyClass::CONTROLLER_TRAIT), ]; } From 341c2e62bd3cc496147d6aff0475bb24247a423d Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Sun, 4 May 2025 18:59:46 +0200 Subject: [PATCH 39/53] [symfony 4.4] split of symfony configs per package (#733) * split SymfonySetProvider per versions * [symfony 4.4] Split of per package configs --- .../symfony4/symfony42/symfony42-finder.php | 3 +- .../symfony4/symfony42/symfony42-forms.php | 24 +- .../symfony43/symfony43-framework-bundle.php | 9 +- .../symfony43/symfony43-twig-bundle.php | 3 +- config/sets/symfony/symfony4/symfony44.php | 42 +- .../symfony4/symfony44/symfony44-console.php | 13 + .../symfony44-dependency-injection.php | 12 + .../symfony44/symfony44-http-kernel.php | 25 + .../symfony44/symfony44-security-core.php | 12 + .../symfony44/symfony44-templating.php | 12 + ...izationCheckerIsGrantedExtractorRector.php | 41 +- src/Enum/SymfonyClass.php | 5 + src/Set/SetProvider/Symfony3SetProvider.php | 145 +++++ src/Set/SetProvider/Symfony4SetProvider.php | 329 ++++++++++++ src/Set/SetProvider/Symfony5SetProvider.php | 52 ++ src/Set/SetProvider/Symfony6SetProvider.php | 52 ++ src/Set/SetProvider/Symfony7SetProvider.php | 40 ++ src/Set/SetProvider/SymfonySetProvider.php | 500 +----------------- 18 files changed, 767 insertions(+), 552 deletions(-) create mode 100644 config/sets/symfony/symfony4/symfony44/symfony44-console.php create mode 100644 config/sets/symfony/symfony4/symfony44/symfony44-dependency-injection.php create mode 100644 config/sets/symfony/symfony4/symfony44/symfony44-http-kernel.php create mode 100644 config/sets/symfony/symfony4/symfony44/symfony44-security-core.php create mode 100644 config/sets/symfony/symfony4/symfony44/symfony44-templating.php create mode 100644 src/Set/SetProvider/Symfony3SetProvider.php create mode 100644 src/Set/SetProvider/Symfony4SetProvider.php create mode 100644 src/Set/SetProvider/Symfony5SetProvider.php create mode 100644 src/Set/SetProvider/Symfony6SetProvider.php create mode 100644 src/Set/SetProvider/Symfony7SetProvider.php diff --git a/config/sets/symfony/symfony4/symfony42/symfony42-finder.php b/config/sets/symfony/symfony4/symfony42/symfony42-finder.php index d813abd7..ab3d39c0 100644 --- a/config/sets/symfony/symfony4/symfony42/symfony42-finder.php +++ b/config/sets/symfony/symfony4/symfony42/symfony42-finder.php @@ -2,6 +2,7 @@ declare(strict_types=1); +use Rector\Arguments\NodeAnalyzer\ArgumentAddingScope; use Rector\Arguments\Rector\ClassMethod\ArgumentAdderRector; use Rector\Arguments\ValueObject\ArgumentAdder; use Rector\Config\RectorConfig; @@ -15,7 +16,7 @@ null, false, null, - \Rector\Arguments\NodeAnalyzer\ArgumentAddingScope::SCOPE_METHOD_CALL + ArgumentAddingScope::SCOPE_METHOD_CALL ), ]); }; diff --git a/config/sets/symfony/symfony4/symfony42/symfony42-forms.php b/config/sets/symfony/symfony4/symfony42/symfony42-forms.php index 9c7f4527..dd4238c7 100644 --- a/config/sets/symfony/symfony4/symfony42/symfony42-forms.php +++ b/config/sets/symfony/symfony4/symfony42/symfony42-forms.php @@ -2,6 +2,14 @@ declare(strict_types=1); +use PHPStan\Type\IterableType; +use Rector\TypeDeclaration\Rector\ClassMethod\AddReturnTypeDeclarationRector; +use Rector\TypeDeclaration\ValueObject\AddReturnTypeDeclaration; +use Rector\Visibility\Rector\ClassMethod\ChangeMethodVisibilityRector; +use Rector\Visibility\ValueObject\ChangeMethodVisibility; +use Rector\ValueObject\Visibility; +use Rector\Transform\Rector\ClassMethod\WrapReturnRector; +use Rector\Transform\ValueObject\WrapReturn; use PHPStan\Type\MixedType; use Rector\Config\RectorConfig; use Rector\Renaming\Rector\MethodCall\RenameMethodRector; @@ -12,12 +20,12 @@ new MethodCallRename('Symfony\Component\Form\AbstractTypeExtension', 'getExtendedType', 'getExtendedTypes'), ]); - $iterableType = new \PHPStan\Type\IterableType(new MixedType(), new MixedType()); + $iterableType = new IterableType(new MixedType(), new MixedType()); $rectorConfig->ruleWithConfiguration( - \Rector\TypeDeclaration\Rector\ClassMethod\AddReturnTypeDeclarationRector::class, + AddReturnTypeDeclarationRector::class, [ - new \Rector\TypeDeclaration\ValueObject\AddReturnTypeDeclaration( + new AddReturnTypeDeclaration( 'Symfony\Component\Form\AbstractTypeExtension', 'getExtendedTypes', $iterableType @@ -26,19 +34,19 @@ ); $rectorConfig->ruleWithConfiguration( - \Rector\Visibility\Rector\ClassMethod\ChangeMethodVisibilityRector::class, - [new \Rector\Visibility\ValueObject\ChangeMethodVisibility( + ChangeMethodVisibilityRector::class, + [new ChangeMethodVisibility( 'Symfony\Component\Form\AbstractTypeExtension', 'getExtendedTypes', - \Rector\ValueObject\Visibility::STATIC + Visibility::STATIC ), ] ); $rectorConfig->ruleWithConfiguration( - \Rector\Transform\Rector\ClassMethod\WrapReturnRector::class, + WrapReturnRector::class, [ - new \Rector\Transform\ValueObject\WrapReturn( + new WrapReturn( 'Symfony\Component\Form\AbstractTypeExtension', 'getExtendedTypes', true diff --git a/config/sets/symfony/symfony4/symfony43/symfony43-framework-bundle.php b/config/sets/symfony/symfony4/symfony43/symfony43-framework-bundle.php index 82844996..276089a8 100644 --- a/config/sets/symfony/symfony4/symfony43/symfony43-framework-bundle.php +++ b/config/sets/symfony/symfony4/symfony43/symfony43-framework-bundle.php @@ -2,6 +2,9 @@ declare(strict_types=1); +use Rector\Symfony\Symfony43\Rector\MethodCall\ConvertRenderTemplateShortNotationToBundleSyntaxRector; +use Rector\Symfony\Symfony43\Rector\MethodCall\WebTestCaseAssertIsSuccessfulRector; +use Rector\Symfony\Symfony43\Rector\MethodCall\WebTestCaseAssertResponseCodeRector; use Rector\Config\RectorConfig; use Rector\Renaming\Rector\Name\RenameClassRector; @@ -15,10 +18,10 @@ ]); $rectorConfig->rules([ - \Rector\Symfony\Symfony43\Rector\MethodCall\ConvertRenderTemplateShortNotationToBundleSyntaxRector::class, + ConvertRenderTemplateShortNotationToBundleSyntaxRector::class, # https://symfony.com/blog/new-in-symfony-4-3-better-test-assertions // - \Rector\Symfony\Symfony43\Rector\MethodCall\WebTestCaseAssertIsSuccessfulRector::class, - \Rector\Symfony\Symfony43\Rector\MethodCall\WebTestCaseAssertResponseCodeRector::class, + WebTestCaseAssertIsSuccessfulRector::class, + WebTestCaseAssertResponseCodeRector::class, ]); }; diff --git a/config/sets/symfony/symfony4/symfony43/symfony43-twig-bundle.php b/config/sets/symfony/symfony4/symfony43/symfony43-twig-bundle.php index 1b8399a5..c189f177 100644 --- a/config/sets/symfony/symfony4/symfony43/symfony43-twig-bundle.php +++ b/config/sets/symfony/symfony4/symfony43/symfony43-twig-bundle.php @@ -2,10 +2,11 @@ declare(strict_types=1); +use Rector\Symfony\Symfony43\Rector\StmtsAwareInterface\TwigBundleFilesystemLoaderToTwigRector; use Rector\Config\RectorConfig; return static function (RectorConfig $rectorConfig): void { $rectorConfig->rules([ - \Rector\Symfony\Symfony43\Rector\StmtsAwareInterface\TwigBundleFilesystemLoaderToTwigRector::class, + TwigBundleFilesystemLoaderToTwigRector::class, ]); }; diff --git a/config/sets/symfony/symfony4/symfony44.php b/config/sets/symfony/symfony4/symfony44.php index 3d2e52b0..2fe19897 100644 --- a/config/sets/symfony/symfony4/symfony44.php +++ b/config/sets/symfony/symfony4/symfony44.php @@ -3,43 +3,13 @@ declare(strict_types=1); use Rector\Config\RectorConfig; -use Rector\Renaming\Rector\FuncCall\RenameFunctionRector; -use Rector\Renaming\Rector\MethodCall\RenameMethodRector; -use Rector\Renaming\Rector\Name\RenameClassRector; -use Rector\Renaming\ValueObject\MethodCallRename; -use Rector\Symfony\Symfony44\Rector\ClassMethod\ConsoleExecuteReturnIntRector; -use Rector\Symfony\Symfony44\Rector\MethodCall\AuthorizationCheckerIsGrantedExtractorRector; -# https://github.com/symfony/symfony/blob/4.4/UPGRADE-4.4.md +// https://github.com/symfony/symfony/blob/4.4/UPGRADE-4.4.md return static function (RectorConfig $rectorConfig): void { - $rectorConfig->rules([ - // https://github.com/symfony/symfony/pull/33775 - ConsoleExecuteReturnIntRector::class, - // https://github.com/symfony/symfony/blob/4.4/UPGRADE-4.4.md#security - AuthorizationCheckerIsGrantedExtractorRector::class, - ]); - - $rectorConfig->ruleWithConfiguration(RenameClassRector::class, [ - 'Symfony\Component\Templating\EngineInterface' => 'Twig\Environment', - ]); - - $rectorConfig->ruleWithConfiguration(RenameFunctionRector::class, [ - 'Symfony\Component\DependencyInjection\Loader\Configurator\tagged' => 'Symfony\Component\DependencyInjection\Loader\Configurator\tagged_iterator', - ]); - - $rectorConfig->ruleWithConfiguration(RenameMethodRector::class, [ - # https://github.com/symfony/http-kernel/blob/801b925e308518ddf821ba91952c41ae77c77507/Event/GetResponseForExceptionEvent.php#L55 - new MethodCallRename( - 'Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent', - 'getException', - 'getThrowable' - ), - # https://github.com/symfony/http-kernel/blob/801b925e308518ddf821ba91952c41ae77c77507/Event/GetResponseForExceptionEvent.php#L67 - new MethodCallRename( - 'Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent', - 'setException', - 'setThrowable' - ), - ]); + $rectorConfig->import(__DIR__ . '/symfony44/symfony44-dependency-injection.php'); + $rectorConfig->import(__DIR__ . '/symfony44/symfony44-console.php'); + $rectorConfig->import(__DIR__ . '/symfony44/symfony44-http-kernel.php'); + $rectorConfig->import(__DIR__ . '/symfony44/symfony44-templating.php'); + $rectorConfig->import(__DIR__ . '/symfony44/symfony44-security-core.php'); }; diff --git a/config/sets/symfony/symfony4/symfony44/symfony44-console.php b/config/sets/symfony/symfony4/symfony44/symfony44-console.php new file mode 100644 index 00000000..0804f8f3 --- /dev/null +++ b/config/sets/symfony/symfony4/symfony44/symfony44-console.php @@ -0,0 +1,13 @@ +rules([ + // https://github.com/symfony/symfony/pull/33775 + ConsoleExecuteReturnIntRector::class, + ]); +}; diff --git a/config/sets/symfony/symfony4/symfony44/symfony44-dependency-injection.php b/config/sets/symfony/symfony4/symfony44/symfony44-dependency-injection.php new file mode 100644 index 00000000..73513ce3 --- /dev/null +++ b/config/sets/symfony/symfony4/symfony44/symfony44-dependency-injection.php @@ -0,0 +1,12 @@ +ruleWithConfiguration(RenameFunctionRector::class, [ + 'Symfony\Component\DependencyInjection\Loader\Configurator\tagged' => 'Symfony\Component\DependencyInjection\Loader\Configurator\tagged_iterator', + ]); +}; diff --git a/config/sets/symfony/symfony4/symfony44/symfony44-http-kernel.php b/config/sets/symfony/symfony4/symfony44/symfony44-http-kernel.php new file mode 100644 index 00000000..ee793b43 --- /dev/null +++ b/config/sets/symfony/symfony4/symfony44/symfony44-http-kernel.php @@ -0,0 +1,25 @@ +ruleWithConfiguration(RenameMethodRector::class, [ + // https://github.com/symfony/http-kernel/blob/801b925e308518ddf821ba91952c41ae77c77507/Event/GetResponseForExceptionEvent.php#L55 + new MethodCallRename( + 'Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent', + 'getException', + 'getThrowable' + ), + + // https://github.com/symfony/http-kernel/blob/801b925e308518ddf821ba91952c41ae77c77507/Event/GetResponseForExceptionEvent.php#L67 + new MethodCallRename( + 'Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent', + 'setException', + 'setThrowable' + ), + ]); +}; diff --git a/config/sets/symfony/symfony4/symfony44/symfony44-security-core.php b/config/sets/symfony/symfony4/symfony44/symfony44-security-core.php new file mode 100644 index 00000000..59510bbb --- /dev/null +++ b/config/sets/symfony/symfony4/symfony44/symfony44-security-core.php @@ -0,0 +1,12 @@ +rules([ + AuthorizationCheckerIsGrantedExtractorRector::class, + ]); +}; diff --git a/config/sets/symfony/symfony4/symfony44/symfony44-templating.php b/config/sets/symfony/symfony4/symfony44/symfony44-templating.php new file mode 100644 index 00000000..834ec702 --- /dev/null +++ b/config/sets/symfony/symfony4/symfony44/symfony44-templating.php @@ -0,0 +1,12 @@ +ruleWithConfiguration(RenameClassRector::class, [ + 'Symfony\Component\Templating\EngineInterface' => 'Twig\Environment', + ]); +}; diff --git a/rules/Symfony44/Rector/MethodCall/AuthorizationCheckerIsGrantedExtractorRector.php b/rules/Symfony44/Rector/MethodCall/AuthorizationCheckerIsGrantedExtractorRector.php index e01ecf9a..2d1316d9 100644 --- a/rules/Symfony44/Rector/MethodCall/AuthorizationCheckerIsGrantedExtractorRector.php +++ b/rules/Symfony44/Rector/MethodCall/AuthorizationCheckerIsGrantedExtractorRector.php @@ -13,6 +13,7 @@ use PHPStan\Type\ObjectType; use Rector\NodeAnalyzer\ArgsAnalyzer; use Rector\Rector\AbstractRector; +use Rector\Symfony\Enum\SymfonyClass; use Rector\Symfony\TypeAnalyzer\ControllerAnalyzer; use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; @@ -37,12 +38,44 @@ public function getRuleDefinition(): RuleDefinition [ new CodeSample( <<<'CODE_SAMPLE' -if ($this->authorizationChecker->isGranted(['ROLE_USER', 'ROLE_ADMIN'])) { +use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; + +final class SomeController +{ + public function __construct( + private AuthorizationCheckerInterface $authorizationChecker + ) { + } + + public function hasAccess(): bool + { + if ($this->authorizationChecker->isGranted(['ROLE_USER', 'ROLE_ADMIN'])) { + return true; + } + + return false; + } } CODE_SAMPLE , <<<'CODE_SAMPLE' -if ($this->authorizationChecker->isGranted('ROLE_USER') || $this->authorizationChecker->isGranted('ROLE_ADMIN')) { +use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; + +final class SomeController +{ + public function __construct( + private AuthorizationCheckerInterface $authorizationChecker + ) { + } + + public function hasAccess(): bool + { + if ($this->authorizationChecker->isGranted('ROLE_USER') || $this->authorizationChecker->isGranted('ROLE_ADMIN')) { + return true; + } + + return false; + } } CODE_SAMPLE ), @@ -72,9 +105,7 @@ public function refactor(Node $node): MethodCall|BooleanOr|null return null; } - $authorizationChecker = new ObjectType( - 'Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface' - ); + $authorizationChecker = new ObjectType(SymfonyClass::AUTHORIZATION_CHECKER); if (! $authorizationChecker->isSuperTypeOf($objectType)->yes()) { return null; } diff --git a/src/Enum/SymfonyClass.php b/src/Enum/SymfonyClass.php index f3822834..3286da34 100644 --- a/src/Enum/SymfonyClass.php +++ b/src/Enum/SymfonyClass.php @@ -100,4 +100,9 @@ final class SymfonyClass * @var string */ public const CONTROLLER_TRAIT = 'Symfony\Bundle\FrameworkBundle\Controller\ControllerTrait'; + + /** + * @var string + */ + public const AUTHORIZATION_CHECKER = 'Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface'; } diff --git a/src/Set/SetProvider/Symfony3SetProvider.php b/src/Set/SetProvider/Symfony3SetProvider.php new file mode 100644 index 00000000..2f0b6f25 --- /dev/null +++ b/src/Set/SetProvider/Symfony3SetProvider.php @@ -0,0 +1,145 @@ + Date: Sun, 4 May 2025 19:15:17 +0200 Subject: [PATCH 40/53] [config] Split off set to set provider for Symfony 3.2-3.4 (#734) * split SymfonySetProvider per versions * [symfony 4.4] Split of per package configs * [symfony 3.x] Split of Symfony 3.3 configs * [symfony 3.4] split of per package configs * update set providers --- config/sets/symfony/symfony3/symfony32.php | 12 +--- .../symfony32-dependency-injection.php | 19 ++++++ config/sets/symfony/symfony3/symfony33.php | 56 ++---------------- .../symfony3/symfony33/symfony33-console.php | 16 +++++ .../symfony3/symfony33/symfony33-debug.php | 13 +++++ .../symfony33-dependency-injection.php | 44 ++++++++++++++ .../symfony33/symfony33-framework-bundle.php | 19 ++++++ config/sets/symfony/symfony3/symfony34.php | 23 +------- .../symfony34-dependency-injection.php | 10 ++++ ...ymfony34-sensio-framework-extra-bundle.php | 16 +++++ .../symfony3/symfony34/symfony34-yaml.php | 18 ++++++ .../symfony4/symfony42/symfony42-forms.php | 22 +++---- .../symfony43/symfony43-framework-bundle.php | 4 +- .../symfony43/symfony43-twig-bundle.php | 6 +- .../symfony44/symfony44-security-core.php | 4 +- .../ContainerGetNameToTypeInTestsRector.php | 18 +++--- src/Set/SetProvider/Symfony3SetProvider.php | 58 +++++++++++++++++++ 17 files changed, 245 insertions(+), 113 deletions(-) create mode 100644 config/sets/symfony/symfony3/symfony32/symfony32-dependency-injection.php create mode 100644 config/sets/symfony/symfony3/symfony33/symfony33-console.php create mode 100644 config/sets/symfony/symfony3/symfony33/symfony33-debug.php create mode 100644 config/sets/symfony/symfony3/symfony33/symfony33-dependency-injection.php create mode 100644 config/sets/symfony/symfony3/symfony33/symfony33-framework-bundle.php create mode 100644 config/sets/symfony/symfony3/symfony34/symfony34-dependency-injection.php create mode 100644 config/sets/symfony/symfony3/symfony34/symfony34-sensio-framework-extra-bundle.php create mode 100644 config/sets/symfony/symfony3/symfony34/symfony34-yaml.php diff --git a/config/sets/symfony/symfony3/symfony32.php b/config/sets/symfony/symfony3/symfony32.php index 39d4fb31..696d849f 100644 --- a/config/sets/symfony/symfony3/symfony32.php +++ b/config/sets/symfony/symfony3/symfony32.php @@ -2,18 +2,8 @@ declare(strict_types=1); -use Rector\Arguments\Rector\ClassMethod\ArgumentAdderRector; -use Rector\Arguments\ValueObject\ArgumentAdder; use Rector\Config\RectorConfig; return static function (RectorConfig $rectorConfig): void { - $rectorConfig->ruleWithConfiguration(ArgumentAdderRector::class, [ - new ArgumentAdder( - 'Symfony\Component\DependencyInjection\ContainerBuilder', - 'addCompilerPass', - 2, - 'priority', - 0 - ), - ]); + $rectorConfig->import(__DIR__ . '/symfony32/symfony32-dependency-injection.php'); }; diff --git a/config/sets/symfony/symfony3/symfony32/symfony32-dependency-injection.php b/config/sets/symfony/symfony3/symfony32/symfony32-dependency-injection.php new file mode 100644 index 00000000..39d4fb31 --- /dev/null +++ b/config/sets/symfony/symfony3/symfony32/symfony32-dependency-injection.php @@ -0,0 +1,19 @@ +ruleWithConfiguration(ArgumentAdderRector::class, [ + new ArgumentAdder( + 'Symfony\Component\DependencyInjection\ContainerBuilder', + 'addCompilerPass', + 2, + 'priority', + 0 + ), + ]); +}; diff --git a/config/sets/symfony/symfony3/symfony33.php b/config/sets/symfony/symfony3/symfony33.php index 0a8f08c4..71106836 100644 --- a/config/sets/symfony/symfony3/symfony33.php +++ b/config/sets/symfony/symfony3/symfony33.php @@ -2,59 +2,11 @@ declare(strict_types=1); -use Rector\Arguments\Rector\ClassMethod\ArgumentAdderRector; -use Rector\Arguments\ValueObject\ArgumentAdder; use Rector\Config\RectorConfig; -use Rector\Renaming\Rector\MethodCall\RenameMethodRector; -use Rector\Renaming\Rector\Name\RenameClassRector; -use Rector\Renaming\ValueObject\MethodCallRename; -use Rector\Symfony\Symfony33\Rector\ClassConstFetch\ConsoleExceptionToErrorEventConstantRector; return static function (RectorConfig $rectorConfig): void { - $rectorConfig->ruleWithConfiguration(ArgumentAdderRector::class, [ - new ArgumentAdder( - 'Symfony\Component\DependencyInjection\ContainerBuilder', - 'compile', - 0, - 'resolveEnvPlaceholders', - false - ), - new ArgumentAdder( - 'Symfony\Component\DependencyInjection\ContainerBuilder', - 'addCompilerPass', - 2, - 'priority', - 0 - ), - new ArgumentAdder( - 'Symfony\Component\DependencyInjection\Compiler\ServiceReferenceGraph', - 'connect', - 6, - 'weak', - false - ), - ]); - - $rectorConfig->rule(ConsoleExceptionToErrorEventConstantRector::class); - - $rectorConfig->ruleWithConfiguration(RenameClassRector::class, [ - # console - 'Symfony\Component\Console\Event\ConsoleExceptionEvent' => 'Symfony\Component\Console\Event\ConsoleErrorEvent', - # debug - 'Symfony\Component\Debug\Exception\ContextErrorException' => 'ErrorException', - # dependency-injection - 'Symfony\Component\DependencyInjection\DefinitionDecorator' => 'Symfony\Component\DependencyInjection\ChildDefinition', - # framework bundle - 'Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddConsoleCommandPass' => 'Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass', - 'Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\SerializerPass' => 'Symfony\Component\Serializer\DependencyInjection\SerializerPass', - 'Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\FormPass' => 'Symfony\Component\Form\DependencyInjection\FormPass', - 'Symfony\Bundle\FrameworkBundle\EventListener\SessionListener' => 'Symfony\Component\HttpKernel\EventListener\SessionListener', - 'Symfony\Bundle\FrameworkBundle\EventListener\TestSessionListenr' => 'Symfony\Component\HttpKernel\EventListener\TestSessionListener', - 'Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ConfigCachePass' => 'Symfony\Component\Config\DependencyInjection\ConfigCachePass', - 'Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\PropertyInfoPass' => 'Symfony\Component\PropertyInfo\DependencyInjection\PropertyInfoPass', - ]); - - $rectorConfig->ruleWithConfiguration(RenameMethodRector::class, [ - new MethodCallRename('Symfony\Component\DependencyInjection\Container', 'isFrozen', 'isCompiled'), - ]); + $rectorConfig->import(__DIR__ . '/symfony33/symfony33-console.php'); + $rectorConfig->import(__DIR__ . '/symfony33/symfony33-debug.php'); + $rectorConfig->import(__DIR__ . '/symfony33/symfony33-dependency-injection.php'); + $rectorConfig->import(__DIR__ . '/symfony33/symfony33-framework-bundle.php'); }; diff --git a/config/sets/symfony/symfony3/symfony33/symfony33-console.php b/config/sets/symfony/symfony3/symfony33/symfony33-console.php new file mode 100644 index 00000000..3735565a --- /dev/null +++ b/config/sets/symfony/symfony3/symfony33/symfony33-console.php @@ -0,0 +1,16 @@ +rules([ConsoleExceptionToErrorEventConstantRector::class]); + + $rectorConfig->ruleWithConfiguration(RenameClassRector::class, [ + // console + 'Symfony\Component\Console\Event\ConsoleExceptionEvent' => 'Symfony\Component\Console\Event\ConsoleErrorEvent', + ]); +}; diff --git a/config/sets/symfony/symfony3/symfony33/symfony33-debug.php b/config/sets/symfony/symfony3/symfony33/symfony33-debug.php new file mode 100644 index 00000000..492d6a22 --- /dev/null +++ b/config/sets/symfony/symfony3/symfony33/symfony33-debug.php @@ -0,0 +1,13 @@ +ruleWithConfiguration(RenameClassRector::class, [ + // debug + 'Symfony\Component\Debug\Exception\ContextErrorException' => 'ErrorException', + ]); +}; diff --git a/config/sets/symfony/symfony3/symfony33/symfony33-dependency-injection.php b/config/sets/symfony/symfony3/symfony33/symfony33-dependency-injection.php new file mode 100644 index 00000000..614ca644 --- /dev/null +++ b/config/sets/symfony/symfony3/symfony33/symfony33-dependency-injection.php @@ -0,0 +1,44 @@ +ruleWithConfiguration(ArgumentAdderRector::class, [ + new ArgumentAdder( + 'Symfony\Component\DependencyInjection\ContainerBuilder', + 'compile', + 0, + 'resolveEnvPlaceholders', + false + ), + new ArgumentAdder( + 'Symfony\Component\DependencyInjection\ContainerBuilder', + 'addCompilerPass', + 2, + 'priority', + 0 + ), + new ArgumentAdder( + 'Symfony\Component\DependencyInjection\Compiler\ServiceReferenceGraph', + 'connect', + 6, + 'weak', + false + ), + ]); + + $rectorConfig->ruleWithConfiguration(RenameClassRector::class, [ + 'Symfony\Component\DependencyInjection\DefinitionDecorator' => 'Symfony\Component\DependencyInjection\ChildDefinition', + ]); + + $rectorConfig->ruleWithConfiguration(RenameMethodRector::class, [ + new MethodCallRename('Symfony\Component\DependencyInjection\Container', 'isFrozen', 'isCompiled'), + ]); +}; diff --git a/config/sets/symfony/symfony3/symfony33/symfony33-framework-bundle.php b/config/sets/symfony/symfony3/symfony33/symfony33-framework-bundle.php new file mode 100644 index 00000000..3cfe7b00 --- /dev/null +++ b/config/sets/symfony/symfony3/symfony33/symfony33-framework-bundle.php @@ -0,0 +1,19 @@ +ruleWithConfiguration(RenameClassRector::class, [ + # framework bundle + 'Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddConsoleCommandPass' => 'Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass', + 'Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\SerializerPass' => 'Symfony\Component\Serializer\DependencyInjection\SerializerPass', + 'Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\FormPass' => 'Symfony\Component\Form\DependencyInjection\FormPass', + 'Symfony\Bundle\FrameworkBundle\EventListener\SessionListener' => 'Symfony\Component\HttpKernel\EventListener\SessionListener', + 'Symfony\Bundle\FrameworkBundle\EventListener\TestSessionListenr' => 'Symfony\Component\HttpKernel\EventListener\TestSessionListener', + 'Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ConfigCachePass' => 'Symfony\Component\Config\DependencyInjection\ConfigCachePass', + 'Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\PropertyInfoPass' => 'Symfony\Component\PropertyInfo\DependencyInjection\PropertyInfoPass', + ]); +}; diff --git a/config/sets/symfony/symfony3/symfony34.php b/config/sets/symfony/symfony3/symfony34.php index 3e554229..51de6e82 100644 --- a/config/sets/symfony/symfony3/symfony34.php +++ b/config/sets/symfony/symfony3/symfony34.php @@ -3,27 +3,10 @@ declare(strict_types=1); use Rector\Config\RectorConfig; -use Rector\Removing\Rector\ClassMethod\ArgumentRemoverRector; -use Rector\Removing\ValueObject\ArgumentRemover; -use Rector\Symfony\Symfony34\Rector\ClassMethod\MergeMethodAnnotationToRouteAnnotationRector; -use Rector\Symfony\Symfony34\Rector\ClassMethod\RemoveServiceFromSensioRouteRector; -use Rector\Symfony\Symfony34\Rector\ClassMethod\ReplaceSensioRouteAnnotationWithSymfonyRector; -use Rector\Symfony\Symfony34\Rector\Closure\ContainerGetNameToTypeInTestsRector; return static function (RectorConfig $rectorConfig): void { - $rectorConfig->ruleWithConfiguration(ArgumentRemoverRector::class, [ - new ArgumentRemover( - 'Symfony\Component\Yaml\Yaml', - 'parse', - 2, - ['Symfony\Component\Yaml\Yaml::PARSE_KEYS_AS_STRINGS'] - ), - ]); + $rectorConfig->import(__DIR__ . '/symfony34/symfony34-yaml.php'); + $rectorConfig->import(__DIR__ . '/symfony34/symfony34-dependency-injection.php'); + $rectorConfig->import(__DIR__ . '/symfony34/symfony34-sensio-framework-extra-bundle.php'); - $rectorConfig->rules([ - MergeMethodAnnotationToRouteAnnotationRector::class, - RemoveServiceFromSensioRouteRector::class, - ReplaceSensioRouteAnnotationWithSymfonyRector::class, - ContainerGetNameToTypeInTestsRector::class, - ]); }; diff --git a/config/sets/symfony/symfony3/symfony34/symfony34-dependency-injection.php b/config/sets/symfony/symfony3/symfony34/symfony34-dependency-injection.php new file mode 100644 index 00000000..08a87eff --- /dev/null +++ b/config/sets/symfony/symfony3/symfony34/symfony34-dependency-injection.php @@ -0,0 +1,10 @@ +rules([ContainerGetNameToTypeInTestsRector::class]); +}; diff --git a/config/sets/symfony/symfony3/symfony34/symfony34-sensio-framework-extra-bundle.php b/config/sets/symfony/symfony3/symfony34/symfony34-sensio-framework-extra-bundle.php new file mode 100644 index 00000000..890ccf74 --- /dev/null +++ b/config/sets/symfony/symfony3/symfony34/symfony34-sensio-framework-extra-bundle.php @@ -0,0 +1,16 @@ +rules([ + MergeMethodAnnotationToRouteAnnotationRector::class, + RemoveServiceFromSensioRouteRector::class, + ReplaceSensioRouteAnnotationWithSymfonyRector::class, + ]); +}; diff --git a/config/sets/symfony/symfony3/symfony34/symfony34-yaml.php b/config/sets/symfony/symfony3/symfony34/symfony34-yaml.php new file mode 100644 index 00000000..237dc1cc --- /dev/null +++ b/config/sets/symfony/symfony3/symfony34/symfony34-yaml.php @@ -0,0 +1,18 @@ +ruleWithConfiguration(ArgumentRemoverRector::class, [ + new ArgumentRemover( + 'Symfony\Component\Yaml\Yaml', + 'parse', + 2, + ['Symfony\Component\Yaml\Yaml::PARSE_KEYS_AS_STRINGS'] + ), + ]); +}; diff --git a/config/sets/symfony/symfony4/symfony42/symfony42-forms.php b/config/sets/symfony/symfony4/symfony42/symfony42-forms.php index dd4238c7..ae5f8201 100644 --- a/config/sets/symfony/symfony4/symfony42/symfony42-forms.php +++ b/config/sets/symfony/symfony4/symfony42/symfony42-forms.php @@ -3,17 +3,17 @@ declare(strict_types=1); use PHPStan\Type\IterableType; -use Rector\TypeDeclaration\Rector\ClassMethod\AddReturnTypeDeclarationRector; -use Rector\TypeDeclaration\ValueObject\AddReturnTypeDeclaration; -use Rector\Visibility\Rector\ClassMethod\ChangeMethodVisibilityRector; -use Rector\Visibility\ValueObject\ChangeMethodVisibility; -use Rector\ValueObject\Visibility; -use Rector\Transform\Rector\ClassMethod\WrapReturnRector; -use Rector\Transform\ValueObject\WrapReturn; use PHPStan\Type\MixedType; use Rector\Config\RectorConfig; use Rector\Renaming\Rector\MethodCall\RenameMethodRector; use Rector\Renaming\ValueObject\MethodCallRename; +use Rector\Transform\Rector\ClassMethod\WrapReturnRector; +use Rector\Transform\ValueObject\WrapReturn; +use Rector\TypeDeclaration\Rector\ClassMethod\AddReturnTypeDeclarationRector; +use Rector\TypeDeclaration\ValueObject\AddReturnTypeDeclaration; +use Rector\ValueObject\Visibility; +use Rector\Visibility\Rector\ClassMethod\ChangeMethodVisibilityRector; +use Rector\Visibility\ValueObject\ChangeMethodVisibility; return static function (RectorConfig $rectorConfig): void { $rectorConfig->ruleWithConfiguration(RenameMethodRector::class, [ @@ -45,12 +45,6 @@ $rectorConfig->ruleWithConfiguration( WrapReturnRector::class, - [ - new WrapReturn( - 'Symfony\Component\Form\AbstractTypeExtension', - 'getExtendedTypes', - true - ), - ] + [new WrapReturn('Symfony\Component\Form\AbstractTypeExtension', 'getExtendedTypes', true)] ); }; diff --git a/config/sets/symfony/symfony4/symfony43/symfony43-framework-bundle.php b/config/sets/symfony/symfony4/symfony43/symfony43-framework-bundle.php index 276089a8..5a4e2ee7 100644 --- a/config/sets/symfony/symfony4/symfony43/symfony43-framework-bundle.php +++ b/config/sets/symfony/symfony4/symfony43/symfony43-framework-bundle.php @@ -2,11 +2,11 @@ declare(strict_types=1); +use Rector\Config\RectorConfig; +use Rector\Renaming\Rector\Name\RenameClassRector; use Rector\Symfony\Symfony43\Rector\MethodCall\ConvertRenderTemplateShortNotationToBundleSyntaxRector; use Rector\Symfony\Symfony43\Rector\MethodCall\WebTestCaseAssertIsSuccessfulRector; use Rector\Symfony\Symfony43\Rector\MethodCall\WebTestCaseAssertResponseCodeRector; -use Rector\Config\RectorConfig; -use Rector\Renaming\Rector\Name\RenameClassRector; return static function (RectorConfig $rectorConfig): void { $rectorConfig->ruleWithConfiguration(RenameClassRector::class, [ diff --git a/config/sets/symfony/symfony4/symfony43/symfony43-twig-bundle.php b/config/sets/symfony/symfony4/symfony43/symfony43-twig-bundle.php index c189f177..903b98e0 100644 --- a/config/sets/symfony/symfony4/symfony43/symfony43-twig-bundle.php +++ b/config/sets/symfony/symfony4/symfony43/symfony43-twig-bundle.php @@ -2,11 +2,9 @@ declare(strict_types=1); -use Rector\Symfony\Symfony43\Rector\StmtsAwareInterface\TwigBundleFilesystemLoaderToTwigRector; use Rector\Config\RectorConfig; +use Rector\Symfony\Symfony43\Rector\StmtsAwareInterface\TwigBundleFilesystemLoaderToTwigRector; return static function (RectorConfig $rectorConfig): void { - $rectorConfig->rules([ - TwigBundleFilesystemLoaderToTwigRector::class, - ]); + $rectorConfig->rules([TwigBundleFilesystemLoaderToTwigRector::class]); }; diff --git a/config/sets/symfony/symfony4/symfony44/symfony44-security-core.php b/config/sets/symfony/symfony4/symfony44/symfony44-security-core.php index 59510bbb..c6ee9603 100644 --- a/config/sets/symfony/symfony4/symfony44/symfony44-security-core.php +++ b/config/sets/symfony/symfony4/symfony44/symfony44-security-core.php @@ -6,7 +6,5 @@ use Rector\Symfony\Symfony44\Rector\MethodCall\AuthorizationCheckerIsGrantedExtractorRector; return static function (RectorConfig $rectorConfig): void { - $rectorConfig->rules([ - AuthorizationCheckerIsGrantedExtractorRector::class, - ]); + $rectorConfig->rules([AuthorizationCheckerIsGrantedExtractorRector::class]); }; diff --git a/rules/Symfony34/Rector/Closure/ContainerGetNameToTypeInTestsRector.php b/rules/Symfony34/Rector/Closure/ContainerGetNameToTypeInTestsRector.php index d2f4976f..3b304436 100644 --- a/rules/Symfony34/Rector/Closure/ContainerGetNameToTypeInTestsRector.php +++ b/rules/Symfony34/Rector/Closure/ContainerGetNameToTypeInTestsRector.php @@ -30,9 +30,11 @@ public function __construct( public function getRuleDefinition(): RuleDefinition { - return new RuleDefinition('Change $container->get("some_name") to bare type, useful since Symfony 3.4', [ - new CodeSample( - <<<'CODE_SAMPLE' + return new RuleDefinition( + 'Change $container->get("some_name") in tests to bare type, useful since Symfony 3.4', + [ + new CodeSample( + <<<'CODE_SAMPLE' use PHPUnit\Framework\TestCase; final class SomeTest extends TestCase @@ -45,8 +47,8 @@ public function run() } CODE_SAMPLE - , - <<<'CODE_SAMPLE' + , + <<<'CODE_SAMPLE' use PHPUnit\Framework\TestCase; final class SomeTest extends TestCase @@ -58,8 +60,10 @@ public function run() } } CODE_SAMPLE - ), - ]); + ), + + ] + ); } /** diff --git a/src/Set/SetProvider/Symfony3SetProvider.php b/src/Set/SetProvider/Symfony3SetProvider.php index 2f0b6f25..8ff0343f 100644 --- a/src/Set/SetProvider/Symfony3SetProvider.php +++ b/src/Set/SetProvider/Symfony3SetProvider.php @@ -128,18 +128,76 @@ public function provide(): array '3.2', __DIR__ . '/../../../config/sets/symfony/symfony3/symfony32.php' ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/dependency-injection', + '3.2', + __DIR__ . '/../../../config/sets/symfony/symfony3/symfony32/symfony32-dependency-injection.php' + ), + new ComposerTriggeredSet( SetGroup::SYMFONY, 'symfony/symfony', '3.3', __DIR__ . '/../../../config/sets/symfony/symfony3/symfony33.php' ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/console', + '3.3', + __DIR__ . '/../../../config/sets/symfony/symfony3/symfony33/symfony33-console.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/debug', + '3.3', + __DIR__ . '/../../../config/sets/symfony/symfony3/symfony33/symfony33-debug.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/dependency-injection', + '3.3', + __DIR__ . '/../../../config/sets/symfony/symfony3/symfony33/symfony33-dependency-injection.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/framework-bundle', + '3.3', + __DIR__ . '/../../../config/sets/symfony/symfony3/symfony33/symfony33-framework-bundle.php' + ), + new ComposerTriggeredSet( SetGroup::SYMFONY, 'symfony/symfony', '3.4', __DIR__ . '/../../../config/sets/symfony/symfony3/symfony34.php' ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/dependency-injection', + '3.4', + __DIR__ . '/../../../config/sets/symfony/symfony3/symfony34/symfony34-dependency-injection.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'sensio/framework-extra-bundle', + '3.4', + __DIR__ . '/../../../config/sets/symfony/symfony3/symfony34/symfony34-sensio-framework-extra-bundle.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/yaml', + '3.4', + __DIR__ . '/../../../config/sets/symfony/symfony3/symfony34/symfony34-yaml.php' + ), ]; } } From dd2d5561c76bb8ed9210b3d6a9f162c8922d2849 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Sun, 4 May 2025 19:37:09 +0200 Subject: [PATCH 41/53] [symfony 5.0 and 5.1] Split config to per-package configs (#735) --- config/sets/symfony/symfony5/symfony50.php | 13 ++ .../symfony5/symfony50/symfony50-console.php | 14 ++ .../symfony5/symfony50/symfony50-debug.php | 12 ++ .../symfony50}/symfony50-types.php | 25 ++++ config/sets/symfony/symfony5/symfony51.php | 20 +++ .../symfony5/symfony51/symfony51-config.php | 17 +++ .../symfony5/symfony51/symfony51-console.php | 13 ++ .../symfony51-dependency-injection.php | 28 ++++ .../symfony51/symfony51-event-dispatcher.php | 12 ++ .../symfony5/symfony51/symfony51-forms.php | 59 ++++++++ .../symfony51/symfony51-framework-bundle.php | 23 +++ .../symfony51/symfony51-http-foundation.php | 16 +++ .../symfony51/symfony51-inflector.php | 13 ++ .../symfony5/symfony51/symfony51-notifier.php | 14 ++ .../symfony51/symfony51-security-core.php | 13 ++ .../symfony51/symfony51-security-http.php | 15 ++ .../symfony52-validator-attributes.php | 0 .../sets/symfony/{ => symfony5}/symfony52.php | 0 .../sets/symfony/{ => symfony5}/symfony53.php | 0 .../sets/symfony/{ => symfony5}/symfony54.php | 0 config/sets/symfony/symfony50.php | 53 ------- config/sets/symfony/symfony51.php | 131 ------------------ .../sets/symfony/{ => symfony6}/symfony60.php | 2 +- .../sets/symfony/{ => symfony6}/symfony61.php | 0 .../sets/symfony/{ => symfony6}/symfony62.php | 0 .../sets/symfony/{ => symfony6}/symfony63.php | 0 .../sets/symfony/{ => symfony6}/symfony64.php | 0 src/Set/SetProvider/Symfony5SetProvider.php | 110 ++++++++++++++- src/Set/SetProvider/Symfony6SetProvider.php | 10 +- src/Set/SetProvider/SymfonySetProvider.php | 2 +- src/Set/SymfonySetList.php | 24 ++-- 31 files changed, 429 insertions(+), 210 deletions(-) create mode 100644 config/sets/symfony/symfony5/symfony50.php create mode 100644 config/sets/symfony/symfony5/symfony50/symfony50-console.php create mode 100644 config/sets/symfony/symfony5/symfony50/symfony50-debug.php rename config/sets/symfony/{ => symfony5/symfony50}/symfony50-types.php (94%) create mode 100644 config/sets/symfony/symfony5/symfony51.php create mode 100644 config/sets/symfony/symfony5/symfony51/symfony51-config.php create mode 100644 config/sets/symfony/symfony5/symfony51/symfony51-console.php create mode 100644 config/sets/symfony/symfony5/symfony51/symfony51-dependency-injection.php create mode 100644 config/sets/symfony/symfony5/symfony51/symfony51-event-dispatcher.php create mode 100644 config/sets/symfony/symfony5/symfony51/symfony51-forms.php create mode 100644 config/sets/symfony/symfony5/symfony51/symfony51-framework-bundle.php create mode 100644 config/sets/symfony/symfony5/symfony51/symfony51-http-foundation.php create mode 100644 config/sets/symfony/symfony5/symfony51/symfony51-inflector.php create mode 100644 config/sets/symfony/symfony5/symfony51/symfony51-notifier.php create mode 100644 config/sets/symfony/symfony5/symfony51/symfony51-security-core.php create mode 100644 config/sets/symfony/symfony5/symfony51/symfony51-security-http.php rename config/sets/symfony/{ => symfony5}/symfony52-validator-attributes.php (100%) rename config/sets/symfony/{ => symfony5}/symfony52.php (100%) rename config/sets/symfony/{ => symfony5}/symfony53.php (100%) rename config/sets/symfony/{ => symfony5}/symfony54.php (100%) delete mode 100644 config/sets/symfony/symfony50.php delete mode 100644 config/sets/symfony/symfony51.php rename config/sets/symfony/{ => symfony6}/symfony60.php (97%) rename config/sets/symfony/{ => symfony6}/symfony61.php (100%) rename config/sets/symfony/{ => symfony6}/symfony62.php (100%) rename config/sets/symfony/{ => symfony6}/symfony63.php (100%) rename config/sets/symfony/{ => symfony6}/symfony64.php (100%) diff --git a/config/sets/symfony/symfony5/symfony50.php b/config/sets/symfony/symfony5/symfony50.php new file mode 100644 index 00000000..450e0623 --- /dev/null +++ b/config/sets/symfony/symfony5/symfony50.php @@ -0,0 +1,13 @@ +import(__DIR__ . '/symfony50/symfony50-types.php'); + $rectorConfig->import(__DIR__ . '/symfony50/symfony50-console.php'); + $rectorConfig->import(__DIR__ . '/symfony50/symfony50-debug.php'); +}; diff --git a/config/sets/symfony/symfony5/symfony50/symfony50-console.php b/config/sets/symfony/symfony5/symfony50/symfony50-console.php new file mode 100644 index 00000000..43ecfa16 --- /dev/null +++ b/config/sets/symfony/symfony5/symfony50/symfony50-console.php @@ -0,0 +1,14 @@ +ruleWithConfiguration(RenameMethodRector::class, [ + new MethodCallRename('Symfony\Component\Console\Application', 'renderException', 'renderThrowable'), + new MethodCallRename('Symfony\Component\Console\Application', 'doRenderException', 'doRenderThrowable'), + ]); +}; diff --git a/config/sets/symfony/symfony5/symfony50/symfony50-debug.php b/config/sets/symfony/symfony5/symfony50/symfony50-debug.php new file mode 100644 index 00000000..9e4dbab1 --- /dev/null +++ b/config/sets/symfony/symfony5/symfony50/symfony50-debug.php @@ -0,0 +1,12 @@ +ruleWithConfiguration(RenameClassRector::class, [ + 'Symfony\Component\Debug\Debug' => 'Symfony\Component\ErrorHandler\Debug', + ]); +}; diff --git a/config/sets/symfony/symfony50-types.php b/config/sets/symfony/symfony5/symfony50/symfony50-types.php similarity index 94% rename from config/sets/symfony/symfony50-types.php rename to config/sets/symfony/symfony5/symfony50/symfony50-types.php index 18e1482e..a687fed9 100644 --- a/config/sets/symfony/symfony50-types.php +++ b/config/sets/symfony/symfony5/symfony50/symfony50-types.php @@ -355,5 +355,30 @@ 1, new StringType() ), + + new AddParamTypeDeclaration( + 'Symfony\Component\Security\Core\User\UserProviderInterface', + 'loadUserByUsername', + 0, + new StringType(), + ), + new AddParamTypeDeclaration( + 'Symfony\Component\Security\Core\User\UserProviderInterface', + 'supportsClass', + 0, + new StringType(), + ), + new AddParamTypeDeclaration( + 'Symfony\Bridge\Doctrine\Security\User\EntityUserProvider', + 'loadUserByUsername', + 0, + new StringType(), + ), + new AddParamTypeDeclaration( + 'Symfony\Bridge\Doctrine\Security\User\EntityUserProvider', + 'supportsClass', + 0, + new StringType(), + ), ]); }; diff --git a/config/sets/symfony/symfony5/symfony51.php b/config/sets/symfony/symfony5/symfony51.php new file mode 100644 index 00000000..c0a7ece1 --- /dev/null +++ b/config/sets/symfony/symfony5/symfony51.php @@ -0,0 +1,20 @@ +import(__DIR__ . '/symfony51/symfony51-config.php'); + $rectorConfig->import(__DIR__ . '/symfony51/symfony51-console.php'); + $rectorConfig->import(__DIR__ . '/symfony51/symfony51-dependency-injection.php'); + $rectorConfig->import(__DIR__ . '/symfony51/symfony51-event-dispatcher.php'); + $rectorConfig->import(__DIR__ . '/symfony51/symfony51-forms.php'); + $rectorConfig->import(__DIR__ . '/symfony51/symfony51-framework-bundle.php'); + $rectorConfig->import(__DIR__ . '/symfony51/symfony51-http-foundation.php'); + $rectorConfig->import(__DIR__ . '/symfony51/symfony51-inflector.php'); + $rectorConfig->import(__DIR__ . '/symfony51/symfony51-notifier.php'); + $rectorConfig->import(__DIR__ . '/symfony51/symfony51-security-http.php'); + +}; diff --git a/config/sets/symfony/symfony5/symfony51/symfony51-config.php b/config/sets/symfony/symfony5/symfony51/symfony51-config.php new file mode 100644 index 00000000..d306f643 --- /dev/null +++ b/config/sets/symfony/symfony5/symfony51/symfony51-config.php @@ -0,0 +1,17 @@ +ruleWithConfiguration(RenameMethodRector::class, [ + new MethodCallRename( + 'Symfony\Component\Config\Definition\BaseNode', + 'getDeprecationMessage', + 'getDeprecation' + ), + ]); +}; diff --git a/config/sets/symfony/symfony5/symfony51/symfony51-console.php b/config/sets/symfony/symfony5/symfony51/symfony51-console.php new file mode 100644 index 00000000..06dd6904 --- /dev/null +++ b/config/sets/symfony/symfony5/symfony51/symfony51-console.php @@ -0,0 +1,13 @@ +rules([ + // @see https://symfony.com/blog/new-in-symfony-5-1-misc-improvements-part-1#added-constants-for-command-exit-codes + CommandConstantReturnCodeRector::class, + ]); +}; diff --git a/config/sets/symfony/symfony5/symfony51/symfony51-dependency-injection.php b/config/sets/symfony/symfony5/symfony51/symfony51-dependency-injection.php new file mode 100644 index 00000000..593b257c --- /dev/null +++ b/config/sets/symfony/symfony5/symfony51/symfony51-dependency-injection.php @@ -0,0 +1,28 @@ +ruleWithConfiguration(RenameFunctionRector::class, [ + 'Symfony\Component\DependencyInjection\Loader\Configuraton\inline' => 'Symfony\Component\DependencyInjection\Loader\Configuraton\inline_service', + 'Symfony\Component\DependencyInjection\Loader\Configuraton\ref' => 'Symfony\Component\DependencyInjection\Loader\Configuraton\service', + ]); + + $rectorConfig->ruleWithConfiguration(RenameMethodRector::class, [ + new MethodCallRename( + 'Symfony\Component\DependencyInjection\Definition', + 'getDeprecationMessage', + 'getDeprecation' + ), + new MethodCallRename( + 'Symfony\Component\DependencyInjection\Alias', + 'getDeprecationMessage', + 'getDeprecation' + ), + ]); +}; diff --git a/config/sets/symfony/symfony5/symfony51/symfony51-event-dispatcher.php b/config/sets/symfony/symfony5/symfony51/symfony51-event-dispatcher.php new file mode 100644 index 00000000..a904f727 --- /dev/null +++ b/config/sets/symfony/symfony5/symfony51/symfony51-event-dispatcher.php @@ -0,0 +1,12 @@ +ruleWithConfiguration(RenameClassRector::class, [ + 'Symfony\Component\EventDispatcher\LegacyEventDispatcherProxy' => 'Symfony\Component\EventDispatcher\EventDispatcherInterface', + ]); +}; diff --git a/config/sets/symfony/symfony5/symfony51/symfony51-forms.php b/config/sets/symfony/symfony5/symfony51/symfony51-forms.php new file mode 100644 index 00000000..b275a467 --- /dev/null +++ b/config/sets/symfony/symfony5/symfony51/symfony51-forms.php @@ -0,0 +1,59 @@ +ruleWithConfiguration(RenameClassRector::class, [ + 'Symfony\Component\Form\Extension\Validator\Util\ServerParams' => 'Symfony\Component\Form\Util\ServerParams', + ]); + + $rectorConfig->ruleWithConfiguration(RenameClassConstFetchRector::class, [ + new RenameClassAndConstFetch( + 'Symfony\Component\Form\Extension\Core\DataTransformer\NumberToLocalizedStringTransformer', + 'ROUND_FLOOR', + 'NumberFormatter', + 'ROUND_FLOOR' + ), + new RenameClassAndConstFetch( + 'Symfony\Component\Form\Extension\Core\DataTransformer\NumberToLocalizedStringTransformer', + 'ROUND_DOWN', + 'NumberFormatter', + 'ROUND_DOWN' + ), + new RenameClassAndConstFetch( + 'Symfony\Component\Form\Extension\Core\DataTransformer\NumberToLocalizedStringTransformer', + 'ROUND_HALF_DOWN', + 'NumberFormatter', + 'ROUND_HALFDOWN' + ), + new RenameClassAndConstFetch( + 'Symfony\Component\Form\Extension\Core\DataTransformer\NumberToLocalizedStringTransformer', + 'ROUND_HALF_EVEN', + 'NumberFormatter', + 'ROUND_HALFEVEN' + ), + new RenameClassAndConstFetch( + 'Symfony\Component\Form\Extension\Core\DataTransformer\NumberToLocalizedStringTransformer', + 'ROUND_HALFUP', + 'NumberFormatter', + 'ROUND_HALFUP' + ), + new RenameClassAndConstFetch( + 'Symfony\Component\Form\Extension\Core\DataTransformer\NumberToLocalizedStringTransformer', + 'ROUND_UP', + 'NumberFormatter', + 'ROUND_UP' + ), + new RenameClassAndConstFetch( + 'Symfony\Component\Form\Extension\Core\DataTransformer\NumberToLocalizedStringTransformer', + 'ROUND_CEILING', + 'NumberFormatter', + 'ROUND_CEILING' + ), + ]); +}; diff --git a/config/sets/symfony/symfony5/symfony51/symfony51-framework-bundle.php b/config/sets/symfony/symfony5/symfony51/symfony51-framework-bundle.php new file mode 100644 index 00000000..6445ce3c --- /dev/null +++ b/config/sets/symfony/symfony5/symfony51/symfony51-framework-bundle.php @@ -0,0 +1,23 @@ +rules([RouteCollectionBuilderToRoutingConfiguratorRector::class]); + + // @see https://github.com/symfony/symfony/pull/36943 + $rectorConfig->ruleWithConfiguration(AddParamTypeDeclarationRector::class, [ + new AddParamTypeDeclaration( + 'Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait', + 'configureRoutes', + 0, + new ObjectType('Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator') + ), + ]); +}; diff --git a/config/sets/symfony/symfony5/symfony51/symfony51-http-foundation.php b/config/sets/symfony/symfony5/symfony51/symfony51-http-foundation.php new file mode 100644 index 00000000..b173120a --- /dev/null +++ b/config/sets/symfony/symfony5/symfony51/symfony51-http-foundation.php @@ -0,0 +1,16 @@ +ruleWithConfiguration(StaticCallToNewRector::class, [ + new StaticCallToNew('Symfony\Component\HttpFoundation\Response', 'create'), + new StaticCallToNew('Symfony\Component\HttpFoundation\JsonResponse', 'create'), + new StaticCallToNew('Symfony\Component\HttpFoundation\RedirectResponse', 'create'), + new StaticCallToNew('Symfony\Component\HttpFoundation\StreamedResponse', 'create'), + ]); +}; diff --git a/config/sets/symfony/symfony5/symfony51/symfony51-inflector.php b/config/sets/symfony/symfony5/symfony51/symfony51-inflector.php new file mode 100644 index 00000000..625d778c --- /dev/null +++ b/config/sets/symfony/symfony5/symfony51/symfony51-inflector.php @@ -0,0 +1,13 @@ +ruleWithConfiguration(RenameClassRector::class, [ + // @see https://github.com/symfony/symfony/pull/35092 + 'Symfony\Component\Inflector' => 'Symfony\Component\String\Inflector\InflectorInterface', + ]); +}; diff --git a/config/sets/symfony/symfony5/symfony51/symfony51-notifier.php b/config/sets/symfony/symfony5/symfony51/symfony51-notifier.php new file mode 100644 index 00000000..47486ab6 --- /dev/null +++ b/config/sets/symfony/symfony5/symfony51/symfony51-notifier.php @@ -0,0 +1,14 @@ +ruleWithConfiguration(RenameMethodRector::class, [ + // @see https://github.com/symfony/symfony/pull/35828 + new MethodCallRename('Symfony\Component\Notifier\Bridge\Slack\Slack', 'channel', 'recipient'), + ]); +}; diff --git a/config/sets/symfony/symfony5/symfony51/symfony51-security-core.php b/config/sets/symfony/symfony5/symfony51/symfony51-security-core.php new file mode 100644 index 00000000..0ccf58c0 --- /dev/null +++ b/config/sets/symfony/symfony5/symfony51/symfony51-security-core.php @@ -0,0 +1,13 @@ +ruleWithConfiguration(RenameStringRector::class, [ + // @see https://github.com/symfony/symfony/pull/35858 + 'ROLE_PREVIOUS_ADMIN' => 'IS_IMPERSONATOR', + ]); +}; diff --git a/config/sets/symfony/symfony5/symfony51/symfony51-security-http.php b/config/sets/symfony/symfony5/symfony51/symfony51-security-http.php new file mode 100644 index 00000000..b21ee710 --- /dev/null +++ b/config/sets/symfony/symfony5/symfony51/symfony51-security-http.php @@ -0,0 +1,15 @@ +rules([ + // @see https://github.com/symfony/symfony/pull/36243 + LogoutHandlerToLogoutEventSubscriberRector::class, + LogoutSuccessHandlerToLogoutEventSubscriberRector::class, + ]); +}; diff --git a/config/sets/symfony/symfony52-validator-attributes.php b/config/sets/symfony/symfony5/symfony52-validator-attributes.php similarity index 100% rename from config/sets/symfony/symfony52-validator-attributes.php rename to config/sets/symfony/symfony5/symfony52-validator-attributes.php diff --git a/config/sets/symfony/symfony52.php b/config/sets/symfony/symfony5/symfony52.php similarity index 100% rename from config/sets/symfony/symfony52.php rename to config/sets/symfony/symfony5/symfony52.php diff --git a/config/sets/symfony/symfony53.php b/config/sets/symfony/symfony5/symfony53.php similarity index 100% rename from config/sets/symfony/symfony53.php rename to config/sets/symfony/symfony5/symfony53.php diff --git a/config/sets/symfony/symfony54.php b/config/sets/symfony/symfony5/symfony54.php similarity index 100% rename from config/sets/symfony/symfony54.php rename to config/sets/symfony/symfony5/symfony54.php diff --git a/config/sets/symfony/symfony50.php b/config/sets/symfony/symfony50.php deleted file mode 100644 index 6f06b45c..00000000 --- a/config/sets/symfony/symfony50.php +++ /dev/null @@ -1,53 +0,0 @@ -import(__DIR__ . '/symfony50-types.php'); - - $rectorConfig->ruleWithConfiguration(AddParamTypeDeclarationRector::class, [ - new AddParamTypeDeclaration( - 'Symfony\Component\Security\Core\User\UserProviderInterface', - 'loadUserByUsername', - 0, - new StringType(), - ), - new AddParamTypeDeclaration( - 'Symfony\Component\Security\Core\User\UserProviderInterface', - 'supportsClass', - 0, - new StringType(), - ), - new AddParamTypeDeclaration( - 'Symfony\Bridge\Doctrine\Security\User\EntityUserProvider', - 'loadUserByUsername', - 0, - new StringType(), - ), - new AddParamTypeDeclaration( - 'Symfony\Bridge\Doctrine\Security\User\EntityUserProvider', - 'supportsClass', - 0, - new StringType(), - ), - ]); - - $rectorConfig->ruleWithConfiguration(RenameClassRector::class, [ - 'Symfony\Component\Debug\Debug' => 'Symfony\Component\ErrorHandler\Debug', - ]); - - $rectorConfig->ruleWithConfiguration(RenameMethodRector::class, [ - new MethodCallRename('Symfony\Component\Console\Application', 'renderException', 'renderThrowable'), - new MethodCallRename('Symfony\Component\Console\Application', 'doRenderException', 'doRenderThrowable'), - ]); -}; diff --git a/config/sets/symfony/symfony51.php b/config/sets/symfony/symfony51.php deleted file mode 100644 index 31290453..00000000 --- a/config/sets/symfony/symfony51.php +++ /dev/null @@ -1,131 +0,0 @@ -rules([ - // @see https://github.com/symfony/symfony/pull/36243 - LogoutHandlerToLogoutEventSubscriberRector::class, - LogoutSuccessHandlerToLogoutEventSubscriberRector::class, - // @see https://symfony.com/blog/new-in-symfony-5-1-misc-improvements-part-1#added-constants-for-command-exit-codes - CommandConstantReturnCodeRector::class, - RouteCollectionBuilderToRoutingConfiguratorRector::class, - ]); - - $rectorConfig->ruleWithConfiguration(RenameClassRector::class, [ - 'Symfony\Component\EventDispatcher\LegacyEventDispatcherProxy' => 'Symfony\Component\EventDispatcher\EventDispatcherInterface', - 'Symfony\Component\Form\Extension\Validator\Util\ServerParams' => 'Symfony\Component\Form\Util\ServerParams', - // @see https://github.com/symfony/symfony/pull/35092 - 'Symfony\Component\Inflector' => 'Symfony\Component\String\Inflector\InflectorInterface', - ]); - - $rectorConfig->ruleWithConfiguration(RenameMethodRector::class, [ - new MethodCallRename( - 'Symfony\Component\Config\Definition\BaseNode', - 'getDeprecationMessage', - 'getDeprecation' - ), - new MethodCallRename( - 'Symfony\Component\DependencyInjection\Definition', - 'getDeprecationMessage', - 'getDeprecation' - ), - new MethodCallRename( - 'Symfony\Component\DependencyInjection\Alias', - 'getDeprecationMessage', - 'getDeprecation' - ), - // @see https://github.com/symfony/symfony/pull/35828 - new MethodCallRename('Symfony\Component\Notifier\Bridge\Slack\Slack', 'channel', 'recipient'), - ]); - - $rectorConfig->ruleWithConfiguration(RenameFunctionRector::class, [ - 'Symfony\Component\DependencyInjection\Loader\Configuraton\inline' => 'Symfony\Component\DependencyInjection\Loader\Configuraton\inline_service', - 'Symfony\Component\DependencyInjection\Loader\Configuraton\ref' => 'Symfony\Component\DependencyInjection\Loader\Configuraton\service', - ]); - - $rectorConfig->ruleWithConfiguration(RenameClassConstFetchRector::class, [ - new RenameClassAndConstFetch( - 'Symfony\Component\Form\Extension\Core\DataTransformer\NumberToLocalizedStringTransformer', - 'ROUND_FLOOR', - 'NumberFormatter', - 'ROUND_FLOOR' - ), - new RenameClassAndConstFetch( - 'Symfony\Component\Form\Extension\Core\DataTransformer\NumberToLocalizedStringTransformer', - 'ROUND_DOWN', - 'NumberFormatter', - 'ROUND_DOWN' - ), - new RenameClassAndConstFetch( - 'Symfony\Component\Form\Extension\Core\DataTransformer\NumberToLocalizedStringTransformer', - 'ROUND_HALF_DOWN', - 'NumberFormatter', - 'ROUND_HALFDOWN' - ), - new RenameClassAndConstFetch( - 'Symfony\Component\Form\Extension\Core\DataTransformer\NumberToLocalizedStringTransformer', - 'ROUND_HALF_EVEN', - 'NumberFormatter', - 'ROUND_HALFEVEN' - ), - new RenameClassAndConstFetch( - 'Symfony\Component\Form\Extension\Core\DataTransformer\NumberToLocalizedStringTransformer', - 'ROUND_HALFUP', - 'NumberFormatter', - 'ROUND_HALFUP' - ), - new RenameClassAndConstFetch( - 'Symfony\Component\Form\Extension\Core\DataTransformer\NumberToLocalizedStringTransformer', - 'ROUND_UP', - 'NumberFormatter', - 'ROUND_UP' - ), - new RenameClassAndConstFetch( - 'Symfony\Component\Form\Extension\Core\DataTransformer\NumberToLocalizedStringTransformer', - 'ROUND_CEILING', - 'NumberFormatter', - 'ROUND_CEILING' - ), - ]); - - // @see https://github.com/symfony/symfony/pull/36943 - $rectorConfig->ruleWithConfiguration(AddParamTypeDeclarationRector::class, [ - new AddParamTypeDeclaration( - 'Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait', - 'configureRoutes', - 0, - new ObjectType('Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator') - ), - ]); - $rectorConfig->ruleWithConfiguration(StaticCallToNewRector::class, [ - new StaticCallToNew('Symfony\Component\HttpFoundation\Response', 'create'), - new StaticCallToNew('Symfony\Component\HttpFoundation\JsonResponse', 'create'), - new StaticCallToNew('Symfony\Component\HttpFoundation\RedirectResponse', 'create'), - new StaticCallToNew('Symfony\Component\HttpFoundation\StreamedResponse', 'create'), - ]); - - $rectorConfig->ruleWithConfiguration(RenameStringRector::class, [ - // @see https://github.com/symfony/symfony/pull/35858 - 'ROLE_PREVIOUS_ADMIN' => 'IS_IMPERSONATOR', - ]); -}; diff --git a/config/sets/symfony/symfony60.php b/config/sets/symfony/symfony6/symfony60.php similarity index 97% rename from config/sets/symfony/symfony60.php rename to config/sets/symfony/symfony6/symfony60.php index b578bd31..b6afc8a1 100644 --- a/config/sets/symfony/symfony60.php +++ b/config/sets/symfony/symfony6/symfony60.php @@ -21,7 +21,7 @@ return static function (RectorConfig $rectorConfig): void { $rectorConfig->sets([SymfonySetList::ANNOTATIONS_TO_ATTRIBUTES]); - $rectorConfig->import(__DIR__ . '/symfony6/symfony-return-types.php'); + $rectorConfig->import(__DIR__ . '/symfony-return-types.php'); $rectorConfig->ruleWithConfiguration(ReplaceServiceArgumentRector::class, [ new ReplaceServiceArgument('Psr\Container\ContainerInterface', new String_('service_container')), new ReplaceServiceArgument( diff --git a/config/sets/symfony/symfony61.php b/config/sets/symfony/symfony6/symfony61.php similarity index 100% rename from config/sets/symfony/symfony61.php rename to config/sets/symfony/symfony6/symfony61.php diff --git a/config/sets/symfony/symfony62.php b/config/sets/symfony/symfony6/symfony62.php similarity index 100% rename from config/sets/symfony/symfony62.php rename to config/sets/symfony/symfony6/symfony62.php diff --git a/config/sets/symfony/symfony63.php b/config/sets/symfony/symfony6/symfony63.php similarity index 100% rename from config/sets/symfony/symfony63.php rename to config/sets/symfony/symfony6/symfony63.php diff --git a/config/sets/symfony/symfony64.php b/config/sets/symfony/symfony6/symfony64.php similarity index 100% rename from config/sets/symfony/symfony64.php rename to config/sets/symfony/symfony6/symfony64.php diff --git a/src/Set/SetProvider/Symfony5SetProvider.php b/src/Set/SetProvider/Symfony5SetProvider.php index 9342f10b..20956163 100644 --- a/src/Set/SetProvider/Symfony5SetProvider.php +++ b/src/Set/SetProvider/Symfony5SetProvider.php @@ -19,33 +19,129 @@ public function provide(): array return [ new ComposerTriggeredSet( SetGroup::SYMFONY, - 'symfony/*', + 'symfony/symfony', '5.0', - __DIR__ . '/../../../config/sets/symfony/symfony50.php' + __DIR__ . '/../../../config/sets/symfony/symfony5/symfony50.php' ), + new ComposerTriggeredSet( SetGroup::SYMFONY, - 'symfony/*', + 'symfony/console', + '5.0', + __DIR__ . '/../../../config/sets/symfony/symfony5/symfony50/symfony50-console.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/debug', + '5.0', + __DIR__ . '/../../../config/sets/symfony/symfony5/symfony50/symfony50-debug.php' + ), + + // @todo handle types per package? + // __DIR__ . '/../../../config/sets/symfony/symfony5/symfony50/symfony50-types.php' + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/symfony', + '5.1', + __DIR__ . '/../../../config/sets/symfony/symfony5/symfony51.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/config', + '5.1', + __DIR__ . '/../../../config/sets/symfony/symfony5/symfony51/symfony51-config.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/console', + '5.1', + __DIR__ . '/../../../config/sets/symfony/symfony5/symfony51/symfony51-console.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/dependency-injection', + '5.1', + __DIR__ . '/../../../config/sets/symfony/symfony5/symfony51/symfony51-dependency-injection.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/event-dispatcher', + '5.1', + __DIR__ . '/../../../config/sets/symfony/symfony5/symfony51/symfony51-event-dispatcher.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/forms', + '5.1', + __DIR__ . '/../../../config/sets/symfony/symfony5/symfony51/symfony51-forms.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/framework-bundle', '5.1', - __DIR__ . '/../../../config/sets/symfony/symfony51.php' + __DIR__ . '/../../../config/sets/symfony/symfony5/symfony51/symfony51-framework-bundle.php' ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/http-foundation', + '5.1', + __DIR__ . '/../../../config/sets/symfony/symfony5/symfony51/symfony51-http-foundation.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/inflector', + '5.1', + __DIR__ . '/../../../config/sets/symfony/symfony5/symfony51/symfony51-inflector.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/notifier', + '5.1', + __DIR__ . '/../../../config/sets/symfony/symfony5/symfony51/symfony51-notifier.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/security-http', + '5.1', + __DIR__ . '/../../../config/sets/symfony/symfony5/symfony51/symfony51-security-http.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/security-core', + '5.1', + __DIR__ . '/../../../config/sets/symfony/symfony5/symfony51/symfony51-security-core.php' + ), + new ComposerTriggeredSet( SetGroup::SYMFONY, 'symfony/*', '5.2', - __DIR__ . '/../../../config/sets/symfony/symfony52.php' + __DIR__ . '/../../../config/sets/symfony/symfony5/symfony52.php' ), new ComposerTriggeredSet( SetGroup::SYMFONY, 'symfony/*', '5.3', - __DIR__ . '/../../../config/sets/symfony/symfony53.php' + __DIR__ . '/../../../config/sets/symfony/symfony5/symfony53.php' ), new ComposerTriggeredSet( SetGroup::SYMFONY, 'symfony/*', '5.4', - __DIR__ . '/../../../config/sets/symfony/symfony54.php' + __DIR__ . '/../../../config/sets/symfony/symfony5/symfony54.php' ), ]; } diff --git a/src/Set/SetProvider/Symfony6SetProvider.php b/src/Set/SetProvider/Symfony6SetProvider.php index 581897dc..350d347e 100644 --- a/src/Set/SetProvider/Symfony6SetProvider.php +++ b/src/Set/SetProvider/Symfony6SetProvider.php @@ -21,31 +21,31 @@ public function provide(): array SetGroup::SYMFONY, 'symfony/*', '6.0', - __DIR__ . '/../../../config/sets/symfony/symfony60.php' + __DIR__ . '/../../../config/sets/symfony/symfony6/symfony60.php' ), new ComposerTriggeredSet( SetGroup::SYMFONY, 'symfony/*', '6.1', - __DIR__ . '/../../../config/sets/symfony/symfony61.php' + __DIR__ . '/../../../config/sets/symfony/symfony6/symfony61.php' ), new ComposerTriggeredSet( SetGroup::SYMFONY, 'symfony/*', '6.2', - __DIR__ . '/../../../config/sets/symfony/symfony62.php' + __DIR__ . '/../../../config/sets/symfony/symfony6/symfony62.php' ), new ComposerTriggeredSet( SetGroup::SYMFONY, 'symfony/*', '6.3', - __DIR__ . '/../../../config/sets/symfony/symfony63.php' + __DIR__ . '/../../../config/sets/symfony/symfony6/symfony63.php' ), new ComposerTriggeredSet( SetGroup::SYMFONY, 'symfony/*', '6.4', - __DIR__ . '/../../../config/sets/symfony/symfony64.php' + __DIR__ . '/../../../config/sets/symfony/symfony6/symfony64.php' ), ]; } diff --git a/src/Set/SetProvider/SymfonySetProvider.php b/src/Set/SetProvider/SymfonySetProvider.php index 61b9903c..81ef43e5 100644 --- a/src/Set/SetProvider/SymfonySetProvider.php +++ b/src/Set/SetProvider/SymfonySetProvider.php @@ -56,7 +56,7 @@ public function provide(): array new Set( SetGroup::ATTRIBUTES, 'Symfony Validator', - __DIR__ . '/../../../config/sets/symfony/symfony52-validator-attributes.php' + __DIR__ . '/../../../config/sets/symfony/symfony5/symfony52-validator-attributes.php' ), ]; } diff --git a/src/Set/SymfonySetList.php b/src/Set/SymfonySetList.php index a028f274..28ead3b3 100644 --- a/src/Set/SymfonySetList.php +++ b/src/Set/SymfonySetList.php @@ -89,63 +89,63 @@ final class SymfonySetList /** * @var string */ - final public const SYMFONY_50 = __DIR__ . '/../../config/sets/symfony/symfony50.php'; + final public const SYMFONY_50 = __DIR__ . '/../../config/sets/symfony/symfony5/symfony50.php'; /** * @var string */ - final public const SYMFONY_50_TYPES = __DIR__ . '/../../config/sets/symfony/symfony50-types.php'; + final public const SYMFONY_50_TYPES = __DIR__ . '/../../config/sets/symfony/symfony5/symfony50/symfony50-types.php'; /** * @var string */ - final public const SYMFONY_51 = __DIR__ . '/../../config/sets/symfony/symfony51.php'; + final public const SYMFONY_51 = __DIR__ . '/../../config/sets/symfony/symfony5/symfony51.php'; /** * @var string */ - final public const SYMFONY_52 = __DIR__ . '/../../config/sets/symfony/symfony52.php'; + final public const SYMFONY_52 = __DIR__ . '/../../config/sets/symfony/symfony5/symfony52.php'; /** * @var string */ - final public const SYMFONY_53 = __DIR__ . '/../../config/sets/symfony/symfony53.php'; + final public const SYMFONY_53 = __DIR__ . '/../../config/sets/symfony/symfony5/symfony53.php'; /** * @var string */ - final public const SYMFONY_54 = __DIR__ . '/../../config/sets/symfony/symfony54.php'; + final public const SYMFONY_54 = __DIR__ . '/../../config/sets/symfony/symfony5/symfony54.php'; /** * @deprecated Use ->withAttributesSets(symfony: true) in rector.php config instead * @var string */ - final public const SYMFONY_52_VALIDATOR_ATTRIBUTES = __DIR__ . '/../../config/sets/symfony/symfony52-validator-attributes.php'; + final public const SYMFONY_52_VALIDATOR_ATTRIBUTES = __DIR__ . '/../../config/sets/symfony/symfony5/symfony52-validator-attributes.php'; /** * @var string */ - final public const SYMFONY_60 = __DIR__ . '/../../config/sets/symfony/symfony60.php'; + final public const SYMFONY_60 = __DIR__ . '/../../config/sets/symfony/symfony6/symfony60.php'; /** * @var string */ - final public const SYMFONY_61 = __DIR__ . '/../../config/sets/symfony/symfony61.php'; + final public const SYMFONY_61 = __DIR__ . '/../../config/sets/symfony/symfony6/symfony61.php'; /** * @var string */ - final public const SYMFONY_62 = __DIR__ . '/../../config/sets/symfony/symfony62.php'; + final public const SYMFONY_62 = __DIR__ . '/../../config/sets/symfony/symfony6/symfony62.php'; /** * @var string */ - final public const SYMFONY_63 = __DIR__ . '/../../config/sets/symfony/symfony63.php'; + final public const SYMFONY_63 = __DIR__ . '/../../config/sets/symfony/symfony6/symfony63.php'; /** * @var string */ - final public const SYMFONY_64 = __DIR__ . '/../../config/sets/symfony/symfony64.php'; + final public const SYMFONY_64 = __DIR__ . '/../../config/sets/symfony/symfony6/symfony64.php'; /** * @var string From 1a2292e1c203eb48293ef645e0991186617ed9e2 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Sun, 4 May 2025 21:14:32 +0200 Subject: [PATCH 42/53] [symfony 5.2] split of configs per package (#736) --- config/sets/symfony/symfony5/symfony52.php | 172 ++---------------- .../symfony52-dependency-injection.php | 13 ++ .../symfony5/symfony52/symfony52-forms.php | 12 ++ .../symfony52/symfony52-http-foundation.php | 13 ++ .../symfony5/symfony52/symfony52-mime.php | 16 ++ .../symfony5/symfony52/symfony52-notifier.php | 56 ++++++ .../symfony52/symfony52-property-access.php | 13 ++ .../symfony52/symfony52-property-info.php | 13 ++ .../symfony52/symfony52-security-core.php | 53 ++++++ .../symfony52/symfony52-security-http.php | 45 +++++ .../symfony52/symfony52-validator.php | 13 ++ ...tyAccessorCreationBooleanToFlagsRector.php | 4 + src/Set/SetProvider/Symfony5SetProvider.php | 64 ++++++- 13 files changed, 326 insertions(+), 161 deletions(-) create mode 100644 config/sets/symfony/symfony5/symfony52/symfony52-dependency-injection.php create mode 100644 config/sets/symfony/symfony5/symfony52/symfony52-forms.php create mode 100644 config/sets/symfony/symfony5/symfony52/symfony52-http-foundation.php create mode 100644 config/sets/symfony/symfony5/symfony52/symfony52-mime.php create mode 100644 config/sets/symfony/symfony5/symfony52/symfony52-notifier.php create mode 100644 config/sets/symfony/symfony5/symfony52/symfony52-property-access.php create mode 100644 config/sets/symfony/symfony5/symfony52/symfony52-property-info.php create mode 100644 config/sets/symfony/symfony5/symfony52/symfony52-security-core.php create mode 100644 config/sets/symfony/symfony5/symfony52/symfony52-security-http.php create mode 100644 config/sets/symfony/symfony5/symfony52/symfony52-validator.php diff --git a/config/sets/symfony/symfony5/symfony52.php b/config/sets/symfony/symfony5/symfony52.php index 3fd7ea04..8571b4c9 100644 --- a/config/sets/symfony/symfony5/symfony52.php +++ b/config/sets/symfony/symfony5/symfony52.php @@ -2,171 +2,23 @@ declare(strict_types=1); -use PHPStan\Type\ObjectType; use Rector\Config\RectorConfig; -use Rector\Renaming\Rector\ClassConstFetch\RenameClassConstFetchRector; -use Rector\Renaming\Rector\MethodCall\RenameMethodRector; -use Rector\Renaming\Rector\PropertyFetch\RenamePropertyRector; -use Rector\Renaming\ValueObject\MethodCallRename; -use Rector\Renaming\ValueObject\RenameClassAndConstFetch; -use Rector\Renaming\ValueObject\RenameProperty; use Rector\Symfony\Set\SymfonySetList; -use Rector\Symfony\Symfony52\Rector\MethodCall\DefinitionAliasSetPrivateToSetPublicRector; -use Rector\Symfony\Symfony52\Rector\MethodCall\FormBuilderSetDataMapperRector; -use Rector\Symfony\Symfony52\Rector\MethodCall\ReflectionExtractorEnableMagicCallExtractorRector; -use Rector\Symfony\Symfony52\Rector\MethodCall\ValidatorBuilderEnableAnnotationMappingRector; -use Rector\Symfony\Symfony52\Rector\New_\PropertyAccessorCreationBooleanToFlagsRector; -use Rector\Symfony\Symfony52\Rector\New_\PropertyPathMapperToDataMapperRector; -use Rector\Symfony\Symfony52\Rector\StaticCall\BinaryFileResponseCreateToNewInstanceRector; -use Rector\TypeDeclaration\Rector\ClassMethod\AddParamTypeDeclarationRector; -use Rector\TypeDeclaration\ValueObject\AddParamTypeDeclaration; # https://github.com/symfony/symfony/blob/5.x/UPGRADE-5.2.md return static function (RectorConfig $rectorConfig): void { - $rectorConfig->sets([SymfonySetList::ANNOTATIONS_TO_ATTRIBUTES]); + // $rectorConfig->sets([SymfonySetList::ANNOTATIONS_TO_ATTRIBUTES]); + + $rectorConfig->import(__DIR__ . '/symfony52/symfony52-dependency-injection.php'); + $rectorConfig->import(__DIR__ . '/symfony52/symfony52-forms.php'); + $rectorConfig->import(__DIR__ . '/symfony52/symfony52-http-foundation.php'); + $rectorConfig->import(__DIR__ . '/symfony52/symfony52-mime.php'); + $rectorConfig->import(__DIR__ . '/symfony52/symfony52-notifier.php'); + $rectorConfig->import(__DIR__ . '/symfony52/symfony52-property-access.php'); + $rectorConfig->import(__DIR__ . '/symfony52/symfony52-property-info.php'); + $rectorConfig->import(__DIR__ . '/symfony52/symfony52-security-core.php'); + $rectorConfig->import(__DIR__ . '/symfony52/symfony52-security-http.php'); + $rectorConfig->import(__DIR__ . '/symfony52/symfony52-validator.php'); - $rectorConfig->rules([ - // https://github.com/symfony/symfony/blob/5.x/UPGRADE-5.2.md#form - PropertyPathMapperToDataMapperRector::class, - - // https://github.com/symfony/symfony/blob/5.x/UPGRADE-5.2.md#httpfoundation - BinaryFileResponseCreateToNewInstanceRector::class, - - // https://github.com/symfony/symfony/blob/5.x/UPGRADE-5.2.md#propertyaccess - PropertyAccessorCreationBooleanToFlagsRector::class, - - // https://github.com/symfony/symfony/blob/5.x/UPGRADE-5.2.md#propertyinfo - ReflectionExtractorEnableMagicCallExtractorRector::class, - - # https://github.com/symfony/symfony/blob/5.x/UPGRADE-5.2.md#dependencyinjection - DefinitionAliasSetPrivateToSetPublicRector::class, - - # https://github.com/symfony/symfony/blob/5.x/UPGRADE-5.2.md#form - FormBuilderSetDataMapperRector::class, - - # https://github.com/symfony/symfony/blob/5.x/UPGRADE-5.2.md#validator - ValidatorBuilderEnableAnnotationMappingRector::class, - ]); - - # https://github.com/symfony/symfony/blob/5.x/UPGRADE-5.2.md#security - $rectorConfig->ruleWithConfiguration(RenameClassConstFetchRector::class, [ - new RenameClassAndConstFetch( - 'Symfony\Component\Security\Http\Firewall\AccessListener', - 'PUBLIC_ACCESS', - 'Symfony\Component\Security\Core\Authorization\Voter\AuthenticatedVoter', - 'PUBLIC_ACCESS' - ), - ]); - - $rectorConfig->ruleWithConfiguration(RenameMethodRector::class, [ - # https://github.com/symfony/symfony/blob/5.x/UPGRADE-5.2.md#mime - new MethodCallRename('Symfony\Component\Mime\Address', 'fromString', 'create'), - - new MethodCallRename( - 'Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken', - 'setProviderKey', - 'setFirewallName' - ), - new MethodCallRename( - 'Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken', - 'getProviderKey', - 'getFirewallName' - ), - new MethodCallRename( - 'Symfony\Component\Security\Core\Authentication\Token\RememberMeToken', - 'setProviderKey', - 'setFirewallName' - ), - new MethodCallRename( - 'Symfony\Component\Security\Core\Authentication\Token\RememberMeToken', - 'getProviderKey', - 'getFirewallName' - ), - new MethodCallRename( - 'Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken', - 'setProviderKey', - 'setFirewallName' - ), - new MethodCallRename( - 'Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken', - 'getProviderKey', - 'getFirewallName' - ), - new MethodCallRename( - 'Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken', - 'setProviderKey', - 'setFirewallName' - ), - new MethodCallRename( - 'Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken', - 'getProviderKey', - 'getFirewallName' - ), - new MethodCallRename( - 'Symfony\Component\Security\Http\Authentication\DefaultAuthenticationSuccessHandler', - 'setProviderKey', - 'setFirewallName' - ), - new MethodCallRename( - 'Symfony\Component\Security\Http\Authentication\DefaultAuthenticationSuccessHandler', - 'getProviderKey', - 'getFirewallName' - ), - ]); - - # https://github.com/symfony/symfony/blob/5.x/UPGRADE-5.2.md#notifier - $rectorConfig->ruleWithConfiguration(AddParamTypeDeclarationRector::class, [ - new AddParamTypeDeclaration( - 'Symfony\Component\Notifier\NotifierInterface', - 'send', - 1, - new ObjectType('Symfony\Component\Notifier\Recipient\RecipientInterface') - ), - new AddParamTypeDeclaration( - 'Symfony\Component\Notifier\Notifier', - 'getChannels', - 1, - new ObjectType('Symfony\Component\Notifier\Recipient\RecipientInterface') - ), - new AddParamTypeDeclaration( - 'Symfony\Component\Notifier\Channel\ChannelInterface', - 'notify', - 1, - new ObjectType('Symfony\Component\Notifier\Recipient\RecipientInterface') - ), - new AddParamTypeDeclaration( - 'Symfony\Component\Notifier\Channel\ChannelInterface', - 'supports', - 1, - new ObjectType('Symfony\Component\Notifier\Recipient\RecipientInterface') - ), - new AddParamTypeDeclaration( - 'Symfony\Component\Notifier\Notification\ChatNotificationInterface', - 'asChatMessage', - 0, - new ObjectType('Symfony\Component\Notifier\Recipient\RecipientInterface') - ), - new AddParamTypeDeclaration( - 'Symfony\Component\Notifier\Notification\EmailNotificationInterface', - 'asEmailMessage', - 0, - new ObjectType('Symfony\Component\Notifier\Recipient\EmailRecipientInterface') - ), - new AddParamTypeDeclaration( - 'Symfony\Component\Notifier\Notification\SmsNotificationInterface', - 'asSmsMessage', - 0, - new ObjectType('Symfony\Component\Notifier\Recipient\SmsRecipientInterface') - ), - ]); - - # https://github.com/symfony/symfony/blob/5.x/UPGRADE-5.2.md#security - $rectorConfig->ruleWithConfiguration(RenamePropertyRector::class, [ - new RenameProperty( - 'Symfony\Component\Security\Http\RememberMe\AbstractRememberMeServices', - 'providerKey', - 'firewallName' - ), - ]); }; diff --git a/config/sets/symfony/symfony5/symfony52/symfony52-dependency-injection.php b/config/sets/symfony/symfony5/symfony52/symfony52-dependency-injection.php new file mode 100644 index 00000000..3cd62181 --- /dev/null +++ b/config/sets/symfony/symfony5/symfony52/symfony52-dependency-injection.php @@ -0,0 +1,13 @@ +rules([ + # https://github.com/symfony/symfony/blob/5.x/UPGRADE-5.2.md#dependencyinjection + DefinitionAliasSetPrivateToSetPublicRector::class, + ]); +}; diff --git a/config/sets/symfony/symfony5/symfony52/symfony52-forms.php b/config/sets/symfony/symfony5/symfony52/symfony52-forms.php new file mode 100644 index 00000000..bd854929 --- /dev/null +++ b/config/sets/symfony/symfony5/symfony52/symfony52-forms.php @@ -0,0 +1,12 @@ +rules([PropertyPathMapperToDataMapperRector::class, FormBuilderSetDataMapperRector::class]); +}; diff --git a/config/sets/symfony/symfony5/symfony52/symfony52-http-foundation.php b/config/sets/symfony/symfony5/symfony52/symfony52-http-foundation.php new file mode 100644 index 00000000..26029db4 --- /dev/null +++ b/config/sets/symfony/symfony5/symfony52/symfony52-http-foundation.php @@ -0,0 +1,13 @@ +rules([ + // https://github.com/symfony/symfony/blob/5.x/UPGRADE-5.2.md#httpfoundation + BinaryFileResponseCreateToNewInstanceRector::class, + ]); +}; diff --git a/config/sets/symfony/symfony5/symfony52/symfony52-mime.php b/config/sets/symfony/symfony5/symfony52/symfony52-mime.php new file mode 100644 index 00000000..5cea7110 --- /dev/null +++ b/config/sets/symfony/symfony5/symfony52/symfony52-mime.php @@ -0,0 +1,16 @@ +ruleWithConfiguration(RenameMethodRector::class, [ + # https://github.com/symfony/symfony/blob/5.x/UPGRADE-5.2.md#mime + new MethodCallRename('Symfony\Component\Mime\Address', 'fromString', 'create'), + ]); +}; diff --git a/config/sets/symfony/symfony5/symfony52/symfony52-notifier.php b/config/sets/symfony/symfony5/symfony52/symfony52-notifier.php new file mode 100644 index 00000000..cbba35eb --- /dev/null +++ b/config/sets/symfony/symfony5/symfony52/symfony52-notifier.php @@ -0,0 +1,56 @@ +ruleWithConfiguration(AddParamTypeDeclarationRector::class, [ + new AddParamTypeDeclaration( + 'Symfony\Component\Notifier\NotifierInterface', + 'send', + 1, + new ObjectType('Symfony\Component\Notifier\Recipient\RecipientInterface') + ), + new AddParamTypeDeclaration( + 'Symfony\Component\Notifier\Notifier', + 'getChannels', + 1, + new ObjectType('Symfony\Component\Notifier\Recipient\RecipientInterface') + ), + new AddParamTypeDeclaration( + 'Symfony\Component\Notifier\Channel\ChannelInterface', + 'notify', + 1, + new ObjectType('Symfony\Component\Notifier\Recipient\RecipientInterface') + ), + new AddParamTypeDeclaration( + 'Symfony\Component\Notifier\Channel\ChannelInterface', + 'supports', + 1, + new ObjectType('Symfony\Component\Notifier\Recipient\RecipientInterface') + ), + new AddParamTypeDeclaration( + 'Symfony\Component\Notifier\Notification\ChatNotificationInterface', + 'asChatMessage', + 0, + new ObjectType('Symfony\Component\Notifier\Recipient\RecipientInterface') + ), + new AddParamTypeDeclaration( + 'Symfony\Component\Notifier\Notification\EmailNotificationInterface', + 'asEmailMessage', + 0, + new ObjectType('Symfony\Component\Notifier\Recipient\EmailRecipientInterface') + ), + new AddParamTypeDeclaration( + 'Symfony\Component\Notifier\Notification\SmsNotificationInterface', + 'asSmsMessage', + 0, + new ObjectType('Symfony\Component\Notifier\Recipient\SmsRecipientInterface') + ), + ]); +}; diff --git a/config/sets/symfony/symfony5/symfony52/symfony52-property-access.php b/config/sets/symfony/symfony5/symfony52/symfony52-property-access.php new file mode 100644 index 00000000..d4d50c69 --- /dev/null +++ b/config/sets/symfony/symfony5/symfony52/symfony52-property-access.php @@ -0,0 +1,13 @@ +rules([ + // https://github.com/symfony/symfony/blob/5.x/UPGRADE-5.2.md#propertyaccess + PropertyAccessorCreationBooleanToFlagsRector::class, + ]); +}; diff --git a/config/sets/symfony/symfony5/symfony52/symfony52-property-info.php b/config/sets/symfony/symfony5/symfony52/symfony52-property-info.php new file mode 100644 index 00000000..11f3c564 --- /dev/null +++ b/config/sets/symfony/symfony5/symfony52/symfony52-property-info.php @@ -0,0 +1,13 @@ +rules([ + // https://github.com/symfony/symfony/blob/5.x/UPGRADE-5.2.md#propertyinfo + ReflectionExtractorEnableMagicCallExtractorRector::class, + ]); +}; diff --git a/config/sets/symfony/symfony5/symfony52/symfony52-security-core.php b/config/sets/symfony/symfony5/symfony52/symfony52-security-core.php new file mode 100644 index 00000000..82a2c9fa --- /dev/null +++ b/config/sets/symfony/symfony5/symfony52/symfony52-security-core.php @@ -0,0 +1,53 @@ +ruleWithConfiguration(RenameMethodRector::class, [ + new MethodCallRename( + 'Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken', + 'setProviderKey', + 'setFirewallName' + ), + new MethodCallRename( + 'Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken', + 'getProviderKey', + 'getFirewallName' + ), + new MethodCallRename( + 'Symfony\Component\Security\Core\Authentication\Token\RememberMeToken', + 'setProviderKey', + 'setFirewallName' + ), + new MethodCallRename( + 'Symfony\Component\Security\Core\Authentication\Token\RememberMeToken', + 'getProviderKey', + 'getFirewallName' + ), + new MethodCallRename( + 'Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken', + 'setProviderKey', + 'setFirewallName' + ), + new MethodCallRename( + 'Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken', + 'getProviderKey', + 'getFirewallName' + ), + new MethodCallRename( + 'Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken', + 'setProviderKey', + 'setFirewallName' + ), + new MethodCallRename( + 'Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken', + 'getProviderKey', + 'getFirewallName' + ), + ]); + +}; diff --git a/config/sets/symfony/symfony5/symfony52/symfony52-security-http.php b/config/sets/symfony/symfony5/symfony52/symfony52-security-http.php new file mode 100644 index 00000000..94101332 --- /dev/null +++ b/config/sets/symfony/symfony5/symfony52/symfony52-security-http.php @@ -0,0 +1,45 @@ +ruleWithConfiguration(RenameClassConstFetchRector::class, [ + new RenameClassAndConstFetch( + 'Symfony\Component\Security\Http\Firewall\AccessListener', + 'PUBLIC_ACCESS', + 'Symfony\Component\Security\Core\Authorization\Voter\AuthenticatedVoter', + 'PUBLIC_ACCESS' + ), + ]); + + # https://github.com/symfony/symfony/blob/5.x/UPGRADE-5.2.md#security + $rectorConfig->ruleWithConfiguration(RenamePropertyRector::class, [ + new RenameProperty( + 'Symfony\Component\Security\Http\RememberMe\AbstractRememberMeServices', + 'providerKey', + 'firewallName' + ), + ]); + + $rectorConfig->ruleWithConfiguration(RenameMethodRector::class, [ + new MethodCallRename( + 'Symfony\Component\Security\Http\Authentication\DefaultAuthenticationSuccessHandler', + 'setProviderKey', + 'setFirewallName' + ), + new MethodCallRename( + 'Symfony\Component\Security\Http\Authentication\DefaultAuthenticationSuccessHandler', + 'getProviderKey', + 'getFirewallName' + ), + ]); +}; diff --git a/config/sets/symfony/symfony5/symfony52/symfony52-validator.php b/config/sets/symfony/symfony5/symfony52/symfony52-validator.php new file mode 100644 index 00000000..88120808 --- /dev/null +++ b/config/sets/symfony/symfony5/symfony52/symfony52-validator.php @@ -0,0 +1,13 @@ +rules([ + # https://github.com/symfony/symfony/blob/5.x/UPGRADE-5.2.md#validator + ValidatorBuilderEnableAnnotationMappingRector::class, + ]); +}; diff --git a/rules/Symfony52/Rector/New_/PropertyAccessorCreationBooleanToFlagsRector.php b/rules/Symfony52/Rector/New_/PropertyAccessorCreationBooleanToFlagsRector.php index 71451c89..3e656cd3 100644 --- a/rules/Symfony52/Rector/New_/PropertyAccessorCreationBooleanToFlagsRector.php +++ b/rules/Symfony52/Rector/New_/PropertyAccessorCreationBooleanToFlagsRector.php @@ -31,6 +31,8 @@ public function getRuleDefinition(): RuleDefinition return new RuleDefinition('Changes first argument of PropertyAccessor::__construct() to flags from boolean', [ new CodeSample( <<<'CODE_SAMPLE' +use Symfony\Component\PropertyAccess\PropertyAccessor; + class SomeClass { public function run() @@ -41,6 +43,8 @@ public function run() CODE_SAMPLE , <<<'CODE_SAMPLE' +use Symfony\Component\PropertyAccess\PropertyAccessor; + class SomeClass { public function run() diff --git a/src/Set/SetProvider/Symfony5SetProvider.php b/src/Set/SetProvider/Symfony5SetProvider.php index 20956163..53085b80 100644 --- a/src/Set/SetProvider/Symfony5SetProvider.php +++ b/src/Set/SetProvider/Symfony5SetProvider.php @@ -127,10 +127,72 @@ public function provide(): array new ComposerTriggeredSet( SetGroup::SYMFONY, - 'symfony/*', + 'symfony/symfony', '5.2', __DIR__ . '/../../../config/sets/symfony/symfony5/symfony52.php' ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/dependency-injection', + '5.2', + __DIR__ . '/../../../config/sets/symfony/symfony5/symfony52/symfony52-dependency-injection.php', + ), + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/forms', + '5.2', + __DIR__ . '/../../../config/sets/symfony/symfony5/symfony52/symfony52-forms.php', + ), + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/http-foundation', + '5.2', + __DIR__ . '/../../../config/sets/symfony/symfony5/symfony52/symfony52-http-foundation.php', + ), + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/mime', + '5.2', + __DIR__ . '/../../../config/sets/symfony/symfony5/symfony52/symfony52-mime.php', + ), + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/notifier', + '5.2', + __DIR__ . '/../../../config/sets/symfony/symfony5/symfony52/symfony52-notifier.php', + ), + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/property-access', + '5.2', + __DIR__ . '/../../../config/sets/symfony/symfony5/symfony52/symfony52-property-access.php', + ), + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/property-info', + '5.2', + __DIR__ . '/../../../config/sets/symfony/symfony5/symfony52/symfony52-property-info.php', + ), + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/security-core', + '5.2', + __DIR__ . '/../../../config/sets/symfony/symfony5/symfony52/symfony52-security-core.php', + ), + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/security-http', + '5.2', + __DIR__ . '/../../../config/sets/symfony/symfony5/symfony52/symfony52-security-http.php', + ), + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/validator', + '5.2', + __DIR__ . '/../../../config/sets/symfony/symfony5/symfony52/symfony52-validator.php', + ), + new ComposerTriggeredSet( SetGroup::SYMFONY, 'symfony/*', From e2c8f99b3cf96cf96e071f5675dcb7ecb2793120 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Mon, 5 May 2025 06:05:32 +0700 Subject: [PATCH 43/53] Fix typo symfony/forms -> symfony/form (#737) --- config/sets/symfony/symfony3/symfony30.php | 2 +- .../symfony30/{symfony30-forms.php => symfony30-form.php} | 0 config/sets/symfony/symfony4/symfony40.php | 2 +- .../symfony40/{symfony40-forms.php => symfony40-form.php} | 0 config/sets/symfony/symfony4/symfony42.php | 2 +- .../symfony42/{symfony42-forms.php => symfony42-form.php} | 0 config/sets/symfony/symfony5/symfony51.php | 2 +- .../symfony51/{symfony51-forms.php => symfony51-form.php} | 0 config/sets/symfony/symfony5/symfony52.php | 2 +- .../symfony52/{symfony52-forms.php => symfony52-form.php} | 0 src/Set/SetProvider/Symfony3SetProvider.php | 4 ++-- src/Set/SetProvider/Symfony4SetProvider.php | 8 ++++---- src/Set/SetProvider/Symfony5SetProvider.php | 8 ++++---- 13 files changed, 15 insertions(+), 15 deletions(-) rename config/sets/symfony/symfony3/symfony30/{symfony30-forms.php => symfony30-form.php} (100%) rename config/sets/symfony/symfony4/symfony40/{symfony40-forms.php => symfony40-form.php} (100%) rename config/sets/symfony/symfony4/symfony42/{symfony42-forms.php => symfony42-form.php} (100%) rename config/sets/symfony/symfony5/symfony51/{symfony51-forms.php => symfony51-form.php} (100%) rename config/sets/symfony/symfony5/symfony52/{symfony52-forms.php => symfony52-form.php} (100%) diff --git a/config/sets/symfony/symfony3/symfony30.php b/config/sets/symfony/symfony3/symfony30.php index dd527cd4..402cbcbb 100644 --- a/config/sets/symfony/symfony3/symfony30.php +++ b/config/sets/symfony/symfony3/symfony30.php @@ -10,7 +10,7 @@ return static function (RectorConfig $rectorConfig): void { $rectorConfig->import(__DIR__ . '/symfony30/symfony30-class-loader.php'); $rectorConfig->import(__DIR__ . '/symfony30/symfony30-console.php'); - $rectorConfig->import(__DIR__ . '/symfony30/symfony30-forms.php'); + $rectorConfig->import(__DIR__ . '/symfony30/symfony30-form.php'); $rectorConfig->import(__DIR__ . '/symfony30/symfony30-security.php'); $rectorConfig->import(__DIR__ . '/symfony30/symfony30-process.php'); $rectorConfig->import(__DIR__ . '/symfony30/symfony30-property-access.php'); diff --git a/config/sets/symfony/symfony3/symfony30/symfony30-forms.php b/config/sets/symfony/symfony3/symfony30/symfony30-form.php similarity index 100% rename from config/sets/symfony/symfony3/symfony30/symfony30-forms.php rename to config/sets/symfony/symfony3/symfony30/symfony30-form.php diff --git a/config/sets/symfony/symfony4/symfony40.php b/config/sets/symfony/symfony4/symfony40.php index 19e2cf46..c6b81271 100644 --- a/config/sets/symfony/symfony4/symfony40.php +++ b/config/sets/symfony/symfony4/symfony40.php @@ -8,6 +8,6 @@ $rectorConfig->import(__DIR__ . '/symfony40/symfony40-validator.php'); $rectorConfig->import(__DIR__ . '/symfony40/symfony40-dependency-injection.php'); $rectorConfig->import(__DIR__ . '/symfony40/symfony40-process.php'); - $rectorConfig->import(__DIR__ . '/symfony40/symfony40-forms.php'); + $rectorConfig->import(__DIR__ . '/symfony40/symfony40-form.php'); $rectorConfig->import(__DIR__ . '/symfony40/symfony40-var-dumper.php'); }; diff --git a/config/sets/symfony/symfony4/symfony40/symfony40-forms.php b/config/sets/symfony/symfony4/symfony40/symfony40-form.php similarity index 100% rename from config/sets/symfony/symfony4/symfony40/symfony40-forms.php rename to config/sets/symfony/symfony4/symfony40/symfony40-form.php diff --git a/config/sets/symfony/symfony4/symfony42.php b/config/sets/symfony/symfony4/symfony42.php index 2425a8a3..583a3676 100644 --- a/config/sets/symfony/symfony4/symfony42.php +++ b/config/sets/symfony/symfony4/symfony42.php @@ -17,6 +17,6 @@ $rectorConfig->import(__DIR__ . '/symfony42/symfony42-finder.php'); $rectorConfig->import(__DIR__ . '/symfony42/symfony42-monolog-bridge.php'); $rectorConfig->import(__DIR__ . '/symfony42/symfony42-serializer.php'); - $rectorConfig->import(__DIR__ . '/symfony42/symfony42-forms.php'); + $rectorConfig->import(__DIR__ . '/symfony42/symfony42-form.php'); $rectorConfig->import(__DIR__ . '/symfony42/symfony42-cache.php'); }; diff --git a/config/sets/symfony/symfony4/symfony42/symfony42-forms.php b/config/sets/symfony/symfony4/symfony42/symfony42-form.php similarity index 100% rename from config/sets/symfony/symfony4/symfony42/symfony42-forms.php rename to config/sets/symfony/symfony4/symfony42/symfony42-form.php diff --git a/config/sets/symfony/symfony5/symfony51.php b/config/sets/symfony/symfony5/symfony51.php index c0a7ece1..a85f399f 100644 --- a/config/sets/symfony/symfony5/symfony51.php +++ b/config/sets/symfony/symfony5/symfony51.php @@ -10,7 +10,7 @@ $rectorConfig->import(__DIR__ . '/symfony51/symfony51-console.php'); $rectorConfig->import(__DIR__ . '/symfony51/symfony51-dependency-injection.php'); $rectorConfig->import(__DIR__ . '/symfony51/symfony51-event-dispatcher.php'); - $rectorConfig->import(__DIR__ . '/symfony51/symfony51-forms.php'); + $rectorConfig->import(__DIR__ . '/symfony51/symfony51-form.php'); $rectorConfig->import(__DIR__ . '/symfony51/symfony51-framework-bundle.php'); $rectorConfig->import(__DIR__ . '/symfony51/symfony51-http-foundation.php'); $rectorConfig->import(__DIR__ . '/symfony51/symfony51-inflector.php'); diff --git a/config/sets/symfony/symfony5/symfony51/symfony51-forms.php b/config/sets/symfony/symfony5/symfony51/symfony51-form.php similarity index 100% rename from config/sets/symfony/symfony5/symfony51/symfony51-forms.php rename to config/sets/symfony/symfony5/symfony51/symfony51-form.php diff --git a/config/sets/symfony/symfony5/symfony52.php b/config/sets/symfony/symfony5/symfony52.php index 8571b4c9..85acffd3 100644 --- a/config/sets/symfony/symfony5/symfony52.php +++ b/config/sets/symfony/symfony5/symfony52.php @@ -11,7 +11,7 @@ // $rectorConfig->sets([SymfonySetList::ANNOTATIONS_TO_ATTRIBUTES]); $rectorConfig->import(__DIR__ . '/symfony52/symfony52-dependency-injection.php'); - $rectorConfig->import(__DIR__ . '/symfony52/symfony52-forms.php'); + $rectorConfig->import(__DIR__ . '/symfony52/symfony52-form.php'); $rectorConfig->import(__DIR__ . '/symfony52/symfony52-http-foundation.php'); $rectorConfig->import(__DIR__ . '/symfony52/symfony52-mime.php'); $rectorConfig->import(__DIR__ . '/symfony52/symfony52-notifier.php'); diff --git a/config/sets/symfony/symfony5/symfony52/symfony52-forms.php b/config/sets/symfony/symfony5/symfony52/symfony52-form.php similarity index 100% rename from config/sets/symfony/symfony5/symfony52/symfony52-forms.php rename to config/sets/symfony/symfony5/symfony52/symfony52-form.php diff --git a/src/Set/SetProvider/Symfony3SetProvider.php b/src/Set/SetProvider/Symfony3SetProvider.php index 8ff0343f..ad25987c 100644 --- a/src/Set/SetProvider/Symfony3SetProvider.php +++ b/src/Set/SetProvider/Symfony3SetProvider.php @@ -47,9 +47,9 @@ public function provide(): array new ComposerTriggeredSet( SetGroup::SYMFONY, - 'symfony/forms', + 'symfony/form', '3.0', - __DIR__ . '/../../../config/sets/symfony/symfony3/symfony30/symfony30-forms.php' + __DIR__ . '/../../../config/sets/symfony/symfony3/symfony30/symfony30-form.php' ), new ComposerTriggeredSet( diff --git a/src/Set/SetProvider/Symfony4SetProvider.php b/src/Set/SetProvider/Symfony4SetProvider.php index 30c3b1dc..d2f8998a 100644 --- a/src/Set/SetProvider/Symfony4SetProvider.php +++ b/src/Set/SetProvider/Symfony4SetProvider.php @@ -54,9 +54,9 @@ public function provide(): array new ComposerTriggeredSet( SetGroup::SYMFONY, - 'symfony/forms', + 'symfony/form', '4.0', - __DIR__ . '/../../../config/sets/symfony/symfony4/symfony40/symfony40-forms.php' + __DIR__ . '/../../../config/sets/symfony/symfony4/symfony40/symfony40-form.php' ), new ComposerTriggeredSet( @@ -152,9 +152,9 @@ public function provide(): array new ComposerTriggeredSet( SetGroup::SYMFONY, - 'symfony/forms', + 'symfony/form', '4.2', - __DIR__ . '/../../../config/sets/symfony/symfony4/symfony42/symfony42-forms.php' + __DIR__ . '/../../../config/sets/symfony/symfony4/symfony42/symfony42-form.php' ), new ComposerTriggeredSet( diff --git a/src/Set/SetProvider/Symfony5SetProvider.php b/src/Set/SetProvider/Symfony5SetProvider.php index 53085b80..650c2efb 100644 --- a/src/Set/SetProvider/Symfony5SetProvider.php +++ b/src/Set/SetProvider/Symfony5SetProvider.php @@ -78,9 +78,9 @@ public function provide(): array new ComposerTriggeredSet( SetGroup::SYMFONY, - 'symfony/forms', + 'symfony/form', '5.1', - __DIR__ . '/../../../config/sets/symfony/symfony5/symfony51/symfony51-forms.php' + __DIR__ . '/../../../config/sets/symfony/symfony5/symfony51/symfony51-form.php' ), new ComposerTriggeredSet( @@ -140,9 +140,9 @@ public function provide(): array ), new ComposerTriggeredSet( SetGroup::SYMFONY, - 'symfony/forms', + 'symfony/form', '5.2', - __DIR__ . '/../../../config/sets/symfony/symfony5/symfony52/symfony52-forms.php', + __DIR__ . '/../../../config/sets/symfony/symfony5/symfony52/symfony52-form.php', ), new ComposerTriggeredSet( SetGroup::SYMFONY, From 269aaae2de0ce4a6aed8cd6d953aba0bce1a5beb Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Mon, 5 May 2025 07:01:11 +0700 Subject: [PATCH 44/53] [symfony 5.3] split of configs per package (#738) * [symfony 5.3] split of configs per package * register symfony53-http-foundation * register symfony53-http-foundation * fix typo path * add symfony53-console * add symfony53-http-kernel * add symfony53-http-kernel * remove unused imports * fix name * comment like other * remove unused imports * add symfony53-core * add symfony53-mailer * add symfony53-form * add symfony53 * add symfony53-framework-bundle --- config/sets/symfony/symfony5/symfony52.php | 1 - config/sets/symfony/symfony5/symfony53.php | 111 ++---------------- .../symfony5/symfony53/symfony53-console.php | 18 +++ .../symfony5/symfony53/symfony53-form.php | 27 +++++ .../symfony53/symfony53-framework-bundle.php | 10 ++ .../symfony53/symfony53-http-foundation.php | 18 +++ .../symfony53/symfony53-http-kernel.php | 25 ++++ .../symfony5/symfony53/symfony53-mailer.php | 18 +++ .../symfony53/symfony53-security-core.php | 49 ++++++++ rector.php | 2 +- .../StringExtensionToConfigBuilderRector.php | 1 - .../CollectServiceArgumentsNodeVisitor.php | 1 - .../Trait_/TraitGetByTypeToInjectRector.php | 1 - src/Set/SetProvider/Symfony5SetProvider.php | 52 +++++++- 14 files changed, 226 insertions(+), 108 deletions(-) create mode 100644 config/sets/symfony/symfony5/symfony53/symfony53-console.php create mode 100644 config/sets/symfony/symfony5/symfony53/symfony53-form.php create mode 100644 config/sets/symfony/symfony5/symfony53/symfony53-framework-bundle.php create mode 100644 config/sets/symfony/symfony5/symfony53/symfony53-http-foundation.php create mode 100644 config/sets/symfony/symfony5/symfony53/symfony53-http-kernel.php create mode 100644 config/sets/symfony/symfony5/symfony53/symfony53-mailer.php create mode 100644 config/sets/symfony/symfony5/symfony53/symfony53-security-core.php diff --git a/config/sets/symfony/symfony5/symfony52.php b/config/sets/symfony/symfony5/symfony52.php index 85acffd3..f5ccb00b 100644 --- a/config/sets/symfony/symfony5/symfony52.php +++ b/config/sets/symfony/symfony5/symfony52.php @@ -3,7 +3,6 @@ declare(strict_types=1); use Rector\Config\RectorConfig; -use Rector\Symfony\Set\SymfonySetList; # https://github.com/symfony/symfony/blob/5.x/UPGRADE-5.2.md diff --git a/config/sets/symfony/symfony5/symfony53.php b/config/sets/symfony/symfony5/symfony53.php index 4f187dba..6f02d381 100644 --- a/config/sets/symfony/symfony5/symfony53.php +++ b/config/sets/symfony/symfony5/symfony53.php @@ -2,112 +2,19 @@ declare(strict_types=1); -use PHPStan\Type\ObjectType; -use PHPStan\Type\StringType; use Rector\Config\RectorConfig; -use Rector\Renaming\Rector\ClassConstFetch\RenameClassConstFetchRector; -use Rector\Renaming\Rector\MethodCall\RenameMethodRector; -use Rector\Renaming\Rector\Name\RenameClassRector; -use Rector\Renaming\ValueObject\MethodCallRename; -use Rector\Renaming\ValueObject\RenameClassConstFetch; -use Rector\Symfony\Set\SymfonySetList; use Rector\Symfony\Symfony53\Rector\StaticPropertyFetch\KernelTestCaseContainerPropertyDeprecationRector; -use Rector\TypeDeclaration\Rector\ClassMethod\AddParamTypeDeclarationRector; -use Rector\TypeDeclaration\Rector\ClassMethod\AddReturnTypeDeclarationRector; -use Rector\TypeDeclaration\ValueObject\AddParamTypeDeclaration; -use Rector\TypeDeclaration\ValueObject\AddReturnTypeDeclaration; # https://github.com/symfony/symfony/blob/5.4/UPGRADE-5.3.md return static function (RectorConfig $rectorConfig): void { - $rectorConfig->sets([SymfonySetList::ANNOTATIONS_TO_ATTRIBUTES]); - - $rectorConfig->ruleWithConfiguration(RenameMethodRector::class, [ - // @see https://github.com/symfony/symfony/pull/40536 - new MethodCallRename( - 'Symfony\Component\HttpFoundation\RequestStack', - 'getMasterRequest', - 'getMainRequest', - ), - new MethodCallRename('Symfony\Component\Console\Helper\Helper', 'strlen', 'width'), - new MethodCallRename( - 'Symfony\Component\Console\Helper\Helper', - 'strlenWithoutDecoration', - 'removeDecoration', - ), - new MethodCallRename('Symfony\Component\HttpKernel\Event\KernelEvent', 'isMasterRequest', 'isMainRequest'), - new MethodCallRename( - 'Symfony\Component\Security\Core\Authentication\Token\TokenInterface', - 'getUsername', - 'getUserIdentifier', - ), - new MethodCallRename( - 'Symfony\Component\Security\Core\Exception\UsernameNotFoundException', - 'getUsername', - 'getUserIdentifier' - ), - new MethodCallRename( - 'Symfony\Component\Security\Core\Exception\UsernameNotFoundException', - 'setUsername', - 'setUserIdentifier' - ), - new MethodCallRename( - 'Symfony\Component\Security\Core\Authentication\RememberMe\PersistentTokenInterface', - 'getUsername', - 'getUserIdentifier' - ), - ]); - - $rectorConfig->ruleWithConfiguration(RenameClassRector::class, [ - 'Symfony\Component\Security\Core\Exception\UsernameNotFoundException' => 'Symfony\Component\Security\Core\Exception\UserNotFoundException', - // @see https://github.com/symfony/symfony/pull/39802 - 'Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface' => 'Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactoryInterface', - 'Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder' => 'Symfony\Component\PasswordHasher\Hasher\MessageDigestPasswordHasher', - 'Symfony\Component\Security\Core\Encoder\MigratingPasswordEncoder' => 'Symfony\Component\PasswordHasher\Hasher\MigratingPasswordHasher', - 'Symfony\Component\Security\Core\Encoder\NativePasswordEncoder' => 'Symfony\Component\PasswordHasher\Hasher\NativePasswordHasher', - 'Symfony\Component\Security\Core\Encoder\PasswordEncoderInterface' => 'Symfony\Component\PasswordHasher\PasswordHasherInterface', - 'Symfony\Component\Security\Core\Encoder\Pbkdf2PasswordEncoder' => 'Symfony\Component\PasswordHasher\Hasher\Pbkdf2PasswordHasher', - 'Symfony\Component\Security\Core\Encoder\PlaintextPasswordEncoder' => 'Symfony\Component\PasswordHasher\Hasher\PlaintextPasswordHasher', - 'Symfony\Component\Security\Core\Encoder\SelfSaltingEncoderInterface' => 'Symfony\Component\PasswordHasher\LegacyPasswordHasherInterface', - 'Symfony\Component\Security\Core\Encoder\SodiumPasswordEncoder' => 'Symfony\Component\PasswordHasher\Hasher\SodiumPasswordHasher', - 'Symfony\Component\Security\Core\Encoder\UserPasswordEncoder' => 'Symfony\Component\PasswordHasher\Hasher\UserPasswordHasher', - 'Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface' => 'Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface', - ]); - - $rectorConfig->ruleWithConfiguration(AddReturnTypeDeclarationRector::class, [ - new AddReturnTypeDeclaration( - 'Symfony\Component\Mailer\Transport\AbstractTransportFactory', - 'getEndpoint', - new StringType(), - ), - ]); - - // rename constant - $rectorConfig->ruleWithConfiguration(RenameClassConstFetchRector::class, [ - // @see https://github.com/symfony/symfony/pull/40536 - new RenameClassConstFetch( - 'Symfony\Component\HttpKernel\HttpKernelInterface', - 'MASTER_REQUEST', - 'MAIN_REQUEST' - ), - ]); - - $rectorConfig->ruleWithConfiguration(AddParamTypeDeclarationRector::class, [ - // @see https://github.com/symfony/symfony/commit/ce77be2507631cd12e4ca37510dab37f4c2b759a - new AddParamTypeDeclaration( - 'Symfony\Component\Form\DataMapperInterface', - 'mapFormsToData', - 0, - new ObjectType(Traversable::class) - ), - // @see https://github.com/symfony/symfony/commit/ce77be2507631cd12e4ca37510dab37f4c2b759a - new AddParamTypeDeclaration( - 'Symfony\Component\Form\DataMapperInterface', - 'mapDataToForms', - 1, - new ObjectType(Traversable::class) - ), - ]); - - $rectorConfig->rules([KernelTestCaseContainerPropertyDeprecationRector::class]); + // $rectorConfig->sets([SymfonySetList::ANNOTATIONS_TO_ATTRIBUTES]); + + $rectorConfig->import(__DIR__ . '/symfony53/symfony53-http-foundation.php'); + $rectorConfig->import(__DIR__ . '/symfony53/symfony53-console.php'); + $rectorConfig->import(__DIR__ . '/symfony53/symfony53-http-kernel.php'); + $rectorConfig->import(__DIR__ . '/symfony53/symfony53-security-core.php'); + $rectorConfig->import(__DIR__ . '/symfony53/symfony53-mailer.php'); + $rectorConfig->import(__DIR__ . '/symfony53/symfony53-form.php'); + $rectorConfig->import(__DIR__ . '/symfony53/symfony53-framework-bundle.php'); }; diff --git a/config/sets/symfony/symfony5/symfony53/symfony53-console.php b/config/sets/symfony/symfony5/symfony53/symfony53-console.php new file mode 100644 index 00000000..0485b22c --- /dev/null +++ b/config/sets/symfony/symfony5/symfony53/symfony53-console.php @@ -0,0 +1,18 @@ +ruleWithConfiguration(RenameMethodRector::class, [ + new MethodCallRename('Symfony\Component\Console\Helper\Helper', 'strlen', 'width'), + new MethodCallRename( + 'Symfony\Component\Console\Helper\Helper', + 'strlenWithoutDecoration', + 'removeDecoration', + ), + ]); +}; diff --git a/config/sets/symfony/symfony5/symfony53/symfony53-form.php b/config/sets/symfony/symfony5/symfony53/symfony53-form.php new file mode 100644 index 00000000..107ed88f --- /dev/null +++ b/config/sets/symfony/symfony5/symfony53/symfony53-form.php @@ -0,0 +1,27 @@ +ruleWithConfiguration(AddParamTypeDeclarationRector::class, [ + // @see https://github.com/symfony/symfony/commit/ce77be2507631cd12e4ca37510dab37f4c2b759a + new AddParamTypeDeclaration( + 'Symfony\Component\Form\DataMapperInterface', + 'mapFormsToData', + 0, + new ObjectType(Traversable::class) + ), + // @see https://github.com/symfony/symfony/commit/ce77be2507631cd12e4ca37510dab37f4c2b759a + new AddParamTypeDeclaration( + 'Symfony\Component\Form\DataMapperInterface', + 'mapDataToForms', + 1, + new ObjectType(Traversable::class) + ), + ]); +}; diff --git a/config/sets/symfony/symfony5/symfony53/symfony53-framework-bundle.php b/config/sets/symfony/symfony5/symfony53/symfony53-framework-bundle.php new file mode 100644 index 00000000..989cb52d --- /dev/null +++ b/config/sets/symfony/symfony5/symfony53/symfony53-framework-bundle.php @@ -0,0 +1,10 @@ +rules([KernelTestCaseContainerPropertyDeprecationRector::class]); +}; diff --git a/config/sets/symfony/symfony5/symfony53/symfony53-http-foundation.php b/config/sets/symfony/symfony5/symfony53/symfony53-http-foundation.php new file mode 100644 index 00000000..fcbc160f --- /dev/null +++ b/config/sets/symfony/symfony5/symfony53/symfony53-http-foundation.php @@ -0,0 +1,18 @@ +ruleWithConfiguration(RenameMethodRector::class, [ + // @see https://github.com/symfony/symfony/pull/40536 + new MethodCallRename( + 'Symfony\Component\HttpFoundation\RequestStack', + 'getMasterRequest', + 'getMainRequest', + ), + ]); +}; diff --git a/config/sets/symfony/symfony5/symfony53/symfony53-http-kernel.php b/config/sets/symfony/symfony5/symfony53/symfony53-http-kernel.php new file mode 100644 index 00000000..89630fc7 --- /dev/null +++ b/config/sets/symfony/symfony5/symfony53/symfony53-http-kernel.php @@ -0,0 +1,25 @@ +ruleWithConfiguration(RenameMethodRector::class, [ + new MethodCallRename('Symfony\Component\HttpKernel\Event\KernelEvent', 'isMasterRequest', 'isMainRequest'), + ]); + + // rename constant + $rectorConfig->ruleWithConfiguration(RenameClassConstFetchRector::class, [ + // @see https://github.com/symfony/symfony/pull/40536 + new RenameClassConstFetch( + 'Symfony\Component\HttpKernel\HttpKernelInterface', + 'MASTER_REQUEST', + 'MAIN_REQUEST' + ), + ]); +}; diff --git a/config/sets/symfony/symfony5/symfony53/symfony53-mailer.php b/config/sets/symfony/symfony5/symfony53/symfony53-mailer.php new file mode 100644 index 00000000..01292441 --- /dev/null +++ b/config/sets/symfony/symfony5/symfony53/symfony53-mailer.php @@ -0,0 +1,18 @@ +ruleWithConfiguration(AddReturnTypeDeclarationRector::class, [ + new AddReturnTypeDeclaration( + 'Symfony\Component\Mailer\Transport\AbstractTransportFactory', + 'getEndpoint', + new StringType(), + ), + ]); +}; diff --git a/config/sets/symfony/symfony5/symfony53/symfony53-security-core.php b/config/sets/symfony/symfony5/symfony53/symfony53-security-core.php new file mode 100644 index 00000000..8fa47ded --- /dev/null +++ b/config/sets/symfony/symfony5/symfony53/symfony53-security-core.php @@ -0,0 +1,49 @@ +ruleWithConfiguration(RenameMethodRector::class, [ + new MethodCallRename( + 'Symfony\Component\Security\Core\Authentication\Token\TokenInterface', + 'getUsername', + 'getUserIdentifier', + ), + new MethodCallRename( + 'Symfony\Component\Security\Core\Exception\UsernameNotFoundException', + 'getUsername', + 'getUserIdentifier' + ), + new MethodCallRename( + 'Symfony\Component\Security\Core\Exception\UsernameNotFoundException', + 'setUsername', + 'setUserIdentifier' + ), + new MethodCallRename( + 'Symfony\Component\Security\Core\Authentication\RememberMe\PersistentTokenInterface', + 'getUsername', + 'getUserIdentifier' + ), + ]); + + $rectorConfig->ruleWithConfiguration(RenameClassRector::class, [ + 'Symfony\Component\Security\Core\Exception\UsernameNotFoundException' => 'Symfony\Component\Security\Core\Exception\UserNotFoundException', + // @see https://github.com/symfony/symfony/pull/39802 + 'Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface' => 'Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactoryInterface', + 'Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder' => 'Symfony\Component\PasswordHasher\Hasher\MessageDigestPasswordHasher', + 'Symfony\Component\Security\Core\Encoder\MigratingPasswordEncoder' => 'Symfony\Component\PasswordHasher\Hasher\MigratingPasswordHasher', + 'Symfony\Component\Security\Core\Encoder\NativePasswordEncoder' => 'Symfony\Component\PasswordHasher\Hasher\NativePasswordHasher', + 'Symfony\Component\Security\Core\Encoder\PasswordEncoderInterface' => 'Symfony\Component\PasswordHasher\PasswordHasherInterface', + 'Symfony\Component\Security\Core\Encoder\Pbkdf2PasswordEncoder' => 'Symfony\Component\PasswordHasher\Hasher\Pbkdf2PasswordHasher', + 'Symfony\Component\Security\Core\Encoder\PlaintextPasswordEncoder' => 'Symfony\Component\PasswordHasher\Hasher\PlaintextPasswordHasher', + 'Symfony\Component\Security\Core\Encoder\SelfSaltingEncoderInterface' => 'Symfony\Component\PasswordHasher\LegacyPasswordHasherInterface', + 'Symfony\Component\Security\Core\Encoder\SodiumPasswordEncoder' => 'Symfony\Component\PasswordHasher\Hasher\SodiumPasswordHasher', + 'Symfony\Component\Security\Core\Encoder\UserPasswordEncoder' => 'Symfony\Component\PasswordHasher\Hasher\UserPasswordHasher', + 'Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface' => 'Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface', + ]); +}; diff --git a/rector.php b/rector.php index f11081f4..3659749f 100644 --- a/rector.php +++ b/rector.php @@ -54,4 +54,4 @@ naming: true, rectorPreset: true ) - ->withImportNames(); + ->withImportNames(removeUnusedImports: true); diff --git a/rules/CodeQuality/Rector/Closure/StringExtensionToConfigBuilderRector.php b/rules/CodeQuality/Rector/Closure/StringExtensionToConfigBuilderRector.php index e4253930..b3b8bd3f 100644 --- a/rules/CodeQuality/Rector/Closure/StringExtensionToConfigBuilderRector.php +++ b/rules/CodeQuality/Rector/Closure/StringExtensionToConfigBuilderRector.php @@ -9,7 +9,6 @@ use PhpParser\Node\Expr\Closure; use PhpParser\Node\Expr\MethodCall; use PhpParser\Node\Expr\Variable; -use PhpParser\Node\Param; use PhpParser\Node\Stmt\Expression; use Rector\Exception\NotImplementedYetException; use Rector\Naming\Naming\PropertyNaming; diff --git a/rules/Configs/NodeVisitor/CollectServiceArgumentsNodeVisitor.php b/rules/Configs/NodeVisitor/CollectServiceArgumentsNodeVisitor.php index 6e8b5936..199d0048 100644 --- a/rules/Configs/NodeVisitor/CollectServiceArgumentsNodeVisitor.php +++ b/rules/Configs/NodeVisitor/CollectServiceArgumentsNodeVisitor.php @@ -6,7 +6,6 @@ use Nette\Utils\Strings; use PhpParser\Node; -use PhpParser\Node\Arg; use PhpParser\Node\ArrayItem; use PhpParser\Node\Expr; use PhpParser\Node\Expr\Array_; diff --git a/rules/DependencyInjection/Rector/Trait_/TraitGetByTypeToInjectRector.php b/rules/DependencyInjection/Rector/Trait_/TraitGetByTypeToInjectRector.php index 3c4921c8..febf5e27 100644 --- a/rules/DependencyInjection/Rector/Trait_/TraitGetByTypeToInjectRector.php +++ b/rules/DependencyInjection/Rector/Trait_/TraitGetByTypeToInjectRector.php @@ -8,7 +8,6 @@ use PhpParser\Node; use PhpParser\Node\Expr\MethodCall; use PhpParser\Node\Name\FullyQualified; -use PhpParser\Node\Param; use PhpParser\Node\PropertyItem; use PhpParser\Node\Stmt\Property; use PhpParser\Node\Stmt\Trait_; diff --git a/src/Set/SetProvider/Symfony5SetProvider.php b/src/Set/SetProvider/Symfony5SetProvider.php index 650c2efb..b5ac7572 100644 --- a/src/Set/SetProvider/Symfony5SetProvider.php +++ b/src/Set/SetProvider/Symfony5SetProvider.php @@ -195,10 +195,60 @@ public function provide(): array new ComposerTriggeredSet( SetGroup::SYMFONY, - 'symfony/*', + 'symfony/symfony', '5.3', __DIR__ . '/../../../config/sets/symfony/symfony5/symfony53.php' ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/http-foundation', + '5.3', + __DIR__ . '/../../../config/sets/symfony/symfony5/symfony53/symfony53-http-foundation.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/console', + '5.3', + __DIR__ . '/../../../config/sets/symfony/symfony5/symfony53/symfony53-console.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/http-kernel', + '5.3', + __DIR__ . '/../../../config/sets/symfony/symfony5/symfony53/symfony53-http-kernel.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/security-core', + '5.3', + __DIR__ . '/../../../config/sets/symfony/symfony5/symfony53/symfony53-security-core.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/security-mailer', + '5.3', + __DIR__ . '/../../../config/sets/symfony/symfony5/symfony53/symfony53-mailer.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/form', + '5.3', + __DIR__ . '/../../../config/sets/symfony/symfony5/symfony53/symfony53-form.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/framework-bundle', + '5.3', + __DIR__ . '/../../../config/sets/symfony/symfony5/symfony53/symfony53-framework-bundle.php' + ), + new ComposerTriggeredSet( SetGroup::SYMFONY, 'symfony/*', From b7bb9369b17941a1abe1c9c44ebf1572a7dceb1e Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Mon, 5 May 2025 12:03:44 +0700 Subject: [PATCH 45/53] [symfony 5.4] split of configs per package (#739) * [symfony 5.4] split of configs per package * [symfony 5.4] split of configs per package * add security-bundle * add security * add security * add cache * add http-kernel * add notifier * clean up --- config/sets/symfony/symfony5/symfony54.php | 78 ++----------------- .../symfony5/symfony54/symfony54-cache.php | 13 ++++ .../symfony54/symfony54-http-kernel.php | 14 ++++ .../symfony5/symfony54/symfony54-notifier.php | 14 ++++ .../symfony54/symfony54-security-bundle.php | 24 ++++++ .../symfony5/symfony54/symfony54-security.php | 42 ++++++++++ .../symfony54/symfony54-validator.php | 18 +++++ src/Set/SetProvider/Symfony5SetProvider.php | 44 ++++++++++- 8 files changed, 175 insertions(+), 72 deletions(-) create mode 100644 config/sets/symfony/symfony5/symfony54/symfony54-cache.php create mode 100644 config/sets/symfony/symfony5/symfony54/symfony54-http-kernel.php create mode 100644 config/sets/symfony/symfony5/symfony54/symfony54-notifier.php create mode 100644 config/sets/symfony/symfony5/symfony54/symfony54-security-bundle.php create mode 100644 config/sets/symfony/symfony5/symfony54/symfony54-security.php create mode 100644 config/sets/symfony/symfony5/symfony54/symfony54-validator.php diff --git a/config/sets/symfony/symfony5/symfony54.php b/config/sets/symfony/symfony5/symfony54.php index 21e4b258..e2ad6e04 100644 --- a/config/sets/symfony/symfony5/symfony54.php +++ b/config/sets/symfony/symfony5/symfony54.php @@ -3,80 +3,16 @@ declare(strict_types=1); use Rector\Config\RectorConfig; -use Rector\Php80\Rector\Class_\AnnotationToAttributeRector; -use Rector\Php80\ValueObject\AnnotationToAttribute; -use Rector\Renaming\Rector\ClassConstFetch\RenameClassConstFetchRector; -use Rector\Renaming\Rector\MethodCall\RenameMethodRector; -use Rector\Renaming\Rector\Name\RenameClassRector; -use Rector\Renaming\ValueObject\MethodCallRename; -use Rector\Renaming\ValueObject\RenameClassAndConstFetch; -use Rector\Renaming\ValueObject\RenameClassConstFetch; -use Rector\Symfony\Set\SymfonySetList; # https://github.com/symfony/symfony/blob/5.x/UPGRADE-5.4.md return static function (RectorConfig $rectorConfig): void { - $rectorConfig->sets([SymfonySetList::ANNOTATIONS_TO_ATTRIBUTES]); + // $rectorConfig->sets([SymfonySetList::ANNOTATIONS_TO_ATTRIBUTES]); - // @see https://symfony.com/blog/new-in-symfony-5-4-nested-validation-attributes - // @see https://github.com/symfony/symfony/pull/41994 - $rectorConfig->ruleWithConfiguration(AnnotationToAttributeRector::class, [ - new AnnotationToAttribute('Symfony\Component\Validator\Constraints\All'), - new AnnotationToAttribute('Symfony\Component\Validator\Constraints\Collection'), - new AnnotationToAttribute('Symfony\Component\Validator\Constraints\AtLeastOneOf'), - new AnnotationToAttribute('Symfony\Component\Validator\Constraints\Sequentially'), - ]); - $rectorConfig->ruleWithConfiguration(RenameMethodRector::class, [ - // @see https://github.com/symfony/symfony/pull/42582 - new MethodCallRename( - 'Symfony\Bundle\SecurityBundle\Security\FirewallConfig', - 'getListeners', - 'getAuthenticators' - ), - // @see https://github.com/symfony/symfony/pull/41754 - new MethodCallRename( - 'Symfony\Bundle\SecurityBundle\DependencyInjection\SecurityExtension', - 'addSecurityListenerFactory', - 'addAuthenticatorFactory' - ), - ]); - - $rectorConfig->ruleWithConfiguration(RenameClassConstFetchRector::class, [ - new RenameClassAndConstFetch( - 'Symfony\Component\Security\Core\AuthenticationEvents', - 'AUTHENTICATION_SUCCESS', - 'Symfony\Component\Security\Core\Event\AuthenticationSuccessEvent', - 'class' - ), - new RenameClassAndConstFetch( - 'Symfony\Component\Security\Core\AuthenticationEvents', - 'AUTHENTICATION_FAILURE', - 'Symfony\Component\Security\Core\Event\AuthenticationFailureEvent', - 'class' - ), - // @see https://github.com/symfony/symfony/pull/42510 - new RenameClassConstFetch( - 'Symfony\Component\Security\Core\Authorization\Voter\AuthenticatedVoter', - 'IS_ANONYMOUS', - 'PUBLIC_ACCESS' - ), - new RenameClassConstFetch( - 'Symfony\Component\Security\Core\Authorization\Voter\AuthenticatedVoter', - 'IS_AUTHENTICATED_ANONYMOUSLY', - 'PUBLIC_ACCESS' - ), - ]); - - $rectorConfig->ruleWithConfiguration(RenameClassRector::class, [ - // @see https://github.com/symfony/symfony/pull/42050 - 'Symfony\Component\Security\Http\Event\DeauthenticatedEvent' => 'Symfony\Component\Security\Http\Event\TokenDeauthenticatedEvent', - // @see https://github.com/symfony/symfony/pull/42965 - 'Symfony\Component\Cache\Adapter\DoctrineAdapter' => 'Doctrine\Common\Cache\Psr6\CacheAdapter', - // @see https://github.com/symfony/symfony/pull/45615 - 'Symfony\Component\HttpKernel\EventListener\AbstractTestSessionListener' => 'Symfony\Component\HttpKernel\EventListener\AbstractSessionListener', - 'Symfony\Component\HttpKernel\EventListener\TestSessionListener' => 'Symfony\Component\HttpKernel\EventListener\SessionListener', - // @see https://github.com/symfony/symfony/pull/44271 - 'Symfony\Component\Notifier\Bridge\Nexmo\NexmoTransportFactory' => 'Symfony\Component\Notifier\Bridge\Vonage\VonageTransportFactory', - 'Symfony\Component\Notifier\Bridge\Nexmo\NexmoTransport' => 'Symfony\Component\Notifier\Bridge\Vonage\VonageTransport', - ]); + $rectorConfig->import(__DIR__ . '/symfony54/symfony54-validator.php'); + $rectorConfig->import(__DIR__ . '/symfony54/symfony54-security-bundle.php'); + $rectorConfig->import(__DIR__ . '/symfony54/symfony54-security.php'); + $rectorConfig->import(__DIR__ . '/symfony54/symfony54-cache.php'); + $rectorConfig->import(__DIR__ . '/symfony54/symfony54-http-kernel.php'); + $rectorConfig->import(__DIR__ . '/symfony54/symfony54-notifier.php'); }; diff --git a/config/sets/symfony/symfony5/symfony54/symfony54-cache.php b/config/sets/symfony/symfony5/symfony54/symfony54-cache.php new file mode 100644 index 00000000..fbdfcd42 --- /dev/null +++ b/config/sets/symfony/symfony5/symfony54/symfony54-cache.php @@ -0,0 +1,13 @@ +ruleWithConfiguration(RenameClassRector::class, [ + // @see https://github.com/symfony/symfony/pull/42965 + 'Symfony\Component\Cache\Adapter\DoctrineAdapter' => 'Doctrine\Common\Cache\Psr6\CacheAdapter', + ]); +}; diff --git a/config/sets/symfony/symfony5/symfony54/symfony54-http-kernel.php b/config/sets/symfony/symfony5/symfony54/symfony54-http-kernel.php new file mode 100644 index 00000000..40b2318f --- /dev/null +++ b/config/sets/symfony/symfony5/symfony54/symfony54-http-kernel.php @@ -0,0 +1,14 @@ +ruleWithConfiguration(RenameClassRector::class, [ + // @see https://github.com/symfony/symfony/pull/45615 + 'Symfony\Component\HttpKernel\EventListener\AbstractTestSessionListener' => 'Symfony\Component\HttpKernel\EventListener\AbstractSessionListener', + 'Symfony\Component\HttpKernel\EventListener\TestSessionListener' => 'Symfony\Component\HttpKernel\EventListener\SessionListener', + ]); +}; diff --git a/config/sets/symfony/symfony5/symfony54/symfony54-notifier.php b/config/sets/symfony/symfony5/symfony54/symfony54-notifier.php new file mode 100644 index 00000000..aeee6b81 --- /dev/null +++ b/config/sets/symfony/symfony5/symfony54/symfony54-notifier.php @@ -0,0 +1,14 @@ +ruleWithConfiguration(RenameClassRector::class, [ + // @see https://github.com/symfony/symfony/pull/44271 + 'Symfony\Component\Notifier\Bridge\Nexmo\NexmoTransportFactory' => 'Symfony\Component\Notifier\Bridge\Vonage\VonageTransportFactory', + 'Symfony\Component\Notifier\Bridge\Nexmo\NexmoTransport' => 'Symfony\Component\Notifier\Bridge\Vonage\VonageTransport', + ]); +}; diff --git a/config/sets/symfony/symfony5/symfony54/symfony54-security-bundle.php b/config/sets/symfony/symfony5/symfony54/symfony54-security-bundle.php new file mode 100644 index 00000000..ac917b7b --- /dev/null +++ b/config/sets/symfony/symfony5/symfony54/symfony54-security-bundle.php @@ -0,0 +1,24 @@ +ruleWithConfiguration(RenameMethodRector::class, [ + // @see https://github.com/symfony/symfony/pull/42582 + new MethodCallRename( + 'Symfony\Bundle\SecurityBundle\Security\FirewallConfig', + 'getListeners', + 'getAuthenticators' + ), + // @see https://github.com/symfony/symfony/pull/41754 + new MethodCallRename( + 'Symfony\Bundle\SecurityBundle\DependencyInjection\SecurityExtension', + 'addSecurityListenerFactory', + 'addAuthenticatorFactory' + ), + ]); +}; diff --git a/config/sets/symfony/symfony5/symfony54/symfony54-security.php b/config/sets/symfony/symfony5/symfony54/symfony54-security.php new file mode 100644 index 00000000..d5791ed2 --- /dev/null +++ b/config/sets/symfony/symfony5/symfony54/symfony54-security.php @@ -0,0 +1,42 @@ +ruleWithConfiguration(RenameClassConstFetchRector::class, [ + new RenameClassAndConstFetch( + 'Symfony\Component\Security\Core\AuthenticationEvents', + 'AUTHENTICATION_SUCCESS', + 'Symfony\Component\Security\Core\Event\AuthenticationSuccessEvent', + 'class' + ), + new RenameClassAndConstFetch( + 'Symfony\Component\Security\Core\AuthenticationEvents', + 'AUTHENTICATION_FAILURE', + 'Symfony\Component\Security\Core\Event\AuthenticationFailureEvent', + 'class' + ), + // @see https://github.com/symfony/symfony/pull/42510 + new RenameClassConstFetch( + 'Symfony\Component\Security\Core\Authorization\Voter\AuthenticatedVoter', + 'IS_ANONYMOUS', + 'PUBLIC_ACCESS' + ), + new RenameClassConstFetch( + 'Symfony\Component\Security\Core\Authorization\Voter\AuthenticatedVoter', + 'IS_AUTHENTICATED_ANONYMOUSLY', + 'PUBLIC_ACCESS' + ), + ]); + + $rectorConfig->ruleWithConfiguration(RenameClassRector::class, [ + // @see https://github.com/symfony/symfony/pull/42050 + 'Symfony\Component\Security\Http\Event\DeauthenticatedEvent' => 'Symfony\Component\Security\Http\Event\TokenDeauthenticatedEvent', + ]); +}; diff --git a/config/sets/symfony/symfony5/symfony54/symfony54-validator.php b/config/sets/symfony/symfony5/symfony54/symfony54-validator.php new file mode 100644 index 00000000..f3a446e3 --- /dev/null +++ b/config/sets/symfony/symfony5/symfony54/symfony54-validator.php @@ -0,0 +1,18 @@ +ruleWithConfiguration(AnnotationToAttributeRector::class, [ + new AnnotationToAttribute('Symfony\Component\Validator\Constraints\All'), + new AnnotationToAttribute('Symfony\Component\Validator\Constraints\Collection'), + new AnnotationToAttribute('Symfony\Component\Validator\Constraints\AtLeastOneOf'), + new AnnotationToAttribute('Symfony\Component\Validator\Constraints\Sequentially'), + ]); +}; diff --git a/src/Set/SetProvider/Symfony5SetProvider.php b/src/Set/SetProvider/Symfony5SetProvider.php index b5ac7572..dc3570fa 100644 --- a/src/Set/SetProvider/Symfony5SetProvider.php +++ b/src/Set/SetProvider/Symfony5SetProvider.php @@ -251,10 +251,52 @@ public function provide(): array new ComposerTriggeredSet( SetGroup::SYMFONY, - 'symfony/*', + 'symfony/symfony', '5.4', __DIR__ . '/../../../config/sets/symfony/symfony5/symfony54.php' ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/validator', + '5.4', + __DIR__ . '/../../../config/sets/symfony/symfony5/symfony54/symfony54-validator.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/security-bundle', + '5.4', + __DIR__ . '/../../../config/sets/symfony/symfony5/symfony54/symfony54-security-bundle.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/security-bundle', + '5.4', + __DIR__ . '/../../../config/sets/symfony/symfony5/symfony54/symfony54-security.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/cache', + '5.4', + __DIR__ . '/../../../config/sets/symfony/symfony5/symfony54/symfony54-cache.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/http-kernel', + '5.4', + __DIR__ . '/../../../config/sets/symfony/symfony5/symfony54/symfony54-http-kernel.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/notifier', + '5.4', + __DIR__ . '/../../../config/sets/symfony/symfony5/symfony54/symfony54-notifier.php' + ), ]; } } From 5ff23b02f70e66f4d427e55aa4bfd8b229eecac1 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Mon, 5 May 2025 13:50:30 +0700 Subject: [PATCH 46/53] [symfony 60] split of configs per package (#740) * [symfony 60] split of configs per package * add symfony-contracts * add symfony-contracts * add symfony-config * add framework-bundle * add doctrine-bridge * add security core --- config/sets/symfony/symfony6/symfony60.php | 75 ++----------------- .../symfony6/symfony60/symfony60-config.php | 25 +++++++ .../symfony60/symfony60-contracts.php | 13 ++++ .../symfony60-dependency-injection.php | 18 +++++ .../symfony60/symfony60-doctrine-bridge.php | 20 +++++ .../symfony60/symfony60-framework-bundle.php | 21 ++++++ .../symfony60/symfony60-security-core.php | 23 ++++++ src/Set/SetProvider/Symfony6SetProvider.php | 45 ++++++++++- 8 files changed, 172 insertions(+), 68 deletions(-) create mode 100644 config/sets/symfony/symfony6/symfony60/symfony60-config.php create mode 100644 config/sets/symfony/symfony6/symfony60/symfony60-contracts.php create mode 100644 config/sets/symfony/symfony6/symfony60/symfony60-dependency-injection.php create mode 100644 config/sets/symfony/symfony6/symfony60/symfony60-doctrine-bridge.php create mode 100644 config/sets/symfony/symfony6/symfony60/symfony60-framework-bundle.php create mode 100644 config/sets/symfony/symfony6/symfony60/symfony60-security-core.php diff --git a/config/sets/symfony/symfony6/symfony60.php b/config/sets/symfony/symfony6/symfony60.php index b6afc8a1..e80bde6d 100644 --- a/config/sets/symfony/symfony6/symfony60.php +++ b/config/sets/symfony/symfony6/symfony60.php @@ -2,78 +2,19 @@ declare(strict_types=1); -use PhpParser\Node\Scalar\String_; -use PHPStan\Type\MixedType; -use PHPStan\Type\ObjectType; use Rector\Config\RectorConfig; -use Rector\Renaming\Rector\MethodCall\RenameMethodRector; -use Rector\Renaming\Rector\Name\RenameClassRector; -use Rector\Renaming\ValueObject\MethodCallRename; -use Rector\Symfony\Set\SymfonySetList; -use Rector\Symfony\Symfony60\Rector\FuncCall\ReplaceServiceArgumentRector; -use Rector\Symfony\Symfony60\Rector\MethodCall\GetHelperControllerToServiceRector; -use Rector\Symfony\ValueObject\ReplaceServiceArgument; -use Rector\TypeDeclaration\Rector\ClassMethod\AddParamTypeDeclarationRector; -use Rector\TypeDeclaration\ValueObject\AddParamTypeDeclaration; # https://github.com/symfony/symfony/blob/6.1/UPGRADE-6.0.md return static function (RectorConfig $rectorConfig): void { - $rectorConfig->sets([SymfonySetList::ANNOTATIONS_TO_ATTRIBUTES]); + // $rectorConfig->sets([SymfonySetList::ANNOTATIONS_TO_ATTRIBUTES]); - $rectorConfig->import(__DIR__ . '/symfony-return-types.php'); - $rectorConfig->ruleWithConfiguration(ReplaceServiceArgumentRector::class, [ - new ReplaceServiceArgument('Psr\Container\ContainerInterface', new String_('service_container')), - new ReplaceServiceArgument( - 'Symfony\Component\DependencyInjection\ContainerInterface', - new String_('service_container') - ), - ]); + $rectorConfig->import(__DIR__ . '/symfony-return-types.php'); // todo: extract this as well - $rectorConfig->ruleWithConfiguration(RenameClassRector::class, [ - // @see https://github.com/symfony/symfony/pull/39484 - 'Symfony\Contracts\HttpClient\HttpClientInterface\RemoteJsonManifestVersionStrategy' => 'Symfony\Component\Asset\VersionStrategy\JsonManifestVersionStrategy', - ]); - - $rectorConfig->ruleWithConfiguration(AddParamTypeDeclarationRector::class, [ - new AddParamTypeDeclaration( - 'Symfony\Component\Config\Loader\LoaderInterface', - 'load', - 0, - new MixedType(true) - ), - new AddParamTypeDeclaration( - 'Symfony\Component\Config\Loader\LoaderInterface', - 'supports', - 0, - new MixedType(true) - ), - new AddParamTypeDeclaration( - 'Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait', - 'configureRoutes', - 0, - new ObjectType('Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator'), - ), - ]); - - $rectorConfig->ruleWithConfiguration(RenameMethodRector::class, [ - // @see https://github.com/symfony/symfony/pull/40403 - new MethodCallRename( - 'Symfony\Bridge\Doctrine\Security\User\UserLoaderInterface', - 'loadUserByUsername', - 'loadUserByIdentifier' - ), - new MethodCallRename( - 'Symfony\Component\Security\Core\User\UserProviderInterface', - 'loadUserByUsername', - 'loadUserByIdentifier', - ), - // @see https://github.com/rectorphp/rector-symfony/issues/112 - new MethodCallRename( - 'Symfony\Component\Security\Core\User\UserInterface', - 'getUsername', - 'getUserIdentifier', - ), - ]); - $rectorConfig->rule(GetHelperControllerToServiceRector::class); + $rectorConfig->import(__DIR__ . '/symfony60/symfony60-dependency-injection.php'); + $rectorConfig->import(__DIR__ . '/symfony60/symfony60-contracts.php'); + $rectorConfig->import(__DIR__ . '/symfony60/symfony60-config.php'); + $rectorConfig->import(__DIR__ . '/symfony60/symfony60-framework-bundle.php'); + $rectorConfig->import(__DIR__ . '/symfony60/symfony60-doctrine-bridge.php'); + $rectorConfig->import(__DIR__ . '/symfony60/symfony60-security-core.php'); }; diff --git a/config/sets/symfony/symfony6/symfony60/symfony60-config.php b/config/sets/symfony/symfony6/symfony60/symfony60-config.php new file mode 100644 index 00000000..a954aa5b --- /dev/null +++ b/config/sets/symfony/symfony6/symfony60/symfony60-config.php @@ -0,0 +1,25 @@ +ruleWithConfiguration(AddParamTypeDeclarationRector::class, [ + new AddParamTypeDeclaration( + 'Symfony\Component\Config\Loader\LoaderInterface', + 'load', + 0, + new MixedType(true) + ), + new AddParamTypeDeclaration( + 'Symfony\Component\Config\Loader\LoaderInterface', + 'supports', + 0, + new MixedType(true) + ), + ]); +}; diff --git a/config/sets/symfony/symfony6/symfony60/symfony60-contracts.php b/config/sets/symfony/symfony6/symfony60/symfony60-contracts.php new file mode 100644 index 00000000..26318e47 --- /dev/null +++ b/config/sets/symfony/symfony6/symfony60/symfony60-contracts.php @@ -0,0 +1,13 @@ +ruleWithConfiguration(RenameClassRector::class, [ + // @see https://github.com/symfony/symfony/pull/39484 + 'Symfony\Contracts\HttpClient\HttpClientInterface\RemoteJsonManifestVersionStrategy' => 'Symfony\Component\Asset\VersionStrategy\JsonManifestVersionStrategy', + ]); +}; diff --git a/config/sets/symfony/symfony6/symfony60/symfony60-dependency-injection.php b/config/sets/symfony/symfony6/symfony60/symfony60-dependency-injection.php new file mode 100644 index 00000000..4bf9cdd9 --- /dev/null +++ b/config/sets/symfony/symfony6/symfony60/symfony60-dependency-injection.php @@ -0,0 +1,18 @@ +ruleWithConfiguration(ReplaceServiceArgumentRector::class, [ + new ReplaceServiceArgument('Psr\Container\ContainerInterface', new String_('service_container')), + new ReplaceServiceArgument( + 'Symfony\Component\DependencyInjection\ContainerInterface', + new String_('service_container') + ), + ]); +}; diff --git a/config/sets/symfony/symfony6/symfony60/symfony60-doctrine-bridge.php b/config/sets/symfony/symfony6/symfony60/symfony60-doctrine-bridge.php new file mode 100644 index 00000000..6172ca0b --- /dev/null +++ b/config/sets/symfony/symfony6/symfony60/symfony60-doctrine-bridge.php @@ -0,0 +1,20 @@ +ruleWithConfiguration(RenameMethodRector::class, [ + // @see https://github.com/symfony/symfony/pull/40403 + new MethodCallRename( + 'Symfony\Bridge\Doctrine\Security\User\UserLoaderInterface', + 'loadUserByUsername', + 'loadUserByIdentifier' + ), + ]); +}; diff --git a/config/sets/symfony/symfony6/symfony60/symfony60-framework-bundle.php b/config/sets/symfony/symfony6/symfony60/symfony60-framework-bundle.php new file mode 100644 index 00000000..a39bf210 --- /dev/null +++ b/config/sets/symfony/symfony6/symfony60/symfony60-framework-bundle.php @@ -0,0 +1,21 @@ +ruleWithConfiguration(AddParamTypeDeclarationRector::class, [ + new AddParamTypeDeclaration( + 'Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait', + 'configureRoutes', + 0, + new ObjectType('Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator'), + ), + ]); + $rectorConfig->rule(GetHelperControllerToServiceRector::class); +}; diff --git a/config/sets/symfony/symfony6/symfony60/symfony60-security-core.php b/config/sets/symfony/symfony6/symfony60/symfony60-security-core.php new file mode 100644 index 00000000..8e745abf --- /dev/null +++ b/config/sets/symfony/symfony6/symfony60/symfony60-security-core.php @@ -0,0 +1,23 @@ +ruleWithConfiguration(RenameMethodRector::class, [ + new MethodCallRename( + 'Symfony\Component\Security\Core\User\UserProviderInterface', + 'loadUserByUsername', + 'loadUserByIdentifier', + ), + // @see https://github.com/rectorphp/rector-symfony/issues/112 + new MethodCallRename( + 'Symfony\Component\Security\Core\User\UserInterface', + 'getUsername', + 'getUserIdentifier', + ), + ]); +}; diff --git a/src/Set/SetProvider/Symfony6SetProvider.php b/src/Set/SetProvider/Symfony6SetProvider.php index 350d347e..101304e3 100644 --- a/src/Set/SetProvider/Symfony6SetProvider.php +++ b/src/Set/SetProvider/Symfony6SetProvider.php @@ -19,10 +19,53 @@ public function provide(): array return [ new ComposerTriggeredSet( SetGroup::SYMFONY, - 'symfony/*', + 'symfony/symfony', '6.0', __DIR__ . '/../../../config/sets/symfony/symfony6/symfony60.php' ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/dependency-injection', + '6.0', + __DIR__ . '/../../../config/sets/symfony/symfony6/symfony60/symfony60-dependency-injection.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/contracts', + '6.0', + __DIR__ . '/../../../config/sets/symfony/symfony6/symfony60/symfony60-contracts.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/config', + '6.0', + __DIR__ . '/../../../config/sets/symfony/symfony6/symfony60/symfony60-config.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/framework-bundle', + '6.0', + __DIR__ . '/../../../config/sets/symfony/symfony6/symfony60/symfony60-framework-bundle.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/doctrine-bridge', + '6.0', + __DIR__ . '/../../../config/sets/symfony/symfony6/symfony60/symfony60-doctrine-bridge.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/security-core', + '6.0', + __DIR__ . '/../../../config/sets/symfony/symfony6/symfony60/symfony60-security-core.php' + ), + new ComposerTriggeredSet( SetGroup::SYMFONY, 'symfony/*', From ad93adef585d70e72fe889275fbfcae66f8d2e33 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Mon, 5 May 2025 13:54:24 +0700 Subject: [PATCH 47/53] Extract to symfony-core and symfony-http on 5.4 (#741) --- config/sets/symfony/symfony5/symfony54.php | 3 ++- ...y54-security.php => symfony54-security-core.php} | 6 ------ .../symfony5/symfony54/symfony54-security-http.php | 13 +++++++++++++ src/Set/SetProvider/Symfony5SetProvider.php | 11 +++++++++-- 4 files changed, 24 insertions(+), 9 deletions(-) rename config/sets/symfony/symfony5/symfony54/{symfony54-security.php => symfony54-security-core.php} (80%) create mode 100644 config/sets/symfony/symfony5/symfony54/symfony54-security-http.php diff --git a/config/sets/symfony/symfony5/symfony54.php b/config/sets/symfony/symfony5/symfony54.php index e2ad6e04..4f551ce2 100644 --- a/config/sets/symfony/symfony5/symfony54.php +++ b/config/sets/symfony/symfony5/symfony54.php @@ -11,7 +11,8 @@ $rectorConfig->import(__DIR__ . '/symfony54/symfony54-validator.php'); $rectorConfig->import(__DIR__ . '/symfony54/symfony54-security-bundle.php'); - $rectorConfig->import(__DIR__ . '/symfony54/symfony54-security.php'); + $rectorConfig->import(__DIR__ . '/symfony54/symfony54-security-core.php'); + $rectorConfig->import(__DIR__ . '/symfony54/symfony54-security-http.php'); $rectorConfig->import(__DIR__ . '/symfony54/symfony54-cache.php'); $rectorConfig->import(__DIR__ . '/symfony54/symfony54-http-kernel.php'); $rectorConfig->import(__DIR__ . '/symfony54/symfony54-notifier.php'); diff --git a/config/sets/symfony/symfony5/symfony54/symfony54-security.php b/config/sets/symfony/symfony5/symfony54/symfony54-security-core.php similarity index 80% rename from config/sets/symfony/symfony5/symfony54/symfony54-security.php rename to config/sets/symfony/symfony5/symfony54/symfony54-security-core.php index d5791ed2..f9447874 100644 --- a/config/sets/symfony/symfony5/symfony54/symfony54-security.php +++ b/config/sets/symfony/symfony5/symfony54/symfony54-security-core.php @@ -4,7 +4,6 @@ use Rector\Config\RectorConfig; use Rector\Renaming\Rector\ClassConstFetch\RenameClassConstFetchRector; -use Rector\Renaming\Rector\Name\RenameClassRector; use Rector\Renaming\ValueObject\RenameClassAndConstFetch; use Rector\Renaming\ValueObject\RenameClassConstFetch; @@ -34,9 +33,4 @@ 'PUBLIC_ACCESS' ), ]); - - $rectorConfig->ruleWithConfiguration(RenameClassRector::class, [ - // @see https://github.com/symfony/symfony/pull/42050 - 'Symfony\Component\Security\Http\Event\DeauthenticatedEvent' => 'Symfony\Component\Security\Http\Event\TokenDeauthenticatedEvent', - ]); }; diff --git a/config/sets/symfony/symfony5/symfony54/symfony54-security-http.php b/config/sets/symfony/symfony5/symfony54/symfony54-security-http.php new file mode 100644 index 00000000..85537433 --- /dev/null +++ b/config/sets/symfony/symfony5/symfony54/symfony54-security-http.php @@ -0,0 +1,13 @@ +ruleWithConfiguration(RenameClassRector::class, [ + // @see https://github.com/symfony/symfony/pull/42050 + 'Symfony\Component\Security\Http\Event\DeauthenticatedEvent' => 'Symfony\Component\Security\Http\Event\TokenDeauthenticatedEvent', + ]); +}; diff --git a/src/Set/SetProvider/Symfony5SetProvider.php b/src/Set/SetProvider/Symfony5SetProvider.php index dc3570fa..8015ac74 100644 --- a/src/Set/SetProvider/Symfony5SetProvider.php +++ b/src/Set/SetProvider/Symfony5SetProvider.php @@ -272,9 +272,16 @@ public function provide(): array new ComposerTriggeredSet( SetGroup::SYMFONY, - 'symfony/security-bundle', + 'symfony/security-core', + '5.4', + __DIR__ . '/../../../config/sets/symfony/symfony5/symfony54/symfony54-security-core.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/security-http', '5.4', - __DIR__ . '/../../../config/sets/symfony/symfony5/symfony54/symfony54-security.php' + __DIR__ . '/../../../config/sets/symfony/symfony5/symfony54/symfony54-security-http.php' ), new ComposerTriggeredSet( From 37d320e78c4ea0a5e719b46e27abb6d8e9691da1 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Mon, 5 May 2025 16:14:50 +0200 Subject: [PATCH 48/53] [7.3] Update InvokableCommandRector to InvokableCommandInputAttributeRector to improve discoverability (#743) --- config/sets/symfony/symfony5/symfony53.php | 1 - config/sets/symfony/symfony73.php | 4 ++-- .../Fixture/skip_has_help_attribute_command.php.inc | 2 +- .../Fixture/some_command.php.inc | 4 ++-- .../Fixture/some_command_with_method_chaining.php.inc | 4 ++-- .../Fixture/some_command_with_set_help.php.inc | 4 ++-- .../InvokableCommandInputAttributeRectorTest.php} | 4 ++-- .../config/configured_rule.php | 10 ++++++++++ .../InvokableCommandRector/config/configured_rule.php | 10 ---------- ...or.php => InvokableCommandInputAttributeRector.php} | 4 ++-- 10 files changed, 23 insertions(+), 24 deletions(-) rename rules-tests/Symfony73/Rector/Class_/{InvokableCommandRector => InvokableCommandInputAttributeRector}/Fixture/some_command.php.inc (95%) rename rules-tests/Symfony73/Rector/Class_/{InvokableCommandRector => InvokableCommandInputAttributeRector}/Fixture/some_command_with_method_chaining.php.inc (95%) rename rules-tests/Symfony73/Rector/Class_/{InvokableCommandRector => InvokableCommandInputAttributeRector}/Fixture/some_command_with_set_help.php.inc (96%) rename rules-tests/Symfony73/Rector/Class_/{InvokableCommandRector/InvokableCommandRectorTest.php => InvokableCommandInputAttributeRector/InvokableCommandInputAttributeRectorTest.php} (84%) create mode 100644 rules-tests/Symfony73/Rector/Class_/InvokableCommandInputAttributeRector/config/configured_rule.php delete mode 100644 rules-tests/Symfony73/Rector/Class_/InvokableCommandRector/config/configured_rule.php rename rules/Symfony73/Rector/Class_/{InvokableCommandRector.php => InvokableCommandInputAttributeRector.php} (98%) diff --git a/config/sets/symfony/symfony5/symfony53.php b/config/sets/symfony/symfony5/symfony53.php index 6f02d381..b54037e5 100644 --- a/config/sets/symfony/symfony5/symfony53.php +++ b/config/sets/symfony/symfony5/symfony53.php @@ -3,7 +3,6 @@ declare(strict_types=1); use Rector\Config\RectorConfig; -use Rector\Symfony\Symfony53\Rector\StaticPropertyFetch\KernelTestCaseContainerPropertyDeprecationRector; # https://github.com/symfony/symfony/blob/5.4/UPGRADE-5.3.md diff --git a/config/sets/symfony/symfony73.php b/config/sets/symfony/symfony73.php index 1896a5e3..2c2ae0ad 100644 --- a/config/sets/symfony/symfony73.php +++ b/config/sets/symfony/symfony73.php @@ -4,9 +4,9 @@ use Rector\Config\RectorConfig; use Rector\Symfony\Symfony73\Rector\Class_\CommandHelpToAttributeRector; -use Rector\Symfony\Symfony73\Rector\Class_\InvokableCommandRector; +use Rector\Symfony\Symfony73\Rector\Class_\InvokableCommandInputAttributeRector; // @see https://github.com/symfony/symfony/blame/7.3/UPGRADE-7.3.md return RectorConfig::configure() - ->withRules([CommandHelpToAttributeRector::class, InvokableCommandRector::class]); + ->withRules([CommandHelpToAttributeRector::class, InvokableCommandInputAttributeRector::class]); diff --git a/rules-tests/Symfony73/Rector/Class_/CommandHelpToAttributeRector/Fixture/skip_has_help_attribute_command.php.inc b/rules-tests/Symfony73/Rector/Class_/CommandHelpToAttributeRector/Fixture/skip_has_help_attribute_command.php.inc index e559f801..65f90158 100644 --- a/rules-tests/Symfony73/Rector/Class_/CommandHelpToAttributeRector/Fixture/skip_has_help_attribute_command.php.inc +++ b/rules-tests/Symfony73/Rector/Class_/CommandHelpToAttributeRector/Fixture/skip_has_help_attribute_command.php.inc @@ -1,6 +1,6 @@ rule(InvokableCommandInputAttributeRector::class); +}; diff --git a/rules-tests/Symfony73/Rector/Class_/InvokableCommandRector/config/configured_rule.php b/rules-tests/Symfony73/Rector/Class_/InvokableCommandRector/config/configured_rule.php deleted file mode 100644 index a96cce4b..00000000 --- a/rules-tests/Symfony73/Rector/Class_/InvokableCommandRector/config/configured_rule.php +++ /dev/null @@ -1,10 +0,0 @@ -rule(InvokableCommandRector::class); -}; diff --git a/rules/Symfony73/Rector/Class_/InvokableCommandRector.php b/rules/Symfony73/Rector/Class_/InvokableCommandInputAttributeRector.php similarity index 98% rename from rules/Symfony73/Rector/Class_/InvokableCommandRector.php rename to rules/Symfony73/Rector/Class_/InvokableCommandInputAttributeRector.php index fb8abe30..41fc7719 100644 --- a/rules/Symfony73/Rector/Class_/InvokableCommandRector.php +++ b/rules/Symfony73/Rector/Class_/InvokableCommandInputAttributeRector.php @@ -29,9 +29,9 @@ * @see https://github.com/symfony/symfony-docs/issues/20553 * @see https://github.com/symfony/symfony/pull/59340 * - * @see \Rector\Symfony\Tests\Symfony73\Rector\Class_\InvokableCommandRector\InvokableCommandRectorTest + * @see \Rector\Symfony\Tests\Symfony73\Rector\Class_\InvokableCommandInputAttributeRector\InvokableCommandRectorTest */ -final class InvokableCommandRector extends AbstractRector +final class InvokableCommandInputAttributeRector extends AbstractRector { private const MIGRATED_CONFIGURE_CALLS = ['addArgument', 'addOption']; From 14d71b6f52f274c7aa96cef3c5540f1ef4aa45f4 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Tue, 6 May 2025 23:19:44 +0700 Subject: [PATCH 49/53] [symfony 61] split of configs per package (#744) * [symfony 61] split of configs per package * add validator * add validator * add console * add twig bridge --- config/sets/symfony/symfony6/symfony61.php | 24 +++----------- .../symfony6/symfony61/symfony61-console.php | 14 +++++++++ .../symfony61/symfony61-serializer.php | 14 +++++++++ .../symfony61/symfony61-twig-bridge.php | 10 ++++++ .../symfony61/symfony61-validator.php | 16 ++++++++++ src/Set/SetProvider/Symfony6SetProvider.php | 31 ++++++++++++++++++- 6 files changed, 88 insertions(+), 21 deletions(-) create mode 100644 config/sets/symfony/symfony6/symfony61/symfony61-console.php create mode 100644 config/sets/symfony/symfony6/symfony61/symfony61-serializer.php create mode 100644 config/sets/symfony/symfony6/symfony61/symfony61-twig-bridge.php create mode 100644 config/sets/symfony/symfony6/symfony61/symfony61-validator.php diff --git a/config/sets/symfony/symfony6/symfony61.php b/config/sets/symfony/symfony6/symfony61.php index 84d4ad6b..97c9eac3 100644 --- a/config/sets/symfony/symfony6/symfony61.php +++ b/config/sets/symfony/symfony6/symfony61.php @@ -3,28 +3,12 @@ declare(strict_types=1); use Rector\Config\RectorConfig; -use Rector\Renaming\Rector\Name\RenameClassRector; -use Rector\Symfony\Symfony61\Rector\Class_\CommandConfigureToAttributeRector; -use Rector\Symfony\Symfony61\Rector\Class_\CommandPropertyToAttributeRector; -use Rector\Symfony\Symfony61\Rector\Class_\MagicClosureTwigExtensionToNativeMethodsRector; -use Rector\Symfony\Symfony61\Rector\StaticPropertyFetch\ErrorNamesPropertyToConstantRector; # https://github.com/symfony/symfony/blob/6.1/UPGRADE-6.1.md return static function (RectorConfig $rectorConfig): void { - $rectorConfig->rules([ - CommandConfigureToAttributeRector::class, - CommandPropertyToAttributeRector::class, - ErrorNamesPropertyToConstantRector::class, - MagicClosureTwigExtensionToNativeMethodsRector::class, - ]); - - $rectorConfig->ruleWithConfiguration(RenameClassRector::class, [ - // @see https://github.com/symfony/symfony/pull/43982 - 'Symfony\Component\Serializer\Normalizer\ContextAwareDenormalizerInterface' => 'Symfony\Component\Serializer\Normalizer\DenormalizerInterface', - 'Symfony\Component\Serializer\Normalizer\ContextAwareNormalizerInterface' => 'Symfony\Component\Serializer\Normalizer\NormalizerInterface', - // @see https://github.com/symfony/symfony/pull/45623 - 'Symfony\Component\Validator\Constraints\ExpressionLanguageSyntax' => 'Symfony\Component\Validator\Constraints\ExpressionSyntax', - 'Symfony\Component\Validator\Constraints\ExpressionLanguageSyntaxValidator' => 'Symfony\Component\Validator\Constraints\ExpressionSyntaxValidator', - ]); + $rectorConfig->import(__DIR__ . '/symfony61/symfony61-serializer.php'); + $rectorConfig->import(__DIR__ . '/symfony61/symfony61-validator.php'); + $rectorConfig->import(__DIR__ . '/symfony61/symfony61-console.php'); + $rectorConfig->import(__DIR__ . '/symfony61/symfony61-twig-bridge.php'); }; diff --git a/config/sets/symfony/symfony6/symfony61/symfony61-console.php b/config/sets/symfony/symfony6/symfony61/symfony61-console.php new file mode 100644 index 00000000..c9207808 --- /dev/null +++ b/config/sets/symfony/symfony6/symfony61/symfony61-console.php @@ -0,0 +1,14 @@ +rules([ + CommandConfigureToAttributeRector::class, + CommandPropertyToAttributeRector::class, + ]); +}; diff --git a/config/sets/symfony/symfony6/symfony61/symfony61-serializer.php b/config/sets/symfony/symfony6/symfony61/symfony61-serializer.php new file mode 100644 index 00000000..3ea81200 --- /dev/null +++ b/config/sets/symfony/symfony6/symfony61/symfony61-serializer.php @@ -0,0 +1,14 @@ +ruleWithConfiguration(RenameClassRector::class, [ + // @see https://github.com/symfony/symfony/pull/43982 + 'Symfony\Component\Serializer\Normalizer\ContextAwareDenormalizerInterface' => 'Symfony\Component\Serializer\Normalizer\DenormalizerInterface', + 'Symfony\Component\Serializer\Normalizer\ContextAwareNormalizerInterface' => 'Symfony\Component\Serializer\Normalizer\NormalizerInterface', + ]); +}; diff --git a/config/sets/symfony/symfony6/symfony61/symfony61-twig-bridge.php b/config/sets/symfony/symfony6/symfony61/symfony61-twig-bridge.php new file mode 100644 index 00000000..928fa6cd --- /dev/null +++ b/config/sets/symfony/symfony6/symfony61/symfony61-twig-bridge.php @@ -0,0 +1,10 @@ +rule(MagicClosureTwigExtensionToNativeMethodsRector::class); +}; diff --git a/config/sets/symfony/symfony6/symfony61/symfony61-validator.php b/config/sets/symfony/symfony6/symfony61/symfony61-validator.php new file mode 100644 index 00000000..eac0207d --- /dev/null +++ b/config/sets/symfony/symfony6/symfony61/symfony61-validator.php @@ -0,0 +1,16 @@ +rule(ErrorNamesPropertyToConstantRector::class); + $rectorConfig->ruleWithConfiguration(RenameClassRector::class, [ + // @see https://github.com/symfony/symfony/pull/45623 + 'Symfony\Component\Validator\Constraints\ExpressionLanguageSyntax' => 'Symfony\Component\Validator\Constraints\ExpressionSyntax', + 'Symfony\Component\Validator\Constraints\ExpressionLanguageSyntaxValidator' => 'Symfony\Component\Validator\Constraints\ExpressionSyntaxValidator', + ]); +}; diff --git a/src/Set/SetProvider/Symfony6SetProvider.php b/src/Set/SetProvider/Symfony6SetProvider.php index 101304e3..6e3d2fd2 100644 --- a/src/Set/SetProvider/Symfony6SetProvider.php +++ b/src/Set/SetProvider/Symfony6SetProvider.php @@ -68,10 +68,39 @@ public function provide(): array new ComposerTriggeredSet( SetGroup::SYMFONY, - 'symfony/*', + 'symfony/symfony', '6.1', __DIR__ . '/../../../config/sets/symfony/symfony6/symfony61.php' ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/serializer', + '6.1', + __DIR__ . '/../../../config/sets/symfony/symfony6/symfony61/symfony61-serializer.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/validator', + '6.1', + __DIR__ . '/../../../config/sets/symfony/symfony6/symfony61/symfony61-validator.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/console', + '6.1', + __DIR__ . '/../../../config/sets/symfony/symfony6/symfony61/symfony61-console.php' + ), + + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/twig-bridge', + '6.1', + __DIR__ . '/../../../config/sets/symfony/symfony6/symfony61/symfony61-twig-bridge.php' + ), + new ComposerTriggeredSet( SetGroup::SYMFONY, 'symfony/*', From 53cfe337eb56779f47582ec3004fbec89ed4557a Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Wed, 7 May 2025 00:47:43 +0700 Subject: [PATCH 50/53] [symfony 62] split of configs per package (#745) * [symfony 62] split of configs per package * add mime * add http-kernel * add framework-bundle * add http-foundation * add HttpKernel rename * add twig-bridge rename * add security-http * add translation * add security http attribute * add doctrine-bridge * add messenger * add mail-pace-mailer --- config/sets/symfony/symfony6/symfony62.php | 108 ++---------------- .../symfony62/symfony62-doctrine-bridge.php | 10 ++ .../symfony62/symfony62-framework-bundle.php | 24 ++++ .../symfony62/symfony62-http-foundation.php | 32 ++++++ .../symfony62/symfony62-http-kernel.php | 25 ++++ .../symfony62/symfony62-mail-pace-mailer.php | 19 +++ .../symfony62/symfony62-messenger.php | 15 +++ .../symfony6/symfony62/symfony62-mime.php | 17 +++ .../symfony62/symfony62-security-core.php | 48 ++++++++ .../symfony62/symfony62-security-http.php | 19 +++ .../symfony62/symfony62-translation.php | 17 +++ .../symfony62/symfony62-twig-bridge.php | 17 +++ src/Set/SetProvider/Symfony6SetProvider.php | 69 ++++++++++- 13 files changed, 322 insertions(+), 98 deletions(-) create mode 100644 config/sets/symfony/symfony6/symfony62/symfony62-doctrine-bridge.php create mode 100644 config/sets/symfony/symfony6/symfony62/symfony62-framework-bundle.php create mode 100644 config/sets/symfony/symfony6/symfony62/symfony62-http-foundation.php create mode 100644 config/sets/symfony/symfony6/symfony62/symfony62-http-kernel.php create mode 100644 config/sets/symfony/symfony6/symfony62/symfony62-mail-pace-mailer.php create mode 100644 config/sets/symfony/symfony6/symfony62/symfony62-messenger.php create mode 100644 config/sets/symfony/symfony6/symfony62/symfony62-mime.php create mode 100644 config/sets/symfony/symfony6/symfony62/symfony62-security-core.php create mode 100644 config/sets/symfony/symfony6/symfony62/symfony62-security-http.php create mode 100644 config/sets/symfony/symfony6/symfony62/symfony62-translation.php create mode 100644 config/sets/symfony/symfony6/symfony62/symfony62-twig-bridge.php diff --git a/config/sets/symfony/symfony6/symfony62.php b/config/sets/symfony/symfony6/symfony62.php index 69aa6086..fd8a16d7 100644 --- a/config/sets/symfony/symfony6/symfony62.php +++ b/config/sets/symfony/symfony6/symfony62.php @@ -5,31 +5,8 @@ use Rector\Config\RectorConfig; use Rector\Php80\Rector\Class_\AnnotationToAttributeRector; use Rector\Php80\ValueObject\AnnotationToAttribute; -use Rector\Renaming\Rector\ClassConstFetch\RenameClassConstFetchRector; -use Rector\Renaming\Rector\MethodCall\RenameMethodRector; -use Rector\Renaming\Rector\Name\RenameClassRector; -use Rector\Renaming\ValueObject\MethodCallRename; -use Rector\Renaming\ValueObject\RenameClassAndConstFetch; -use Rector\Symfony\Symfony62\Rector\Class_\MessageHandlerInterfaceToAttributeRector; -use Rector\Symfony\Symfony62\Rector\Class_\MessageSubscriberInterfaceToAttributeRector; -use Rector\Symfony\Symfony62\Rector\Class_\SecurityAttributeToIsGrantedAttributeRector; -use Rector\Symfony\Symfony62\Rector\ClassMethod\ClassMethod\ArgumentValueResolverToValueResolverRector; -use Rector\Symfony\Symfony62\Rector\ClassMethod\ParamConverterAttributeToMapEntityAttributeRector; -use Rector\Symfony\Symfony62\Rector\MethodCall\SimplifyFormRenderingRector; return static function (RectorConfig $rectorConfig): void { - $rectorConfig->rules([ - SimplifyFormRenderingRector::class, - SecurityAttributeToIsGrantedAttributeRector::class, - ParamConverterAttributeToMapEntityAttributeRector::class, - - // @see https://github.com/symfony/symfony/pull/47068, #[AsMessageHandler] attribute - MessageHandlerInterfaceToAttributeRector::class, - MessageSubscriberInterfaceToAttributeRector::class, - // @see https://github.com/symfony/symfony/pull/47363 - ArgumentValueResolverToValueResolverRector::class, - ]); - // change to attribute before rename // https://symfony.com/blog/new-in-symfony-6-2-built-in-cache-security-template-and-doctrine-attributes // @see https://github.com/rectorphp/rector-symfony/issues/535#issuecomment-1783983383 @@ -42,78 +19,15 @@ new AnnotationToAttribute('Sensio\Bundle\FrameworkExtraBundle\Configuration\Template'), ]); - // https://symfony.com/blog/new-in-symfony-6-2-built-in-cache-security-template-and-doctrine-attributes - $rectorConfig->ruleWithConfiguration( - RenameClassRector::class, - [ - // @see https://github.com/symfony/symfony/pull/46907 - 'Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted' => 'Symfony\Component\Security\Http\Attribute\IsGranted', - // @see https://github.com/symfony/symfony/pull/46880 - 'Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache' => 'Symfony\Component\HttpKernel\Attribute\Cache', - // @see https://github.com/symfony/symfony/pull/46906 - 'Sensio\Bundle\FrameworkExtraBundle\Configuration\Template' => 'Symfony\Bridge\Twig\Attribute\Template', - // @see https://github.com/symfony/symfony/pull/46714 - 'Symfony\Component\Mailer\Bridge\OhMySmtp\Transport\OhMySmtpApiTransport' => 'Symfony\Component\Mailer\Bridge\MailPace\Transport\MailPaceApiTransport', - 'Symfony\Component\Mailer\Bridge\OhMySmtp\Transport\OhMySmtpSmtpTransport' => 'Symfony\Component\Mailer\Bridge\MailPace\Transport\MailPaceSmtpTransport', - 'Symfony\Component\Mailer\Bridge\OhMySmtp\Transport\OhMySmtpTransportFactory' => 'Symfony\Component\Mailer\Bridge\MailPace\Transport\MailPaceTransportFactory', - // @see https://github.com/symfony/symfony/pull/47363 - 'Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface' => 'Symfony\Component\HttpKernel\Controller\ValueResolverInterface', - // @see https://github.com/symfony/symfony/pull/46094 - 'Symfony\Component\Security\Core\Security' => 'Symfony\Bundle\SecurityBundle\Security', - // @see https://github.com/symfony/symfony/pull/46161 - 'Symfony\Component\Translation\Extractor\PhpAstExtractor' => 'Symfony\Component\Translation\Extractor\PhpAstExtractor', - // @see https://github.com/symfony/symfony/pull/47595 - 'Symfony\Component\HttpFoundation\ExpressionRequestMatcher' => 'Symfony\Component\HttpFoundation\RequestMatcher\ExpressionRequestMatcher', - 'Symfony\Component\HttpFoundation\RequestMatcher' => 'Symfony\Component\HttpFoundation\ChainRequestMatcher', - ], - ); - - $rectorConfig->ruleWithConfiguration( - RenameMethodRector::class, - [ - // @see https://github.com/symfony/symfony/pull/46854 - new MethodCallRename( - 'Symfony\Bundle\FrameworkBundle\Controller\AbstractController', - 'renderForm', - 'render' - ), - // @see https://github.com/symfony/symfony/pull/45034 - new MethodCallRename( - 'Symfony\Component\HttpFoundation\Request', - 'getContentType', - 'getContentTypeFormat' - ), - // @see https://github.com/symfony/symfony/pull/47711 - new MethodCallRename('Symfony\Component\Mime\Email', 'attachPart', 'addPart'), - ], - ); - - // @see https://github.com/symfony/symfony/pull/46094 - // @see https://github.com/symfony/symfony/pull/48554 - $rectorConfig->ruleWithConfiguration(RenameClassConstFetchRector::class, [ - new RenameClassAndConstFetch( - 'Symfony\Component\Security\Core\Security', - 'ACCESS_DENIED_ERROR', - 'Symfony\Component\Security\Http\SecurityRequestAttributes', - 'ACCESS_DENIED_ERROR' - ), - new RenameClassAndConstFetch( - 'Symfony\Component\Security\Core\Security', - 'AUTHENTICATION_ERROR', - 'Symfony\Component\Security\Http\SecurityRequestAttributes', - 'AUTHENTICATION_ERROR' - ), - new RenameClassAndConstFetch( - 'Symfony\Component\Security\Core\Security', - 'LAST_USERNAME', - 'Symfony\Component\Security\Http\SecurityRequestAttributes', - 'LAST_USERNAME' - ), - new RenameClassAndConstFetch( - 'Symfony\Component\Security\Core\Security', - 'MAX_USERNAME_LENGTH', - 'Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge', - 'MAX_USERNAME_LENGTH' - ), - ]); + $rectorConfig->import(__DIR__ . '/symfony62/symfony62-security-core.php'); + $rectorConfig->import(__DIR__ . '/symfony62/symfony62-security-http.php'); + $rectorConfig->import(__DIR__ . '/symfony62/symfony62-mime.php'); + $rectorConfig->import(__DIR__ . '/symfony62/symfony62-http-kernel.php'); + $rectorConfig->import(__DIR__ . '/symfony62/symfony62-framework-bundle.php'); + $rectorConfig->import(__DIR__ . '/symfony62/symfony62-http-foundation.php'); + $rectorConfig->import(__DIR__ . '/symfony62/symfony62-twig-bridge.php'); + $rectorConfig->import(__DIR__ . '/symfony62/symfony62-translation.php'); + $rectorConfig->import(__DIR__ . '/symfony62/symfony62-doctrine-bridge.php'); + $rectorConfig->import(__DIR__ . '/symfony62/symfony62-messenger.php'); + $rectorConfig->import(__DIR__ . '/symfony62/symfony62-mail-pace-mailer.php'); }; diff --git a/config/sets/symfony/symfony6/symfony62/symfony62-doctrine-bridge.php b/config/sets/symfony/symfony6/symfony62/symfony62-doctrine-bridge.php new file mode 100644 index 00000000..9a3f18a7 --- /dev/null +++ b/config/sets/symfony/symfony6/symfony62/symfony62-doctrine-bridge.php @@ -0,0 +1,10 @@ +rule(ParamConverterAttributeToMapEntityAttributeRector::class); +}; diff --git a/config/sets/symfony/symfony6/symfony62/symfony62-framework-bundle.php b/config/sets/symfony/symfony6/symfony62/symfony62-framework-bundle.php new file mode 100644 index 00000000..51876555 --- /dev/null +++ b/config/sets/symfony/symfony6/symfony62/symfony62-framework-bundle.php @@ -0,0 +1,24 @@ +rule(SimplifyFormRenderingRector::class); + + $rectorConfig->ruleWithConfiguration( + RenameMethodRector::class, + [ + // @see https://github.com/symfony/symfony/pull/46854 + new MethodCallRename( + 'Symfony\Bundle\FrameworkBundle\Controller\AbstractController', + 'renderForm', + 'render' + ), + ], + ); +}; diff --git a/config/sets/symfony/symfony6/symfony62/symfony62-http-foundation.php b/config/sets/symfony/symfony6/symfony62/symfony62-http-foundation.php new file mode 100644 index 00000000..30854a40 --- /dev/null +++ b/config/sets/symfony/symfony6/symfony62/symfony62-http-foundation.php @@ -0,0 +1,32 @@ +ruleWithConfiguration( + RenameClassRector::class, + [ + // @see https://github.com/symfony/symfony/pull/47595 + 'Symfony\Component\HttpFoundation\ExpressionRequestMatcher' => 'Symfony\Component\HttpFoundation\RequestMatcher\ExpressionRequestMatcher', + 'Symfony\Component\HttpFoundation\RequestMatcher' => 'Symfony\Component\HttpFoundation\ChainRequestMatcher', + ], + ); + + $rectorConfig->ruleWithConfiguration( + RenameMethodRector::class, + [ + // @see https://github.com/symfony/symfony/pull/45034 + new MethodCallRename( + 'Symfony\Component\HttpFoundation\Request', + 'getContentType', + 'getContentTypeFormat' + ), + ], + ); +}; diff --git a/config/sets/symfony/symfony6/symfony62/symfony62-http-kernel.php b/config/sets/symfony/symfony6/symfony62/symfony62-http-kernel.php new file mode 100644 index 00000000..093805ae --- /dev/null +++ b/config/sets/symfony/symfony6/symfony62/symfony62-http-kernel.php @@ -0,0 +1,25 @@ +rules([ + // @see https://github.com/symfony/symfony/pull/47363 + ArgumentValueResolverToValueResolverRector::class, + ]); + + // https://symfony.com/blog/new-in-symfony-6-2-built-in-cache-security-template-and-doctrine-attributes + $rectorConfig->ruleWithConfiguration( + RenameClassRector::class, + [ + // @see https://github.com/symfony/symfony/pull/46880 + 'Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache' => 'Symfony\Component\HttpKernel\Attribute\Cache', + // @see https://github.com/symfony/symfony/pull/47363 + 'Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface' => 'Symfony\Component\HttpKernel\Controller\ValueResolverInterface', + ], + ); +}; diff --git a/config/sets/symfony/symfony6/symfony62/symfony62-mail-pace-mailer.php b/config/sets/symfony/symfony6/symfony62/symfony62-mail-pace-mailer.php new file mode 100644 index 00000000..3f9349cb --- /dev/null +++ b/config/sets/symfony/symfony6/symfony62/symfony62-mail-pace-mailer.php @@ -0,0 +1,19 @@ +ruleWithConfiguration( + RenameClassRector::class, + [ + // @see https://github.com/symfony/symfony/pull/46714 + 'Symfony\Component\Mailer\Bridge\OhMySmtp\Transport\OhMySmtpApiTransport' => 'Symfony\Component\Mailer\Bridge\MailPace\Transport\MailPaceApiTransport', + 'Symfony\Component\Mailer\Bridge\OhMySmtp\Transport\OhMySmtpSmtpTransport' => 'Symfony\Component\Mailer\Bridge\MailPace\Transport\MailPaceSmtpTransport', + 'Symfony\Component\Mailer\Bridge\OhMySmtp\Transport\OhMySmtpTransportFactory' => 'Symfony\Component\Mailer\Bridge\MailPace\Transport\MailPaceTransportFactory', + ], + ); +}; diff --git a/config/sets/symfony/symfony6/symfony62/symfony62-messenger.php b/config/sets/symfony/symfony6/symfony62/symfony62-messenger.php new file mode 100644 index 00000000..55f635c1 --- /dev/null +++ b/config/sets/symfony/symfony6/symfony62/symfony62-messenger.php @@ -0,0 +1,15 @@ +rules([ + // @see https://github.com/symfony/symfony/pull/47068, #[AsMessageHandler] attribute + MessageHandlerInterfaceToAttributeRector::class, + MessageSubscriberInterfaceToAttributeRector::class, + ]); +}; diff --git a/config/sets/symfony/symfony6/symfony62/symfony62-mime.php b/config/sets/symfony/symfony6/symfony62/symfony62-mime.php new file mode 100644 index 00000000..85ec9339 --- /dev/null +++ b/config/sets/symfony/symfony6/symfony62/symfony62-mime.php @@ -0,0 +1,17 @@ +ruleWithConfiguration( + RenameMethodRector::class, + [ + // @see https://github.com/symfony/symfony/pull/47711 + new MethodCallRename('Symfony\Component\Mime\Email', 'attachPart', 'addPart'), + ], + ); +}; diff --git a/config/sets/symfony/symfony6/symfony62/symfony62-security-core.php b/config/sets/symfony/symfony6/symfony62/symfony62-security-core.php new file mode 100644 index 00000000..68be856b --- /dev/null +++ b/config/sets/symfony/symfony6/symfony62/symfony62-security-core.php @@ -0,0 +1,48 @@ +ruleWithConfiguration( + RenameClassRector::class, + [ + // @see https://github.com/symfony/symfony/pull/46094 + 'Symfony\Component\Security\Core\Security' => 'Symfony\Bundle\SecurityBundle\Security', + ], + ); + + // @see https://github.com/symfony/symfony/pull/46094 + // @see https://github.com/symfony/symfony/pull/48554 + $rectorConfig->ruleWithConfiguration(RenameClassConstFetchRector::class, [ + new RenameClassAndConstFetch( + 'Symfony\Component\Security\Core\Security', + 'ACCESS_DENIED_ERROR', + 'Symfony\Component\Security\Http\SecurityRequestAttributes', + 'ACCESS_DENIED_ERROR' + ), + new RenameClassAndConstFetch( + 'Symfony\Component\Security\Core\Security', + 'AUTHENTICATION_ERROR', + 'Symfony\Component\Security\Http\SecurityRequestAttributes', + 'AUTHENTICATION_ERROR' + ), + new RenameClassAndConstFetch( + 'Symfony\Component\Security\Core\Security', + 'LAST_USERNAME', + 'Symfony\Component\Security\Http\SecurityRequestAttributes', + 'LAST_USERNAME' + ), + new RenameClassAndConstFetch( + 'Symfony\Component\Security\Core\Security', + 'MAX_USERNAME_LENGTH', + 'Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge', + 'MAX_USERNAME_LENGTH' + ), + ]); +}; diff --git a/config/sets/symfony/symfony6/symfony62/symfony62-security-http.php b/config/sets/symfony/symfony6/symfony62/symfony62-security-http.php new file mode 100644 index 00000000..95ea65ca --- /dev/null +++ b/config/sets/symfony/symfony6/symfony62/symfony62-security-http.php @@ -0,0 +1,19 @@ +rule(SecurityAttributeToIsGrantedAttributeRector::class); + // https://symfony.com/blog/new-in-symfony-6-2-built-in-cache-security-template-and-doctrine-attributes + $rectorConfig->ruleWithConfiguration( + RenameClassRector::class, + [ + // @see https://github.com/symfony/symfony/pull/46907 + 'Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted' => 'Symfony\Component\Security\Http\Attribute\IsGranted', + ], + ); +}; diff --git a/config/sets/symfony/symfony6/symfony62/symfony62-translation.php b/config/sets/symfony/symfony6/symfony62/symfony62-translation.php new file mode 100644 index 00000000..6010a7a7 --- /dev/null +++ b/config/sets/symfony/symfony6/symfony62/symfony62-translation.php @@ -0,0 +1,17 @@ +ruleWithConfiguration( + RenameClassRector::class, + [ + // @see https://github.com/symfony/symfony/pull/46161 + 'Symfony\Component\Translation\Extractor\PhpAstExtractor' => 'Symfony\Component\Translation\Extractor\PhpAstExtractor', + ], + ); +}; diff --git a/config/sets/symfony/symfony6/symfony62/symfony62-twig-bridge.php b/config/sets/symfony/symfony6/symfony62/symfony62-twig-bridge.php new file mode 100644 index 00000000..a27cb35c --- /dev/null +++ b/config/sets/symfony/symfony6/symfony62/symfony62-twig-bridge.php @@ -0,0 +1,17 @@ +ruleWithConfiguration( + RenameClassRector::class, + [ + // @see https://github.com/symfony/symfony/pull/46906 + 'Sensio\Bundle\FrameworkExtraBundle\Configuration\Template' => 'Symfony\Bridge\Twig\Attribute\Template', + ], + ); +}; diff --git a/src/Set/SetProvider/Symfony6SetProvider.php b/src/Set/SetProvider/Symfony6SetProvider.php index 6e3d2fd2..1450e869 100644 --- a/src/Set/SetProvider/Symfony6SetProvider.php +++ b/src/Set/SetProvider/Symfony6SetProvider.php @@ -103,10 +103,77 @@ public function provide(): array new ComposerTriggeredSet( SetGroup::SYMFONY, - 'symfony/*', + 'symfony/symfony', '6.2', __DIR__ . '/../../../config/sets/symfony/symfony6/symfony62.php' ), + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/security-core', + '6.2', + __DIR__ . '/../../../config/sets/symfony/symfony6/symfony62/symfony62-security-core.php' + ), + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/security-http', + '6.2', + __DIR__ . '/../../../config/sets/symfony/symfony6/symfony62/symfony62-security-http.php' + ), + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/mime', + '6.2', + __DIR__ . '/../../../config/sets/symfony/symfony6/symfony62/symfony62-mime.php' + ), + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/http-kernel', + '6.2', + __DIR__ . '/../../../config/sets/symfony/symfony6/symfony62/symfony62-http-kernel.php' + ), + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/framework-bundle', + '6.2', + __DIR__ . '/../../../config/sets/symfony/symfony6/symfony62/symfony62-framework-bundle.php' + ), + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/http-foundation', + '6.2', + __DIR__ . '/../../../config/sets/symfony/symfony6/symfony62/symfony62-http-foundation.php' + ), + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/twig-bridge', + '6.2', + __DIR__ . '/../../../config/sets/symfony/symfony6/symfony62/symfony62-twig-bridge.php' + ), + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/translation', + '6.2', + __DIR__ . '/../../../config/sets/symfony/symfony6/symfony62/symfony62-translation.php' + ), + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/doctrine-bridge', + '6.2', + __DIR__ . '/../../../config/sets/symfony/symfony6/symfony62/symfony62-doctrine-bridge.php' + ), + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/messenger', + '6.2', + __DIR__ . '/../../../config/sets/symfony/symfony6/symfony62/symfony62-messenger.php' + ), + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/mail-pace-mailer', + '6.2', + __DIR__ . '/../../../config/sets/symfony/symfony6/symfony62/symfony62-mail-pace-mailer.php' + ), + new ComposerTriggeredSet( SetGroup::SYMFONY, 'symfony/*', From 9b78b8bc60f669c849917757358e3bb2a5db2f70 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Wed, 7 May 2025 01:04:42 +0700 Subject: [PATCH 51/53] [symfony 63] split of configs per package (#746) * [symfony 63] split of configs per package * add http-client * add messenger * add console * add dep --- config/sets/symfony/symfony6/symfony63.php | 28 +++---------------- .../symfony6/symfony63/symfony63-console.php | 13 +++++++++ .../symfony63-dependency-injection.php | 22 +++++++++++++++ .../symfony63/symfony63-http-client.php | 16 +++++++++++ .../symfony63/symfony63-messenger.php | 19 +++++++++++++ src/Set/SetProvider/Symfony6SetProvider.php | 27 +++++++++++++++++- 6 files changed, 100 insertions(+), 25 deletions(-) create mode 100644 config/sets/symfony/symfony6/symfony63/symfony63-console.php create mode 100644 config/sets/symfony/symfony6/symfony63/symfony63-dependency-injection.php create mode 100644 config/sets/symfony/symfony6/symfony63/symfony63-http-client.php create mode 100644 config/sets/symfony/symfony6/symfony63/symfony63-messenger.php diff --git a/config/sets/symfony/symfony6/symfony63.php b/config/sets/symfony/symfony6/symfony63.php index 5c33feea..c1434228 100644 --- a/config/sets/symfony/symfony6/symfony63.php +++ b/config/sets/symfony/symfony6/symfony63.php @@ -3,32 +3,12 @@ declare(strict_types=1); use Rector\Config\RectorConfig; -use Rector\Renaming\Rector\Name\RenameClassRector; -use Rector\Symfony\Symfony63\Rector\Class_\ParamAndEnvAttributeRector; -use Rector\Symfony\Symfony63\Rector\Class_\SignalableCommandInterfaceReturnTypeRector; // @see https://github.com/symfony/symfony/blob/6.3/UPGRADE-6.3.md // @see \Rector\Symfony\Tests\Set\Symfony63\Symfony63Test return static function (RectorConfig $rectorConfig): void { - $rectorConfig->ruleWithConfiguration( - RenameClassRector::class, - [ - // @see https://github.com/symfony/symfony/commit/b653adf426aedc66d16c5fc1cf71e261f20b9638 - 'Symfony\Component\DependencyInjection\Attribute\MapDecorated' => 'Symfony\Component\DependencyInjection\Attribute\AutowireDecorated', - // @see https://github.com/symfony/symfony/commit/20ab567385e3812ef661dae01a1fdc5d1bde2666 - '\Http\Client\HttpClient' => 'Psr\Http\Client\ClientInterface', - // @see https://github.com/symfony/symfony/commit/9415b438b75204c72ff66b838307b73646393cbf - 'Symfony\Component\Messenger\EventListener\StopWorkerOnSigtermSignalListener' => 'Symfony\Component\Messenger\EventListener\StopWorkerOnSignalsListener', - // @see https://github.com/symfony/symfony/commit/a7926b2d83f35fe53c41a28d8055490cc1955928 - 'Symfony\Component\Messenger\Transport\InMemoryTransport' => 'Symfony\Component\Messenger\Transport\InMemory\InMemoryTransport', - 'Symfony\Component\Messenger\Transport\InMemoryTransportFactory' => 'Symfony\Component\Messenger\Transport\InMemory\InMemoryTransportFactory', - ], - ); - - $rectorConfig->rules([ - // @see https://github.com/symfony/symfony/commit/1650e3861b5fcd931e5d3eb1dd84bad764020d8e - SignalableCommandInterfaceReturnTypeRector::class, - // @see https://symfony.com/blog/new-in-symfony-6-3-dependency-injection-improvements#new-options-for-autowire-attribute - ParamAndEnvAttributeRector::class, - ]); + $rectorConfig->import(__DIR__ . '/symfony63/symfony63-dependency-injection.php'); + $rectorConfig->import(__DIR__ . '/symfony63/symfony63-http-client.php'); + $rectorConfig->import(__DIR__ . '/symfony63/symfony63-messenger.php'); + $rectorConfig->import(__DIR__ . '/symfony63/symfony63-console.php'); }; diff --git a/config/sets/symfony/symfony6/symfony63/symfony63-console.php b/config/sets/symfony/symfony6/symfony63/symfony63-console.php new file mode 100644 index 00000000..28834c50 --- /dev/null +++ b/config/sets/symfony/symfony6/symfony63/symfony63-console.php @@ -0,0 +1,13 @@ +rules([ + // @see https://github.com/symfony/symfony/commit/1650e3861b5fcd931e5d3eb1dd84bad764020d8e + SignalableCommandInterfaceReturnTypeRector::class, + ]); +}; diff --git a/config/sets/symfony/symfony6/symfony63/symfony63-dependency-injection.php b/config/sets/symfony/symfony6/symfony63/symfony63-dependency-injection.php new file mode 100644 index 00000000..8909aaf2 --- /dev/null +++ b/config/sets/symfony/symfony6/symfony63/symfony63-dependency-injection.php @@ -0,0 +1,22 @@ +rules([ + // @see https://symfony.com/blog/new-in-symfony-6-3-dependency-injection-improvements#new-options-for-autowire-attribute + ParamAndEnvAttributeRector::class, + ]); + + $rectorConfig->ruleWithConfiguration( + RenameClassRector::class, + [ + // @see https://github.com/symfony/symfony/commit/b653adf426aedc66d16c5fc1cf71e261f20b9638 + 'Symfony\Component\DependencyInjection\Attribute\MapDecorated' => 'Symfony\Component\DependencyInjection\Attribute\AutowireDecorated', + ], + ); +}; diff --git a/config/sets/symfony/symfony6/symfony63/symfony63-http-client.php b/config/sets/symfony/symfony6/symfony63/symfony63-http-client.php new file mode 100644 index 00000000..ca22adea --- /dev/null +++ b/config/sets/symfony/symfony6/symfony63/symfony63-http-client.php @@ -0,0 +1,16 @@ +ruleWithConfiguration( + RenameClassRector::class, + [ + // @see https://github.com/symfony/symfony/commit/20ab567385e3812ef661dae01a1fdc5d1bde2666 + 'Http\Client\HttpClient' => 'Psr\Http\Client\ClientInterface', + ], + ); +}; diff --git a/config/sets/symfony/symfony6/symfony63/symfony63-messenger.php b/config/sets/symfony/symfony6/symfony63/symfony63-messenger.php new file mode 100644 index 00000000..8486ed97 --- /dev/null +++ b/config/sets/symfony/symfony6/symfony63/symfony63-messenger.php @@ -0,0 +1,19 @@ +ruleWithConfiguration( + RenameClassRector::class, + [ + // @see https://github.com/symfony/symfony/commit/9415b438b75204c72ff66b838307b73646393cbf + 'Symfony\Component\Messenger\EventListener\StopWorkerOnSigtermSignalListener' => 'Symfony\Component\Messenger\EventListener\StopWorkerOnSignalsListener', + // @see https://github.com/symfony/symfony/commit/a7926b2d83f35fe53c41a28d8055490cc1955928 + 'Symfony\Component\Messenger\Transport\InMemoryTransport' => 'Symfony\Component\Messenger\Transport\InMemory\InMemoryTransport', + 'Symfony\Component\Messenger\Transport\InMemoryTransportFactory' => 'Symfony\Component\Messenger\Transport\InMemory\InMemoryTransportFactory', + ], + ); +}; diff --git a/src/Set/SetProvider/Symfony6SetProvider.php b/src/Set/SetProvider/Symfony6SetProvider.php index 1450e869..294d5e72 100644 --- a/src/Set/SetProvider/Symfony6SetProvider.php +++ b/src/Set/SetProvider/Symfony6SetProvider.php @@ -176,10 +176,35 @@ public function provide(): array new ComposerTriggeredSet( SetGroup::SYMFONY, - 'symfony/*', + 'symfony/symfony', '6.3', __DIR__ . '/../../../config/sets/symfony/symfony6/symfony63.php' ), + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/dependency-injection', + '6.3', + __DIR__ . '/../../../config/sets/symfony/symfony6/symfony63/symfony63-dependency-injection.php' + ), + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/http-client', + '6.3', + __DIR__ . '/../../../config/sets/symfony/symfony6/symfony63/symfony63-http-client.php' + ), + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/messenger', + '6.3', + __DIR__ . '/../../../config/sets/symfony/symfony6/symfony63/symfony63-messenger.php' + ), + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/console', + '6.3', + __DIR__ . '/../../../config/sets/symfony/symfony6/symfony63/symfony63-console.php' + ), + new ComposerTriggeredSet( SetGroup::SYMFONY, 'symfony/*', From 3d3cfd92dfc35479bb10ef3957d8dc2f57baba99 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Wed, 7 May 2025 01:18:29 +0700 Subject: [PATCH 52/53] [symfony 64] split of configs per package (#747) * [symfony 64] split of configs per package * add form * add http-foundation * add error-handler --- config/sets/symfony/symfony6/symfony64.php | 37 ++----------------- .../symfony64/symfony64-error-handler.php | 16 ++++++++ .../symfony6/symfony64/symfony64-form.php | 24 ++++++++++++ .../symfony64/symfony64-http-foundation.php | 16 ++++++++ .../symfony6/symfony64/symfony64-routing.php | 16 ++++++++ src/Set/SetProvider/Symfony6SetProvider.php | 26 ++++++++++++- 6 files changed, 101 insertions(+), 34 deletions(-) create mode 100644 config/sets/symfony/symfony6/symfony64/symfony64-error-handler.php create mode 100644 config/sets/symfony/symfony6/symfony64/symfony64-form.php create mode 100644 config/sets/symfony/symfony6/symfony64/symfony64-http-foundation.php create mode 100644 config/sets/symfony/symfony6/symfony64/symfony64-routing.php diff --git a/config/sets/symfony/symfony6/symfony64.php b/config/sets/symfony/symfony6/symfony64.php index 5d7a2cab..aa5355be 100644 --- a/config/sets/symfony/symfony6/symfony64.php +++ b/config/sets/symfony/symfony6/symfony64.php @@ -2,41 +2,12 @@ declare(strict_types=1); -use PHPStan\Type\MixedType; use Rector\Config\RectorConfig; -use Rector\Renaming\Rector\Class_\RenameAttributeRector; -use Rector\Renaming\Rector\Name\RenameClassRector; -use Rector\Renaming\ValueObject\RenameAttribute; -use Rector\TypeDeclaration\Rector\ClassMethod\AddReturnTypeDeclarationRector; -use Rector\TypeDeclaration\ValueObject\AddReturnTypeDeclaration; // @see https://github.com/symfony/symfony/blob/6.4/UPGRADE-6.4.md return static function (RectorConfig $rectorConfig): void { - $rectorConfig->ruleWithConfiguration( - RenameClassRector::class, - [ - 'Symfony\Component\HttpKernel\UriSigner' => 'Symfony\Component\HttpFoundation\UriSigner', - 'Symfony\Component\HttpKernel\Debug\FileLinkFormatter' => 'Symfony\Component\ErrorHandler\ErrorRenderer\FileLinkFormatter', - ], - ); - - $rectorConfig->ruleWithConfiguration(RenameAttributeRector::class, [ - new RenameAttribute( - 'Symfony\Component\Routing\Annotation\Route', - 'Symfony\Component\Routing\Attribute\Route' - ), - ]); - - $rectorConfig->ruleWithConfiguration(AddReturnTypeDeclarationRector::class, [ - new AddReturnTypeDeclaration( - 'Symfony\Component\Form\DataTransformerInterface', - 'transform', - new MixedType(), - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\Form\DataTransformerInterface', - 'reverseTransform', - new MixedType(), - ), - ]); + $rectorConfig->import(__DIR__ . '/symfony64/symfony64-routing.php'); + $rectorConfig->import(__DIR__ . '/symfony64/symfony64-form.php'); + $rectorConfig->import(__DIR__ . '/symfony64/symfony64-http-foundation.php'); + $rectorConfig->import(__DIR__ . '/symfony64/symfony64-error-handler.php'); }; diff --git a/config/sets/symfony/symfony6/symfony64/symfony64-error-handler.php b/config/sets/symfony/symfony6/symfony64/symfony64-error-handler.php new file mode 100644 index 00000000..55337a94 --- /dev/null +++ b/config/sets/symfony/symfony6/symfony64/symfony64-error-handler.php @@ -0,0 +1,16 @@ +ruleWithConfiguration( + RenameClassRector::class, + [ + 'Symfony\Component\HttpKernel\Debug\FileLinkFormatter' => 'Symfony\Component\ErrorHandler\ErrorRenderer\FileLinkFormatter', + ], + ); +}; diff --git a/config/sets/symfony/symfony6/symfony64/symfony64-form.php b/config/sets/symfony/symfony6/symfony64/symfony64-form.php new file mode 100644 index 00000000..62a1c530 --- /dev/null +++ b/config/sets/symfony/symfony6/symfony64/symfony64-form.php @@ -0,0 +1,24 @@ +ruleWithConfiguration(AddReturnTypeDeclarationRector::class, [ + new AddReturnTypeDeclaration( + 'Symfony\Component\Form\DataTransformerInterface', + 'transform', + new MixedType(), + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\Form\DataTransformerInterface', + 'reverseTransform', + new MixedType(), + ), + ]); +}; diff --git a/config/sets/symfony/symfony6/symfony64/symfony64-http-foundation.php b/config/sets/symfony/symfony6/symfony64/symfony64-http-foundation.php new file mode 100644 index 00000000..4c6b4490 --- /dev/null +++ b/config/sets/symfony/symfony6/symfony64/symfony64-http-foundation.php @@ -0,0 +1,16 @@ +ruleWithConfiguration( + RenameClassRector::class, + [ + 'Symfony\Component\HttpKernel\UriSigner' => 'Symfony\Component\HttpFoundation\UriSigner', + ], + ); +}; diff --git a/config/sets/symfony/symfony6/symfony64/symfony64-routing.php b/config/sets/symfony/symfony6/symfony64/symfony64-routing.php new file mode 100644 index 00000000..370cf016 --- /dev/null +++ b/config/sets/symfony/symfony6/symfony64/symfony64-routing.php @@ -0,0 +1,16 @@ +ruleWithConfiguration(RenameAttributeRector::class, [ + new RenameAttribute( + 'Symfony\Component\Routing\Annotation\Route', + 'Symfony\Component\Routing\Attribute\Route' + ), + ]); +}; diff --git a/src/Set/SetProvider/Symfony6SetProvider.php b/src/Set/SetProvider/Symfony6SetProvider.php index 294d5e72..86d72984 100644 --- a/src/Set/SetProvider/Symfony6SetProvider.php +++ b/src/Set/SetProvider/Symfony6SetProvider.php @@ -207,10 +207,34 @@ public function provide(): array new ComposerTriggeredSet( SetGroup::SYMFONY, - 'symfony/*', + 'symfony/symfony', '6.4', __DIR__ . '/../../../config/sets/symfony/symfony6/symfony64.php' ), + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/routing', + '6.4', + __DIR__ . '/../../../config/sets/symfony/symfony6/symfony64/symfony64-routing.php' + ), + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/form', + '6.4', + __DIR__ . '/../../../config/sets/symfony/symfony6/symfony64/symfony64-form.php' + ), + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/http-foundation', + '6.4', + __DIR__ . '/../../../config/sets/symfony/symfony6/symfony64/symfony64-http-foundation.php' + ), + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/error-handler', + '6.4', + __DIR__ . '/../../../config/sets/symfony/symfony6/symfony64/symfony64-error-handler.php' + ), ]; } } From 11955c3f974425327e1f8b3d150ecac9cddf74eb Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Wed, 7 May 2025 10:39:59 +0700 Subject: [PATCH 53/53] [symfony 70] split of configs per package (#748) * [symfony 70] split of configs per package * add dependency injection * fix path * add serializer * add http-foundation * add contracts * add contracts --- config/sets/symfony/symfony7/symfony70.php | 13 ++++++ .../symfony70/symfony70-contracts.php | 14 ++++++ .../symfony70-dependency-injection.php | 17 ++++++++ .../symfony70/symfony70-http-foundation.php | 21 +++++++++ .../symfony70/symfony70-serializer.php | 14 ++++++ config/sets/symfony/symfony70.php | 43 ------------------- src/Set/SetProvider/Symfony7SetProvider.php | 29 ++++++++++++- src/Set/SymfonySetList.php | 2 +- 8 files changed, 107 insertions(+), 46 deletions(-) create mode 100644 config/sets/symfony/symfony7/symfony70.php create mode 100644 config/sets/symfony/symfony7/symfony70/symfony70-contracts.php create mode 100644 config/sets/symfony/symfony7/symfony70/symfony70-dependency-injection.php create mode 100644 config/sets/symfony/symfony7/symfony70/symfony70-http-foundation.php create mode 100644 config/sets/symfony/symfony7/symfony70/symfony70-serializer.php delete mode 100644 config/sets/symfony/symfony70.php diff --git a/config/sets/symfony/symfony7/symfony70.php b/config/sets/symfony/symfony7/symfony70.php new file mode 100644 index 00000000..af452a80 --- /dev/null +++ b/config/sets/symfony/symfony7/symfony70.php @@ -0,0 +1,13 @@ +import(__DIR__ . '/symfony70/symfony70-dependency-injection.php'); + $rectorConfig->import(__DIR__ . '/symfony70/symfony70-serializer.php'); + $rectorConfig->import(__DIR__ . '/symfony70/symfony70-http-foundation.php'); + $rectorConfig->import(__DIR__ . '/symfony70/symfony70-contracts.php'); +}; diff --git a/config/sets/symfony/symfony7/symfony70/symfony70-contracts.php b/config/sets/symfony/symfony7/symfony70/symfony70-contracts.php new file mode 100644 index 00000000..aba8f82a --- /dev/null +++ b/config/sets/symfony/symfony7/symfony70/symfony70-contracts.php @@ -0,0 +1,14 @@ +ruleWithConfiguration(AnnotationToAttributeRector::class, [ + new AnnotationToAttribute('required', 'Symfony\Contracts\Service\Attribute\Required'), + ]); +}; diff --git a/config/sets/symfony/symfony7/symfony70/symfony70-dependency-injection.php b/config/sets/symfony/symfony7/symfony70/symfony70-dependency-injection.php new file mode 100644 index 00000000..d1cf81c4 --- /dev/null +++ b/config/sets/symfony/symfony7/symfony70/symfony70-dependency-injection.php @@ -0,0 +1,17 @@ +ruleWithConfiguration(RenameAttributeRector::class, [ + new RenameAttribute( + 'Symfony\Component\DependencyInjection\Attribute\MapDecorated', + 'Symfony\Component\DependencyInjection\Attribute\AutowireDecorated', + ), + ]); +}; diff --git a/config/sets/symfony/symfony7/symfony70/symfony70-http-foundation.php b/config/sets/symfony/symfony7/symfony70/symfony70-http-foundation.php new file mode 100644 index 00000000..8c430577 --- /dev/null +++ b/config/sets/symfony/symfony7/symfony70/symfony70-http-foundation.php @@ -0,0 +1,21 @@ +ruleWithConfiguration(RenameClassRector::class, [ + // @see https://github.com/symfony/symfony/blob/7.0/UPGRADE-7.0.md#httpfoundation + 'Symfony\Component\HttpFoundation\RequestMatcher' => 'Symfony\Component\HttpFoundation\ChainRequestMatcher', + 'Symfony\Component\HttpFoundation\ExpressionRequestMatcher' => 'Symfony\Component\HttpFoundation\RequestMatcher\ExpressionRequestMatcher', + ]); + + // @see https://github.com/symfony/symfony/pull/50826 + $rectorConfig->ruleWithConfiguration(RenameMethodRector::class, [ + new MethodCallRename('Symfony\Component\HttpFoundation\Request', 'getContentType', 'getContentTypeFormat'), + ]); +}; diff --git a/config/sets/symfony/symfony7/symfony70/symfony70-serializer.php b/config/sets/symfony/symfony7/symfony70/symfony70-serializer.php new file mode 100644 index 00000000..9540058d --- /dev/null +++ b/config/sets/symfony/symfony7/symfony70/symfony70-serializer.php @@ -0,0 +1,14 @@ +ruleWithConfiguration(RenameClassRector::class, [ + // @see https://github.com/symfony/symfony/blob/7.0/UPGRADE-7.0.md#frameworkbundle + 'Symfony\Component\Serializer\Normalizer\ObjectNormalizer' => 'Symfony\Component\Serializer\Normalizer\NormalizerInterface', + 'Symfony\Component\Serializer\Normalizer\PropertyNormalizer' => 'Symfony\Component\Serializer\Normalizer\NormalizerInterface', + ]); +}; diff --git a/config/sets/symfony/symfony70.php b/config/sets/symfony/symfony70.php deleted file mode 100644 index 7eb6cbb1..00000000 --- a/config/sets/symfony/symfony70.php +++ /dev/null @@ -1,43 +0,0 @@ -ruleWithConfiguration(RenameAttributeRector::class, [ - new RenameAttribute( - 'Symfony\Component\DependencyInjection\Attribute\MapDecorated', - 'Symfony\Component\DependencyInjection\Attribute\AutowireDecorated', - ), - ]); - - $rectorConfig->ruleWithConfiguration(RenameClassRector::class, [ - // @see https://github.com/symfony/symfony/blob/7.0/UPGRADE-7.0.md#frameworkbundle - 'Symfony\Component\Serializer\Normalizer\ObjectNormalizer' => 'Symfony\Component\Serializer\Normalizer\NormalizerInterface', - 'Symfony\Component\Serializer\Normalizer\PropertyNormalizer' => 'Symfony\Component\Serializer\Normalizer\NormalizerInterface', - - // @see https://github.com/symfony/symfony/blob/7.0/UPGRADE-7.0.md#httpfoundation - 'Symfony\Component\HttpFoundation\RequestMatcher' => 'Symfony\Component\HttpFoundation\ChainRequestMatcher', - 'Symfony\Component\HttpFoundation\ExpressionRequestMatcher' => 'Symfony\Component\HttpFoundation\RequestMatcher\ExpressionRequestMatcher', - ]); - - // @see https://github.com/symfony/symfony/pull/50826 - $rectorConfig->ruleWithConfiguration(RenameMethodRector::class, [ - new MethodCallRename('Symfony\Component\HttpFoundation\Request', 'getContentType', 'getContentTypeFormat'), - ]); - - // the "@required" was dropped, use attribute instead - $rectorConfig->ruleWithConfiguration(AnnotationToAttributeRector::class, [ - new AnnotationToAttribute('required', 'Symfony\Contracts\Service\Attribute\Required'), - ]); -}; diff --git a/src/Set/SetProvider/Symfony7SetProvider.php b/src/Set/SetProvider/Symfony7SetProvider.php index 998bb026..e37cf6af 100644 --- a/src/Set/SetProvider/Symfony7SetProvider.php +++ b/src/Set/SetProvider/Symfony7SetProvider.php @@ -19,10 +19,35 @@ public function provide(): array return [ new ComposerTriggeredSet( SetGroup::SYMFONY, - 'symfony/*', + 'symfony/symfony', + '7.0', + __DIR__ . '/../../../config/sets/symfony/symfony7/symfony70.php' + ), + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/dependency-injection', + '7.0', + __DIR__ . '/../../../config/sets/symfony/symfony7/symfony70/symfony70-dependency-injection.php' + ), + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/serializer', '7.0', - __DIR__ . '/../../../config/sets/symfony/symfony70.php' + __DIR__ . '/../../../config/sets/symfony/symfony7/symfony70/symfony70-serializer.php' ), + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/http-foundation', + '7.0', + __DIR__ . '/../../../config/sets/symfony/symfony7/symfony70/symfony70-http-foundation.php' + ), + new ComposerTriggeredSet( + SetGroup::SYMFONY, + 'symfony/contracts', + '7.0', + __DIR__ . '/../../../config/sets/symfony/symfony7/symfony70/symfony70-contracts.php' + ), + new ComposerTriggeredSet( SetGroup::SYMFONY, 'symfony/*', diff --git a/src/Set/SymfonySetList.php b/src/Set/SymfonySetList.php index 28ead3b3..58e40ad2 100644 --- a/src/Set/SymfonySetList.php +++ b/src/Set/SymfonySetList.php @@ -150,7 +150,7 @@ final class SymfonySetList /** * @var string */ - final public const SYMFONY_70 = __DIR__ . '/../../config/sets/symfony/symfony70.php'; + final public const SYMFONY_70 = __DIR__ . '/../../config/sets/symfony/symfony7/symfony70.php'; /** * @var string