diff --git a/config/level/php/php73.yml b/config/level/php/php73.yml index 2f6c135722d..782598691a7 100644 --- a/config/level/php/php73.yml +++ b/config/level/php/php73.yml @@ -3,3 +3,4 @@ services: Rector\Php\Rector\FuncCall\ArrayKeyFirstLastRector: ~ Rector\Php\Rector\FuncCall\SensitiveDefineRector: ~ Rector\Php\Rector\ConstFetch\SensitiveConstantNameRector: ~ + Rector\Php\Rector\String\SensitiveHereNowDocRector: ~ diff --git a/packages/ContributorTools/src/Command/CreateRectorCommand.php b/packages/ContributorTools/src/Command/CreateRectorCommand.php index c4d7831f82e..1969cbf7150 100644 --- a/packages/ContributorTools/src/Command/CreateRectorCommand.php +++ b/packages/ContributorTools/src/Command/CreateRectorCommand.php @@ -115,9 +115,9 @@ final class CreateRectorCommand extends Command '_Category_' => $configuration->getCategory(), '_Description_' => $configuration->getDescription(), '_Name_' => $configuration->getName(), - '_CodeBefore_' => $configuration->getCodeBefore(), + '_CodeBefore_' => trim($configuration->getCodeBefore()) . PHP_EOL, '_CodeBeforeExample_' => $this->prepareCodeForDefinition($configuration->getCodeBefore()), - '_CodeAfter_' => $configuration->getCodeAfter(), + '_CodeAfter_' => trim($configuration->getCodeAfter()) . PHP_EOL, '_CodeAfterExample_' => $this->prepareCodeForDefinition($configuration->getCodeAfter()), ]; diff --git a/packages/Php/src/Rector/String/SensitiveHereNowDocRector.php b/packages/Php/src/Rector/String/SensitiveHereNowDocRector.php new file mode 100644 index 00000000000..87b156902e1 --- /dev/null +++ b/packages/Php/src/Rector/String/SensitiveHereNowDocRector.php @@ -0,0 +1,84 @@ +getAttribute('kind'), [String_::KIND_HEREDOC, String_::KIND_NOWDOC], true)) { + return null; + } + + // the doc label is not in the string → ok + $docLabel = $node->getAttribute('docLabel'); + + if (! Strings::contains($node->value, $docLabel)) { + return null; + } + + $node->setAttribute('docLabel', $this->uniquateDocLabel($node->value, $docLabel)); + + // invoke redraw + $node->setAttribute(Attribute::ORIGINAL_NODE, null); + + return $node; + } + + private function uniquateDocLabel(string $value, string $docLabel): string + { + $docLabel .= self::WRAP_SUFFIX; + $docLabelCounterTemplate = $docLabel . '_%d'; + + $i = 0; + while (Strings::contains($value, $docLabel)) { + $docLabel = sprintf($docLabelCounterTemplate, ++$i); + } + + return $docLabel; + } +} diff --git a/packages/Php/tests/Rector/String/SensitiveHereNowDocRector/Correct/correct.php.inc b/packages/Php/tests/Rector/String/SensitiveHereNowDocRector/Correct/correct.php.inc new file mode 100644 index 00000000000..7014a40d04c --- /dev/null +++ b/packages/Php/tests/Rector/String/SensitiveHereNowDocRector/Correct/correct.php.inc @@ -0,0 +1,16 @@ +doTestFileMatchesExpectedContent($wrong, $fixed); + } + + public function provideWrongToFixedFiles(): Iterator + { + yield [__DIR__ . '/Wrong/wrong.php.inc', __DIR__ . '/Correct/correct.php.inc']; + } + + protected function provideConfig(): string + { + return __DIR__ . '/config.yml'; + } +} diff --git a/packages/Php/tests/Rector/String/SensitiveHereNowDocRector/Wrong/wrong.php.inc b/packages/Php/tests/Rector/String/SensitiveHereNowDocRector/Wrong/wrong.php.inc new file mode 100644 index 00000000000..bd383dcb3e1 --- /dev/null +++ b/packages/Php/tests/Rector/String/SensitiveHereNowDocRector/Wrong/wrong.php.inc @@ -0,0 +1,16 @@ +