diff --git a/composer.json b/composer.json index 5bfccf2e3..2de1eaa98 100644 --- a/composer.json +++ b/composer.json @@ -8,21 +8,25 @@ "ext-xml": "*" }, "require-dev": { + "phpecs/phpecs": "^2.0.1", "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", + "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/phpstan-rules": "^14.6", "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/symfony-code-quality.php b/config/sets/symfony/symfony-code-quality.php index 330a73ba4..1255e98f0 100644 --- a/config/sets/symfony/symfony-code-quality.php +++ b/config/sets/symfony/symfony-code-quality.php @@ -3,9 +3,13 @@ declare(strict_types=1); 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; +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; @@ -28,7 +32,17 @@ ActionSuffixRemoverRector::class, LoadValidatorMetadataToAnnotationRector::class, + // request method + RequestIsMainRector::class, + // tests AssertSameResponseCodeWithDebugContentsRector::class, + + // routing + InlineClassRoutePrefixRector::class, + + // narrow attributes + SingleConditionSecurityAttributeToIsGrantedRector::class, + SplitAndSecurityAttributeToIsGrantedRector::class, ]); }; diff --git a/config/sets/symfony/symfony3/symfony30.php b/config/sets/symfony/symfony3/symfony30.php new file mode 100644 index 000000000..402cbcbb1 --- /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-form.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 000000000..e6fb1eb78 --- /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 000000000..16d254c2c --- /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 000000000..24b786409 --- /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 000000000..bdac3bf33 --- /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-form.php b/config/sets/symfony/symfony3/symfony30/symfony30-form.php new file mode 100644 index 000000000..82dd1652c --- /dev/null +++ b/config/sets/symfony/symfony3/symfony30/symfony30-form.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 000000000..a1e80d199 --- /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 000000000..62b2b223f --- /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 000000000..d82c03528 --- /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 000000000..eec3421c4 --- /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 000000000..9f97bee63 --- /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 000000000..ba64fc1a9 --- /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 000000000..d51460ecd --- /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 000000000..fda92eef9 --- /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/symfony3/symfony31.php b/config/sets/symfony/symfony3/symfony31.php new file mode 100644 index 000000000..7aa92b7f2 --- /dev/null +++ b/config/sets/symfony/symfony3/symfony31.php @@ -0,0 +1,9 @@ +import(__DIR__ . '/symfony31/symfony31-yaml.php'); +}; diff --git a/config/sets/symfony/symfony31.php b/config/sets/symfony/symfony3/symfony31/symfony31-yaml.php similarity index 100% rename from config/sets/symfony/symfony31.php rename to config/sets/symfony/symfony3/symfony31/symfony31-yaml.php diff --git a/config/sets/symfony/symfony3/symfony32.php b/config/sets/symfony/symfony3/symfony32.php new file mode 100644 index 000000000..696d849f0 --- /dev/null +++ b/config/sets/symfony/symfony3/symfony32.php @@ -0,0 +1,9 @@ +import(__DIR__ . '/symfony32/symfony32-dependency-injection.php'); +}; diff --git a/config/sets/symfony/symfony32.php b/config/sets/symfony/symfony3/symfony32/symfony32-dependency-injection.php similarity index 100% rename from config/sets/symfony/symfony32.php rename to config/sets/symfony/symfony3/symfony32/symfony32-dependency-injection.php diff --git a/config/sets/symfony/symfony3/symfony33.php b/config/sets/symfony/symfony3/symfony33.php new file mode 100644 index 000000000..711068364 --- /dev/null +++ b/config/sets/symfony/symfony3/symfony33.php @@ -0,0 +1,12 @@ +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 000000000..3735565ac --- /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 000000000..492d6a221 --- /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 000000000..614ca6445 --- /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 000000000..3cfe7b001 --- /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 new file mode 100644 index 000000000..51de6e82f --- /dev/null +++ b/config/sets/symfony/symfony3/symfony34.php @@ -0,0 +1,12 @@ +import(__DIR__ . '/symfony34/symfony34-yaml.php'); + $rectorConfig->import(__DIR__ . '/symfony34/symfony34-dependency-injection.php'); + $rectorConfig->import(__DIR__ . '/symfony34/symfony34-sensio-framework-extra-bundle.php'); + +}; 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 000000000..08a87eff1 --- /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/symfony34.php b/config/sets/symfony/symfony3/symfony34/symfony34-sensio-framework-extra-bundle.php similarity index 54% rename from config/sets/symfony/symfony34.php rename to config/sets/symfony/symfony3/symfony34/symfony34-sensio-framework-extra-bundle.php index 3e5542297..890ccf743 100644 --- a/config/sets/symfony/symfony34.php +++ b/config/sets/symfony/symfony3/symfony34/symfony34-sensio-framework-extra-bundle.php @@ -3,27 +3,14 @@ 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->rules([ MergeMethodAnnotationToRouteAnnotationRector::class, RemoveServiceFromSensioRouteRector::class, ReplaceSensioRouteAnnotationWithSymfonyRector::class, - ContainerGetNameToTypeInTestsRector::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 000000000..237dc1cc6 --- /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/symfony30.php b/config/sets/symfony/symfony30.php deleted file mode 100644 index 0aa8c6eec..000000000 --- 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/config/sets/symfony/symfony33.php b/config/sets/symfony/symfony33.php deleted file mode 100644 index 0a8f08c4c..000000000 --- a/config/sets/symfony/symfony33.php +++ /dev/null @@ -1,60 +0,0 @@ -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'), - ]); -}; diff --git a/config/sets/symfony/symfony4/symfony40.php b/config/sets/symfony/symfony4/symfony40.php new file mode 100644 index 000000000..c6b812714 --- /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-form.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 000000000..d029830b5 --- /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-form.php b/config/sets/symfony/symfony4/symfony40/symfony40-form.php new file mode 100644 index 000000000..f54ea6514 --- /dev/null +++ b/config/sets/symfony/symfony4/symfony40/symfony40-form.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 000000000..02a69337a --- /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 000000000..9475e8648 --- /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 000000000..b676c11bf --- /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/symfony4/symfony41.php b/config/sets/symfony/symfony4/symfony41.php new file mode 100644 index 000000000..ee504d832 --- /dev/null +++ b/config/sets/symfony/symfony4/symfony41.php @@ -0,0 +1,13 @@ +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 326b4c2fd..54d00edd3 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 000000000..265595231 --- /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 000000000..78e7376c8 --- /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 000000000..5f519315b --- /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/symfony4/symfony42.php b/config/sets/symfony/symfony4/symfony42.php new file mode 100644 index 000000000..583a36761 --- /dev/null +++ b/config/sets/symfony/symfony4/symfony42.php @@ -0,0 +1,22 @@ +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-form.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 000000000..e8fd3ea27 --- /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 000000000..349c41681 --- /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 000000000..f6196ca22 --- /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 000000000..ab3d39c04 --- /dev/null +++ b/config/sets/symfony/symfony4/symfony42/symfony42-finder.php @@ -0,0 +1,22 @@ +ruleWithConfiguration(ArgumentAdderRector::class, [ + new ArgumentAdder( + 'Symfony\Component\Finder\Finder', + 'sortByName', + 0, + null, + false, + null, + ArgumentAddingScope::SCOPE_METHOD_CALL + ), + ]); +}; diff --git a/config/sets/symfony/symfony4/symfony42/symfony42-form.php b/config/sets/symfony/symfony4/symfony42/symfony42-form.php new file mode 100644 index 000000000..ae5f82018 --- /dev/null +++ b/config/sets/symfony/symfony4/symfony42/symfony42-form.php @@ -0,0 +1,50 @@ +ruleWithConfiguration(RenameMethodRector::class, [ + 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)] + ); +}; 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 000000000..da1e0ad1e --- /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 000000000..cf74f67bc --- /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 000000000..42643b8b8 --- /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 000000000..3cd972ef8 --- /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 000000000..4abe48e0d --- /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 000000000..5627f0b3d --- /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 000000000..331446f5c --- /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/config/sets/symfony/symfony4/symfony43.php b/config/sets/symfony/symfony4/symfony43.php new file mode 100644 index 000000000..b977b86a5 --- /dev/null +++ b/config/sets/symfony/symfony4/symfony43.php @@ -0,0 +1,20 @@ +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 000000000..0fac5a6fc --- /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 000000000..5dfb98a61 --- /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 000000000..a23ef4e67 --- /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 000000000..5a4e2ee7d --- /dev/null +++ b/config/sets/symfony/symfony4/symfony43/symfony43-framework-bundle.php @@ -0,0 +1,27 @@ +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([ + ConvertRenderTemplateShortNotationToBundleSyntaxRector::class, + # https://symfony.com/blog/new-in-symfony-4-3-better-test-assertions + // + WebTestCaseAssertIsSuccessfulRector::class, + 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 000000000..7f5f9b7d3 --- /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 000000000..bdd0d7d6f --- /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 000000000..e9382013a --- /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 000000000..29e8c128f --- /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 000000000..fbd042523 --- /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 000000000..903b98e01 --- /dev/null +++ b/config/sets/symfony/symfony4/symfony43/symfony43-twig-bundle.php @@ -0,0 +1,10 @@ +rules([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 000000000..709cd6521 --- /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/config/sets/symfony/symfony4/symfony44.php b/config/sets/symfony/symfony4/symfony44.php new file mode 100644 index 000000000..2fe19897a --- /dev/null +++ b/config/sets/symfony/symfony4/symfony44.php @@ -0,0 +1,15 @@ +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 000000000..0804f8f36 --- /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 000000000..73513ce39 --- /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 000000000..ee793b435 --- /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 000000000..c6ee96035 --- /dev/null +++ b/config/sets/symfony/symfony4/symfony44/symfony44-security-core.php @@ -0,0 +1,10 @@ +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 000000000..834ec702c --- /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/config/sets/symfony/symfony40.php b/config/sets/symfony/symfony40.php deleted file mode 100644 index 61e4afaa9..000000000 --- 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/config/sets/symfony/symfony42.php b/config/sets/symfony/symfony42.php deleted file mode 100644 index 541301f0d..000000000 --- a/config/sets/symfony/symfony42.php +++ /dev/null @@ -1,191 +0,0 @@ -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 - ), - ]); -}; diff --git a/config/sets/symfony/symfony43.php b/config/sets/symfony/symfony43.php deleted file mode 100644 index e71f91fe2..000000000 --- a/config/sets/symfony/symfony43.php +++ /dev/null @@ -1,97 +0,0 @@ -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', - [] - ), - ]); -}; diff --git a/config/sets/symfony/symfony44.php b/config/sets/symfony/symfony44.php deleted file mode 100644 index 3d2e52b07..000000000 --- a/config/sets/symfony/symfony44.php +++ /dev/null @@ -1,45 +0,0 @@ -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' - ), - ]); -}; diff --git a/config/sets/symfony/symfony5/symfony50.php b/config/sets/symfony/symfony5/symfony50.php new file mode 100644 index 000000000..450e06234 --- /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/symfony50.php b/config/sets/symfony/symfony5/symfony50/symfony50-console.php similarity index 61% rename from config/sets/symfony/symfony50.php rename to config/sets/symfony/symfony5/symfony50/symfony50-console.php index e1aeef386..43ecfa163 100644 --- a/config/sets/symfony/symfony50.php +++ b/config/sets/symfony/symfony5/symfony50/symfony50-console.php @@ -4,18 +4,9 @@ use Rector\Config\RectorConfig; use Rector\Renaming\Rector\MethodCall\RenameMethodRector; -use Rector\Renaming\Rector\Name\RenameClassRector; use Rector\Renaming\ValueObject\MethodCallRename; -# 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(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/symfony5/symfony50/symfony50-debug.php b/config/sets/symfony/symfony5/symfony50/symfony50-debug.php new file mode 100644 index 000000000..9e4dbab1b --- /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 18e1482e8..a687fed9d 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 000000000..a85f399fd --- /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-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'); + $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 000000000..d306f643c --- /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 000000000..06dd69045 --- /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 000000000..593b257ca --- /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 000000000..a904f727b --- /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-form.php b/config/sets/symfony/symfony5/symfony51/symfony51-form.php new file mode 100644 index 000000000..b275a467a --- /dev/null +++ b/config/sets/symfony/symfony5/symfony51/symfony51-form.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 000000000..6445ce3c6 --- /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 000000000..b173120a2 --- /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 000000000..625d778cc --- /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 000000000..47486ab63 --- /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 000000000..0ccf58c09 --- /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 000000000..b21ee7103 --- /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/symfony5/symfony52.php b/config/sets/symfony/symfony5/symfony52.php new file mode 100644 index 000000000..f5ccb00ba --- /dev/null +++ b/config/sets/symfony/symfony5/symfony52.php @@ -0,0 +1,23 @@ +sets([SymfonySetList::ANNOTATIONS_TO_ATTRIBUTES]); + + $rectorConfig->import(__DIR__ . '/symfony52/symfony52-dependency-injection.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'); + $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'); + +}; 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 000000000..3cd62181a --- /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-form.php b/config/sets/symfony/symfony5/symfony52/symfony52-form.php new file mode 100644 index 000000000..bd8549294 --- /dev/null +++ b/config/sets/symfony/symfony5/symfony52/symfony52-form.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 000000000..26029db43 --- /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 000000000..5cea71101 --- /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 000000000..cbba35ebb --- /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 000000000..d4d50c694 --- /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 000000000..11f3c5645 --- /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 000000000..82a2c9fa7 --- /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 000000000..941013328 --- /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 000000000..88120808f --- /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/config/sets/symfony/symfony5/symfony53.php b/config/sets/symfony/symfony5/symfony53.php new file mode 100644 index 000000000..b54037e56 --- /dev/null +++ b/config/sets/symfony/symfony5/symfony53.php @@ -0,0 +1,19 @@ +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 000000000..0485b22ca --- /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 000000000..107ed88f5 --- /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 000000000..989cb52d0 --- /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 000000000..fcbc160f1 --- /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 000000000..89630fc7e --- /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 000000000..012924418 --- /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/symfony53.php b/config/sets/symfony/symfony5/symfony53/symfony53-security-core.php similarity index 52% rename from config/sets/symfony/symfony53.php rename to config/sets/symfony/symfony5/symfony53/symfony53-security-core.php index 4f187dba9..8fa47ded5 100644 --- a/config/sets/symfony/symfony53.php +++ b/config/sets/symfony/symfony5/symfony53/symfony53-security-core.php @@ -2,40 +2,13 @@ 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', @@ -73,41 +46,4 @@ '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]); }; diff --git a/config/sets/symfony/symfony5/symfony54.php b/config/sets/symfony/symfony5/symfony54.php new file mode 100644 index 000000000..4f551ce25 --- /dev/null +++ b/config/sets/symfony/symfony5/symfony54.php @@ -0,0 +1,19 @@ +sets([SymfonySetList::ANNOTATIONS_TO_ATTRIBUTES]); + + $rectorConfig->import(__DIR__ . '/symfony54/symfony54-validator.php'); + $rectorConfig->import(__DIR__ . '/symfony54/symfony54-security-bundle.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-cache.php b/config/sets/symfony/symfony5/symfony54/symfony54-cache.php new file mode 100644 index 000000000..fbdfcd429 --- /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 000000000..40b2318f1 --- /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 000000000..aeee6b818 --- /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 000000000..ac917b7be --- /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-core.php b/config/sets/symfony/symfony5/symfony54/symfony54-security-core.php new file mode 100644 index 000000000..f94478740 --- /dev/null +++ b/config/sets/symfony/symfony5/symfony54/symfony54-security-core.php @@ -0,0 +1,36 @@ +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' + ), + ]); +}; 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 000000000..855374334 --- /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/config/sets/symfony/symfony5/symfony54/symfony54-validator.php b/config/sets/symfony/symfony5/symfony54/symfony54-validator.php new file mode 100644 index 000000000..f3a446e36 --- /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/config/sets/symfony/symfony51.php b/config/sets/symfony/symfony51.php deleted file mode 100644 index 312904532..000000000 --- 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/symfony52.php b/config/sets/symfony/symfony52.php deleted file mode 100644 index 3fd7ea046..000000000 --- a/config/sets/symfony/symfony52.php +++ /dev/null @@ -1,172 +0,0 @@ -sets([SymfonySetList::ANNOTATIONS_TO_ATTRIBUTES]); - - $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/symfony54.php b/config/sets/symfony/symfony54.php deleted file mode 100644 index 21e4b2580..000000000 --- a/config/sets/symfony/symfony54.php +++ /dev/null @@ -1,82 +0,0 @@ -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', - ]); -}; diff --git a/config/sets/symfony/symfony6/symfony-return-types.php b/config/sets/symfony/symfony6/symfony-return-types.php deleted file mode 100644 index ff50c6391..000000000 --- a/config/sets/symfony/symfony6/symfony-return-types.php +++ /dev/null @@ -1,584 +0,0 @@ -newInstanceWithoutConstructor(); - - $privatesAccessor = new PrivatesAccessor(); - $privatesAccessor->setPrivateProperty($scalarArrayObjectUnionType, 'types', $scalarArrayObjectUnionedTypes); - $rectorConfig->ruleWithConfiguration(AddReturnTypeDeclarationRector::class, [ - new AddReturnTypeDeclaration('Symfony\Component\Config\Loader\LoaderInterface', 'load', new MixedType()), - new AddReturnTypeDeclaration('Symfony\Component\Config\Loader\Loader', 'import', new MixedType()), - new AddReturnTypeDeclaration( - 'Symfony\Component\HttpKernel\KernelInterface', - 'registerBundles', - $iterableType, - ), - // @see https://wouterj.nl/2021/09/symfony-6-native-typing#when-upgrading-to-symfony-54 - new AddReturnTypeDeclaration( - 'Symfony\Component\Security\Core\User\UserInterface', - 'getRoles', - new ArrayType(new MixedType(), new MixedType()) - ), - // @see https://github.com/symfony/symfony/pull/43028/files - new AddReturnTypeDeclaration( - 'Symfony\Component\Console\Helper\HelperInterface', - 'getName', - new StringType() - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\BrowserKit\AbstractBrowser', - 'doRequestInProcess', - new ObjectWithoutClassType() - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\BrowserKit\AbstractBrowser', - 'doRequest', - new ObjectWithoutClassType() - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\BrowserKit\AbstractBrowser', - 'filterRequest', - new ObjectWithoutClassType() - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\BrowserKit\AbstractBrowser', - 'filterResponse', - $browserKitResponseType - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\Config\Definition\ConfigurationInterface', - 'getConfigTreeBuilder', - new ObjectType('Symfony\Component\Config\Definition\Builder\TreeBuilder') - ), - new AddReturnTypeDeclaration('Symfony\Component\Config\FileLocator', 'locate', new UnionType([ - new StringType(), - $arrayType, - ])), - new AddReturnTypeDeclaration('Symfony\Component\Config\FileLocatorInterface', 'locate', new UnionType([ - new StringType(), - $arrayType, - ])), - new AddReturnTypeDeclaration('Symfony\Component\Config\Loader\FileLoader', 'import', new MixedType()), - new AddReturnTypeDeclaration('Symfony\Component\Config\Loader\Loader', 'import', new MixedType()), - new AddReturnTypeDeclaration('Symfony\Component\Config\Loader\LoaderInterface', 'load', new MixedType()), - new AddReturnTypeDeclaration( - 'Symfony\Component\Config\Loader\LoaderInterface', - 'supports', - new BooleanType() - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\Config\Loader\LoaderInterface', - 'getResolver', - new ObjectType('Symfony\Component\Config\Loader\LoaderResolverInterface') - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\Config\ResourceCheckerInterface', - 'supports', - new BooleanType() - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\Config\ResourceCheckerInterface', - 'isFresh', - new BooleanType() - ), - new AddReturnTypeDeclaration('Symfony\Component\Console\Application', 'doRun', new IntegerType()), - new AddReturnTypeDeclaration('Symfony\Component\Console\Application', 'getLongVersion', new StringType()), - new AddReturnTypeDeclaration('Symfony\Component\Console\Application', 'add', new UnionType([ - new NullType(), - $commandType, - ])), - new AddReturnTypeDeclaration('Symfony\Component\Console\Application', 'get', $commandType), - new AddReturnTypeDeclaration('Symfony\Component\Console\Application', 'find', $commandType), - new AddReturnTypeDeclaration('Symfony\Component\Console\Application', 'all', $arrayType), - new AddReturnTypeDeclaration('Symfony\Component\Console\Application', 'doRunCommand', new IntegerType()), - new AddReturnTypeDeclaration('Symfony\Component\Console\Command\Command', 'isEnabled', new BooleanType()), - new AddReturnTypeDeclaration('Symfony\Component\Console\Command\Command', 'execute', new IntegerType()), - new AddReturnTypeDeclaration( - 'Symfony\Component\Console\Helper\HelperInterface', - 'getName', - new StringType() - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\Console\Input\InputInterface', - 'getParameterOption', - new MixedType() - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\Console\Input\InputInterface', - 'getArgument', - new MixedType() - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\Console\Input\InputInterface', - 'getOption', - new MixedType() - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\DependencyInjection\Compiler\AbstractRecursivePass', - 'processValue', - new MixedType() - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\DependencyInjection\Extension\ConfigurationExtensionInterface', - 'getConfiguration', - new UnionType([new NullType(), $configurationType]) - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\DependencyInjection\Extension\Extension', - 'getXsdValidationBasePath', - new UnionType([new StringType(), new ConstantBooleanType(false)]) - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\DependencyInjection\Extension\Extension', - 'getNamespace', - new StringType() - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\DependencyInjection\Extension\Extension', - 'getConfiguration', - new UnionType([new NullType(), $configurationType]) - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\DependencyInjection\Extension\ExtensionInterface', - 'getNamespace', - new StringType() - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\DependencyInjection\Extension\ExtensionInterface', - 'getXsdValidationBasePath', - new UnionType([new StringType(), new ConstantBooleanType(false)]) - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\DependencyInjection\Extension\ExtensionInterface', - 'getAlias', - new StringType() - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\DependencyInjection\LazyProxy\Instantiator\InstantiatorInterface', - 'instantiateProxy', - new ObjectWithoutClassType() - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\EventDispatcher\EventSubscriberInterface', - 'getSubscribedEvents', - $arrayType - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface', - 'getFunctions', - $arrayType - ), - new AddReturnTypeDeclaration('Symfony\Component\Form\AbstractExtension', 'loadTypes', $arrayType), - new AddReturnTypeDeclaration( - 'Symfony\Component\Form\AbstractExtension', - 'loadTypeGuesser', - new UnionType([new NullType(), new ObjectType('Symfony\Component\Form\FormTypeGuesserInterface')]) - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\Form\AbstractRendererEngine', - 'loadResourceForBlockName', - new BooleanType() - ), - new AddReturnTypeDeclaration('Symfony\Component\Form\AbstractType', 'getBlockPrefix', new StringType()), - new AddReturnTypeDeclaration('Symfony\Component\Form\AbstractType', 'getParent', $nullableStringType), - new AddReturnTypeDeclaration( - 'Symfony\Component\Form\DataTransformerInterface', - 'transform', - new MixedType() - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\Form\DataTransformerInterface', - 'reverseTransform', - new MixedType() - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\Form\FormRendererEngineInterface', - 'renderBlock', - new StringType() - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\Form\FormTypeGuesserInterface', - 'guessType', - new UnionType([new NullType(), $typeGuessType]), - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\Form\FormTypeGuesserInterface', - 'guessRequired', - $nullableValueGuessType - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\Form\FormTypeGuesserInterface', - 'guessMaxLength', - $nullableValueGuessType - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\Form\FormTypeGuesserInterface', - 'guessPattern', - $nullableValueGuessType - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\Form\FormTypeInterface', - 'getBlockPrefix', - new StringType() - ), - new AddReturnTypeDeclaration('Symfony\Component\Form\FormTypeInterface', 'getParent', $nullableStringType), - new AddReturnTypeDeclaration('Symfony\Component\Form\FormTypeInterface', 'buildForm', new VoidType()), - new AddReturnTypeDeclaration('Symfony\Component\Form\FormTypeInterface', 'configureOptions', new VoidType()), - new AddReturnTypeDeclaration( - 'Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface', - 'isOptional', - new BooleanType() - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface', - 'warmUp', - $arrayType - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\HttpKernel\DataCollector\DataCollector', - 'getCasters', - $arrayType - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface', - 'getName', - new StringType() - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\HttpKernel\HttpCache\HttpCache', - 'forward', - $httpFoundationResponseType - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\HttpKernel\HttpKernelBrowser', - 'doRequest', - $httpFoundationResponseType - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\HttpKernel\HttpKernelBrowser', - 'getScript', - new StringType() - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\HttpKernel\Log\DebugLoggerInterface', - 'getLogs', - $arrayType - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\HttpKernel\Log\DebugLoggerInterface', - 'countErrors', - new IntegerType() - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\OptionsResolver\OptionsResolver', - 'setNormalizer', - new SimpleStaticType('Symfony\Component\OptionsResolver\OptionsResolver') - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\OptionsResolver\OptionsResolver', - 'setAllowedValues', - new SimpleStaticType('Symfony\Component\OptionsResolver\OptionsResolver') - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\OptionsResolver\OptionsResolver', - 'addAllowedValues', - new SimpleStaticType('Symfony\Component\OptionsResolver\OptionsResolver') - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\OptionsResolver\OptionsResolver', - 'setAllowedTypes', - new SimpleStaticType('Symfony\Component\OptionsResolver\OptionsResolver') - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\OptionsResolver\OptionsResolver', - 'addAllowedTypes', - new SimpleStaticType('Symfony\Component\OptionsResolver\OptionsResolver') - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\PropertyAccess\PropertyPathInterface', - 'getLength', - new IntegerType() - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\PropertyAccess\PropertyPathInterface', - 'getParent', - new UnionType([ - new NullType(), - new ObjectType('Symfony\Component\PropertyAccess\PropertyPathInterface'), - ]) - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\PropertyAccess\PropertyPathInterface', - 'getElements', - $arrayType - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\PropertyAccess\PropertyPathInterface', - 'getElement', - new StringType() - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\PropertyAccess\PropertyPathInterface', - 'isProperty', - new BooleanType() - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\PropertyAccess\PropertyPathInterface', - 'isIndex', - new BooleanType() - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\PropertyInfo\PropertyAccessExtractorInterface', - 'isReadable', - $nullableBooleanType - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\PropertyInfo\PropertyAccessExtractorInterface', - 'isWritable', - $nullableBooleanType - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\PropertyInfo\PropertyListExtractorInterface', - 'getProperties', - $nullableArrayType - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface', - 'getTypes', - $nullableArrayType - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\Routing\Loader\AnnotationClassLoader', - 'getDefaultRouteName', - new StringType() - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\Routing\Router', - 'getRouteCollection', - $routeCollectionType - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\Routing\RouterInterface', - 'getRouteCollection', - $routeCollectionType - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\Security\Core\Authentication\RememberMe\TokenProviderInterface', - 'loadTokenBySeries', - new ObjectType('Symfony\Component\Security\Core\Authentication\RememberMe\PersistentTokenInterface') - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\Security\Core\Authorization\Voter\VoterInterface', - 'vote', - new IntegerType() - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\Security\Core\Exception\AuthenticationException', - 'getMessageKey', - new StringType() - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\Security\Core\User\UserProviderInterface', - 'refreshUser', - new ObjectType('Symfony\Component\Security\Core\User\UserInterface') - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\Security\Core\User\UserProviderInterface', - 'supportsClass', - new BooleanType() - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface', - 'start', - $httpFoundationResponseType - ), - new AddReturnTypeDeclaration('Symfony\Component\Security\Http\Firewall', 'getSubscribedEvents', $arrayType), - new AddReturnTypeDeclaration( - 'Symfony\Component\Security\Http\FirewallMapInterface', - 'getListeners', - $arrayType - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\Serializer\Encoder\DecoderInterface', - 'decode', - new MixedType() - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\Serializer\Encoder\DecoderInterface', - 'supportsDecoding', - new BooleanType() - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\Serializer\Normalizer\AbstractNormalizer', - 'getAllowedAttributes', - new UnionType([$arrayType, new BooleanType()]) - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\Serializer\Normalizer\AbstractNormalizer', - 'isAllowedAttribute', - new BooleanType() - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\Serializer\Normalizer\AbstractNormalizer', - 'instantiateObject', - new ObjectWithoutClassType() - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer', - 'supportsNormalization', - new BooleanType() - ), - - new AddReturnTypeDeclaration( - 'Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer', - 'instantiateObject', - new ObjectWithoutClassType() - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer', - 'extractAttributes', - $arrayType - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer', - 'getAttributeValue', - new MixedType() - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer', - 'supportsDenormalization', - new BooleanType() - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer', - 'denormalize', - new MixedType() - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\Serializer\Normalizer\DenormalizerInterface', - 'denormalize', - new MixedType() - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\Serializer\Normalizer\DenormalizerInterface', - 'supportsDenormalization', - new BooleanType() - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\Serializer\Normalizer\NormalizerInterface', - 'supportsNormalization', - new BooleanType() - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\Templating\Helper\HelperInterface', - 'getName', - new StringType() - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\Translation\Extractor\AbstractFileExtractor', - 'canBeExtracted', - new BooleanType() - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\Translation\Extractor\AbstractFileExtractor', - 'extractFromDirectory', - $iterableType - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\Validator\Constraint', - 'getDefaultOption', - $nullableStringType - ), - new AddReturnTypeDeclaration('Symfony\Component\Validator\Constraint', 'getRequiredOptions', $arrayType), - new AddReturnTypeDeclaration('Symfony\Component\Validator\Constraint', 'validatedBy', new StringType()), - new AddReturnTypeDeclaration( - 'Symfony\Component\Validator\Constraint', - 'getTargets', - new UnionType([new StringType(), $arrayType]) - ), - - new AddReturnTypeDeclaration( - 'Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer', - 'normalize', - $scalarArrayObjectUnionType - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\DependencyInjection\Container', - 'getParameter', - new UnionType($scalarTypes) - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\DependencyInjection\ContainerInterface', - 'getParameter', - new UnionType($scalarTypes) - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\Serializer\Normalizer\NormalizerInterface', - 'normalize', - $scalarArrayObjectUnionType - ), - new AddReturnTypeDeclaration( - 'Symfony\Component\Security\Http\Authenticator\AuthenticatorInterface', - 'authenticate', - new ObjectType('Symfony\Component\Security\Http\Authenticator\Passport\Passport') - ), - ]); -}; diff --git a/config/sets/symfony/symfony6/symfony60.php b/config/sets/symfony/symfony6/symfony60.php new file mode 100644 index 000000000..5f71659a0 --- /dev/null +++ b/config/sets/symfony/symfony6/symfony60.php @@ -0,0 +1,33 @@ +sets([SymfonySetList::ANNOTATIONS_TO_ATTRIBUTES]); + + $rectorConfig->import(__DIR__ . '/symfony60/symfony60-serializer.php'); + $rectorConfig->import(__DIR__ . '/symfony60/symfony60-security-http.php'); + $rectorConfig->import(__DIR__ . '/symfony60/symfony60-console.php'); + $rectorConfig->import(__DIR__ . '/symfony60/symfony60-browser-kit.php'); + $rectorConfig->import(__DIR__ . '/symfony60/symfony60-http-kernel.php'); + $rectorConfig->import(__DIR__ . '/symfony60/symfony60-validator.php'); + $rectorConfig->import(__DIR__ . '/symfony60/symfony60-form.php'); + $rectorConfig->import(__DIR__ . '/symfony60/symfony60-translation.php'); + $rectorConfig->import(__DIR__ . '/symfony60/symfony60-property-access.php'); + $rectorConfig->import(__DIR__ . '/symfony60/symfony60-property-info.php'); + $rectorConfig->import(__DIR__ . '/symfony60/symfony60-routing.php'); + $rectorConfig->import(__DIR__ . '/symfony60/symfony60-templating.php'); + $rectorConfig->import(__DIR__ . '/symfony60/symfony60-event-dispatcher.php'); + $rectorConfig->import(__DIR__ . '/symfony60/symfony60-expression-language.php'); + $rectorConfig->import(__DIR__ . '/symfony60/symfony60-options-resolver.php'); + $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-browser-kit.php b/config/sets/symfony/symfony6/symfony60/symfony60-browser-kit.php new file mode 100644 index 000000000..ec6fde0c9 --- /dev/null +++ b/config/sets/symfony/symfony6/symfony60/symfony60-browser-kit.php @@ -0,0 +1,38 @@ +ruleWithConfiguration(AddReturnTypeDeclarationRector::class, [ + new AddReturnTypeDeclaration( + 'Symfony\Component\BrowserKit\AbstractBrowser', + 'doRequestInProcess', + new ObjectWithoutClassType() + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\BrowserKit\AbstractBrowser', + 'doRequest', + new ObjectWithoutClassType() + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\BrowserKit\AbstractBrowser', + 'filterRequest', + new ObjectWithoutClassType() + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\BrowserKit\AbstractBrowser', + 'filterResponse', + $browserKitResponseType + ), + ]); +}; 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 000000000..dbda13770 --- /dev/null +++ b/config/sets/symfony/symfony6/symfony60/symfony60-config.php @@ -0,0 +1,75 @@ +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) + ), + ]); + + $arrayType = new ArrayType(new MixedType(), new MixedType()); + + $rectorConfig->ruleWithConfiguration(AddReturnTypeDeclarationRector::class, [ + new AddReturnTypeDeclaration('Symfony\Component\Config\Loader\LoaderInterface', 'load', new MixedType()), + new AddReturnTypeDeclaration('Symfony\Component\Config\Loader\Loader', 'import', new MixedType()), + new AddReturnTypeDeclaration( + 'Symfony\Component\Config\Definition\ConfigurationInterface', + 'getConfigTreeBuilder', + new ObjectType('Symfony\Component\Config\Definition\Builder\TreeBuilder') + ), + new AddReturnTypeDeclaration('Symfony\Component\Config\FileLocator', 'locate', new UnionType([ + new StringType(), + $arrayType, + ])), + new AddReturnTypeDeclaration('Symfony\Component\Config\FileLocatorInterface', 'locate', new UnionType([ + new StringType(), + $arrayType, + ])), + new AddReturnTypeDeclaration('Symfony\Component\Config\Loader\FileLoader', 'import', new MixedType()), + new AddReturnTypeDeclaration('Symfony\Component\Config\Loader\Loader', 'import', new MixedType()), + new AddReturnTypeDeclaration('Symfony\Component\Config\Loader\LoaderInterface', 'load', new MixedType()), + new AddReturnTypeDeclaration( + 'Symfony\Component\Config\Loader\LoaderInterface', + 'supports', + new BooleanType() + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\Config\Loader\LoaderInterface', + 'getResolver', + new ObjectType('Symfony\Component\Config\Loader\LoaderResolverInterface') + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\Config\ResourceCheckerInterface', + 'supports', + new BooleanType() + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\Config\ResourceCheckerInterface', + 'isFresh', + new BooleanType() + ), + ]); +}; diff --git a/config/sets/symfony/symfony6/symfony60/symfony60-console.php b/config/sets/symfony/symfony6/symfony60/symfony60-console.php new file mode 100644 index 000000000..a34619fd1 --- /dev/null +++ b/config/sets/symfony/symfony6/symfony60/symfony60-console.php @@ -0,0 +1,65 @@ +ruleWithConfiguration(AddReturnTypeDeclarationRector::class, [ + // @see https://github.com/symfony/symfony/pull/43028/files + new AddReturnTypeDeclaration( + 'Symfony\Component\Console\Helper\HelperInterface', + 'getName', + new StringType() + ), + + new AddReturnTypeDeclaration('Symfony\Component\Console\Application', 'doRun', new IntegerType()), + new AddReturnTypeDeclaration('Symfony\Component\Console\Application', 'getLongVersion', new StringType()), + new AddReturnTypeDeclaration('Symfony\Component\Console\Application', 'add', new UnionType([ + new NullType(), + $commandType, + ])), + new AddReturnTypeDeclaration('Symfony\Component\Console\Application', 'get', $commandType), + new AddReturnTypeDeclaration('Symfony\Component\Console\Application', 'find', $commandType), + new AddReturnTypeDeclaration('Symfony\Component\Console\Application', 'all', $arrayType), + new AddReturnTypeDeclaration('Symfony\Component\Console\Application', 'doRunCommand', new IntegerType()), + new AddReturnTypeDeclaration('Symfony\Component\Console\Command\Command', 'isEnabled', new BooleanType()), + new AddReturnTypeDeclaration('Symfony\Component\Console\Command\Command', 'execute', new IntegerType()), + new AddReturnTypeDeclaration( + 'Symfony\Component\Console\Helper\HelperInterface', + 'getName', + new StringType() + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\Console\Input\InputInterface', + 'getParameterOption', + new MixedType() + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\Console\Input\InputInterface', + 'getArgument', + new MixedType() + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\Console\Input\InputInterface', + 'getOption', + new MixedType() + ), + ]); +}; 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 000000000..26318e476 --- /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 000000000..e156ca702 --- /dev/null +++ b/config/sets/symfony/symfony6/symfony60/symfony60-dependency-injection.php @@ -0,0 +1,101 @@ +ruleWithConfiguration(ReplaceServiceArgumentRector::class, [ + new ReplaceServiceArgument('Psr\Container\ContainerInterface', new String_('service_container')), + new ReplaceServiceArgument( + 'Symfony\Component\DependencyInjection\ContainerInterface', + new String_('service_container') + ), + ]); + + $configurationType = new ObjectType('Symfony\Component\Config\Definition\ConfigurationInterface'); + + $arrayType = new ArrayType(new MixedType(), new MixedType()); + $scalarTypes = [ + $arrayType, + new BooleanType(), + new StringType(), + new IntegerType(), + new FloatType(), + new NullType(), + ]; + + $rectorConfig->ruleWithConfiguration(AddReturnTypeDeclarationRector::class, [ + new AddReturnTypeDeclaration( + 'Symfony\Component\DependencyInjection\Compiler\AbstractRecursivePass', + 'processValue', + new MixedType() + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\DependencyInjection\Extension\ConfigurationExtensionInterface', + 'getConfiguration', + new UnionType([new NullType(), $configurationType]) + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\DependencyInjection\Extension\Extension', + 'getXsdValidationBasePath', + new UnionType([new StringType(), new ConstantBooleanType(false)]) + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\DependencyInjection\Extension\Extension', + 'getNamespace', + new StringType() + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\DependencyInjection\Extension\Extension', + 'getConfiguration', + new UnionType([new NullType(), $configurationType]) + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\DependencyInjection\Extension\ExtensionInterface', + 'getNamespace', + new StringType() + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\DependencyInjection\Extension\ExtensionInterface', + 'getXsdValidationBasePath', + new UnionType([new StringType(), new ConstantBooleanType(false)]) + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\DependencyInjection\Extension\ExtensionInterface', + 'getAlias', + new StringType() + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\DependencyInjection\LazyProxy\Instantiator\InstantiatorInterface', + 'instantiateProxy', + new ObjectWithoutClassType() + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\DependencyInjection\Container', + 'getParameter', + new UnionType($scalarTypes) + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\DependencyInjection\ContainerInterface', + 'getParameter', + new UnionType($scalarTypes) + ), + ]); +}; 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 000000000..6172ca0bf --- /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-event-dispatcher.php b/config/sets/symfony/symfony6/symfony60/symfony60-event-dispatcher.php new file mode 100644 index 000000000..e44144aca --- /dev/null +++ b/config/sets/symfony/symfony6/symfony60/symfony60-event-dispatcher.php @@ -0,0 +1,24 @@ +ruleWithConfiguration(AddReturnTypeDeclarationRector::class, [ + new AddReturnTypeDeclaration( + 'Symfony\Component\EventDispatcher\EventSubscriberInterface', + 'getSubscribedEvents', + $arrayType + ), + ]); +}; diff --git a/config/sets/symfony/symfony6/symfony60/symfony60-expression-language.php b/config/sets/symfony/symfony6/symfony60/symfony60-expression-language.php new file mode 100644 index 000000000..6ef58ad27 --- /dev/null +++ b/config/sets/symfony/symfony6/symfony60/symfony60-expression-language.php @@ -0,0 +1,24 @@ +ruleWithConfiguration(AddReturnTypeDeclarationRector::class, [ + new AddReturnTypeDeclaration( + 'Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface', + 'getFunctions', + $arrayType + ), + ]); +}; diff --git a/config/sets/symfony/symfony6/symfony60/symfony60-form.php b/config/sets/symfony/symfony6/symfony60/symfony60-form.php new file mode 100644 index 000000000..21c887093 --- /dev/null +++ b/config/sets/symfony/symfony6/symfony60/symfony60-form.php @@ -0,0 +1,88 @@ +ruleWithConfiguration(AddReturnTypeDeclarationRector::class, [ + new AddReturnTypeDeclaration('Symfony\Component\Form\AbstractExtension', 'loadTypes', $arrayType), + new AddReturnTypeDeclaration( + 'Symfony\Component\Form\AbstractExtension', + 'loadTypeGuesser', + new UnionType([new NullType(), new ObjectType('Symfony\Component\Form\FormTypeGuesserInterface')]) + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\Form\AbstractRendererEngine', + 'loadResourceForBlockName', + new BooleanType() + ), + new AddReturnTypeDeclaration('Symfony\Component\Form\AbstractType', 'getBlockPrefix', new StringType()), + new AddReturnTypeDeclaration('Symfony\Component\Form\AbstractType', 'getParent', $nullableStringType), + new AddReturnTypeDeclaration( + 'Symfony\Component\Form\DataTransformerInterface', + 'transform', + new MixedType() + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\Form\DataTransformerInterface', + 'reverseTransform', + new MixedType() + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\Form\FormRendererEngineInterface', + 'renderBlock', + new StringType() + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\Form\FormTypeGuesserInterface', + 'guessType', + new UnionType([new NullType(), $typeGuessType]), + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\Form\FormTypeGuesserInterface', + 'guessRequired', + $nullableValueGuessType + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\Form\FormTypeGuesserInterface', + 'guessMaxLength', + $nullableValueGuessType + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\Form\FormTypeGuesserInterface', + 'guessPattern', + $nullableValueGuessType + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\Form\FormTypeInterface', + 'getBlockPrefix', + new StringType() + ), + new AddReturnTypeDeclaration('Symfony\Component\Form\FormTypeInterface', 'getParent', $nullableStringType), + new AddReturnTypeDeclaration('Symfony\Component\Form\FormTypeInterface', 'buildForm', new VoidType()), + new AddReturnTypeDeclaration('Symfony\Component\Form\FormTypeInterface', 'configureOptions', new VoidType()), + ]); +}; 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 000000000..a39bf2101 --- /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-http-kernel.php b/config/sets/symfony/symfony6/symfony60/symfony60-http-kernel.php new file mode 100644 index 000000000..e60bbeee7 --- /dev/null +++ b/config/sets/symfony/symfony6/symfony60/symfony60-http-kernel.php @@ -0,0 +1,76 @@ +ruleWithConfiguration(AddReturnTypeDeclarationRector::class, [ + new AddReturnTypeDeclaration( + 'Symfony\Component\HttpKernel\KernelInterface', + 'registerBundles', + $iterableType, + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface', + 'isOptional', + new BooleanType() + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface', + 'warmUp', + $arrayType + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\HttpKernel\DataCollector\DataCollector', + 'getCasters', + $arrayType + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface', + 'getName', + new StringType() + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\HttpKernel\HttpCache\HttpCache', + 'forward', + $httpFoundationResponseType + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\HttpKernel\HttpKernelBrowser', + 'doRequest', + $httpFoundationResponseType + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\HttpKernel\HttpKernelBrowser', + 'getScript', + new StringType() + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\HttpKernel\Log\DebugLoggerInterface', + 'getLogs', + $arrayType + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\HttpKernel\Log\DebugLoggerInterface', + 'countErrors', + new IntegerType() + ), + ]); +}; diff --git a/config/sets/symfony/symfony6/symfony60/symfony60-options-resolver.php b/config/sets/symfony/symfony6/symfony60/symfony60-options-resolver.php new file mode 100644 index 000000000..a8642d0cc --- /dev/null +++ b/config/sets/symfony/symfony6/symfony60/symfony60-options-resolver.php @@ -0,0 +1,41 @@ +ruleWithConfiguration(AddReturnTypeDeclarationRector::class, [ + new AddReturnTypeDeclaration( + 'Symfony\Component\OptionsResolver\OptionsResolver', + 'setNormalizer', + new SimpleStaticType('Symfony\Component\OptionsResolver\OptionsResolver') + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\OptionsResolver\OptionsResolver', + 'setAllowedValues', + new SimpleStaticType('Symfony\Component\OptionsResolver\OptionsResolver') + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\OptionsResolver\OptionsResolver', + 'addAllowedValues', + new SimpleStaticType('Symfony\Component\OptionsResolver\OptionsResolver') + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\OptionsResolver\OptionsResolver', + 'setAllowedTypes', + new SimpleStaticType('Symfony\Component\OptionsResolver\OptionsResolver') + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\OptionsResolver\OptionsResolver', + 'addAllowedTypes', + new SimpleStaticType('Symfony\Component\OptionsResolver\OptionsResolver') + ), + ]); +}; diff --git a/config/sets/symfony/symfony6/symfony60/symfony60-property-access.php b/config/sets/symfony/symfony6/symfony60/symfony60-property-access.php new file mode 100644 index 000000000..a915ee7e6 --- /dev/null +++ b/config/sets/symfony/symfony6/symfony60/symfony60-property-access.php @@ -0,0 +1,58 @@ +ruleWithConfiguration(AddReturnTypeDeclarationRector::class, [ + new AddReturnTypeDeclaration( + 'Symfony\Component\PropertyAccess\PropertyPathInterface', + 'getLength', + new IntegerType() + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\PropertyAccess\PropertyPathInterface', + 'getParent', + new UnionType([ + new NullType(), + new ObjectType('Symfony\Component\PropertyAccess\PropertyPathInterface'), + ]) + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\PropertyAccess\PropertyPathInterface', + 'getElements', + $arrayType + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\PropertyAccess\PropertyPathInterface', + 'getElement', + new StringType() + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\PropertyAccess\PropertyPathInterface', + 'isProperty', + new BooleanType() + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\PropertyAccess\PropertyPathInterface', + 'isIndex', + new BooleanType() + ), + ]); +}; diff --git a/config/sets/symfony/symfony6/symfony60/symfony60-property-info.php b/config/sets/symfony/symfony6/symfony60/symfony60-property-info.php new file mode 100644 index 000000000..48fb6d660 --- /dev/null +++ b/config/sets/symfony/symfony6/symfony60/symfony60-property-info.php @@ -0,0 +1,45 @@ +ruleWithConfiguration(AddReturnTypeDeclarationRector::class, [ + new AddReturnTypeDeclaration( + 'Symfony\Component\PropertyInfo\PropertyAccessExtractorInterface', + 'isReadable', + $nullableBooleanType + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\PropertyInfo\PropertyAccessExtractorInterface', + 'isWritable', + $nullableBooleanType + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\PropertyInfo\PropertyListExtractorInterface', + 'getProperties', + $nullableArrayType + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface', + 'getTypes', + $nullableArrayType + ), + ]); +}; diff --git a/config/sets/symfony/symfony6/symfony60/symfony60-routing.php b/config/sets/symfony/symfony6/symfony60/symfony60-routing.php new file mode 100644 index 000000000..7459c6249 --- /dev/null +++ b/config/sets/symfony/symfony6/symfony60/symfony60-routing.php @@ -0,0 +1,34 @@ +ruleWithConfiguration(AddReturnTypeDeclarationRector::class, [ + new AddReturnTypeDeclaration( + 'Symfony\Component\Routing\Loader\AnnotationClassLoader', + 'getDefaultRouteName', + new StringType() + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\Routing\Router', + 'getRouteCollection', + $routeCollectionType + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\Routing\RouterInterface', + 'getRouteCollection', + $routeCollectionType + ), + ]); +}; 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 000000000..80cde8631 --- /dev/null +++ b/config/sets/symfony/symfony6/symfony60/symfony60-security-core.php @@ -0,0 +1,66 @@ +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', + ), + ]); + + $rectorConfig->ruleWithConfiguration(AddReturnTypeDeclarationRector::class, [ + // @see https://wouterj.nl/2021/09/symfony-6-native-typing#when-upgrading-to-symfony-54 + new AddReturnTypeDeclaration( + 'Symfony\Component\Security\Core\User\UserInterface', + 'getRoles', + new ArrayType(new MixedType(), new MixedType()) + ), + + new AddReturnTypeDeclaration( + 'Symfony\Component\Security\Core\Authentication\RememberMe\TokenProviderInterface', + 'loadTokenBySeries', + new ObjectType('Symfony\Component\Security\Core\Authentication\RememberMe\PersistentTokenInterface') + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\Security\Core\Authorization\Voter\VoterInterface', + 'vote', + new IntegerType() + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\Security\Core\Exception\AuthenticationException', + 'getMessageKey', + new StringType() + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\Security\Core\User\UserProviderInterface', + 'refreshUser', + new ObjectType('Symfony\Component\Security\Core\User\UserInterface') + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\Security\Core\User\UserProviderInterface', + 'supportsClass', + new BooleanType() + ), + ]); +}; diff --git a/config/sets/symfony/symfony6/symfony60/symfony60-security-http.php b/config/sets/symfony/symfony6/symfony60/symfony60-security-http.php new file mode 100644 index 000000000..2433a5782 --- /dev/null +++ b/config/sets/symfony/symfony6/symfony60/symfony60-security-http.php @@ -0,0 +1,37 @@ +ruleWithConfiguration(AddReturnTypeDeclarationRector::class, [ + new AddReturnTypeDeclaration( + 'Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface', + 'start', + $httpFoundationResponseType + ), + new AddReturnTypeDeclaration('Symfony\Component\Security\Http\Firewall', 'getSubscribedEvents', $arrayType), + new AddReturnTypeDeclaration( + 'Symfony\Component\Security\Http\FirewallMapInterface', + 'getListeners', + $arrayType + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\Security\Http\Authenticator\AuthenticatorInterface', + 'authenticate', + new ObjectType('Symfony\Component\Security\Http\Authenticator\Passport\Passport') + ), + ]); +}; diff --git a/config/sets/symfony/symfony6/symfony60/symfony60-serializer.php b/config/sets/symfony/symfony6/symfony60/symfony60-serializer.php new file mode 100644 index 000000000..abc63fdf1 --- /dev/null +++ b/config/sets/symfony/symfony6/symfony60/symfony60-serializer.php @@ -0,0 +1,128 @@ +newInstanceWithoutConstructor(); + + $privatesAccessor = new PrivatesAccessor(); + $privatesAccessor->setPrivateProperty($scalarArrayObjectUnionType, 'types', $scalarArrayObjectUnionedTypes); + $rectorConfig->ruleWithConfiguration(AddReturnTypeDeclarationRector::class, [ + new AddReturnTypeDeclaration( + 'Symfony\Component\Serializer\Encoder\DecoderInterface', + 'decode', + new MixedType() + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\Serializer\Encoder\DecoderInterface', + 'supportsDecoding', + new BooleanType() + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\Serializer\Normalizer\AbstractNormalizer', + 'getAllowedAttributes', + new UnionType([$arrayType, new BooleanType()]) + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\Serializer\Normalizer\AbstractNormalizer', + 'isAllowedAttribute', + new BooleanType() + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\Serializer\Normalizer\AbstractNormalizer', + 'instantiateObject', + new ObjectWithoutClassType() + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer', + 'supportsNormalization', + new BooleanType() + ), + + new AddReturnTypeDeclaration( + 'Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer', + 'instantiateObject', + new ObjectWithoutClassType() + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer', + 'extractAttributes', + $arrayType + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer', + 'getAttributeValue', + new MixedType() + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer', + 'supportsDenormalization', + new BooleanType() + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer', + 'denormalize', + new MixedType() + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\Serializer\Normalizer\DenormalizerInterface', + 'denormalize', + new MixedType() + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\Serializer\Normalizer\DenormalizerInterface', + 'supportsDenormalization', + new BooleanType() + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\Serializer\Normalizer\NormalizerInterface', + 'supportsNormalization', + new BooleanType() + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer', + 'normalize', + $scalarArrayObjectUnionType + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\Serializer\Normalizer\NormalizerInterface', + 'normalize', + $scalarArrayObjectUnionType + ), + ]); +}; diff --git a/config/sets/symfony/symfony6/symfony60/symfony60-templating.php b/config/sets/symfony/symfony6/symfony60/symfony60-templating.php new file mode 100644 index 000000000..2620badb0 --- /dev/null +++ b/config/sets/symfony/symfony6/symfony60/symfony60-templating.php @@ -0,0 +1,21 @@ +ruleWithConfiguration(AddReturnTypeDeclarationRector::class, [ + new AddReturnTypeDeclaration( + 'Symfony\Component\Templating\Helper\HelperInterface', + 'getName', + new StringType() + ), + ]); +}; diff --git a/config/sets/symfony/symfony6/symfony60/symfony60-translation.php b/config/sets/symfony/symfony6/symfony60/symfony60-translation.php new file mode 100644 index 000000000..eec9dcb1a --- /dev/null +++ b/config/sets/symfony/symfony6/symfony60/symfony60-translation.php @@ -0,0 +1,30 @@ +ruleWithConfiguration(AddReturnTypeDeclarationRector::class, [ + new AddReturnTypeDeclaration( + 'Symfony\Component\Translation\Extractor\AbstractFileExtractor', + 'canBeExtracted', + new BooleanType() + ), + new AddReturnTypeDeclaration( + 'Symfony\Component\Translation\Extractor\AbstractFileExtractor', + 'extractFromDirectory', + $iterableType + ), + ]); +}; diff --git a/config/sets/symfony/symfony6/symfony60/symfony60-validator.php b/config/sets/symfony/symfony6/symfony60/symfony60-validator.php new file mode 100644 index 000000000..a1602ae4e --- /dev/null +++ b/config/sets/symfony/symfony6/symfony60/symfony60-validator.php @@ -0,0 +1,35 @@ +ruleWithConfiguration(AddReturnTypeDeclarationRector::class, [ + new AddReturnTypeDeclaration( + 'Symfony\Component\Validator\Constraint', + 'getDefaultOption', + $nullableStringType + ), + new AddReturnTypeDeclaration('Symfony\Component\Validator\Constraint', 'getRequiredOptions', $arrayType), + new AddReturnTypeDeclaration('Symfony\Component\Validator\Constraint', 'validatedBy', new StringType()), + new AddReturnTypeDeclaration( + 'Symfony\Component\Validator\Constraint', + 'getTargets', + new UnionType([new StringType(), $arrayType]) + ), + ]); +}; diff --git a/config/sets/symfony/symfony6/symfony61.php b/config/sets/symfony/symfony6/symfony61.php new file mode 100644 index 000000000..97c9eac39 --- /dev/null +++ b/config/sets/symfony/symfony6/symfony61.php @@ -0,0 +1,14 @@ +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 000000000..6030d88bb --- /dev/null +++ b/config/sets/symfony/symfony6/symfony61/symfony61-console.php @@ -0,0 +1,11 @@ +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 000000000..3ea812002 --- /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 000000000..928fa6cd3 --- /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 000000000..eac0207d1 --- /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/config/sets/symfony/symfony6/symfony62.php b/config/sets/symfony/symfony6/symfony62.php new file mode 100644 index 000000000..fd8a16d76 --- /dev/null +++ b/config/sets/symfony/symfony6/symfony62.php @@ -0,0 +1,33 @@ +ruleWithConfiguration(AnnotationToAttributeRector::class, [ + // @see https://github.com/symfony/symfony/pull/46907 + new AnnotationToAttribute('Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted'), + // @see https://github.com/symfony/symfony/pull/46880 + new AnnotationToAttribute('Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache'), + // @see https://github.com/symfony/symfony/pull/46906 + new AnnotationToAttribute('Sensio\Bundle\FrameworkExtraBundle\Configuration\Template'), + ]); + + $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 000000000..9a3f18a73 --- /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 000000000..518765553 --- /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 000000000..30854a409 --- /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 000000000..093805ae1 --- /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 000000000..3f9349cbb --- /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 000000000..55f635c1f --- /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 000000000..85ec93399 --- /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 000000000..68be856b3 --- /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 000000000..add1d3093 --- /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 000000000..6010a7a75 --- /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 000000000..a27cb35c6 --- /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/config/sets/symfony/symfony6/symfony63.php b/config/sets/symfony/symfony6/symfony63.php new file mode 100644 index 000000000..c14342289 --- /dev/null +++ b/config/sets/symfony/symfony6/symfony63.php @@ -0,0 +1,14 @@ +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 000000000..28834c50d --- /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 000000000..91029da3c --- /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 000000000..ca22adea8 --- /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 000000000..8486ed970 --- /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/config/sets/symfony/symfony6/symfony64.php b/config/sets/symfony/symfony6/symfony64.php new file mode 100644 index 000000000..aa5355be9 --- /dev/null +++ b/config/sets/symfony/symfony6/symfony64.php @@ -0,0 +1,13 @@ +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 000000000..55337a948 --- /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/symfony64.php b/config/sets/symfony/symfony6/symfony64/symfony64-form.php similarity index 51% rename from config/sets/symfony/symfony64.php rename to config/sets/symfony/symfony6/symfony64/symfony64-form.php index 5d7a2cab9..62a1c5306 100644 --- a/config/sets/symfony/symfony64.php +++ b/config/sets/symfony/symfony6/symfony64/symfony64-form.php @@ -4,29 +4,11 @@ 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', 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 000000000..4c6b44902 --- /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 000000000..370cf016a --- /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/config/sets/symfony/symfony60.php b/config/sets/symfony/symfony60.php deleted file mode 100644 index 49d9c8108..000000000 --- a/config/sets/symfony/symfony60.php +++ /dev/null @@ -1,68 +0,0 @@ -sets([SymfonySetList::ANNOTATIONS_TO_ATTRIBUTES]); - - $rectorConfig->import(__DIR__ . '/symfony6/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->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\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); -}; diff --git a/config/sets/symfony/symfony61.php b/config/sets/symfony/symfony61.php deleted file mode 100644 index 84d4ad6b6..000000000 --- a/config/sets/symfony/symfony61.php +++ /dev/null @@ -1,30 +0,0 @@ -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', - ]); -}; diff --git a/config/sets/symfony/symfony62.php b/config/sets/symfony/symfony62.php deleted file mode 100644 index 69aa6086b..000000000 --- a/config/sets/symfony/symfony62.php +++ /dev/null @@ -1,119 +0,0 @@ -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 - $rectorConfig->ruleWithConfiguration(AnnotationToAttributeRector::class, [ - // @see https://github.com/symfony/symfony/pull/46907 - new AnnotationToAttribute('Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted'), - // @see https://github.com/symfony/symfony/pull/46880 - new AnnotationToAttribute('Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache'), - // @see https://github.com/symfony/symfony/pull/46906 - 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' - ), - ]); -}; diff --git a/config/sets/symfony/symfony63.php b/config/sets/symfony/symfony63.php deleted file mode 100644 index 5c33feea5..000000000 --- a/config/sets/symfony/symfony63.php +++ /dev/null @@ -1,34 +0,0 @@ -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, - ]); -}; diff --git a/config/sets/symfony/symfony7/symfony70.php b/config/sets/symfony/symfony7/symfony70.php new file mode 100644 index 000000000..af452a802 --- /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 000000000..aba8f82ae --- /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 000000000..d1cf81c45 --- /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 000000000..8c4305770 --- /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 000000000..020fb1be2 --- /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/symfony7/symfony71.php b/config/sets/symfony/symfony7/symfony71.php new file mode 100644 index 000000000..8552c08a1 --- /dev/null +++ b/config/sets/symfony/symfony7/symfony71.php @@ -0,0 +1,12 @@ +import(__DIR__ . '/symfony71/symfony71-dependency-injection.php'); + $rectorConfig->import(__DIR__ . '/symfony71/symfony71-serializer.php'); +}; diff --git a/config/sets/symfony/symfony71.php b/config/sets/symfony/symfony7/symfony71/symfony71-dependency-injection.php similarity index 53% rename from config/sets/symfony/symfony71.php rename to config/sets/symfony/symfony7/symfony71/symfony71-dependency-injection.php index e3de509db..6137f5313 100644 --- a/config/sets/symfony/symfony71.php +++ b/config/sets/symfony/symfony7/symfony71/symfony71-dependency-injection.php @@ -4,15 +4,11 @@ use Rector\Config\RectorConfig; use Rector\Renaming\Rector\Class_\RenameAttributeRector; -use Rector\Renaming\Rector\MethodCall\RenameMethodRector; -use Rector\Renaming\ValueObject\MethodCallRename; use Rector\Renaming\ValueObject\RenameAttribute; -// @see https://github.com/symfony/symfony/blob/7.1/UPGRADE-7.1.md - -return RectorConfig::configure() +return static function (RectorConfig $rectorConfig): void { // @see https://github.com/symfony/symfony/blob/7.1/UPGRADE-7.1.md#dependencyinjection - ->withConfiguredRule(RenameAttributeRector::class, [ + $rectorConfig->ruleWithConfiguration(RenameAttributeRector::class, [ new RenameAttribute( 'Symfony\Component\DependencyInjection\Attribute\TaggedIterator', 'Symfony\Component\DependencyInjection\Attribute\AutowireIterator' @@ -21,12 +17,5 @@ 'Symfony\Component\DependencyInjection\Attribute\TaggedLocator', 'Symfony\Component\DependencyInjection\Attribute\AutowireLocator' ), - ]) - ->withConfiguredRule(RenameMethodRector::class, [ - // typo fix - new MethodCallRename( - 'Symfony\Component\Serializer\Context\Normalizer\AbstractNormalizerContextBuilder', - 'withDefaultContructorArguments', - 'withDefaultConstructorArguments', - ), ]); +}; diff --git a/config/sets/symfony/symfony7/symfony71/symfony71-serializer.php b/config/sets/symfony/symfony7/symfony71/symfony71-serializer.php new file mode 100644 index 000000000..ae14d5ee3 --- /dev/null +++ b/config/sets/symfony/symfony7/symfony71/symfony71-serializer.php @@ -0,0 +1,19 @@ +ruleWithConfiguration(RenameMethodRector::class, [ + // typo fix + new MethodCallRename( + 'Symfony\Component\Serializer\Context\Normalizer\AbstractNormalizerContextBuilder', + 'withDefaultContructorArguments', + 'withDefaultConstructorArguments', + ), + ]); +}; diff --git a/config/sets/symfony/symfony7/symfony72.php b/config/sets/symfony/symfony7/symfony72.php new file mode 100644 index 000000000..e8a629f51 --- /dev/null +++ b/config/sets/symfony/symfony7/symfony72.php @@ -0,0 +1,12 @@ +import(__DIR__ . '/symfony72/symfony72-serializer.php'); + $rectorConfig->import(__DIR__ . '/symfony72/symfony72-http-foundation.php'); +}; diff --git a/config/sets/symfony/symfony7/symfony72/symfony72-http-foundation.php b/config/sets/symfony/symfony7/symfony72/symfony72-http-foundation.php new file mode 100644 index 000000000..1f1a01e91 --- /dev/null +++ b/config/sets/symfony/symfony7/symfony72/symfony72-http-foundation.php @@ -0,0 +1,10 @@ +rules([PushRequestToRequestStackConstructorRector::class]); +}; diff --git a/config/sets/symfony/symfony72.php b/config/sets/symfony/symfony7/symfony72/symfony72-serializer.php similarity index 70% rename from config/sets/symfony/symfony72.php rename to config/sets/symfony/symfony7/symfony72/symfony72-serializer.php index 673fc5fad..da49070de 100644 --- a/config/sets/symfony/symfony72.php +++ b/config/sets/symfony/symfony7/symfony72/symfony72-serializer.php @@ -5,10 +5,9 @@ use Rector\Config\RectorConfig; use Rector\Renaming\Rector\Name\RenameClassRector; -// @see https://github.com/symfony/symfony/blame/7.2/UPGRADE-7.2.md - -return RectorConfig::configure() - ->withConfiguredRule(RenameClassRector::class, [ +return static function (RectorConfig $rectorConfig): void { + $rectorConfig->ruleWithConfiguration(RenameClassRector::class, [ // @see https://github.com/symfony/symfony/blob/7.2/UPGRADE-7.2.md#serializer 'Symfony\Component\Serializer\NameConverter\AdvancedNameConverterInterface' => 'Symfony\Component\Serializer\NameConverter\NameConverterInterface', ]); +}; diff --git a/config/sets/symfony/symfony7/symfony73.php b/config/sets/symfony/symfony7/symfony73.php new file mode 100644 index 000000000..de11a936e --- /dev/null +++ b/config/sets/symfony/symfony7/symfony73.php @@ -0,0 +1,12 @@ +import(__DIR__ . '/symfony73/symfony73-console.php'); + $rectorConfig->import(__DIR__ . '/symfony73/symfony73-twig-bundle.php'); +}; diff --git a/config/sets/symfony/symfony7/symfony73/symfony73-console.php b/config/sets/symfony/symfony7/symfony73/symfony73-console.php new file mode 100644 index 000000000..2b5c6dff8 --- /dev/null +++ b/config/sets/symfony/symfony7/symfony73/symfony73-console.php @@ -0,0 +1,11 @@ +rules([CommandHelpToAttributeRector::class, InvokableCommandInputAttributeRector::class]); +}; diff --git a/config/sets/symfony/symfony7/symfony73/symfony73-twig-bundle.php b/config/sets/symfony/symfony7/symfony73/symfony73-twig-bundle.php new file mode 100644 index 000000000..d18a0b696 --- /dev/null +++ b/config/sets/symfony/symfony7/symfony73/symfony73-twig-bundle.php @@ -0,0 +1,14 @@ +rules([ + GetFiltersToAsTwigFilterAttributeRector::class, + GetFunctionsToAsTwigFunctionAttributeRector::class, + ]); +}; diff --git a/config/sets/symfony/symfony70.php b/config/sets/symfony/symfony70.php deleted file mode 100644 index 7eb6cbb1f..000000000 --- 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/phpstan.neon b/phpstan.neon index 1c88c9948..39fa6b842 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,8 +1,10 @@ +rules: + - Symplify\PHPStanRules\Rules\StringFileAbsolutePathExistsRule + parameters: level: 8 reportUnmatchedIgnoredErrors: false - treatPhpDocTypesAsCertain: false paths: @@ -12,18 +14,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 +55,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/rector.php b/rector.php index f11081f4e..3659749f2 100644 --- a/rector.php +++ b/rector.php @@ -54,4 +54,4 @@ naming: true, rectorPreset: true ) - ->withImportNames(); + ->withImportNames(removeUnusedImports: true); 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 000000000..ae5d82512 --- /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 000000000..4a9f01cbb --- /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 000000000..1e3a6f3aa --- /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 000000000..c62178053 --- /dev/null +++ b/rules-tests/CodeQuality/Rector/AttributeGroup/SingleConditionSecurityAttributeToIsGrantedRector/config/configured_rule.php @@ -0,0 +1,10 @@ +rule(SingleConditionSecurityAttributeToIsGrantedRector::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 000000000..ce8e5b200 --- /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 000000000..30f007e81 --- /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 000000000..5bfe32e5b --- /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 000000000..bdd6c9fb8 --- /dev/null +++ b/rules-tests/CodeQuality/Rector/BinaryOp/RequestIsMainRector/config/configured_rule.php @@ -0,0 +1,10 @@ +rule(RequestIsMainRector::class); +}; diff --git a/rules-tests/CodeQuality/Rector/ClassMethod/TemplateAnnotationToThisRenderRector/Fixture/Attributes/attribute_nested_array.php.inc b/rules-tests/CodeQuality/Rector/ClassMethod/TemplateAnnotationToThisRenderRector/Fixture/Attributes/attribute_nested_array.php.inc new file mode 100755 index 000000000..26a9cb28b --- /dev/null +++ b/rules-tests/CodeQuality/Rector/ClassMethod/TemplateAnnotationToThisRenderRector/Fixture/Attributes/attribute_nested_array.php.inc @@ -0,0 +1,38 @@ + 'world' + ]; + } +} + +?> +----- +render('with_some_template.twig', [ + 'hello' => 'world' + ]); + } +} + +?> diff --git a/rules-tests/CodeQuality/Rector/ClassMethod/TemplateAnnotationToThisRenderRector/Fixture/Attributes/cleanup_return_array_shape.php.inc b/rules-tests/CodeQuality/Rector/ClassMethod/TemplateAnnotationToThisRenderRector/Fixture/Attributes/cleanup_return_array_shape.php.inc new file mode 100755 index 000000000..214bb9771 --- /dev/null +++ b/rules-tests/CodeQuality/Rector/ClassMethod/TemplateAnnotationToThisRenderRector/Fixture/Attributes/cleanup_return_array_shape.php.inc @@ -0,0 +1,41 @@ + 'world' + ]; + } +} + +?> +----- +render('with_some_template.twig', [ + 'hello' => 'world' + ]); + } +} + +?> diff --git a/rules-tests/CodeQuality/Rector/ClassMethod/TemplateAnnotationToThisRenderRector/Fixture/Attributes/keep_direct_new_response.php.inc b/rules-tests/CodeQuality/Rector/ClassMethod/TemplateAnnotationToThisRenderRector/Fixture/Attributes/keep_direct_new_response.php.inc new file mode 100755 index 000000000..a4ad784db --- /dev/null +++ b/rules-tests/CodeQuality/Rector/ClassMethod/TemplateAnnotationToThisRenderRector/Fixture/Attributes/keep_direct_new_response.php.inc @@ -0,0 +1,73 @@ +getItem(); + + if (! $item) { + return new Response('foo'); + } + + $price = 1500; + + return [ + 'hello' => 'world', + 'price' => $price, + ]; + } + + private function getItem(): ?\stdClass + { + if (mt_rand(0, 100)) { + return new \stdClass(); + } + + return null; + } +} + +?> +----- +getItem(); + if (! $item) { + return new Response('foo'); + } + $price = 1500; + return $this->render('with_some_template/some_path.twig', [ + 'hello' => 'world', + 'price' => $price, + ]); + } + + private function getItem(): ?\stdClass + { + if (mt_rand(0, 100)) { + return new \stdClass(); + } + + return null; + } +} + +?> diff --git a/rules-tests/CodeQuality/Rector/ClassMethod/TemplateAnnotationToThisRenderRector/Fixture/Attributes/nested_ternary_redirect.php.inc b/rules-tests/CodeQuality/Rector/ClassMethod/TemplateAnnotationToThisRenderRector/Fixture/Attributes/nested_ternary_redirect.php.inc new file mode 100755 index 000000000..8b4135bcd --- /dev/null +++ b/rules-tests/CodeQuality/Rector/ClassMethod/TemplateAnnotationToThisRenderRector/Fixture/Attributes/nested_ternary_redirect.php.inc @@ -0,0 +1,34 @@ +redirectToRoute('one') : $this->redirectToRoute('two'); + } +} + +?> +----- +redirectToRoute('one') : $this->redirectToRoute('two'); + } +} + +?> diff --git a/rules-tests/CodeQuality/Rector/ClassMethod/TemplateAnnotationToThisRenderRector/Fixture/Attributes/nested_ternary_redirect_then_array.php.inc b/rules-tests/CodeQuality/Rector/ClassMethod/TemplateAnnotationToThisRenderRector/Fixture/Attributes/nested_ternary_redirect_then_array.php.inc new file mode 100755 index 000000000..b73ec6932 --- /dev/null +++ b/rules-tests/CodeQuality/Rector/ClassMethod/TemplateAnnotationToThisRenderRector/Fixture/Attributes/nested_ternary_redirect_then_array.php.inc @@ -0,0 +1,45 @@ +redirectToRoute('one') : $this->redirectToRoute('two'); + } + + return [ + 'key' => 'value' + ]; + } +} + +?> +----- +redirectToRoute('one') : $this->redirectToRoute('two'); + } + return $this->render('with_some_template.twig', [ + 'key' => 'value' + ]); + } +} + +?> diff --git a/rules-tests/CodeQuality/Rector/ClassMethod/TemplateAnnotationToThisRenderRector/Fixture/Attributes/remove_attribute_but_keep_json_response.php.inc b/rules-tests/CodeQuality/Rector/ClassMethod/TemplateAnnotationToThisRenderRector/Fixture/Attributes/remove_attribute_but_keep_json_response.php.inc new file mode 100755 index 000000000..27a752024 --- /dev/null +++ b/rules-tests/CodeQuality/Rector/ClassMethod/TemplateAnnotationToThisRenderRector/Fixture/Attributes/remove_attribute_but_keep_json_response.php.inc @@ -0,0 +1,45 @@ + 'value']; + } + + return new JsonResponse([], Response::HTTP_BAD_REQUEST); + } +} + +?> +----- +render('with_some_template.twig', ['key' => 'value']); + } + return new JsonResponse([], Response::HTTP_BAD_REQUEST); + } +} + +?> diff --git a/rules-tests/CodeQuality/Rector/ClassMethod/TemplateAnnotationToThisRenderRector/Fixture/Attributes/remove_attribute_but_keep_json_response_reversed.php.inc b/rules-tests/CodeQuality/Rector/ClassMethod/TemplateAnnotationToThisRenderRector/Fixture/Attributes/remove_attribute_but_keep_json_response_reversed.php.inc new file mode 100755 index 000000000..c287b8d45 --- /dev/null +++ b/rules-tests/CodeQuality/Rector/ClassMethod/TemplateAnnotationToThisRenderRector/Fixture/Attributes/remove_attribute_but_keep_json_response_reversed.php.inc @@ -0,0 +1,45 @@ + 'value']; + } +} + +?> +----- +render('with_some_template.twig', ['key' => 'value']); + } +} + +?> 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 000000000..767a0e81d --- /dev/null +++ b/rules-tests/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector/Fixture/attribute_routing_class.php.inc @@ -0,0 +1,34 @@ + +----- + 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 000000000..110bd4140 --- /dev/null +++ b/rules-tests/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector/Fixture/attribute_routing_class_with_other_annotation.php.inc @@ -0,0 +1,40 @@ + +----- + 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 000000000..1d1101323 --- /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 000000000..e2ac7f1b0 --- /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 000000000..2ce304254 --- /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/Fixture/with_existing_name.php.inc b/rules-tests/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector/Fixture/with_existing_name.php.inc new file mode 100644 index 000000000..040bd10e1 --- /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 000000000..1191d193e --- /dev/null +++ b/rules-tests/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector/Fixture/with_existing_name2.php.inc @@ -0,0 +1,34 @@ + +----- + 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 000000000..ee362781e --- /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 000000000..5044168a4 --- /dev/null +++ b/rules-tests/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector/config/configured_rule.php @@ -0,0 +1,10 @@ +rule(InlineClassRoutePrefixRector::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 000000000..a51b83fba --- /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/Fixture/with_ampersand_attributes.php.inc b/rules-tests/CodeQuality/Rector/Class_/SplitAndSecurityAttributeToIsGrantedRector/Fixture/with_ampersand_attributes.php.inc new file mode 100644 index 000000000..8ef6db8c3 --- /dev/null +++ b/rules-tests/CodeQuality/Rector/Class_/SplitAndSecurityAttributeToIsGrantedRector/Fixture/with_ampersand_attributes.php.inc @@ -0,0 +1,26 @@ + +----- + 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 000000000..244e8f5c2 --- /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 000000000..99695fc32 --- /dev/null +++ b/rules-tests/CodeQuality/Rector/Class_/SplitAndSecurityAttributeToIsGrantedRector/config/configured_rule.php @@ -0,0 +1,10 @@ +rule(SplitAndSecurityAttributeToIsGrantedRector::class); +}; 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 000000000..bd0f0e5bd --- /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/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 000000000..bd958fc23 --- /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 000000000..1446bb3e7 --- /dev/null +++ b/rules-tests/Configs/Rector/Closure/ServiceSetStringNameToClassNameRector/Source/ExcludedService.php @@ -0,0 +1,9 @@ + + + + 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 eee09ad62..adb8d006c 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/Fixture/prefer_required_setter.php.inc b/rules-tests/DependencyInjection/Rector/Class_/GetBySymfonyStringToConstructorInjectionRector/Fixture/prefer_required_setter.php.inc new file mode 100644 index 000000000..56b71157d --- /dev/null +++ b/rules-tests/DependencyInjection/Rector/Class_/GetBySymfonyStringToConstructorInjectionRector/Fixture/prefer_required_setter.php.inc @@ -0,0 +1,59 @@ +eventDispatcher = $eventDispatcher; + } + + + public function configure() + { + $someType = $this->get('validator'); + } +} + +?> +----- +eventDispatcher = $eventDispatcher; + $this->validator = $validator; + } + + + public function configure() + { + $someType = $this->validator; + } +} + +?> 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 000000000..8a8360c27 --- /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 f5bad67f7..000000000 --- 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/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 000000000..c4413e610 --- /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 000000000..f2d705321 --- /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 000000000..8ac71dfed --- /dev/null +++ b/rules-tests/Symfony62/Rector/Class_/MessageHandlerInterfaceToAttributeRector/Source/AbstractClassWithHandlerInterface.php @@ -0,0 +1,9 @@ +push(Request::create('/')); + } +} + +?> +----- + diff --git a/rules-tests/Symfony72/Rector/StmtsAwareInterface/PushRequestToRequestStackConstructorRector/Fixture/skip_if_already_used.php.inc b/rules-tests/Symfony72/Rector/StmtsAwareInterface/PushRequestToRequestStackConstructorRector/Fixture/skip_if_already_used.php.inc new file mode 100644 index 000000000..087a1d7c0 --- /dev/null +++ b/rules-tests/Symfony72/Rector/StmtsAwareInterface/PushRequestToRequestStackConstructorRector/Fixture/skip_if_already_used.php.inc @@ -0,0 +1,18 @@ +push(Request::create('/')); + } +} diff --git a/rules-tests/Symfony72/Rector/StmtsAwareInterface/PushRequestToRequestStackConstructorRector/Fixture/skip_outside_test_case.php.inc b/rules-tests/Symfony72/Rector/StmtsAwareInterface/PushRequestToRequestStackConstructorRector/Fixture/skip_outside_test_case.php.inc new file mode 100644 index 000000000..848181196 --- /dev/null +++ b/rules-tests/Symfony72/Rector/StmtsAwareInterface/PushRequestToRequestStackConstructorRector/Fixture/skip_outside_test_case.php.inc @@ -0,0 +1,17 @@ +push(Request::create('/')); + } +} diff --git a/rules-tests/Symfony72/Rector/StmtsAwareInterface/PushRequestToRequestStackConstructorRector/PushRequestToRequestStackConstructorRectorTest.php b/rules-tests/Symfony72/Rector/StmtsAwareInterface/PushRequestToRequestStackConstructorRector/PushRequestToRequestStackConstructorRectorTest.php new file mode 100644 index 000000000..57258e751 --- /dev/null +++ b/rules-tests/Symfony72/Rector/StmtsAwareInterface/PushRequestToRequestStackConstructorRector/PushRequestToRequestStackConstructorRectorTest.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/Symfony72/Rector/StmtsAwareInterface/PushRequestToRequestStackConstructorRector/config/configured_rule.php b/rules-tests/Symfony72/Rector/StmtsAwareInterface/PushRequestToRequestStackConstructorRector/config/configured_rule.php new file mode 100644 index 000000000..e09154295 --- /dev/null +++ b/rules-tests/Symfony72/Rector/StmtsAwareInterface/PushRequestToRequestStackConstructorRector/config/configured_rule.php @@ -0,0 +1,10 @@ +rule(PushRequestToRequestStackConstructorRector::class); +}; 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 000000000..415f405fb --- /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 000000000..f84d14219 --- /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 000000000..46fce7e7c --- /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 000000000..65f901589 --- /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 000000000..2be9b2e76 --- /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 000000000..e5cd37d47 --- /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_/GetFiltersToAsTwigFilterAttributeRector/Fixture/some_get_filters.php.inc b/rules-tests/Symfony73/Rector/Class_/GetFiltersToAsTwigFilterAttributeRector/Fixture/some_get_filters.php.inc new file mode 100644 index 000000000..17981e356 --- /dev/null +++ b/rules-tests/Symfony73/Rector/Class_/GetFiltersToAsTwigFilterAttributeRector/Fixture/some_get_filters.php.inc @@ -0,0 +1,39 @@ + +----- + diff --git a/rules-tests/Symfony73/Rector/Class_/GetFiltersToAsTwigFilterAttributeRector/Fixture/with_first_class_callable_filter.php.inc b/rules-tests/Symfony73/Rector/Class_/GetFiltersToAsTwigFilterAttributeRector/Fixture/with_first_class_callable_filter.php.inc new file mode 100644 index 000000000..fbc8564ff --- /dev/null +++ b/rules-tests/Symfony73/Rector/Class_/GetFiltersToAsTwigFilterAttributeRector/Fixture/with_first_class_callable_filter.php.inc @@ -0,0 +1,39 @@ +someFilter(...)), + ]; + } + + public function someFilter($value) + { + return $value; + } +} + +?> +----- + diff --git a/rules-tests/Symfony73/Rector/Class_/GetFiltersToAsTwigFilterAttributeRector/GetFiltersToAsTwigFilterAttributeRectorTest.php b/rules-tests/Symfony73/Rector/Class_/GetFiltersToAsTwigFilterAttributeRector/GetFiltersToAsTwigFilterAttributeRectorTest.php new file mode 100644 index 000000000..bab0f7698 --- /dev/null +++ b/rules-tests/Symfony73/Rector/Class_/GetFiltersToAsTwigFilterAttributeRector/GetFiltersToAsTwigFilterAttributeRectorTest.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_/GetFiltersToAsTwigFilterAttributeRector/config/configured_rule.php b/rules-tests/Symfony73/Rector/Class_/GetFiltersToAsTwigFilterAttributeRector/config/configured_rule.php new file mode 100644 index 000000000..663307514 --- /dev/null +++ b/rules-tests/Symfony73/Rector/Class_/GetFiltersToAsTwigFilterAttributeRector/config/configured_rule.php @@ -0,0 +1,10 @@ +rule(GetFiltersToAsTwigFilterAttributeRector::class); +}; diff --git a/rules-tests/Symfony73/Rector/Class_/GetFunctionsToAsTwigFunctionAttributeRector/Fixture/skip_different_object.php.inc b/rules-tests/Symfony73/Rector/Class_/GetFunctionsToAsTwigFunctionAttributeRector/Fixture/skip_different_object.php.inc new file mode 100644 index 000000000..5f7d2dd1c --- /dev/null +++ b/rules-tests/Symfony73/Rector/Class_/GetFunctionsToAsTwigFunctionAttributeRector/Fixture/skip_different_object.php.inc @@ -0,0 +1,23 @@ +someFunction(...)), + ]; + } + + public function someFunction($value) + { + return $value; + } +} + +?> diff --git a/rules-tests/Symfony73/Rector/Class_/GetFunctionsToAsTwigFunctionAttributeRector/Fixture/skip_magic_closure_name.php.inc b/rules-tests/Symfony73/Rector/Class_/GetFunctionsToAsTwigFunctionAttributeRector/Fixture/skip_magic_closure_name.php.inc new file mode 100644 index 000000000..0d6360ecf --- /dev/null +++ b/rules-tests/Symfony73/Rector/Class_/GetFunctionsToAsTwigFunctionAttributeRector/Fixture/skip_magic_closure_name.php.inc @@ -0,0 +1,27 @@ +{$magic}(...)), + ]; + } + + public function someFunction($value) + { + return $value; + } + + public function anotherFunction($value) + { + return $value; + } +} diff --git a/rules-tests/Symfony73/Rector/Class_/GetFunctionsToAsTwigFunctionAttributeRector/Fixture/some_get_functions.php.inc b/rules-tests/Symfony73/Rector/Class_/GetFunctionsToAsTwigFunctionAttributeRector/Fixture/some_get_functions.php.inc new file mode 100644 index 000000000..9999dc60c --- /dev/null +++ b/rules-tests/Symfony73/Rector/Class_/GetFunctionsToAsTwigFunctionAttributeRector/Fixture/some_get_functions.php.inc @@ -0,0 +1,51 @@ +anotherFunction(...)), + ]; + } + + public function someFunction($value) + { + return $value; + } + + public function anotherFunction($value) + { + return $value; + } +} + +?> +----- + diff --git a/rules-tests/Symfony73/Rector/Class_/GetFunctionsToAsTwigFunctionAttributeRector/GetFunctionsToAsTwigFunctionAttributeRectorTest.php b/rules-tests/Symfony73/Rector/Class_/GetFunctionsToAsTwigFunctionAttributeRector/GetFunctionsToAsTwigFunctionAttributeRectorTest.php new file mode 100644 index 000000000..865f69d4c --- /dev/null +++ b/rules-tests/Symfony73/Rector/Class_/GetFunctionsToAsTwigFunctionAttributeRector/GetFunctionsToAsTwigFunctionAttributeRectorTest.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_/GetFunctionsToAsTwigFunctionAttributeRector/config/configured_rule.php b/rules-tests/Symfony73/Rector/Class_/GetFunctionsToAsTwigFunctionAttributeRector/config/configured_rule.php new file mode 100644 index 000000000..169a350a5 --- /dev/null +++ b/rules-tests/Symfony73/Rector/Class_/GetFunctionsToAsTwigFunctionAttributeRector/config/configured_rule.php @@ -0,0 +1,10 @@ +rule(GetFunctionsToAsTwigFunctionAttributeRector::class); +}; diff --git a/rules-tests/Symfony73/Rector/Class_/InvokableCommandInputAttributeRector/Fixture/name_from_constant.php.inc b/rules-tests/Symfony73/Rector/Class_/InvokableCommandInputAttributeRector/Fixture/name_from_constant.php.inc new file mode 100644 index 000000000..8879a327d --- /dev/null +++ b/rules-tests/Symfony73/Rector/Class_/InvokableCommandInputAttributeRector/Fixture/name_from_constant.php.inc @@ -0,0 +1,64 @@ +addArgument(self::ARGUMENT_NAME, InputArgument::OPTIONAL, 'The name of the person to greet.'); + } + + #[\Override] + protected function execute(InputInterface $input, OutputInterface $output): int + { + $name = $input->getArgument(self::ARGUMENT_NAME); + $output->writeln("Hello {$name}!"); + + return Command::SUCCESS; + } +} + +?> +----- +writeln("Hello {$name}!"); + return Command::SUCCESS; + } +} + +?> diff --git a/rules-tests/Symfony73/Rector/Class_/InvokableCommandInputAttributeRector/Fixture/some_command.php.inc b/rules-tests/Symfony73/Rector/Class_/InvokableCommandInputAttributeRector/Fixture/some_command.php.inc new file mode 100644 index 000000000..a8cc0abe3 --- /dev/null +++ b/rules-tests/Symfony73/Rector/Class_/InvokableCommandInputAttributeRector/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_/InvokableCommandInputAttributeRector/Fixture/some_command_with_method_chaining.php.inc b/rules-tests/Symfony73/Rector/Class_/InvokableCommandInputAttributeRector/Fixture/some_command_with_method_chaining.php.inc new file mode 100644 index 000000000..8dd205187 --- /dev/null +++ b/rules-tests/Symfony73/Rector/Class_/InvokableCommandInputAttributeRector/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_/InvokableCommandInputAttributeRector/Fixture/some_command_with_set_help.php.inc b/rules-tests/Symfony73/Rector/Class_/InvokableCommandInputAttributeRector/Fixture/some_command_with_set_help.php.inc new file mode 100644 index 000000000..1f3923390 --- /dev/null +++ b/rules-tests/Symfony73/Rector/Class_/InvokableCommandInputAttributeRector/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'); + } + + protected 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\Argument(name: 'argument', description: 'Argument description')] + string $argument, #[\Symfony\Component\Console\Attribute\Command\Option] + $option, OutputInterface $output): int + { + $someArgument = $argument; + $someOption = $option; + + // ... + + return 1; + } +} + +?> diff --git a/rules-tests/Symfony73/Rector/Class_/InvokableCommandInputAttributeRector/Fixture/with_optional_argument.php.inc b/rules-tests/Symfony73/Rector/Class_/InvokableCommandInputAttributeRector/Fixture/with_optional_argument.php.inc new file mode 100644 index 000000000..0f06b3376 --- /dev/null +++ b/rules-tests/Symfony73/Rector/Class_/InvokableCommandInputAttributeRector/Fixture/with_optional_argument.php.inc @@ -0,0 +1,61 @@ +addArgument('argument', InputArgument::OPTIONAL, 'Argument description'); + $this->addOption('option', 'o', InputOption::VALUE_NONE, 'Option description'); + } + + protected 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_/InvokableCommandInputAttributeRector/Fixture/with_override.php.inc b/rules-tests/Symfony73/Rector/Class_/InvokableCommandInputAttributeRector/Fixture/with_override.php.inc new file mode 100644 index 000000000..48bbab3b8 --- /dev/null +++ b/rules-tests/Symfony73/Rector/Class_/InvokableCommandInputAttributeRector/Fixture/with_override.php.inc @@ -0,0 +1,61 @@ +addArgument('argument', InputArgument::REQUIRED, 'Argument description'); + $this->addOption('option', 'o', InputOption::VALUE_NONE, 'Option description'); + } + + #[\Override] + protected 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_/InvokableCommandInputAttributeRector/InvokableCommandInputAttributeRectorTest.php b/rules-tests/Symfony73/Rector/Class_/InvokableCommandInputAttributeRector/InvokableCommandInputAttributeRectorTest.php new file mode 100644 index 000000000..551b491e2 --- /dev/null +++ b/rules-tests/Symfony73/Rector/Class_/InvokableCommandInputAttributeRector/InvokableCommandInputAttributeRectorTest.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_/InvokableCommandInputAttributeRector/config/configured_rule.php b/rules-tests/Symfony73/Rector/Class_/InvokableCommandInputAttributeRector/config/configured_rule.php new file mode 100644 index 000000000..bd5997cd1 --- /dev/null +++ b/rules-tests/Symfony73/Rector/Class_/InvokableCommandInputAttributeRector/config/configured_rule.php @@ -0,0 +1,10 @@ +rule(InvokableCommandInputAttributeRector::class); +}; diff --git a/rules/CodeQuality/NodeAnalyzer/AttributePresenceDetector.php b/rules/CodeQuality/NodeAnalyzer/AttributePresenceDetector.php new file mode 100644 index 000000000..69ee1eb24 --- /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 000000000..e956e95e3 --- /dev/null +++ b/rules/CodeQuality/Rector/AttributeGroup/SingleConditionSecurityAttributeToIsGrantedRector.php @@ -0,0 +1,102 @@ +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/BinaryOp/RequestIsMainRector.php b/rules/CodeQuality/Rector/BinaryOp/RequestIsMainRector.php new file mode 100644 index 000000000..0347e0a99 --- /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/rules/CodeQuality/Rector/BinaryOp/ResponseStatusCodeRector.php b/rules/CodeQuality/Rector/BinaryOp/ResponseStatusCodeRector.php index 3a92ea19d..72af7eeac 100644 --- a/rules/CodeQuality/Rector/BinaryOp/ResponseStatusCodeRector.php +++ b/rules/CodeQuality/Rector/BinaryOp/ResponseStatusCodeRector.php @@ -99,7 +99,7 @@ public function refactor(Node $node): ?Node private function processMethodCall(MethodCall $methodCall): CallLike|null { - $methodCallName = $this->nodeNameResolver->getName($methodCall->name); + $methodCallName = $this->getName($methodCall->name); if (! is_string($methodCallName)) { return null; } diff --git a/rules/CodeQuality/Rector/ClassMethod/ActionSuffixRemoverRector.php b/rules/CodeQuality/Rector/ClassMethod/ActionSuffixRemoverRector.php index ec85c9fe7..b165f1d45 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); + $name = $this->getName($classMethod); $newName = Strings::replace($name, sprintf('#%s$#', $suffixToRemove), ''); + if ($newName === $name) { + return null; + } $classMethod->name = new Identifier($newName); + return $classMethod; } } diff --git a/rules/CodeQuality/Rector/ClassMethod/TemplateAnnotationToThisRenderRector.php b/rules/CodeQuality/Rector/ClassMethod/TemplateAnnotationToThisRenderRector.php index 77835565d..6d60d207c 100644 --- a/rules/CodeQuality/Rector/ClassMethod/TemplateAnnotationToThisRenderRector.php +++ b/rules/CodeQuality/Rector/ClassMethod/TemplateAnnotationToThisRenderRector.php @@ -5,6 +5,7 @@ namespace Rector\Symfony\CodeQuality\Rector\ClassMethod; use PhpParser\Node; +use PhpParser\Node\Attribute; use PhpParser\Node\Expr; use PhpParser\Node\Expr\Closure; use PhpParser\Node\Expr\MethodCall; @@ -15,15 +16,19 @@ use PhpParser\Node\Stmt\Function_; use PhpParser\Node\Stmt\Return_; use PhpParser\NodeVisitor; +use PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode; +use PHPStan\PhpDocParser\Ast\Type\ArrayShapeNode; use PHPStan\Type\ArrayType; use PHPStan\Type\Constant\ConstantArrayType; use PHPStan\Type\MixedType; use PHPStan\Type\ObjectType; use Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode; +use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo; use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory; use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTagRemover; use Rector\Comments\NodeDocBlock\DocBlockUpdater; use Rector\Contract\PhpParser\Node\StmtsAwareInterface; +use Rector\Doctrine\NodeAnalyzer\AttrinationFinder; use Rector\PhpParser\Node\BetterNodeFinder; use Rector\Rector\AbstractRector; use Rector\Symfony\Annotation\AnnotationAnalyzer; @@ -37,8 +42,8 @@ use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; /** - * @changelog https://github.com/symfony/symfony-docs/pull/12387#discussion_r329551967 - * @changelog https://symfony.com/doc/current/bundles/SensioFrameworkExtraBundle/annotations/view.html + * @see https://github.com/symfony/symfony-docs/pull/12387#discussion_r329551967 + * @see https://symfony.com/doc/current/bundles/SensioFrameworkExtraBundle/annotations/view.html * * @see \Rector\Symfony\Tests\CodeQuality\Rector\ClassMethod\TemplateAnnotationToThisRenderRector\TemplateAnnotationToThisRenderRectorTest */ @@ -54,6 +59,7 @@ public function __construct( private readonly DocBlockUpdater $docBlockUpdater, private readonly BetterNodeFinder $betterNodeFinder, private readonly PhpDocInfoFactory $phpDocInfoFactory, + private readonly AttrinationFinder $attrinationFinder, ) { } @@ -110,24 +116,16 @@ public function refactor(Node $node): ?Node return null; } - $this->decorateAbstractControllerParentClass($node); - $hasChanged = false; - $classDoctrineAnnotationTagValueNode = $this->annotationAnalyzer->getDoctrineAnnotationTagValueNode( - $node, - SymfonyAnnotation::TEMPLATE - ); + $classTemplateTagValueNodeOrAttribute = $this->attrinationFinder->getByOne($node, SymfonyAnnotation::TEMPLATE); foreach ($node->getMethods() as $classMethod) { - if (! $classMethod->isPublic()) { - continue; - } - $hasClassMethodChanged = $this->replaceTemplateAnnotation( $classMethod, - $classDoctrineAnnotationTagValueNode + $classTemplateTagValueNodeOrAttribute ); + if ($hasClassMethodChanged) { $hasChanged = true; } @@ -137,9 +135,11 @@ public function refactor(Node $node): ?Node return null; } - // cleanup Class_ @Template annotaion - if ($classDoctrineAnnotationTagValueNode instanceof DoctrineAnnotationTagValueNode) { - $this->removeDoctrineAnnotationTagValueNode($node, $classDoctrineAnnotationTagValueNode); + $this->decorateAbstractControllerParentClass($node); + + // cleanup Class_ @Template annotation + if ($classTemplateTagValueNodeOrAttribute instanceof DoctrineAnnotationTagValueNode) { + $this->removeDoctrineAnnotationTagValueNode($node, $classTemplateTagValueNodeOrAttribute); } return $node; @@ -152,29 +152,29 @@ 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( ClassMethod $classMethod, - ?DoctrineAnnotationTagValueNode $classDoctrineAnnotationTagValueNode + DoctrineAnnotationTagValueNode | Attribute | null $classTagValueNodeOrAttribute ): bool { if (! $classMethod->isPublic()) { return false; } - $doctrineAnnotationTagValueNode = $this->annotationAnalyzer->getDoctrineAnnotationTagValueNode( + $methodTemplateTagValueNodeOrAttribute = $this->attrinationFinder->getByOne( $classMethod, SymfonyAnnotation::TEMPLATE ); - if ($doctrineAnnotationTagValueNode instanceof DoctrineAnnotationTagValueNode) { - return $this->refactorClassMethod($classMethod, $doctrineAnnotationTagValueNode); + if ($methodTemplateTagValueNodeOrAttribute !== null) { + return $this->refactorClassMethod($classMethod, $methodTemplateTagValueNodeOrAttribute); } - // global @Template access - if ($classDoctrineAnnotationTagValueNode instanceof DoctrineAnnotationTagValueNode) { - return $this->refactorClassMethod($classMethod, $classDoctrineAnnotationTagValueNode); + // fallback to global @Template/#[Template] access + if ($classTagValueNodeOrAttribute instanceof DoctrineAnnotationTagValueNode || $classTagValueNodeOrAttribute instanceof Attribute) { + return $this->refactorClassMethod($classMethod, $classTagValueNodeOrAttribute); } return false; @@ -182,19 +182,18 @@ private function replaceTemplateAnnotation( private function refactorClassMethod( ClassMethod $classMethod, - DoctrineAnnotationTagValueNode $templateDoctrineAnnotationTagValueNode + DoctrineAnnotationTagValueNode | Attribute $templateTagValueNodeOrAttribute, ): bool { $hasThisRenderOrReturnsResponse = $this->hasLastReturnResponse($classMethod); $hasChanged = false; $this->traverseNodesWithCallable($classMethod, function (Node $node) use ( - $templateDoctrineAnnotationTagValueNode, + $templateTagValueNodeOrAttribute, $hasThisRenderOrReturnsResponse, $classMethod, &$hasChanged ): ?int { - // keep as similar type if ($node instanceof Closure || $node instanceof Function_) { return NodeVisitor::DONT_TRAVERSE_CURRENT_AND_CHILDREN; @@ -204,29 +203,33 @@ private function refactorClassMethod( return null; } - $this->refactorStmtsAwareNode( + $hasChangedNode = $this->refactorStmtsAwareNode( $node, - $templateDoctrineAnnotationTagValueNode, + $templateTagValueNodeOrAttribute, $hasThisRenderOrReturnsResponse, $classMethod ); - - $hasChanged = true; + if ($hasChangedNode) { + $hasChanged = true; + } return null; }); + // remove return array shape details + $this->removeReturnArrayShapeDocblock($classMethod); + if (! $this->emptyReturnNodeFinder->hasNoOrEmptyReturns($classMethod)) { return $hasChanged; } $thisRenderMethodCall = $this->thisRenderFactory->create( null, - $templateDoctrineAnnotationTagValueNode, + $templateTagValueNodeOrAttribute, $classMethod ); - $this->refactorNoReturn($classMethod, $thisRenderMethodCall, $templateDoctrineAnnotationTagValueNode); + $this->refactorNoReturn($classMethod, $thisRenderMethodCall, $templateTagValueNodeOrAttribute); return true; } @@ -253,28 +256,28 @@ private function hasLastReturnResponse(ClassMethod $classMethod): bool private function refactorReturn( Return_ $return, - DoctrineAnnotationTagValueNode $templateDoctrineAnnotationTagValueNode, + DoctrineAnnotationTagValueNode | Attribute $templateTagValueNodeOrAttribute, 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 $thisRenderMethodCall = $this->thisRenderFactory->create( $return, - $templateDoctrineAnnotationTagValueNode, + $templateTagValueNodeOrAttribute, $classMethod ); - $this->refactorReturnWithValue( + return $this->refactorReturnWithValue( $return, $hasThisRenderOrReturnsResponse, $thisRenderMethodCall, $classMethod, - $templateDoctrineAnnotationTagValueNode + $templateTagValueNodeOrAttribute ); } @@ -294,75 +297,124 @@ private function refactorReturnWithValue( bool $hasThisRenderOrReturnsResponse, MethodCall $thisRenderMethodCall, ClassMethod $classMethod, - DoctrineAnnotationTagValueNode $doctrineAnnotationTagValueNode - ): void { + DoctrineAnnotationTagValueNode | Attribute $doctrineTagValueNodeOrAttribute + ): bool { /** @var Expr $lastReturnExpr */ $lastReturnExpr = $return->expr; $returnStaticType = $this->getType($lastReturnExpr); + $responseObjectType = new ObjectType(SymfonyClass::RESPONSE); - if (! $return->expr instanceof MethodCall) { - if (! $hasThisRenderOrReturnsResponse || $returnStaticType instanceof ConstantArrayType) { + // change contents only if the value is not Response yet + if (! $responseObjectType->isSuperTypeOf($returnStaticType)->yes()) { + if (! $return->expr instanceof MethodCall) { + if (! $hasThisRenderOrReturnsResponse || $returnStaticType instanceof ConstantArrayType) { + $return->expr = $thisRenderMethodCall; + } + } elseif ($returnStaticType instanceof ArrayType) { $return->expr = $thisRenderMethodCall; + } elseif ($returnStaticType instanceof MixedType) { + // nothing we can do + return false; } - } elseif ($returnStaticType instanceof ArrayType) { - $return->expr = $thisRenderMethodCall; - } elseif ($returnStaticType instanceof MixedType) { - // nothing we can do - return; - } - $isArrayOrResponseType = $this->arrayUnionResponseTypeAnalyzer->isArrayUnionResponseType( - $returnStaticType, - SymfonyClass::RESPONSE - ); + $isArrayOrResponseType = $this->arrayUnionResponseTypeAnalyzer->isArrayUnionResponseType( + $returnStaticType, + SymfonyClass::RESPONSE + ); - // skip as the original class method has to change first - if ($isArrayOrResponseType) { - return; + // skip as the original class method has to change first + if ($isArrayOrResponseType) { + return false; + } } // already response - $this->removeDoctrineAnnotationTagValueNode($classMethod, $doctrineAnnotationTagValueNode); + $this->removeDoctrineAnnotationTagValueNode($classMethod, $doctrineTagValueNodeOrAttribute); $this->returnTypeDeclarationUpdater->updateClassMethod($classMethod, SymfonyClass::RESPONSE); + + return true; } private function removeDoctrineAnnotationTagValueNode( Class_|ClassMethod $node, - DoctrineAnnotationTagValueNode $doctrineAnnotationTagValueNode + DoctrineAnnotationTagValueNode | Attribute $doctrineTagValueNodeOrAttribute ): void { - $phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($node); - $this->phpDocTagRemover->removeTagValueFromNode($phpDocInfo, $doctrineAnnotationTagValueNode); + if ($doctrineTagValueNodeOrAttribute instanceof DoctrineAnnotationTagValueNode) { + $phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($node); + $this->phpDocTagRemover->removeTagValueFromNode($phpDocInfo, $doctrineTagValueNodeOrAttribute); + + $this->docBlockUpdater->updateRefactoredNodeWithPhpDocInfo($node); + + return; + } + + foreach ($node->attrGroups as $attrGroupKey => $attrGroup) { + foreach ($attrGroup->attrs as $attributeKey => $attribute) { + if ($attribute === $doctrineTagValueNodeOrAttribute) { + unset($attrGroup->attrs[$attributeKey]); + } + } - $this->docBlockUpdater->updateRefactoredNodeWithPhpDocInfo($node); + // no attributes left? remove the whole dgroup + if ($attrGroup->attrs === []) { + unset($node->attrGroups[$attrGroupKey]); + } + } } private function refactorStmtsAwareNode( StmtsAwareInterface $stmtsAware, - DoctrineAnnotationTagValueNode $templateDoctrineAnnotationTagValueNode, + DoctrineAnnotationTagValueNode | Attribute $templateTagValueNodeOrAttribute, 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; } - // just created node, skip it + // just created class, skip it if ($stmt->getAttributes() === []) { - return; + return false; } - $this->refactorReturn( + $hasChangedReturn = $this->refactorReturn( $stmt, - $templateDoctrineAnnotationTagValueNode, + $templateTagValueNodeOrAttribute, $hasThisRenderOrReturnsResponse, $classMethod ); + if ($hasChangedReturn) { + $hasChanged = true; + } + } + return $hasChanged; + } + + private function removeReturnArrayShapeDocblock(ClassMethod $classMethod): void + { + $classMethodPhpDocInfo = $this->phpDocInfoFactory->createFromNode($classMethod); + if (! $classMethodPhpDocInfo instanceof PhpDocInfo) { + return; + } + + $returnTagValueNode = $classMethodPhpDocInfo->getReturnTagValue(); + if (! $returnTagValueNode instanceof ReturnTagValueNode) { + return; + } + + if (! $returnTagValueNode->type instanceof ArrayShapeNode) { + return; + } + + if ($classMethodPhpDocInfo->removeByName('@return')) { + $this->docBlockUpdater->updateRefactoredNodeWithPhpDocInfo($classMethod); } } } diff --git a/rules/CodeQuality/Rector/Class_/EventListenerToEventSubscriberRector.php b/rules/CodeQuality/Rector/Class_/EventListenerToEventSubscriberRector.php index cae412d02..8b14c4712 100644 --- a/rules/CodeQuality/Rector/Class_/EventListenerToEventSubscriberRector.php +++ b/rules/CodeQuality/Rector/Class_/EventListenerToEventSubscriberRector.php @@ -9,6 +9,7 @@ use PhpParser\Node\Identifier; use PhpParser\Node\Name\FullyQualified; use PhpParser\Node\Stmt\Class_; +use Rector\CodingStyle\Naming\ClassNaming; use Rector\Php80\NodeAnalyzer\PhpAttributeAnalyzer; use Rector\Rector\AbstractRector; use Rector\Symfony\ApplicationMetadata\ListenerServiceDefinitionProvider; @@ -42,6 +43,7 @@ public function __construct( private readonly GetSubscribedEventsClassMethodFactory $getSubscribedEventsClassMethodFactory, private readonly ClassAnalyzer $classAnalyzer, private readonly PhpAttributeAnalyzer $phpAttributeAnalyzer, + private readonly ClassNaming $classNaming ) { $this->eventNamesToClassConstants = [ // kernel events @@ -151,7 +153,7 @@ private function changeListenerToSubscriberWithMethods(Class_ $class, array $eve { $class->implements[] = new FullyQualified(SymfonyClass::EVENT_SUBSCRIBER_INTERFACE); - $classShortName = $this->nodeNameResolver->getShortName($class); + $classShortName = $this->classNaming->getShortName($class); // remove suffix $classShortName = Strings::replace($classShortName, self::LISTENER_MATCH_REGEX, '$1'); @@ -170,7 +172,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; } @@ -179,10 +181,7 @@ private function hasAsListenerAttribute(Class_ $class): bool continue; } - if ($this->phpAttributeAnalyzer->hasPhpAttribute( - $classMethod, - SymfonyAttribute::EVENT_LISTENER_ATTRIBUTE - )) { + if ($this->phpAttributeAnalyzer->hasPhpAttribute($classMethod, SymfonyAttribute::AS_EVENT_LISTENER)) { return true; } } diff --git a/rules/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector.php b/rules/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector.php new file mode 100644 index 000000000..3b53c7ee7 --- /dev/null +++ b/rules/CodeQuality/Rector/Class_/InlineClassRoutePrefixRector.php @@ -0,0 +1,317 @@ +shouldSkipClass($node)) { + return null; + } + + $classRoutePath = null; + $classRouteName = null; + + // 1. detect attribute + $routeAttributeOrAnnotation = $this->attrinationFinder->getByMany( + $node, + [SymfonyAttribute::ROUTE, SymfonyAnnotation::ROUTE] + ); + + 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) { + return null; + } + + // 2. inline prefix to all method routes + $hasChanged = false; + + foreach ($node->getMethods() as $classMethod) { + if (! $classMethod->isPublic() || $classMethod->isMagic()) { + continue; + } + + // can be route method + $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); + + 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; + } 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; + + 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; + } + } + } + } + } + + if (! $hasChanged) { + return null; + } + + 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 (! $this->controllerAnalyzer->isController($class)) { + return true; + } + + foreach ($class->getMethods() as $classMethod) { + if (! $classMethod->isPublic() || $classMethod->isMagic()) { + continue; + } + + // special cases for FOS rest that should be skipped + 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 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) { + // silent or "path" + if ($arg->name === null || $arg->name->toString() === self::PATH) { + $routeExpr = $arg->value; + if ($routeExpr instanceof String_) { + return $routeExpr->value; + } + } + } + + 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; + } +} diff --git a/rules/CodeQuality/Rector/Class_/SplitAndSecurityAttributeToIsGrantedRector.php b/rules/CodeQuality/Rector/Class_/SplitAndSecurityAttributeToIsGrantedRector.php new file mode 100644 index 000000000..ffb81bc00 --- /dev/null +++ b/rules/CodeQuality/Rector/Class_/SplitAndSecurityAttributeToIsGrantedRector.php @@ -0,0 +1,124 @@ +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 ') && ! str_contains($content, ' && ')) { + continue; + } + + // split by && and "and" + $andItems = str_contains($content, ' && ') ? explode(' && ', $content) : 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; + } +} diff --git a/rules/CodeQuality/Rector/Closure/StringExtensionToConfigBuilderRector.php b/rules/CodeQuality/Rector/Closure/StringExtensionToConfigBuilderRector.php index 58b905d3c..b3b8bd3f6 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; @@ -51,6 +50,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( diff --git a/rules/Configs/NodeVisitor/CollectServiceArgumentsNodeVisitor.php b/rules/Configs/NodeVisitor/CollectServiceArgumentsNodeVisitor.php index 6e8b59367..199d0048f 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/Configs/Rector/ClassMethod/AddRouteAnnotationRector.php b/rules/Configs/Rector/ClassMethod/AddRouteAnnotationRector.php index 98afb02b6..80c888f93 100644 --- a/rules/Configs/Rector/ClassMethod/AddRouteAnnotationRector.php +++ b/rules/Configs/Rector/ClassMethod/AddRouteAnnotationRector.php @@ -140,8 +140,8 @@ public function index() private function resolveControllerReference(Class_ $class, ClassMethod $classMethod): ?string { - $className = $this->nodeNameResolver->getName($class); - $methodName = $this->nodeNameResolver->getName($classMethod); + $className = $this->getName($class); + $methodName = $this->getName($classMethod); if ($methodName === '__invoke') { return $className; diff --git a/rules/DependencyInjection/Rector/Class_/CommandGetByTypeToConstructorInjectionRector.php b/rules/DependencyInjection/Rector/Class_/CommandGetByTypeToConstructorInjectionRector.php index ba303b874..86a5ba6a4 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 3147ee9f0..b1aedc02c 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 bb9236cf1..0a2ced0a4 100644 --- a/rules/DependencyInjection/Rector/Class_/GetBySymfonyStringToConstructorInjectionRector.php +++ b/rules/DependencyInjection/Rector/Class_/GetBySymfonyStringToConstructorInjectionRector.php @@ -31,7 +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_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( @@ -139,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/DependencyInjection/Rector/Trait_/TraitGetByTypeToInjectRector.php b/rules/DependencyInjection/Rector/Trait_/TraitGetByTypeToInjectRector.php index 3c4921c8f..febf5e273 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/rules/DowngradeSymfony70/Rector/Class_/DowngradeSymfonyCommandAttributeRector.php b/rules/DowngradeSymfony70/Rector/Class_/DowngradeSymfonyCommandAttributeRector.php index 3552074db..d0753f951 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/Symfony25/Rector/MethodCall/AddViolationToBuildViolationRector.php b/rules/Symfony25/Rector/MethodCall/AddViolationToBuildViolationRector.php index 13b800b02..fd1eb30b6 100644 --- a/rules/Symfony25/Rector/MethodCall/AddViolationToBuildViolationRector.php +++ b/rules/Symfony25/Rector/MethodCall/AddViolationToBuildViolationRector.php @@ -69,7 +69,7 @@ public function refactor(Node $node): ?MethodCall return null; } - if (! $this->nodeNameResolver->isName($node->name, 'addViolationAt')) { + if (! $this->isName($node->name, 'addViolationAt')) { return null; } diff --git a/rules/Symfony27/Rector/MethodCall/ChangeCollectionTypeOptionNameFromTypeToEntryTypeRector.php b/rules/Symfony27/Rector/MethodCall/ChangeCollectionTypeOptionNameFromTypeToEntryTypeRector.php index c13e2167e..71db08a8c 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/Symfony30/Rector/ClassMethod/GetRequestRector.php b/rules/Symfony30/Rector/ClassMethod/GetRequestRector.php index fe52399c1..bc7343fce 100644 --- a/rules/Symfony30/Rector/ClassMethod/GetRequestRector.php +++ b/rules/Symfony30/Rector/ClassMethod/GetRequestRector.php @@ -140,7 +140,7 @@ private function isActionWithGetRequestInBody(ClassMethod $classMethod): bool return false; } - return $this->nodeNameResolver->isName($node->name, 'get'); + return $this->isName($node->name, 'get'); }); foreach ($getMethodCalls as $getMethodCall) { @@ -159,7 +159,7 @@ private function isGetRequestInAction(ClassMethod $classMethod, MethodCall $meth return false; } - if (! $this->nodeNameResolver->isName($methodCall->var, 'this')) { + if (! $this->isName($methodCall->var, 'this')) { return false; } @@ -187,7 +187,7 @@ private function containsGetRequestMethod(ClassMethod $classMethod): bool return false; } - return $this->nodeNameResolver->isName($node->name, 'getRequest'); + return $this->isName($node->name, 'getRequest'); }); } diff --git a/rules/Symfony30/Rector/ClassMethod/RemoveDefaultGetBlockPrefixRector.php b/rules/Symfony30/Rector/ClassMethod/RemoveDefaultGetBlockPrefixRector.php index 185afa547..fa8748dc5 100644 --- a/rules/Symfony30/Rector/ClassMethod/RemoveDefaultGetBlockPrefixRector.php +++ b/rules/Symfony30/Rector/ClassMethod/RemoveDefaultGetBlockPrefixRector.php @@ -11,6 +11,7 @@ use PhpParser\Node\Stmt\Class_; use PhpParser\Node\Stmt\ClassMethod; use PhpParser\Node\Stmt\Return_; +use Rector\CodingStyle\Naming\ClassNaming; use Rector\PhpParser\Node\Value\ValueResolver; use Rector\Rector\AbstractRector; use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; @@ -24,7 +25,8 @@ final class RemoveDefaultGetBlockPrefixRector extends AbstractRector { public function __construct( - private readonly ValueResolver $valueResolver + private readonly ValueResolver $valueResolver, + private readonly ClassNaming $classNaming ) { } @@ -96,12 +98,12 @@ public function refactor(Node $node): ?Class_ $returnedValue = $this->valueResolver->getValue($returnedExpr); - $className = $this->nodeNameResolver->getName($node); + $className = $this->getName($node); if (! is_string($className)) { continue; } - $shortClassName = $this->nodeNameResolver->getShortName($className); + $shortClassName = $this->classNaming->getShortName($className); if (\str_ends_with($shortClassName, 'Type')) { $shortClassName = (string) Strings::before($shortClassName, 'Type'); } diff --git a/rules/Symfony30/Rector/MethodCall/OptionNameRector.php b/rules/Symfony30/Rector/MethodCall/OptionNameRector.php index d1eecd545..5b691890a 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/rules/Symfony34/Rector/Closure/ContainerGetNameToTypeInTestsRector.php b/rules/Symfony34/Rector/Closure/ContainerGetNameToTypeInTestsRector.php index d2f4976fe..3b304436d 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/rules/Symfony42/Rector/MethodCall/ContainerGetToConstructorInjectionRector.php b/rules/Symfony42/Rector/MethodCall/ContainerGetToConstructorInjectionRector.php index df14f03cb..35f260673 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 + )); } } diff --git a/rules/Symfony42/Rector/New_/StringToArrayArgumentProcessRector.php b/rules/Symfony42/Rector/New_/StringToArrayArgumentProcessRector.php index 908681800..89a1dc3e3 100644 --- a/rules/Symfony42/Rector/New_/StringToArrayArgumentProcessRector.php +++ b/rules/Symfony42/Rector/New_/StringToArrayArgumentProcessRector.php @@ -111,35 +111,43 @@ 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; } private function shouldSkipProcessMethodCall(MethodCall $methodCall): bool { - $methodName = (string) $this->nodeNameResolver->getName($methodCall->name); + $methodName = (string) $this->getName($methodCall->name); 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/Symfony43/Rector/ClassMethod/EventDispatcherParentConstructRector.php b/rules/Symfony43/Rector/ClassMethod/EventDispatcherParentConstructRector.php index 81d6d0ed7..341b4409b 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/Symfony43/Rector/MethodCall/ConvertRenderTemplateShortNotationToBundleSyntaxRector.php b/rules/Symfony43/Rector/MethodCall/ConvertRenderTemplateShortNotationToBundleSyntaxRector.php index 21086ab08..97494599e 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 @@ -77,13 +79,13 @@ public function getNodeTypes(): array */ public function refactor(Node $node): ?Node { - if (! $this->nodeNameResolver->isName($node->name, 'render') && - ! $this->nodeNameResolver->isName($node->name, 'renderView')) { + if (! $this->isName($node->name, 'render') && + ! $this->isName($node->name, 'renderView')) { return null; } $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/rules/Symfony43/Rector/MethodCall/WebTestCaseAssertResponseCodeRector.php b/rules/Symfony43/Rector/MethodCall/WebTestCaseAssertResponseCodeRector.php index 19d704b78..0c9114004 100644 --- a/rules/Symfony43/Rector/MethodCall/WebTestCaseAssertResponseCodeRector.php +++ b/rules/Symfony43/Rector/MethodCall/WebTestCaseAssertResponseCodeRector.php @@ -131,7 +131,7 @@ private function processAssertResponseStatusCodeSame(StaticCall|MethodCall $meth $nestedMethodCall = $secondArg->value; - if (! $this->nodeNameResolver->isName($nestedMethodCall->name, 'getStatusCode')) { + if (! $this->isName($nestedMethodCall->name, 'getStatusCode')) { return null; } diff --git a/rules/Symfony44/Rector/ClassMethod/ConsoleExecuteReturnIntRector.php b/rules/Symfony44/Rector/ClassMethod/ConsoleExecuteReturnIntRector.php index f46e7441d..3e88640cb 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); diff --git a/rules/Symfony44/Rector/MethodCall/AuthorizationCheckerIsGrantedExtractorRector.php b/rules/Symfony44/Rector/MethodCall/AuthorizationCheckerIsGrantedExtractorRector.php index e01ecf9a5..8c1b08324 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,14 +105,12 @@ 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; } - if (! $this->nodeNameResolver->isName($node->name, 'isGranted')) { + if (! $this->isName($node->name, 'isGranted')) { return null; } @@ -146,7 +177,7 @@ private function processExtractIsGranted( private function processControllerMethods(MethodCall $methodCall): MethodCall|BooleanOr|null { - if ($this->nodeNameResolver->isName($methodCall->name, 'isGranted')) { + if ($this->isName($methodCall->name, 'isGranted')) { return $this->handleIsGranted($methodCall); } diff --git a/rules/Symfony51/Rector/ClassMethod/CommandConstantReturnCodeRector.php b/rules/Symfony51/Rector/ClassMethod/CommandConstantReturnCodeRector.php index 4ce8cc171..a06204de1 100644 --- a/rules/Symfony51/Rector/ClassMethod/CommandConstantReturnCodeRector.php +++ b/rules/Symfony51/Rector/ClassMethod/CommandConstantReturnCodeRector.php @@ -80,11 +80,11 @@ 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; } - if (! $this->nodeNameResolver->isName($node, 'execute')) { + if (! $this->isName($node, 'execute')) { return null; } diff --git a/rules/Symfony52/Rector/New_/PropertyAccessorCreationBooleanToFlagsRector.php b/rules/Symfony52/Rector/New_/PropertyAccessorCreationBooleanToFlagsRector.php index 71451c89a..3e656cd3d 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/rules/Symfony53/Rector/StaticPropertyFetch/KernelTestCaseContainerPropertyDeprecationRector.php b/rules/Symfony53/Rector/StaticPropertyFetch/KernelTestCaseContainerPropertyDeprecationRector.php index befb759b8..1b0cd07bf 100644 --- a/rules/Symfony53/Rector/StaticPropertyFetch/KernelTestCaseContainerPropertyDeprecationRector.php +++ b/rules/Symfony53/Rector/StaticPropertyFetch/KernelTestCaseContainerPropertyDeprecationRector.php @@ -70,7 +70,7 @@ public function refactor(Node $node): ?Node return null; } - if ($this->nodeNameResolver->getName($node->name) !== 'container') { + if ($this->getName($node->name) !== 'container') { return null; } diff --git a/rules/Symfony61/Rector/Class_/CommandConfigureToAttributeRector.php b/rules/Symfony61/Rector/Class_/CommandConfigureToAttributeRector.php index c37df3ddc..fcbf7d04d 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->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 5c1a0fced..879fcd572 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/Symfony61/Rector/StaticPropertyFetch/ErrorNamesPropertyToConstantRector.php b/rules/Symfony61/Rector/StaticPropertyFetch/ErrorNamesPropertyToConstantRector.php index 0e8e6b885..3f3aa97e7 100644 --- a/rules/Symfony61/Rector/StaticPropertyFetch/ErrorNamesPropertyToConstantRector.php +++ b/rules/Symfony61/Rector/StaticPropertyFetch/ErrorNamesPropertyToConstantRector.php @@ -73,10 +73,10 @@ 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')) { + if (! $this->isName($node->name, 'errorNames')) { return null; } diff --git a/rules/Symfony62/Rector/Class_/MessageHandlerInterfaceToAttributeRector.php b/rules/Symfony62/Rector/Class_/MessageHandlerInterfaceToAttributeRector.php index 2fde77624..16b0a6275 100644 --- a/rules/Symfony62/Rector/Class_/MessageHandlerInterfaceToAttributeRector.php +++ b/rules/Symfony62/Rector/Class_/MessageHandlerInterfaceToAttributeRector.php @@ -6,10 +6,11 @@ use PhpParser\Node; use PhpParser\Node\Stmt\Class_; +use PHPStan\Reflection\ReflectionProvider; +use PHPStan\Type\ObjectType; use Rector\Php80\NodeAnalyzer\PhpAttributeAnalyzer; use Rector\Rector\AbstractRector; use Rector\Symfony\Helper\MessengerHelper; -use Rector\Symfony\NodeAnalyzer\ClassAnalyzer; use Rector\Symfony\NodeManipulator\ClassManipulator; use Rector\Symfony\ValueObject\ServiceDefinition; use Rector\ValueObject\PhpVersionFeature; @@ -25,8 +26,8 @@ final class MessageHandlerInterfaceToAttributeRector extends AbstractRector impl public function __construct( private readonly MessengerHelper $messengerHelper, private readonly ClassManipulator $classManipulator, - private readonly ClassAnalyzer $classAnalyzer, private readonly PhpAttributeAnalyzer $phpAttributeAnalyzer, + private readonly ReflectionProvider $reflectionProvider ) { } @@ -84,11 +85,19 @@ public function getNodeTypes(): array */ public function refactor(Node $node): ?Node { + if (! $this->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/rules/Symfony62/Rector/Class_/SecurityAttributeToIsGrantedAttributeRector.php b/rules/Symfony62/Rector/Class_/SecurityAttributeToIsGrantedAttributeRector.php index 3f3748a22..48c2a5d83 100644 --- a/rules/Symfony62/Rector/Class_/SecurityAttributeToIsGrantedAttributeRector.php +++ b/rules/Symfony62/Rector/Class_/SecurityAttributeToIsGrantedAttributeRector.php @@ -14,7 +14,11 @@ 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\CodeQuality\NodeAnalyzer\AttributePresenceDetector; +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,16 +32,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 * @see https://regex101.com/r/Si1sDz/1 @@ -50,6 +44,12 @@ 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 AttributePresenceDetector $attributePresenceDetector, + ) { + } + public function provideMinPhpVersion(): int { return PhpVersionFeature::ATTRIBUTES; @@ -84,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() { } @@ -113,15 +113,21 @@ public function getNodeTypes(): array */ public function refactor(Node $node): ?Node { + if (! $this->attributePresenceDetector->detect(SensioAttribute::SECURITY)) { + 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,14 @@ 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" + return SensioAttribute::IS_GRANTED; + } } diff --git a/rules/Symfony72/Rector/StmtsAwareInterface/PushRequestToRequestStackConstructorRector.php b/rules/Symfony72/Rector/StmtsAwareInterface/PushRequestToRequestStackConstructorRector.php new file mode 100644 index 000000000..9617164e1 --- /dev/null +++ b/rules/Symfony72/Rector/StmtsAwareInterface/PushRequestToRequestStackConstructorRector.php @@ -0,0 +1,142 @@ +push($request); + } +} +CODE_SAMPLE + , + <<<'CODE_SAMPLE' +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\RequestStack; +use PHPUnit\Framework\TestCase; + +class SomeClass extends TestCase +{ + public function run() + { + $request = new Request(); + $requestStack = new RequestStack([$request]); + } +} +CODE_SAMPLE + ), + ]); + } + + public function getNodeTypes(): array + { + return [StmtsAwareInterface::class]; + } + + /** + * @param StmtsAwareInterface $node + */ + public function refactor(Node $node): ?StmtsAwareInterface + { + if (! $this->testsNodeAnalyzer->isInTestClass($node)) { + return null; + } + + $requestStack = null; + $hasChanged = false; + + foreach ($node->stmts as $key => $stmt) { + if (! $stmt instanceof Expression) { + continue; + } + + if (! $requestStack instanceof New_) { + $requestStack = $this->matchRequestStackAssignExpr($stmt); + } elseif ($stmt->expr instanceof MethodCall) { + $pushMethodCall = $stmt->expr; + + if ($this->isName($pushMethodCall->name, 'push')) { + // possibly request stack push + $array = new Array_([new ArrayItem($pushMethodCall->getArgs()[0]->value)]); + $requestStack->args[] = new Arg($array); + + $hasChanged = true; + + unset($node->stmts[$key]); + } + } + } + + if ($hasChanged) { + return $node; + } + + return null; + } + + private function matchRequestStackAssignExpr(Expression $expression): ?New_ + { + // 1. find new RequestStack assign + if (! $expression->expr instanceof Assign) { + return null; + } + + $assign = $expression->expr; + if (! $assign->expr instanceof New_) { + return null; + } + + $new = $assign->expr; + if (! $this->isName($new->class, SymfonyClass::REQUEST_STACK)) { + return null; + } + + // skip if already some args are filled + if ($new->getArgs() !== []) { + return null; + } + + return $new; + } +} diff --git a/rules/Symfony73/GetMethodToAsTwigAttributeTransformer.php b/rules/Symfony73/GetMethodToAsTwigAttributeTransformer.php new file mode 100644 index 000000000..6431b61c6 --- /dev/null +++ b/rules/Symfony73/GetMethodToAsTwigAttributeTransformer.php @@ -0,0 +1,119 @@ +reflectionProvider->hasClass($attributeClass)) { + return false; + } + + $getMethod = $class->getMethod($methodName); + if (! $getMethod instanceof ClassMethod) { + return false; + } + + $hasChanged = false; + + foreach ((array) $getMethod->stmts as $stmt) { + // handle return array simple case + if (! $stmt instanceof Return_) { + continue; + } + + if (! $stmt->expr instanceof Array_) { + continue; + } + + $returnArray = $stmt->expr; + foreach ($returnArray->items as $key => $arrayItem) { + if (! $arrayItem->value instanceof New_) { + continue; + } + + if ($arrayItem->value->isFirstClassCallable()) { + continue; + } + + $new = $arrayItem->value; + if (count($new->getArgs()) !== 2) { + continue; + } + + $secondArg = $new->getArgs()[1]; + + if ($this->isLocalCallable($secondArg->value)) { + $localMethodName = $this->localArrayMethodCallableMatcher->match($secondArg->value, $objectType); + if (! is_string($localMethodName)) { + continue; + } + + $localMethod = $class->getMethod($localMethodName); + if (! $localMethod instanceof ClassMethod) { + continue; + } + + $this->decorateMethodWithAttribute($localMethod, $attributeClass); + + // remove old new fuction instance + unset($returnArray->items[$key]); + + $hasChanged = true; + } + } + + $this->returnEmptyArrayMethodRemover->removeClassMethodIfArrayEmpty($class, $returnArray, $methodName); + } + + return $hasChanged; + } + + private function decorateMethodWithAttribute(ClassMethod $classMethod, string $attributeClass): void + { + $classMethod->attrGroups[] = new AttributeGroup([new Attribute(new FullyQualified($attributeClass))]); + } + + private function isLocalCallable(Expr $expr): bool + { + if ($expr instanceof MethodCall && $expr->isFirstClassCallable()) { + return true; + } + + return $expr instanceof Array_ && count($expr->items) === 2; + } +} diff --git a/rules/Symfony73/NodeAnalyzer/CommandArgumentsAndOptionsResolver.php b/rules/Symfony73/NodeAnalyzer/CommandArgumentsAndOptionsResolver.php new file mode 100644 index 000000000..ad49fc3e4 --- /dev/null +++ b/rules/Symfony73/NodeAnalyzer/CommandArgumentsAndOptionsResolver.php @@ -0,0 +1,116 @@ +findMethodCallsByName($configureClassMethod, 'addArgument'); + + $commandArguments = []; + foreach ($addArgumentMethodCalls as $addArgumentMethodCall) { + // @todo extract name, type and requirements + $addArgumentArgs = $addArgumentMethodCall->getArgs(); + + $optionName = $this->valueResolver->getValue($addArgumentArgs[0]->value); + if ($optionName === null) { + // we need string value, otherwise param will not have a name + throw new ShouldNotHappenException('Argument name is required'); + } + + $mode = isset($addArgumentArgs[1]) + ? $this->valueResolver->getValue($addArgumentArgs[1]->value) + : null; + + if ($mode !== null && ! is_numeric($mode)) { + // we need numeric value or null, otherwise param will not have a name + throw new ShouldNotHappenException('Argument mode is required to be null or numeric'); + } + + $description = isset($addArgumentArgs[2]) + ? $this->valueResolver->getValue($addArgumentArgs[2]->value) + : null; + + if (! is_string($description)) { + // we need string value, otherwise param will not have a name + throw new ShouldNotHappenException('Argument description is required'); + } + + $commandArguments[] = new CommandArgument( + $addArgumentArgs[0]->value, + $addArgumentArgs[1]->value, + $addArgumentArgs[2]->value + ); + } + + 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/NodeAnalyzer/LocalArrayMethodCallableMatcher.php b/rules/Symfony73/NodeAnalyzer/LocalArrayMethodCallableMatcher.php new file mode 100644 index 000000000..b496d3b48 --- /dev/null +++ b/rules/Symfony73/NodeAnalyzer/LocalArrayMethodCallableMatcher.php @@ -0,0 +1,51 @@ +name instanceof Identifier) { + return null; + } + + if (! $this->nodeTypeResolver->isObjectType($expr->var, $objectType)) { + return null; + } + + return $expr->name->toString(); + } + + if ($expr instanceof Array_) { + if (! $this->nodeTypeResolver->isObjectType($expr->items[0]->value, $objectType)) { + return null; + } + + $secondItem = $expr->items[1]; + if (! $secondItem->value instanceof String_) { + return null; + } + + return $secondItem->value->value; + } + + return null; + } +} diff --git a/rules/Symfony73/NodeFactory/CommandInvokeParamsFactory.php b/rules/Symfony73/NodeFactory/CommandInvokeParamsFactory.php new file mode 100644 index 000000000..211cb076a --- /dev/null +++ b/rules/Symfony73/NodeFactory/CommandInvokeParamsFactory.php @@ -0,0 +1,100 @@ +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((string) $this->valueResolver->getValue( + $commandArgument->getName() + ))); + + $argumentParam->type = new Identifier('string'); + + $modeValue = $this->valueResolver->getValue($commandArgument->getMode()); + if ($modeValue === null || $modeValue === 2) { + $argumentParam->type = new NullableType($argumentParam->type); + } + + // @todo fill type or default value + // @todo default string, multiple values array + + $argumentParam->attrGroups[] = new AttributeGroup([ + new Attribute( + new FullyQualified(SymfonyAttribute::COMMAND_ARGUMENT), + [ + new Arg(value: $commandArgument->getName(), name: new Identifier('name')), + new Arg(value: $commandArgument->getDescription(), name: new Identifier('description')), + ] + ), + ]); + + $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/NodeRemover/ReturnEmptyArrayMethodRemover.php b/rules/Symfony73/NodeRemover/ReturnEmptyArrayMethodRemover.php new file mode 100644 index 000000000..ad0ec1d0b --- /dev/null +++ b/rules/Symfony73/NodeRemover/ReturnEmptyArrayMethodRemover.php @@ -0,0 +1,31 @@ +items) !== 0) { + return; + } + + foreach ($class->stmts as $key => $classStmt) { + if (! $classStmt instanceof ClassMethod) { + continue; + } + + if ($classStmt->name->toString() !== $methodName) { + continue; + } + + unset($class->stmts[$key]); + } + } +} diff --git a/rules/Symfony73/Rector/Class_/CommandHelpToAttributeRector.php b/rules/Symfony73/Rector/Class_/CommandHelpToAttributeRector.php new file mode 100644 index 000000000..5f5034014 --- /dev/null +++ b/rules/Symfony73/Rector/Class_/CommandHelpToAttributeRector.php @@ -0,0 +1,212 @@ +setHelp() to the "help" named argument of #[AsCommand]', + [ + 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 + { + $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->attributeFinder->findAttributeByClass($node, SymfonyAttribute::AS_COMMAND); + if (! $asCommandAttribute instanceof Attribute) { + 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; + } + + $wrappedHelpString = new String_( + $helpExpr->value, + [ + Attributekey::KIND => String_::KIND_NOWDOC, + AttributeKey::DOC_LABEL => 'TXT', + ] + ); + + $asCommandAttribute->args[] = new Arg($wrappedHelpString, false, false, [], new Identifier('help')); + + if ($configureClassMethod->stmts === []) { + unset($configureClassMethod); + } + + return $node; + } + + /** + * Returns the argument passed to setHelp() and removes the MethodCall node. + */ + private function findAndRemoveSetHelpExpr(ClassMethod $configureClassMethod): ?String_ + { + $helpString = null; + + $this->traverseNodesWithCallable( + (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; + } + 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) $configureClassMethod->stmts as $key => $stmt) { + if ($this->isExpressionVariableThis($stmt)) { + unset($configureClassMethod->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_/GetFiltersToAsTwigFilterAttributeRector.php b/rules/Symfony73/Rector/Class_/GetFiltersToAsTwigFilterAttributeRector.php new file mode 100644 index 000000000..612dafba2 --- /dev/null +++ b/rules/Symfony73/Rector/Class_/GetFiltersToAsTwigFilterAttributeRector.php @@ -0,0 +1,102 @@ +isAbstract() || $node->isAnonymous()) { + return null; + } + + $twigExtensionObjectType = new ObjectType(TwigClass::TWIG_EXTENSION); + if (! $this->isObjectType($node, $twigExtensionObjectType)) { + return null; + } + + $hasChanged = $this->getMethodToAsTwigAttributeTransformer->transformClassGetMethodToAttributeMarker( + $node, + 'getFilters', + TwigClass::AS_TWIG_FILTER_ATTRIBUTE, + $twigExtensionObjectType + ); + + if ($hasChanged) { + return $node; + } + + return null; + } +} diff --git a/rules/Symfony73/Rector/Class_/GetFunctionsToAsTwigFunctionAttributeRector.php b/rules/Symfony73/Rector/Class_/GetFunctionsToAsTwigFunctionAttributeRector.php new file mode 100644 index 000000000..0ef572f24 --- /dev/null +++ b/rules/Symfony73/Rector/Class_/GetFunctionsToAsTwigFunctionAttributeRector.php @@ -0,0 +1,102 @@ +isAbstract() || $node->isAnonymous()) { + return null; + } + + $twigExtensionObjectType = new ObjectType(TwigClass::TWIG_EXTENSION); + if (! $this->isObjectType($node, $twigExtensionObjectType)) { + return null; + } + + $hasChanged = $this->getMethodToAsTwigAttributeTransformer->transformClassGetMethodToAttributeMarker( + $node, + 'getFunctions', + TwigClass::AS_TWIG_FUNCTION_ATTRIBUTE, + $twigExtensionObjectType + ); + + if (! $hasChanged) { + return null; + } + + return $node; + } +} diff --git a/rules/Symfony73/Rector/Class_/InvokableCommandInputAttributeRector.php b/rules/Symfony73/Rector/Class_/InvokableCommandInputAttributeRector.php new file mode 100644 index 000000000..5ef127ed6 --- /dev/null +++ b/rules/Symfony73/Rector/Class_/InvokableCommandInputAttributeRector.php @@ -0,0 +1,290 @@ +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(name: 'argument', description: 'Argument description')] + 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'); + $this->visibilityManipulator->makePublic($executeClassMethod); + + // 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 = array_merge($invokeParams, [$executeClassMethod->params[1]]); + + // 6. remove parent class + $node->extends = null; + + foreach ($executeClassMethod->attrGroups as $attrGroupKey => $attrGroup) { + foreach ($attrGroup->attrs as $attributeKey => $attr) { + if ($this->isName($attr->name, 'Override')) { + unset($attrGroup->attrs[$attributeKey]); + } + } + + if ($attrGroup->attrs === []) { + unset($executeClassMethod->attrGroups[$attrGroupKey]); + } + } + + // 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; + } + + 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; + } + } + + 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 ClassConstFetch || $firstArgValue instanceof ConstFetch) { + return new Variable($this->valueResolver->getValue($firstArgValue)); + } + + if (! $firstArgValue instanceof String_) { + // unable to resolve argument/option name + throw new ShouldNotHappenException(); + } + + return new Variable($firstArgValue->value); + }); + } + + private function isFluentArgumentOptionChain(MethodCall $methodCall): bool + { + $current = $methodCall; + + 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/rules/Symfony73/ValueObject/CommandArgument.php b/rules/Symfony73/ValueObject/CommandArgument.php new file mode 100644 index 000000000..e96377b80 --- /dev/null +++ b/rules/Symfony73/ValueObject/CommandArgument.php @@ -0,0 +1,32 @@ +name; + } + + public function getMode(): Expr + { + return $this->mode; + } + + public function getDescription(): Expr + { + return $this->description; + } +} diff --git a/rules/Symfony73/ValueObject/CommandOption.php b/rules/Symfony73/ValueObject/CommandOption.php new file mode 100644 index 000000000..b6880612b --- /dev/null +++ b/rules/Symfony73/ValueObject/CommandOption.php @@ -0,0 +1,20 @@ +name; + } +} diff --git a/rules/Twig134/Rector/Return_/SimpleFunctionAndFilterRector.php b/rules/Twig134/Rector/Return_/SimpleFunctionAndFilterRector.php index bea17abc2..ce97ac00a 100644 --- a/rules/Twig134/Rector/Return_/SimpleFunctionAndFilterRector.php +++ b/rules/Twig134/Rector/Return_/SimpleFunctionAndFilterRector.php @@ -151,11 +151,11 @@ private function shouldSkip(ClassMethod $classMethod): bool return true; } - if (! $classReflection->isSubclassOf('Twig_Extension')) { + if (! $classReflection->is('Twig_Extension')) { return true; } - return ! $this->nodeNameResolver->isNames($classMethod, ['getFunctions', 'getFilters']); + return ! $this->isNames($classMethod, ['getFunctions', 'getFilters']); } private function processArrayItem(ArrayItem $arrayItem, Type $newNodeType, bool &$hasChanged): void diff --git a/src/Annotation/AnnotationAnalyzer.php b/src/Annotation/AnnotationAnalyzer.php index e13c0ff1b..d705a6e16 100644 --- a/src/Annotation/AnnotationAnalyzer.php +++ b/src/Annotation/AnnotationAnalyzer.php @@ -5,49 +5,28 @@ namespace Rector\Symfony\Annotation; use PhpParser\Node\Stmt\Class_; -use PhpParser\Node\Stmt\ClassMethod; -use Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode; -use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo; -use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory; +use Rector\Doctrine\NodeAnalyzer\AttrinationFinder; use Rector\Symfony\Enum\SymfonyAnnotation; final readonly class AnnotationAnalyzer { public function __construct( - private PhpDocInfoFactory $phpDocInfoFactory, + private AttrinationFinder $attrinationFinder ) { } public function hasClassMethodWithTemplateAnnotation(Class_ $class): bool { - $classTemplateAnnotation = $this->getDoctrineAnnotationTagValueNode($class, SymfonyAnnotation::TEMPLATE); - if ($classTemplateAnnotation instanceof DoctrineAnnotationTagValueNode) { + if ($this->attrinationFinder->hasByOne($class, SymfonyAnnotation::TEMPLATE)) { return true; } foreach ($class->getMethods() as $classMethod) { - $classMethodTemplateAnnotation = $this->getDoctrineAnnotationTagValueNode( - $classMethod, - SymfonyAnnotation::TEMPLATE - ); - - if ($classMethodTemplateAnnotation instanceof DoctrineAnnotationTagValueNode) { + if ($this->attrinationFinder->hasByOne($classMethod, SymfonyAnnotation::TEMPLATE)) { return true; } } return false; } - - public function getDoctrineAnnotationTagValueNode( - Class_|ClassMethod $node, - string $annotationClass - ): ?DoctrineAnnotationTagValueNode { - $phpDocInfo = $this->phpDocInfoFactory->createFromNode($node); - if (! $phpDocInfo instanceof PhpDocInfo) { - return null; - } - - return $phpDocInfo->getByAnnotationClass($annotationClass); - } } diff --git a/src/ApplicationMetadata/ListenerServiceDefinitionProvider.php b/src/ApplicationMetadata/ListenerServiceDefinitionProvider.php index 8da9a2ae3..47ea57f47 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/CommandMethodName.php b/src/Enum/CommandMethodName.php new file mode 100644 index 000000000..e276426c3 --- /dev/null +++ b/src/Enum/CommandMethodName.php @@ -0,0 +1,16 @@ +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/src/NodeAnalyzer/SymfonyClosureExtensionMatcher.php b/src/NodeAnalyzer/SymfonyClosureExtensionMatcher.php index 6ce0a9728..3ad58af77 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', diff --git a/src/NodeAnalyzer/SymfonyTestCaseAnalyzer.php b/src/NodeAnalyzer/SymfonyTestCaseAnalyzer.php index 7e1a211e0..645efbc68 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/NodeFactory/Annotations/AnnotationOrAttributeValueResolver.php b/src/NodeFactory/Annotations/AnnotationOrAttributeValueResolver.php new file mode 100644 index 000000000..ef9de26ab --- /dev/null +++ b/src/NodeFactory/Annotations/AnnotationOrAttributeValueResolver.php @@ -0,0 +1,74 @@ +getValue($desiredKey); + if ($templateParameter instanceof ArrayItemNode) { + $templateParameterValue = $templateParameter->value; + + if ($templateParameterValue instanceof StringNode) { + $templateParameterValue = $templateParameterValue->value; + } + + if (is_string($templateParameterValue)) { + return $templateParameterValue; + } + } + + $arrayItemNode = $tagValueNodeOrAttribute->getSilentValue(); + if ($arrayItemNode instanceof ArrayItemNode) { + $arrayItemNodeValue = $arrayItemNode->value; + + if ($arrayItemNodeValue instanceof StringNode) { + $arrayItemNodeValue = $arrayItemNodeValue->value; + } + + if (is_string($arrayItemNodeValue)) { + return $arrayItemNodeValue; + } + } + + return null; + } + + foreach ($tagValueNodeOrAttribute->args as $attributeArg) { + if (! $this->isKeyEmptyOrMatch($attributeArg, $desiredKey)) { + continue; + } + + if (! $attributeArg->value instanceof String_) { + continue; + } + + return $attributeArg->value->value; + } + + return null; + } + + private function isKeyEmptyOrMatch(Arg $attributeArg, string $desiredKey): bool + { + if (! $attributeArg->name instanceof Identifier) { + return true; + } + + return $attributeArg->name->toString() === $desiredKey; + } +} diff --git a/src/NodeFactory/ThisRenderFactory.php b/src/NodeFactory/ThisRenderFactory.php index f421b2fff..858f47e6d 100644 --- a/src/NodeFactory/ThisRenderFactory.php +++ b/src/NodeFactory/ThisRenderFactory.php @@ -6,6 +6,7 @@ use PhpParser\Node\Arg; use PhpParser\Node\ArrayItem; +use PhpParser\Node\Attribute; use PhpParser\Node\Expr; use PhpParser\Node\Expr\Array_; use PhpParser\Node\Expr\FuncCall; @@ -23,6 +24,7 @@ use Rector\NodeTypeResolver\NodeTypeResolver; use Rector\PhpParser\Node\NodeFactory; use Rector\Symfony\Helper\TemplateGuesser; +use Rector\Symfony\NodeFactory\Annotations\AnnotationOrAttributeValueResolver; final readonly class ThisRenderFactory { @@ -31,20 +33,17 @@ public function __construct( private NodeFactory $nodeFactory, private NodeNameResolver $nodeNameResolver, private NodeTypeResolver $nodeTypeResolver, - private TemplateGuesser $templateGuesser + private TemplateGuesser $templateGuesser, + private AnnotationOrAttributeValueResolver $annotationOrAttributeValueResolver ) { } public function create( ?Return_ $return, - DoctrineAnnotationTagValueNode $templateDoctrineAnnotationTagValueNode, + DoctrineAnnotationTagValueNode | Attribute $templateTagValueNodeOrAttribute, ClassMethod $classMethod ): MethodCall { - $renderArguments = $this->resolveRenderArguments( - $return, - $templateDoctrineAnnotationTagValueNode, - $classMethod - ); + $renderArguments = $this->resolveRenderArguments($return, $templateTagValueNodeOrAttribute, $classMethod); return $this->nodeFactory->createMethodCall('this', 'render', $renderArguments); } @@ -54,14 +53,14 @@ public function create( */ private function resolveRenderArguments( ?Return_ $return, - DoctrineAnnotationTagValueNode $templateDoctrineAnnotationTagValueNode, + DoctrineAnnotationTagValueNode | Attribute $templateTagValueNodeOrAttribute, ClassMethod $classMethod ): array { - $templateNameString = $this->resolveTemplateName($classMethod, $templateDoctrineAnnotationTagValueNode); + $templateNameString = $this->resolveTemplateName($classMethod, $templateTagValueNodeOrAttribute); $arguments = [$templateNameString]; - $parametersExpr = $this->resolveParametersExpr($return, $templateDoctrineAnnotationTagValueNode); + $parametersExpr = $this->resolveParametersExpr($return, $templateTagValueNodeOrAttribute); if ($parametersExpr instanceof Expr) { $arguments[] = new Arg($parametersExpr); } @@ -71,9 +70,9 @@ private function resolveRenderArguments( private function resolveTemplateName( ClassMethod $classMethod, - DoctrineAnnotationTagValueNode $templateDoctrineAnnotationTagValueNode + DoctrineAnnotationTagValueNode | Attribute $templateTagValueNodeOrAttribute ): string { - $template = $this->resolveTemplate($templateDoctrineAnnotationTagValueNode); + $template = $this->annotationOrAttributeValueResolver->resolve($templateTagValueNodeOrAttribute, 'template'); if (is_string($template)) { return $template; } @@ -83,13 +82,22 @@ private function resolveTemplateName( private function resolveParametersExpr( ?Return_ $return, - DoctrineAnnotationTagValueNode $templateDoctrineAnnotationTagValueNode + DoctrineAnnotationTagValueNode | Attribute $templateTagValueNodeOrAttribute ): ?Expr { $vars = []; - $varsArrayItemNode = $templateDoctrineAnnotationTagValueNode->getValue('vars'); - if ($varsArrayItemNode instanceof ArrayItemNode && $varsArrayItemNode->value instanceof CurlyListNode) { - $vars = $varsArrayItemNode->value->getValues(); + if ($templateTagValueNodeOrAttribute instanceof DoctrineAnnotationTagValueNode) { + $varsArrayItemNode = $templateTagValueNodeOrAttribute->getValue('vars'); + if ($varsArrayItemNode instanceof ArrayItemNode && $varsArrayItemNode->value instanceof CurlyListNode) { + $vars = $varsArrayItemNode->value->getValues(); + } + } else { + foreach ($templateTagValueNodeOrAttribute->args as $arg) { + if ($arg->name !== null && $this->nodeNameResolver->isName($arg->name, 'vars')) { + // @todo might need more work + $vars = $arg->value; + } + } } if ($vars !== []) { @@ -144,35 +152,4 @@ private function resolveMethodCall(MethodCall $methodCall): ?Expr return null; } - - private function resolveTemplate(DoctrineAnnotationTagValueNode $doctrineAnnotationTagValueNode): string|null - { - $templateParameter = $doctrineAnnotationTagValueNode->getValue('template'); - if ($templateParameter instanceof ArrayItemNode) { - $templateParameterValue = $templateParameter->value; - - if ($templateParameterValue instanceof StringNode) { - $templateParameterValue = $templateParameterValue->value; - } - - if (is_string($templateParameterValue)) { - return $templateParameterValue; - } - } - - $arrayItemNode = $doctrineAnnotationTagValueNode->getSilentValue(); - if ($arrayItemNode instanceof ArrayItemNode) { - $arrayItemNodeValue = $arrayItemNode->value; - - if ($arrayItemNodeValue instanceof StringNode) { - $arrayItemNodeValue = $arrayItemNodeValue->value; - } - - if (is_string($arrayItemNodeValue)) { - return $arrayItemNodeValue; - } - } - - return null; - } } diff --git a/src/Set/SetProvider/Symfony3SetProvider.php b/src/Set/SetProvider/Symfony3SetProvider.php new file mode 100644 index 000000000..ad25987c9 --- /dev/null +++ b/src/Set/SetProvider/Symfony3SetProvider.php @@ -0,0 +1,203 @@ +withComposerBased(symfony: true) instead + * * @api */ final class SymfonySetList @@ -37,128 +39,133 @@ 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 */ - 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 */ - 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 */ - 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 */ - 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 */ - final public const SYMFONY_71 = __DIR__ . '/../../config/sets/symfony/symfony71.php'; + final public const SYMFONY_71 = __DIR__ . '/../../config/sets/symfony/symfony7/symfony71.php'; /** * @var string */ - final public const SYMFONY_72 = __DIR__ . '/../../config/sets/symfony/symfony72.php'; + final public const SYMFONY_72 = __DIR__ . '/../../config/sets/symfony/symfony7/symfony72.php'; + + /** + * @var string + */ + final public const SYMFONY_73 = __DIR__ . '/../../config/sets/symfony/symfony7/symfony73.php'; /** * @var string diff --git a/src/TypeAnalyzer/ContainerAwareAnalyzer.php b/src/TypeAnalyzer/ContainerAwareAnalyzer.php index 3d05e0947..174901346 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,9 +20,9 @@ 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('Symfony\Bundle\FrameworkBundle\Controller\ControllerTrait'), + new ObjectType(SymfonyClass::ABSTRACT_CONTROLLER), + new ObjectType(SymfonyClass::CONTROLLER), + new ObjectType(SymfonyClass::CONTROLLER_TRAIT), ]; } diff --git a/src/TypeAnalyzer/ControllerAnalyzer.php b/src/TypeAnalyzer/ControllerAnalyzer.php index a452e5ffa..4081c83b4 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->isSubclassOf('Symfony\Bundle\FrameworkBundle\Controller\Controller')) { + if ($classReflection->is(SymfonyClass::CONTROLLER)) { return true; } - return $classReflection->isSubclassOf('Symfony\Bundle\FrameworkBundle\Controller\AbstractController'); + return $classReflection->is(SymfonyClass::ABSTRACT_CONTROLLER); } private function isControllerClass(Class_ $class): bool diff --git a/src/ValueObjectFactory/ServiceMapFactory.php b/src/ValueObjectFactory/ServiceMapFactory.php index 76ea70968..c110bbbd6 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; diff --git a/stubs/Symfony/Bundle/FrameworkExtraBundle/Configuration/Security.php b/stubs/Symfony/Bundle/FrameworkExtraBundle/Configuration/Security.php index ebb0fddd1..ee3376d6a 100644 --- a/stubs/Symfony/Bundle/FrameworkExtraBundle/Configuration/Security.php +++ b/stubs/Symfony/Bundle/FrameworkExtraBundle/Configuration/Security.php @@ -2,6 +2,10 @@ namespace Sensio\Bundle\FrameworkExtraBundle\Configuration; +#[\Attribute] class Security { + public function __construct(string $expression) + { + } } diff --git a/stubs/Symfony/Bundle/FrameworkExtraBundle/Configuration/Template.php b/stubs/Symfony/Bundle/FrameworkExtraBundle/Configuration/Template.php new file mode 100644 index 000000000..ab3832d67 --- /dev/null +++ b/stubs/Symfony/Bundle/FrameworkExtraBundle/Configuration/Template.php @@ -0,0 +1,12 @@ + + * + * 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/stubs/Twig/Attribute/AsTwigFilter.php b/stubs/Twig/Attribute/AsTwigFilter.php new file mode 100644 index 000000000..ae012cc88 --- /dev/null +++ b/stubs/Twig/Attribute/AsTwigFilter.php @@ -0,0 +1,8 @@ +import(__DIR__ . '/../../../../../config/config.php'); - - $rectorConfig->rule(ArgumentValueResolverToValueResolverRector::class); -}; 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 000000000..e12998534 --- /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\Argument(name: 'argument', description: 'Argument description')] + string $argument, #[\Symfony\Component\Console\Attribute\Command\Option] + $option, OutputInterface $output): 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 000000000..a4da73922 --- /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 000000000..219b3986e --- /dev/null +++ b/tests/Set/Symfony73/config/symfony73.php @@ -0,0 +1,10 @@ +sets([SymfonySetList::SYMFONY_73]); +};