Find this useful? Enter your email to receive occasional updates for securing PHP code.
Signing you up...
Thank you for signing up!
PHP Decode
<?php declare(strict_types=1); /* * This file is part of PHP CS Fixer. * * (c) Fabien..
Decoded Output download
<?php
declare(strict_types=1);
/*
* This file is part of PHP CS Fixer.
*
* (c) Fabien Potencier <[email protected]>
* Dariusz Rumiski <[email protected]>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace PhpCsFixer\Fixer\PhpUnit;
use PhpCsFixer\AbstractFixer;
use PhpCsFixer\Fixer\ConfigurableFixerInterface;
use PhpCsFixer\Fixer\ConfigurableFixerTrait;
use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver;
use PhpCsFixer\FixerConfiguration\FixerConfigurationResolverInterface;
use PhpCsFixer\FixerConfiguration\FixerOptionBuilder;
use PhpCsFixer\FixerDefinition\CodeSample;
use PhpCsFixer\FixerDefinition\FixerDefinition;
use PhpCsFixer\FixerDefinition\FixerDefinitionInterface;
use PhpCsFixer\Preg;
use PhpCsFixer\Tokenizer\Analyzer\ClassyAnalyzer;
use PhpCsFixer\Tokenizer\Token;
use PhpCsFixer\Tokenizer\Tokens;
/**
* @author Dariusz Rumiski <[email protected]>
*
* @implements ConfigurableFixerInterface<_AutogeneratedInputConfiguration, _AutogeneratedComputedConfiguration>
*
* @phpstan-type _AutogeneratedInputConfiguration array{
* target?: '4.8'|'5.7'|'6.0'|'newest'
* }
* @phpstan-type _AutogeneratedComputedConfiguration array{
* target: '4.8'|'5.7'|'6.0'|'newest'
* }
*/
final class PhpUnitNamespacedFixer extends AbstractFixer implements ConfigurableFixerInterface
{
/** @use ConfigurableFixerTrait<_AutogeneratedInputConfiguration, _AutogeneratedComputedConfiguration> */
use ConfigurableFixerTrait;
/**
* @var string
*/
private $originalClassRegEx;
/**
* Class Mappings.
*
* * [original classname => new classname] Some classes which match the
* original class regular expression do not have a same-compound name-
* space class and need a dedicated translation table. This trans-
* lation table is defined in @see configure.
*
* @var array<string, string> Class Mappings
*/
private $classMap;
public function getDefinition(): FixerDefinitionInterface
{
$codeSample = '<?php
final class MyTest extends \PHPUnit_Framework_TestCase
{
public function testSomething()
{
PHPUnit_Framework_Assert::assertTrue(true);
}
}
';
return new FixerDefinition(
'PHPUnit classes MUST be used in namespaced version, e.g. `\PHPUnit\Framework\TestCase` instead of `\PHPUnit_Framework_TestCase`.',
[
new CodeSample($codeSample),
new CodeSample($codeSample, ['target' => PhpUnitTargetVersion::VERSION_4_8]),
],
"PHPUnit v6 has finally fully switched to namespaces.\n"
."You could start preparing the upgrade by switching from non-namespaced TestCase to namespaced one.\n"
.'Forward compatibility layer (`\PHPUnit\Framework\TestCase` class) was backported to PHPUnit v4.8.35 and PHPUnit v5.4.0.'."\n"
.'Extended forward compatibility layer (`PHPUnit\Framework\Assert`, `PHPUnit\Framework\BaseTestListener`, `PHPUnit\Framework\TestListener` classes) was introduced in v5.7.0.'."\n",
'Risky when PHPUnit classes are overridden or not accessible, or when project has PHPUnit incompatibilities.'
);
}
public function isCandidate(Tokens $tokens): bool
{
return $tokens->isTokenKindFound(T_STRING);
}
public function isRisky(): bool
{
return true;
}
protected function configurePostNormalisation(): void
{
if (PhpUnitTargetVersion::fulfills($this->configuration['target'], PhpUnitTargetVersion::VERSION_6_0)) {
$this->originalClassRegEx = '/^PHPUnit_\w+$/i';
// @noinspection ClassConstantCanBeUsedInspection
$this->classMap = [
'PHPUnit_Extensions_PhptTestCase' => 'PHPUnit\Runner\PhptTestCase',
'PHPUnit_Framework_Constraint' => 'PHPUnit\Framework\Constraint\Constraint',
'PHPUnit_Framework_Constraint_StringMatches' => 'PHPUnit\Framework\Constraint\StringMatchesFormatDescription',
'PHPUnit_Framework_Constraint_JsonMatches_ErrorMessageProvider' => 'PHPUnit\Framework\Constraint\JsonMatchesErrorMessageProvider',
'PHPUnit_Framework_Constraint_PCREMatch' => 'PHPUnit\Framework\Constraint\RegularExpression',
'PHPUnit_Framework_Constraint_ExceptionMessageRegExp' => 'PHPUnit\Framework\Constraint\ExceptionMessageRegularExpression',
'PHPUnit_Framework_Constraint_And' => 'PHPUnit\Framework\Constraint\LogicalAnd',
'PHPUnit_Framework_Constraint_Or' => 'PHPUnit\Framework\Constraint\LogicalOr',
'PHPUnit_Framework_Constraint_Not' => 'PHPUnit\Framework\Constraint\LogicalNot',
'PHPUnit_Framework_Constraint_Xor' => 'PHPUnit\Framework\Constraint\LogicalXor',
'PHPUnit_Framework_Error' => 'PHPUnit\Framework\Error\Error',
'PHPUnit_Framework_TestSuite_DataProvider' => 'PHPUnit\Framework\DataProviderTestSuite',
'PHPUnit_Framework_MockObject_Invocation_Static' => 'PHPUnit\Framework\MockObject\Invocation\StaticInvocation',
'PHPUnit_Framework_MockObject_Invocation_Object' => 'PHPUnit\Framework\MockObject\Invocation\ObjectInvocation',
'PHPUnit_Framework_MockObject_Stub_Return' => 'PHPUnit\Framework\MockObject\Stub\ReturnStub',
'PHPUnit_Runner_Filter_Group_Exclude' => 'PHPUnit\Runner\Filter\ExcludeGroupFilterIterator',
'PHPUnit_Runner_Filter_Group_Include' => 'PHPUnit\Runner\Filter\IncludeGroupFilterIterator',
'PHPUnit_Runner_Filter_Test' => 'PHPUnit\Runner\Filter\NameFilterIterator',
'PHPUnit_Util_PHP' => 'PHPUnit\Util\PHP\AbstractPhpProcess',
'PHPUnit_Util_PHP_Default' => 'PHPUnit\Util\PHP\DefaultPhpProcess',
'PHPUnit_Util_PHP_Windows' => 'PHPUnit\Util\PHP\WindowsPhpProcess',
'PHPUnit_Util_Regex' => 'PHPUnit\Util\RegularExpression',
'PHPUnit_Util_TestDox_ResultPrinter_XML' => 'PHPUnit\Util\TestDox\XmlResultPrinter',
'PHPUnit_Util_TestDox_ResultPrinter_HTML' => 'PHPUnit\Util\TestDox\HtmlResultPrinter',
'PHPUnit_Util_TestDox_ResultPrinter_Text' => 'PHPUnit\Util\TestDox\TextResultPrinter',
'PHPUnit_Util_TestSuiteIterator' => 'PHPUnit\Framework\TestSuiteIterator',
'PHPUnit_Util_XML' => 'PHPUnit\Util\Xml',
];
} elseif (PhpUnitTargetVersion::fulfills($this->configuration['target'], PhpUnitTargetVersion::VERSION_5_7)) {
$this->originalClassRegEx = '/^PHPUnit_Framework_(TestCase|Assert|BaseTestListener|TestListener)+$/i';
$this->classMap = [];
} else {
$this->originalClassRegEx = '/^PHPUnit_Framework_TestCase$/i';
$this->classMap = [];
}
}
protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
{
$importedOriginalClassesMap = [];
$currIndex = 0;
while (true) {
$currIndex = $tokens->getNextTokenOfKind($currIndex, [[T_STRING]]);
if (null === $currIndex) {
break;
}
$prevIndex = $tokens->getPrevMeaningfulToken($currIndex);
if ($tokens[$prevIndex]->isGivenKind([T_CONST, T_DOUBLE_COLON])) {
continue;
}
$originalClass = $tokens[$currIndex]->getContent();
$allowedReplacementScenarios = (new ClassyAnalyzer())->isClassyInvocation($tokens, $currIndex)
|| $this->isImport($tokens, $currIndex);
if (!$allowedReplacementScenarios || !Preg::match($this->originalClassRegEx, $originalClass)) {
++$currIndex;
continue;
}
$substituteTokens = $this->generateReplacement($originalClass);
$tokens->clearAt($currIndex);
$tokens->insertAt(
$currIndex,
isset($importedOriginalClassesMap[$originalClass]) ? $substituteTokens[$substituteTokens->getSize() - 1] : $substituteTokens
);
$prevIndex = $tokens->getPrevMeaningfulToken($currIndex);
if ($tokens[$prevIndex]->isGivenKind(T_USE)) {
$importedOriginalClassesMap[$originalClass] = true;
} elseif ($tokens[$prevIndex]->isGivenKind(T_NS_SEPARATOR)) {
$prevIndex = $tokens->getPrevMeaningfulToken($prevIndex);
if ($tokens[$prevIndex]->isGivenKind(T_USE)) {
$importedOriginalClassesMap[$originalClass] = true;
}
}
}
}
protected function createConfigurationDefinition(): FixerConfigurationResolverInterface
{
return new FixerConfigurationResolver([
(new FixerOptionBuilder('target', 'Target version of PHPUnit.'))
->setAllowedTypes(['string'])
->setAllowedValues([PhpUnitTargetVersion::VERSION_4_8, PhpUnitTargetVersion::VERSION_5_7, PhpUnitTargetVersion::VERSION_6_0, PhpUnitTargetVersion::VERSION_NEWEST])
->setDefault(PhpUnitTargetVersion::VERSION_NEWEST)
->getOption(),
]);
}
private function generateReplacement(string $originalClassName): Tokens
{
$delimiter = '_';
$string = $originalClassName;
$map = array_change_key_case($this->classMap);
if (isset($map[strtolower($originalClassName)])) {
$delimiter = '\\';
$string = $map[strtolower($originalClassName)];
}
$parts = explode($delimiter, $string);
$tokensArray = [];
while ([] !== $parts) {
$tokensArray[] = new Token([T_STRING, array_shift($parts)]);
if ([] !== $parts) {
$tokensArray[] = new Token([T_NS_SEPARATOR, '\\']);
}
}
return Tokens::fromArray($tokensArray);
}
private function isImport(Tokens $tokens, int $currIndex): bool
{
$prevIndex = $tokens->getPrevMeaningfulToken($currIndex);
if ($tokens[$prevIndex]->isGivenKind([T_NS_SEPARATOR])) {
$prevIndex = $tokens->getPrevMeaningfulToken($prevIndex);
}
return $tokens[$prevIndex]->isGivenKind([T_USE]);
}
}
?>
Did this file decode correctly?
Original Code
<?php
declare(strict_types=1);
/*
* This file is part of PHP CS Fixer.
*
* (c) Fabien Potencier <[email protected]>
* Dariusz Rumiski <[email protected]>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace PhpCsFixer\Fixer\PhpUnit;
use PhpCsFixer\AbstractFixer;
use PhpCsFixer\Fixer\ConfigurableFixerInterface;
use PhpCsFixer\Fixer\ConfigurableFixerTrait;
use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver;
use PhpCsFixer\FixerConfiguration\FixerConfigurationResolverInterface;
use PhpCsFixer\FixerConfiguration\FixerOptionBuilder;
use PhpCsFixer\FixerDefinition\CodeSample;
use PhpCsFixer\FixerDefinition\FixerDefinition;
use PhpCsFixer\FixerDefinition\FixerDefinitionInterface;
use PhpCsFixer\Preg;
use PhpCsFixer\Tokenizer\Analyzer\ClassyAnalyzer;
use PhpCsFixer\Tokenizer\Token;
use PhpCsFixer\Tokenizer\Tokens;
/**
* @author Dariusz Rumiski <[email protected]>
*
* @implements ConfigurableFixerInterface<_AutogeneratedInputConfiguration, _AutogeneratedComputedConfiguration>
*
* @phpstan-type _AutogeneratedInputConfiguration array{
* target?: '4.8'|'5.7'|'6.0'|'newest'
* }
* @phpstan-type _AutogeneratedComputedConfiguration array{
* target: '4.8'|'5.7'|'6.0'|'newest'
* }
*/
final class PhpUnitNamespacedFixer extends AbstractFixer implements ConfigurableFixerInterface
{
/** @use ConfigurableFixerTrait<_AutogeneratedInputConfiguration, _AutogeneratedComputedConfiguration> */
use ConfigurableFixerTrait;
/**
* @var string
*/
private $originalClassRegEx;
/**
* Class Mappings.
*
* * [original classname => new classname] Some classes which match the
* original class regular expression do not have a same-compound name-
* space class and need a dedicated translation table. This trans-
* lation table is defined in @see configure.
*
* @var array<string, string> Class Mappings
*/
private $classMap;
public function getDefinition(): FixerDefinitionInterface
{
$codeSample = '<?php
final class MyTest extends \PHPUnit_Framework_TestCase
{
public function testSomething()
{
PHPUnit_Framework_Assert::assertTrue(true);
}
}
';
return new FixerDefinition(
'PHPUnit classes MUST be used in namespaced version, e.g. `\PHPUnit\Framework\TestCase` instead of `\PHPUnit_Framework_TestCase`.',
[
new CodeSample($codeSample),
new CodeSample($codeSample, ['target' => PhpUnitTargetVersion::VERSION_4_8]),
],
"PHPUnit v6 has finally fully switched to namespaces.\n"
."You could start preparing the upgrade by switching from non-namespaced TestCase to namespaced one.\n"
.'Forward compatibility layer (`\PHPUnit\Framework\TestCase` class) was backported to PHPUnit v4.8.35 and PHPUnit v5.4.0.'."\n"
.'Extended forward compatibility layer (`PHPUnit\Framework\Assert`, `PHPUnit\Framework\BaseTestListener`, `PHPUnit\Framework\TestListener` classes) was introduced in v5.7.0.'."\n",
'Risky when PHPUnit classes are overridden or not accessible, or when project has PHPUnit incompatibilities.'
);
}
public function isCandidate(Tokens $tokens): bool
{
return $tokens->isTokenKindFound(T_STRING);
}
public function isRisky(): bool
{
return true;
}
protected function configurePostNormalisation(): void
{
if (PhpUnitTargetVersion::fulfills($this->configuration['target'], PhpUnitTargetVersion::VERSION_6_0)) {
$this->originalClassRegEx = '/^PHPUnit_\w+$/i';
// @noinspection ClassConstantCanBeUsedInspection
$this->classMap = [
'PHPUnit_Extensions_PhptTestCase' => 'PHPUnit\Runner\PhptTestCase',
'PHPUnit_Framework_Constraint' => 'PHPUnit\Framework\Constraint\Constraint',
'PHPUnit_Framework_Constraint_StringMatches' => 'PHPUnit\Framework\Constraint\StringMatchesFormatDescription',
'PHPUnit_Framework_Constraint_JsonMatches_ErrorMessageProvider' => 'PHPUnit\Framework\Constraint\JsonMatchesErrorMessageProvider',
'PHPUnit_Framework_Constraint_PCREMatch' => 'PHPUnit\Framework\Constraint\RegularExpression',
'PHPUnit_Framework_Constraint_ExceptionMessageRegExp' => 'PHPUnit\Framework\Constraint\ExceptionMessageRegularExpression',
'PHPUnit_Framework_Constraint_And' => 'PHPUnit\Framework\Constraint\LogicalAnd',
'PHPUnit_Framework_Constraint_Or' => 'PHPUnit\Framework\Constraint\LogicalOr',
'PHPUnit_Framework_Constraint_Not' => 'PHPUnit\Framework\Constraint\LogicalNot',
'PHPUnit_Framework_Constraint_Xor' => 'PHPUnit\Framework\Constraint\LogicalXor',
'PHPUnit_Framework_Error' => 'PHPUnit\Framework\Error\Error',
'PHPUnit_Framework_TestSuite_DataProvider' => 'PHPUnit\Framework\DataProviderTestSuite',
'PHPUnit_Framework_MockObject_Invocation_Static' => 'PHPUnit\Framework\MockObject\Invocation\StaticInvocation',
'PHPUnit_Framework_MockObject_Invocation_Object' => 'PHPUnit\Framework\MockObject\Invocation\ObjectInvocation',
'PHPUnit_Framework_MockObject_Stub_Return' => 'PHPUnit\Framework\MockObject\Stub\ReturnStub',
'PHPUnit_Runner_Filter_Group_Exclude' => 'PHPUnit\Runner\Filter\ExcludeGroupFilterIterator',
'PHPUnit_Runner_Filter_Group_Include' => 'PHPUnit\Runner\Filter\IncludeGroupFilterIterator',
'PHPUnit_Runner_Filter_Test' => 'PHPUnit\Runner\Filter\NameFilterIterator',
'PHPUnit_Util_PHP' => 'PHPUnit\Util\PHP\AbstractPhpProcess',
'PHPUnit_Util_PHP_Default' => 'PHPUnit\Util\PHP\DefaultPhpProcess',
'PHPUnit_Util_PHP_Windows' => 'PHPUnit\Util\PHP\WindowsPhpProcess',
'PHPUnit_Util_Regex' => 'PHPUnit\Util\RegularExpression',
'PHPUnit_Util_TestDox_ResultPrinter_XML' => 'PHPUnit\Util\TestDox\XmlResultPrinter',
'PHPUnit_Util_TestDox_ResultPrinter_HTML' => 'PHPUnit\Util\TestDox\HtmlResultPrinter',
'PHPUnit_Util_TestDox_ResultPrinter_Text' => 'PHPUnit\Util\TestDox\TextResultPrinter',
'PHPUnit_Util_TestSuiteIterator' => 'PHPUnit\Framework\TestSuiteIterator',
'PHPUnit_Util_XML' => 'PHPUnit\Util\Xml',
];
} elseif (PhpUnitTargetVersion::fulfills($this->configuration['target'], PhpUnitTargetVersion::VERSION_5_7)) {
$this->originalClassRegEx = '/^PHPUnit_Framework_(TestCase|Assert|BaseTestListener|TestListener)+$/i';
$this->classMap = [];
} else {
$this->originalClassRegEx = '/^PHPUnit_Framework_TestCase$/i';
$this->classMap = [];
}
}
protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
{
$importedOriginalClassesMap = [];
$currIndex = 0;
while (true) {
$currIndex = $tokens->getNextTokenOfKind($currIndex, [[T_STRING]]);
if (null === $currIndex) {
break;
}
$prevIndex = $tokens->getPrevMeaningfulToken($currIndex);
if ($tokens[$prevIndex]->isGivenKind([T_CONST, T_DOUBLE_COLON])) {
continue;
}
$originalClass = $tokens[$currIndex]->getContent();
$allowedReplacementScenarios = (new ClassyAnalyzer())->isClassyInvocation($tokens, $currIndex)
|| $this->isImport($tokens, $currIndex);
if (!$allowedReplacementScenarios || !Preg::match($this->originalClassRegEx, $originalClass)) {
++$currIndex;
continue;
}
$substituteTokens = $this->generateReplacement($originalClass);
$tokens->clearAt($currIndex);
$tokens->insertAt(
$currIndex,
isset($importedOriginalClassesMap[$originalClass]) ? $substituteTokens[$substituteTokens->getSize() - 1] : $substituteTokens
);
$prevIndex = $tokens->getPrevMeaningfulToken($currIndex);
if ($tokens[$prevIndex]->isGivenKind(T_USE)) {
$importedOriginalClassesMap[$originalClass] = true;
} elseif ($tokens[$prevIndex]->isGivenKind(T_NS_SEPARATOR)) {
$prevIndex = $tokens->getPrevMeaningfulToken($prevIndex);
if ($tokens[$prevIndex]->isGivenKind(T_USE)) {
$importedOriginalClassesMap[$originalClass] = true;
}
}
}
}
protected function createConfigurationDefinition(): FixerConfigurationResolverInterface
{
return new FixerConfigurationResolver([
(new FixerOptionBuilder('target', 'Target version of PHPUnit.'))
->setAllowedTypes(['string'])
->setAllowedValues([PhpUnitTargetVersion::VERSION_4_8, PhpUnitTargetVersion::VERSION_5_7, PhpUnitTargetVersion::VERSION_6_0, PhpUnitTargetVersion::VERSION_NEWEST])
->setDefault(PhpUnitTargetVersion::VERSION_NEWEST)
->getOption(),
]);
}
private function generateReplacement(string $originalClassName): Tokens
{
$delimiter = '_';
$string = $originalClassName;
$map = array_change_key_case($this->classMap);
if (isset($map[strtolower($originalClassName)])) {
$delimiter = '\\';
$string = $map[strtolower($originalClassName)];
}
$parts = explode($delimiter, $string);
$tokensArray = [];
while ([] !== $parts) {
$tokensArray[] = new Token([T_STRING, array_shift($parts)]);
if ([] !== $parts) {
$tokensArray[] = new Token([T_NS_SEPARATOR, '\\']);
}
}
return Tokens::fromArray($tokensArray);
}
private function isImport(Tokens $tokens, int $currIndex): bool
{
$prevIndex = $tokens->getPrevMeaningfulToken($currIndex);
if ($tokens[$prevIndex]->isGivenKind([T_NS_SEPARATOR])) {
$prevIndex = $tokens->getPrevMeaningfulToken($prevIndex);
}
return $tokens[$prevIndex]->isGivenKind([T_USE]);
}
}
Function Calls
None |
Stats
MD5 | 819ef7b7700617d0dcb5566bf3d26ec2 |
Eval Count | 0 |
Decode Time | 109 ms |