diff --git a/config/set/php85.php b/config/set/php85.php index a118ca891b9..33e526c3bf2 100644 --- a/config/set/php85.php +++ b/config/set/php85.php @@ -16,6 +16,7 @@ use Rector\Php85\Rector\FuncCall\ChrArgModuloRector; use Rector\Php85\Rector\FuncCall\OrdSingleByteRector; use Rector\Php85\Rector\FuncCall\RemoveFinfoBufferContextArgRector; +use Rector\Php85\Rector\ShellExec\ShellExecFunctionCallOverBackticksRector; use Rector\Php85\Rector\Switch_\ColonAfterSwitchCaseRector; use Rector\Removing\Rector\FuncCall\RemoveFuncCallArgRector; use Rector\Removing\ValueObject\RemoveFuncCallArg; @@ -43,6 +44,7 @@ SleepToSerializeRector::class, OrdSingleByteRector::class, WakeupToUnserializeRector::class, + ShellExecFunctionCallOverBackticksRector::class, ] ); diff --git a/rules-tests/Php85/Rector/ShellExec/ShellExecFunctionCallOverBackticksRector/Fixture/fixture.php.inc b/rules-tests/Php85/Rector/ShellExec/ShellExecFunctionCallOverBackticksRector/Fixture/fixture.php.inc new file mode 100644 index 00000000000..cbec9525569 --- /dev/null +++ b/rules-tests/Php85/Rector/ShellExec/ShellExecFunctionCallOverBackticksRector/Fixture/fixture.php.inc @@ -0,0 +1,29 @@ +$output"; + } +} + +?> +----- +$output"; + } +} + +?> diff --git a/rules-tests/Php85/Rector/ShellExec/ShellExecFunctionCallOverBackticksRector/Fixture/multi_variables.php.inc b/rules-tests/Php85/Rector/ShellExec/ShellExecFunctionCallOverBackticksRector/Fixture/multi_variables.php.inc new file mode 100644 index 00000000000..519a1971922 --- /dev/null +++ b/rules-tests/Php85/Rector/ShellExec/ShellExecFunctionCallOverBackticksRector/Fixture/multi_variables.php.inc @@ -0,0 +1,41 @@ + +----- + diff --git a/rules-tests/Php85/Rector/ShellExec/ShellExecFunctionCallOverBackticksRector/Fixture/skip_empty_backticks.php.inc b/rules-tests/Php85/Rector/ShellExec/ShellExecFunctionCallOverBackticksRector/Fixture/skip_empty_backticks.php.inc new file mode 100644 index 00000000000..16118ad59d7 --- /dev/null +++ b/rules-tests/Php85/Rector/ShellExec/ShellExecFunctionCallOverBackticksRector/Fixture/skip_empty_backticks.php.inc @@ -0,0 +1,11 @@ +$output"; + echo "
$output2
"; + } +} + +?> +----- +$output"; + echo "
$output2
"; + } +} + +?> diff --git a/rules-tests/Php85/Rector/ShellExec/ShellExecFunctionCallOverBackticksRector/ShellExecFunctionCallOverBackticksRectorTest.php b/rules-tests/Php85/Rector/ShellExec/ShellExecFunctionCallOverBackticksRector/ShellExecFunctionCallOverBackticksRectorTest.php new file mode 100644 index 00000000000..988002eff25 --- /dev/null +++ b/rules-tests/Php85/Rector/ShellExec/ShellExecFunctionCallOverBackticksRector/ShellExecFunctionCallOverBackticksRectorTest.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/Php85/Rector/ShellExec/ShellExecFunctionCallOverBackticksRector/config/configured_rule.php b/rules-tests/Php85/Rector/ShellExec/ShellExecFunctionCallOverBackticksRector/config/configured_rule.php new file mode 100644 index 00000000000..ba0bc248b6f --- /dev/null +++ b/rules-tests/Php85/Rector/ShellExec/ShellExecFunctionCallOverBackticksRector/config/configured_rule.php @@ -0,0 +1,13 @@ +rule(ShellExecFunctionCallOverBackticksRector::class); + + $rectorConfig->phpVersion(PhpVersion::PHP_85); +}; diff --git a/rules/Php85/Rector/ShellExec/ShellExecFunctionCallOverBackticksRector.php b/rules/Php85/Rector/ShellExec/ShellExecFunctionCallOverBackticksRector.php new file mode 100644 index 00000000000..ab63d8dc69a --- /dev/null +++ b/rules/Php85/Rector/ShellExec/ShellExecFunctionCallOverBackticksRector.php @@ -0,0 +1,85 @@ +$output"; +CODE_SAMPLE + , + <<<'CODE_SAMPLE' +$output = shell_exec('ls -al'); +echo "
$output
"; +CODE_SAMPLE + ), + ] + ); + } + + public function getNodeTypes(): array + { + return [ShellExec::class]; + } + + /** + * @param ShellExec $node + */ + public function refactor(Node $node): ?Node + { + if ($node->parts === []) { + return null; + } + + $exprs = []; + foreach ($node->parts as $part) { + if ($part instanceof InterpolatedStringPart) { + $exprs[] = new String_($part->value); + continue; + } + + // other parts are Expr (variables, function calls, etc.) + // keep them as-is so they are concatenated + $exprs[] = $part; + } + + // reduce to single concatenated expression + $argExpr = array_shift($exprs); + foreach ($exprs as $expr) { + $argExpr = new Concat($argExpr, $expr); + } + + // create single Arg and call shell_exec + return $this->nodeFactory->createFuncCall('shell_exec', [new Arg($argExpr)]); + } + + public function provideMinPhpVersion(): int + { + return PhpVersionFeature::DEPRECATE_BACKTICKS; + } +} diff --git a/rules/Renaming/Rector/PropertyFetch/RenamePropertyRector.php b/rules/Renaming/Rector/PropertyFetch/RenamePropertyRector.php index 1071f22eb86..c995057363a 100644 --- a/rules/Renaming/Rector/PropertyFetch/RenamePropertyRector.php +++ b/rules/Renaming/Rector/PropertyFetch/RenamePropertyRector.php @@ -111,8 +111,9 @@ private function renameProperty(ClassLike $classLike, RenameProperty $renameProp $property->props[0]->name = new VarLikeIdentifier($newProperty); } - private function refactorPropertyFetch(PropertyFetch|StaticPropertyFetch $propertyFetch): null|PropertyFetch|StaticPropertyFetch - { + private function refactorPropertyFetch( + PropertyFetch|StaticPropertyFetch $propertyFetch + ): null|PropertyFetch|StaticPropertyFetch { foreach ($this->renamedProperties as $renamedProperty) { $oldProperty = $renamedProperty->getOldProperty(); if (! $this->isName($propertyFetch, $oldProperty)) { diff --git a/src/ValueObject/PhpVersionFeature.php b/src/ValueObject/PhpVersionFeature.php index 6730eebcb47..20cf7566cef 100644 --- a/src/ValueObject/PhpVersionFeature.php +++ b/src/ValueObject/PhpVersionFeature.php @@ -834,4 +834,10 @@ final class PhpVersionFeature * @var int */ public const DEPRECATE_ORD_WITH_MULTIBYTE_STRING = PhpVersion::PHP_85; + + /** + * @see https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_backticks_as_an_alias_for_shell_exec + * @var int + */ + public const DEPRECATE_BACKTICKS = PhpVersion::PHP_85; }