diff --git a/config/set/php84.php b/config/set/php84.php index efbcd314594..4ca3c4179c7 100644 --- a/config/set/php84.php +++ b/config/set/php84.php @@ -4,8 +4,9 @@ declare (strict_types=1); namespace RectorPrefix202503; use Rector\Config\RectorConfig; +use Rector\Php84\Rector\FuncCall\AddEscapeArgumentRector; use Rector\Php84\Rector\FuncCall\RoundingModeEnumRector; use Rector\Php84\Rector\Param\ExplicitNullableParamTypeRector; return static function (RectorConfig $rectorConfig) : void { - $rectorConfig->rules([ExplicitNullableParamTypeRector::class, RoundingModeEnumRector::class]); + $rectorConfig->rules([ExplicitNullableParamTypeRector::class, RoundingModeEnumRector::class, AddEscapeArgumentRector::class]); }; diff --git a/rules/Php84/Rector/FuncCall/AddEscapeArgumentRector.php b/rules/Php84/Rector/FuncCall/AddEscapeArgumentRector.php new file mode 100644 index 00000000000..8cb09a2233f --- /dev/null +++ b/rules/Php84/Rector/FuncCall/AddEscapeArgumentRector.php @@ -0,0 +1,99 @@ +isFirstClassCallable()) { + return null; + } + if ($node instanceof FuncCall) { + if (!$this->isNames($node, ['fputcsv', 'fgetcsv', 'str_getcsv'])) { + return null; + } + if ($this->shouldSkipNamedArg($node)) { + return null; + } + $name = $this->getName($node); + if (\in_array($name, ['fputcsv', 'fgetcsv'], \true) && isset($node->getArgs()[4])) { + return null; + } + if ($name === 'str_getcsv' && isset($node->getArgs()[3])) { + return null; + } + $node->args[\count($node->getArgs())] = new Arg(new String_("\\"), \false, \false, [], new Identifier('escape')); + return $node; + } + if (!$this->isObjectType($node->var, new ObjectType('SplFileObject'))) { + return null; + } + $name = $this->getName($node->name); + if (!\in_array($name, ['setCsvControl', 'fputcsv', 'fgetcsv'], \true)) { + return null; + } + if ($this->shouldSkipNamedArg($node)) { + return null; + } + if (\in_array($name, ['setCsvControl', 'fgetcsv'], \true) && isset($node->getArgs()[2])) { + return null; + } + if ($name === 'fputcsv' && isset($node->getArgs()[3])) { + return null; + } + $node->args[\count($node->getArgs())] = new Arg(new String_("\\"), \false, \false, [], new Identifier('escape')); + return $node; + } + /** + * @param \PhpParser\Node\Expr\FuncCall|\PhpParser\Node\Expr\MethodCall $node + */ + private function shouldSkipNamedArg($node) : bool + { + foreach ($node->getArgs() as $arg) { + // already defined in named arg + if ($arg->name instanceof Identifier && $arg->name->toString() === 'escape') { + return \true; + } + } + return \false; + } + public function provideMinPhpVersion() : int + { + return PhpVersionFeature::REQUIRED_ESCAPE_PARAMETER; + } +} diff --git a/src/Application/VersionResolver.php b/src/Application/VersionResolver.php index 598b8523cda..e9138c6daf9 100644 --- a/src/Application/VersionResolver.php +++ b/src/Application/VersionResolver.php @@ -19,12 +19,12 @@ final class VersionResolver * @api * @var string */ - public const PACKAGE_VERSION = '61cb7b5042ebca12c18e1f2df22ecf3ba9d26bdb'; + public const PACKAGE_VERSION = '217026caf877c60eb7a7fd61b5b16d9a642f1662'; /** * @api * @var string */ - public const RELEASE_DATE = '2025-03-12 22:12:48'; + public const RELEASE_DATE = '2025-03-14 23:18:19'; /** * @var int */ diff --git a/src/ValueObject/PhpVersionFeature.php b/src/ValueObject/PhpVersionFeature.php index 6ea1c824545..11c34583858 100644 --- a/src/ValueObject/PhpVersionFeature.php +++ b/src/ValueObject/PhpVersionFeature.php @@ -560,6 +560,11 @@ final class PhpVersionFeature * @var int */ public const ROUNDING_MODES = \Rector\ValueObject\PhpVersion::PHP_84; + /** + * @see https://php.watch/versions/8.4/csv-functions-escape-parameter + * @var int + */ + public const REQUIRED_ESCAPE_PARAMETER = \Rector\ValueObject\PhpVersion::PHP_84; /** * @see https://www.php.net/manual/en/migration83.deprecated.php#migration83.deprecated.ldap * @var int diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php index 46f8eb8617c..b073ae5babe 100644 --- a/vendor/composer/autoload_classmap.php +++ b/vendor/composer/autoload_classmap.php @@ -2044,6 +2044,7 @@ return array( 'Rector\\Php83\\Rector\\ClassMethod\\AddOverrideAttributeToOverriddenMethodsRector' => $baseDir . '/rules/Php83/Rector/ClassMethod/AddOverrideAttributeToOverriddenMethodsRector.php', 'Rector\\Php83\\Rector\\FuncCall\\CombineHostPortLdapUriRector' => $baseDir . '/rules/Php83/Rector/FuncCall/CombineHostPortLdapUriRector.php', 'Rector\\Php83\\Rector\\FuncCall\\RemoveGetClassGetParentClassNoArgsRector' => $baseDir . '/rules/Php83/Rector/FuncCall/RemoveGetClassGetParentClassNoArgsRector.php', + 'Rector\\Php84\\Rector\\FuncCall\\AddEscapeArgumentRector' => $baseDir . '/rules/Php84/Rector/FuncCall/AddEscapeArgumentRector.php', 'Rector\\Php84\\Rector\\FuncCall\\RoundingModeEnumRector' => $baseDir . '/rules/Php84/Rector/FuncCall/RoundingModeEnumRector.php', 'Rector\\Php84\\Rector\\Param\\ExplicitNullableParamTypeRector' => $baseDir . '/rules/Php84/Rector/Param/ExplicitNullableParamTypeRector.php', 'Rector\\PhpAttribute\\AnnotationToAttributeMapper' => $baseDir . '/src/PhpAttribute/AnnotationToAttributeMapper.php', diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index 5c6a23f6af2..5622756ba70 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -2263,6 +2263,7 @@ class ComposerStaticInit82c6a73a31b80aa1be38da0fc895c7e2 'Rector\\Php83\\Rector\\ClassMethod\\AddOverrideAttributeToOverriddenMethodsRector' => __DIR__ . '/../..' . '/rules/Php83/Rector/ClassMethod/AddOverrideAttributeToOverriddenMethodsRector.php', 'Rector\\Php83\\Rector\\FuncCall\\CombineHostPortLdapUriRector' => __DIR__ . '/../..' . '/rules/Php83/Rector/FuncCall/CombineHostPortLdapUriRector.php', 'Rector\\Php83\\Rector\\FuncCall\\RemoveGetClassGetParentClassNoArgsRector' => __DIR__ . '/../..' . '/rules/Php83/Rector/FuncCall/RemoveGetClassGetParentClassNoArgsRector.php', + 'Rector\\Php84\\Rector\\FuncCall\\AddEscapeArgumentRector' => __DIR__ . '/../..' . '/rules/Php84/Rector/FuncCall/AddEscapeArgumentRector.php', 'Rector\\Php84\\Rector\\FuncCall\\RoundingModeEnumRector' => __DIR__ . '/../..' . '/rules/Php84/Rector/FuncCall/RoundingModeEnumRector.php', 'Rector\\Php84\\Rector\\Param\\ExplicitNullableParamTypeRector' => __DIR__ . '/../..' . '/rules/Php84/Rector/Param/ExplicitNullableParamTypeRector.php', 'Rector\\PhpAttribute\\AnnotationToAttributeMapper' => __DIR__ . '/../..' . '/src/PhpAttribute/AnnotationToAttributeMapper.php',