mirror of
https://github.com/rectorphp/rector.git
synced 2025-02-24 11:44:14 +01:00
Merge pull request #103 from RectorPHP/umpirsky-upgrade-fixer
Umpirsky upgrade fixer - Symfony 3.0
This commit is contained in:
commit
09762bd552
14
README.md
14
README.md
@ -144,6 +144,20 @@ You can:
|
||||
'renderFormBegin': ['Nette\Bridges\FormsLatte\Runtime', 'renderFormBegin']
|
||||
```
|
||||
|
||||
- **change class constant name**
|
||||
|
||||
```yml
|
||||
# symfony30.yml
|
||||
rectors:
|
||||
Rector\Rector\Dynamic\ClassConstantReplacerRector:
|
||||
# class:
|
||||
# OLD_CONSTANT: NEW_CONSTANT
|
||||
'Symfony\Component\Form\FormEvents':
|
||||
'PRE_BIND': 'PRE_SUBMIT'
|
||||
'BIND': 'SUBMIT'
|
||||
'POST_BIND': 'POST_SUBMIT'
|
||||
```
|
||||
|
||||
- or **replace underscore naming `_` with namespaces `\`**
|
||||
|
||||
```yml
|
||||
|
40
packages/NodeTypeResolver/src/NodeVisitor/MethodResolver.php
Normal file
40
packages/NodeTypeResolver/src/NodeVisitor/MethodResolver.php
Normal file
@ -0,0 +1,40 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\NodeTypeResolver\NodeVisitor;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use PhpParser\NodeVisitorAbstract;
|
||||
use Rector\Node\Attribute;
|
||||
|
||||
/**
|
||||
* Add attribute 'methodName' with current class name.
|
||||
*/
|
||||
final class MethodResolver extends NodeVisitorAbstract
|
||||
{
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
private $methodName;
|
||||
|
||||
/**
|
||||
* @param Node[] $nodes
|
||||
*/
|
||||
public function beforeTraverse(array $nodes): void
|
||||
{
|
||||
$this->methodName = null;
|
||||
}
|
||||
|
||||
public function enterNode(Node $node): void
|
||||
{
|
||||
if ($node instanceof ClassMethod) {
|
||||
$this->methodName = $node->name->toString();
|
||||
}
|
||||
|
||||
if ($this->methodName === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$node->setAttribute(Attribute::METHOD_NAME, $this->methodName);
|
||||
}
|
||||
}
|
@ -49,6 +49,11 @@ final class Attribute
|
||||
*/
|
||||
public const CLASS_NAME = 'className';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public const METHOD_NAME = 'methodName';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
|
@ -18,6 +18,7 @@ use PhpParser\Node\Expr\PropertyFetch;
|
||||
use PhpParser\Node\Expr\Variable;
|
||||
use PhpParser\Node\Identifier;
|
||||
use PhpParser\Node\Name\FullyQualified;
|
||||
use PhpParser\Node\Param;
|
||||
use PhpParser\Node\Scalar\LNumber;
|
||||
use PhpParser\Node\Scalar\String_;
|
||||
use PhpParser\Node\Stmt\Declare_;
|
||||
@ -105,7 +106,7 @@ final class NodeFactory
|
||||
*/
|
||||
public function createMethodCall(string $variableName, string $methodName): MethodCall
|
||||
{
|
||||
$variableNode = new Variable($variableName);
|
||||
$variableNode = $this->createVariable($variableName);
|
||||
|
||||
return new MethodCall($variableNode, $methodName);
|
||||
}
|
||||
@ -283,4 +284,18 @@ final class NodeFactory
|
||||
{
|
||||
return new PropertyFetch($propertyFetchNode->var, $propertyFetchNode->name);
|
||||
}
|
||||
|
||||
public function createParam(string $name, string $type): Param
|
||||
{
|
||||
return new Param(
|
||||
$this->createVariable($name),
|
||||
null,
|
||||
$type
|
||||
);
|
||||
}
|
||||
|
||||
public function createVariable(string $name): Variable
|
||||
{
|
||||
return new Variable($name);
|
||||
}
|
||||
}
|
||||
|
@ -12,41 +12,60 @@ final class ClassConstAnalyzer
|
||||
/**
|
||||
* @param string[] $constantNames
|
||||
*/
|
||||
public function isClassConstFetchOfClassAndConstantNames(Node $node, string $class, array $constantNames): bool
|
||||
public function isTypeAndNames(Node $node, string $type, array $constantNames): bool
|
||||
{
|
||||
if (! $this->isType($node, $type)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/** @var ClassConstFetch $node */
|
||||
return $this->isNames($node, $constantNames);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $types
|
||||
*/
|
||||
public function matchTypes(Node $node, array $types): ?string
|
||||
{
|
||||
if (! $node instanceof ClassConstFetch) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$class = $this->resolveType($node);
|
||||
|
||||
return in_array($class, $types, true) ? $class : null;
|
||||
}
|
||||
|
||||
private function isType(Node $node, string $type): bool
|
||||
{
|
||||
if (! $node instanceof ClassConstFetch) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! $this->isClassName($node, $class)) {
|
||||
return false;
|
||||
}
|
||||
$nodeClass = $this->resolveType($node);
|
||||
|
||||
return $this->isConstantName($node, $constantNames);
|
||||
}
|
||||
|
||||
private function isClassName(ClassConstFetch $classConstFetchNode, string $className): bool
|
||||
{
|
||||
/** @var FullyQualified $className */
|
||||
$classFullyQualifiedName = $classConstFetchNode->class->getAttribute(Attribute::RESOLVED_NAME);
|
||||
|
||||
if ($classFullyQualifiedName instanceof FullyQualified) {
|
||||
return $classFullyQualifiedName->toString() === $className;
|
||||
}
|
||||
|
||||
// e.g. "$form::FILLED"
|
||||
$nodeClassName = $classConstFetchNode->class->getAttribute(Attribute::CLASS_NAME);
|
||||
|
||||
return $nodeClassName === $className;
|
||||
return $nodeClass === $type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $constantNames
|
||||
* @param string[] $names
|
||||
*/
|
||||
private function isConstantName(ClassConstFetch $node, array $constantNames): bool
|
||||
private function isNames(ClassConstFetch $node, array $names): bool
|
||||
{
|
||||
$nodeConstantName = $node->name->name;
|
||||
|
||||
return in_array($nodeConstantName, $constantNames, true);
|
||||
return in_array($nodeConstantName, $names, true);
|
||||
}
|
||||
|
||||
private function resolveType(ClassConstFetch $classConstFetchNode): string
|
||||
{
|
||||
$classFullyQualifiedName = $classConstFetchNode->class->getAttribute(Attribute::RESOLVED_NAME);
|
||||
|
||||
if ($classFullyQualifiedName instanceof FullyQualified) {
|
||||
return $classFullyQualifiedName->toString();
|
||||
}
|
||||
|
||||
// e.g. "$form::FILLED"
|
||||
return (string) $classConstFetchNode->class->getAttribute(Attribute::CLASS_NAME);
|
||||
}
|
||||
}
|
||||
|
48
src/NodeAnalyzer/Contrib/ControllerMethodAnalyzer.php
Normal file
48
src/NodeAnalyzer/Contrib/ControllerMethodAnalyzer.php
Normal file
@ -0,0 +1,48 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\NodeAnalyzer\Contrib;
|
||||
|
||||
use Nette\Utils\Strings;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use PhpParser\PrettyPrinter\Standard;
|
||||
use Rector\Node\Attribute;
|
||||
|
||||
final class ControllerMethodAnalyzer
|
||||
{
|
||||
/**
|
||||
* @var Standard
|
||||
*/
|
||||
private $standardPrinter;
|
||||
|
||||
public function __construct(Standard $standardPrinter)
|
||||
{
|
||||
$this->standardPrinter = $standardPrinter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect if is <some>Action() in Controller
|
||||
*/
|
||||
public function isAction(Node $node): bool
|
||||
{
|
||||
if (! $node instanceof ClassMethod) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$parentClassName = $node->getAttribute(Attribute::PARENT_CLASS_NAME);
|
||||
$controllerClass = 'Symfony\Bundle\FrameworkBundle\Controller\Controller';
|
||||
|
||||
if ($parentClassName !== $controllerClass) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Strings::endsWith($node->name->toString(), 'Action');
|
||||
}
|
||||
|
||||
public function doesNodeContain(ClassMethod $classMethodNode, string $part): bool
|
||||
{
|
||||
$methodInString = $this->standardPrinter->prettyPrint([$classMethodNode]);
|
||||
|
||||
return Strings::contains($methodInString, $part);
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\NodeAnalyzer;
|
||||
namespace Rector\NodeAnalyzer\Contrib;
|
||||
|
||||
use PhpParser\Node\Expr\MethodCall;
|
||||
use PhpParser\Node\Expr\Variable;
|
@ -48,7 +48,7 @@ final class FormNegativeRulesRector extends AbstractRector
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->classConstAnalyzer->isClassConstFetchOfClassAndConstantNames(
|
||||
return $this->classConstAnalyzer->isTypeAndNames(
|
||||
$node->expr,
|
||||
self::FORM_CLASS,
|
||||
self::RULE_NAMES
|
||||
|
@ -11,7 +11,7 @@ use Rector\Contract\Bridge\ServiceTypeForNameProviderInterface;
|
||||
use Rector\Naming\PropertyNaming;
|
||||
use Rector\Node\Attribute;
|
||||
use Rector\Node\NodeFactory;
|
||||
use Rector\NodeAnalyzer\SymfonyContainerCallsAnalyzer;
|
||||
use Rector\NodeAnalyzer\Contrib\SymfonyContainerCallsAnalyzer;
|
||||
use Rector\Rector\AbstractRector;
|
||||
|
||||
/**
|
||||
|
@ -47,7 +47,7 @@ final class ConsoleExceptionToErrorEventConstantRector extends AbstractRector
|
||||
|
||||
public function isCandidate(Node $node): bool
|
||||
{
|
||||
if ($this->classConstAnalyzer->isClassConstFetchOfClassAndConstantNames(
|
||||
if ($this->classConstAnalyzer->isTypeAndNames(
|
||||
$node,
|
||||
self::CONSOLE_EVENTS_CLASS,
|
||||
['EXCEPTION']
|
||||
|
97
src/Rector/Contrib/Symfony/Form/FormTypeGetParentRector.php
Normal file
97
src/Rector/Contrib/Symfony/Form/FormTypeGetParentRector.php
Normal file
@ -0,0 +1,97 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\Rector\Contrib\Symfony\Form;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Scalar\String_;
|
||||
use Rector\Node\Attribute;
|
||||
use Rector\Node\NodeFactory;
|
||||
use Rector\Rector\AbstractRector;
|
||||
|
||||
/**
|
||||
* Converts all:
|
||||
* - getParent() {
|
||||
* return 'some_string';
|
||||
* }
|
||||
*
|
||||
* into:
|
||||
* - getParent() {
|
||||
* return CollectionType::class;
|
||||
* }
|
||||
*/
|
||||
final class FormTypeGetParentRector extends AbstractRector
|
||||
{
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
private $nameToClassMap = [
|
||||
'birthday' => 'Symfony\Component\Form\Extension\Core\Type\BirthdayType',
|
||||
'checkbox' => 'Symfony\Component\Form\Extension\Core\Type\CheckboxType',
|
||||
'collection' => 'Symfony\Component\Form\Extension\Core\Type\CollectionType',
|
||||
'country' => 'Symfony\Component\Form\Extension\Core\Type\CountryType',
|
||||
'currency' => 'Symfony\Component\Form\Extension\Core\Type\CurrencyType',
|
||||
'date' => 'Symfony\Component\Form\Extension\Core\Type\DateType',
|
||||
'datetime' => 'Symfony\Component\Form\Extension\Core\Type\DatetimeType',
|
||||
'email' => 'Symfony\Component\Form\Extension\Core\Type\EmailType',
|
||||
'file' => 'Symfony\Component\Form\Extension\Core\Type\FileType',
|
||||
'hidden' => 'Symfony\Component\Form\Extension\Core\Type\HiddenType',
|
||||
'integer' => 'Symfony\Component\Form\Extension\Core\Type\IntegerType',
|
||||
'language' => 'Symfony\Component\Form\Extension\Core\Type\LanguageType',
|
||||
'locale' => 'Symfony\Component\Form\Extension\Core\Type\LocaleType',
|
||||
'money' => 'Symfony\Component\Form\Extension\Core\Type\MoneyType',
|
||||
'number' => 'Symfony\Component\Form\Extension\Core\Type\NumberType',
|
||||
'password' => 'Symfony\Component\Form\Extension\Core\Type\PasswordType',
|
||||
'percent' => 'Symfony\Component\Form\Extension\Core\Type\PercentType',
|
||||
'radio' => 'Symfony\Component\Form\Extension\Core\Type\RadioType',
|
||||
'range' => 'Symfony\Component\Form\Extension\Core\Type\RangeType',
|
||||
'repeated' => 'Symfony\Component\Form\Extension\Core\Type\RepeatedType',
|
||||
'search' => 'Symfony\Component\Form\Extension\Core\Type\SearchType',
|
||||
'textarea' => 'Symfony\Component\Form\Extension\Core\Type\TextareaType',
|
||||
'text' => 'Symfony\Component\Form\Extension\Core\Type\TextType',
|
||||
'time' => 'Symfony\Component\Form\Extension\Core\Type\TimeType',
|
||||
'timezone' => 'Symfony\Component\Form\Extension\Core\Type\TimezoneType',
|
||||
'url' => 'Symfony\Component\Form\Extension\Core\Type\UrlType',
|
||||
'button' => 'Symfony\Component\Form\Extension\Core\Type\ButtonType',
|
||||
'submit' => 'Symfony\Component\Form\Extension\Core\Type\SubmitType',
|
||||
'reset' => 'Symfony\Component\Form\Extension\Core\Type\ResetType',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var NodeFactory
|
||||
*/
|
||||
private $nodeFactory;
|
||||
|
||||
public function __construct(NodeFactory $nodeFactory)
|
||||
{
|
||||
$this->nodeFactory = $nodeFactory;
|
||||
}
|
||||
|
||||
public function isCandidate(Node $node): bool
|
||||
{
|
||||
if (! $node instanceof String_ || ! isset($this->nameToClassMap[$node->value])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$parentClassName = $node->getAttribute(Attribute::PARENT_CLASS_NAME);
|
||||
if ($parentClassName !== 'Symfony\Component\Form\AbstractType') {
|
||||
return false;
|
||||
}
|
||||
|
||||
$methodName = $node->getAttribute(Attribute::METHOD_NAME);
|
||||
if ($methodName !== 'getParent') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param String_ $stringNode
|
||||
*/
|
||||
public function refactor(Node $stringNode): ?Node
|
||||
{
|
||||
$class = $this->nameToClassMap[$stringNode->value];
|
||||
|
||||
return $this->nodeFactory->createClassConstantReference($class);
|
||||
}
|
||||
}
|
61
src/Rector/Contrib/Symfony/Form/OptionNameRector.php
Normal file
61
src/Rector/Contrib/Symfony/Form/OptionNameRector.php
Normal file
@ -0,0 +1,61 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\Rector\Contrib\Symfony\Form;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\ArrayItem;
|
||||
use PhpParser\Node\Expr\MethodCall;
|
||||
use PhpParser\Node\Scalar\String_;
|
||||
use Rector\Node\Attribute;
|
||||
use Rector\Rector\AbstractRector;
|
||||
|
||||
/**
|
||||
* Converts all:
|
||||
* - $builder->add('...', ['precision' => '...', 'virtual' => '...'];
|
||||
*
|
||||
*
|
||||
* into:
|
||||
* - $builder->add('...', ['scale' => '...', 'inherit_data' => '...'];
|
||||
*/
|
||||
final class OptionNameRector extends AbstractRector
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $oldToNewOption = [
|
||||
'precision' => 'scale',
|
||||
'virtual' => 'inherit_data',
|
||||
];
|
||||
|
||||
public function isCandidate(Node $node): bool
|
||||
{
|
||||
if (! $node instanceof String_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! isset($this->oldToNewOption[$node->value])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$arrayItemParentNode = $node->getAttribute(Attribute::PARENT_NODE);
|
||||
if (! $arrayItemParentNode instanceof ArrayItem) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$arrayParentNode = $arrayItemParentNode->getAttribute(Attribute::PARENT_NODE);
|
||||
$argParentNode = $arrayParentNode->getAttribute(Attribute::PARENT_NODE);
|
||||
|
||||
/** @var MethodCall $methodCallNode */
|
||||
$methodCallNode = $argParentNode->getAttribute(Attribute::PARENT_NODE);
|
||||
|
||||
return $methodCallNode->name->toString() === 'add';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param MethodCall $node
|
||||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
return new String_($this->oldToNewOption[$node->value]);
|
||||
}
|
||||
}
|
@ -69,11 +69,11 @@ final class StringFormTypeToClassRector extends AbstractRector
|
||||
}
|
||||
|
||||
/**
|
||||
* @param String_ $node
|
||||
* @param String_ $stringNode
|
||||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
public function refactor(Node $stringNode): ?Node
|
||||
{
|
||||
$class = $this->nameToClassMap[$node->value];
|
||||
$class = $this->nameToClassMap[$stringNode->value];
|
||||
|
||||
return $this->nodeFactory->createClassConstantReference($class);
|
||||
}
|
||||
|
110
src/Rector/Contrib/Symfony/HttpKernel/GetRequestRector.php
Normal file
110
src/Rector/Contrib/Symfony/HttpKernel/GetRequestRector.php
Normal file
@ -0,0 +1,110 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\Rector\Contrib\Symfony\HttpKernel;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\MethodCall;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use Rector\Node\Attribute;
|
||||
use Rector\Node\NodeFactory;
|
||||
use Rector\NodeAnalyzer\Contrib\ControllerMethodAnalyzer;
|
||||
use Rector\NodeAnalyzer\MethodCallAnalyzer;
|
||||
use Rector\Rector\AbstractRector;
|
||||
|
||||
/**
|
||||
* Converts all:
|
||||
* public action()
|
||||
* {
|
||||
* $this->getRequest()->...();
|
||||
*
|
||||
* into:
|
||||
* public action(Request $request)
|
||||
* {
|
||||
* $request->...();
|
||||
* }
|
||||
*/
|
||||
final class GetRequestRector extends AbstractRector
|
||||
{
|
||||
/**
|
||||
* @var ControllerMethodAnalyzer
|
||||
*/
|
||||
private $controllerMethodAnalyzer;
|
||||
|
||||
/**
|
||||
* @var NodeFactory
|
||||
*/
|
||||
private $nodeFactory;
|
||||
|
||||
/**
|
||||
* @var MethodCallAnalyzer
|
||||
*/
|
||||
private $methodCallAnalyzer;
|
||||
|
||||
public function __construct(
|
||||
ControllerMethodAnalyzer $controllerMethodAnalyzer,
|
||||
MethodCallAnalyzer $methodCallAnalyzer,
|
||||
NodeFactory $nodeFactory
|
||||
) {
|
||||
$this->controllerMethodAnalyzer = $controllerMethodAnalyzer;
|
||||
$this->nodeFactory = $nodeFactory;
|
||||
$this->methodCallAnalyzer = $methodCallAnalyzer;
|
||||
}
|
||||
|
||||
public function isCandidate(Node $node): bool
|
||||
{
|
||||
if ($this->isActionWithGetRequestInBody($node)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($this->isGetRequestInAction($node)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ClassMethod|MethodCall $classMethodOrMethodCallNode
|
||||
*/
|
||||
public function refactor(Node $classMethodOrMethodCallNode): ?Node
|
||||
{
|
||||
if ($classMethodOrMethodCallNode instanceof ClassMethod) {
|
||||
$requestParam = $this->nodeFactory->createParam('request', 'Symfony\Component\HttpFoundation\Request');
|
||||
|
||||
$classMethodOrMethodCallNode->params[] = $requestParam;
|
||||
|
||||
return $classMethodOrMethodCallNode;
|
||||
}
|
||||
|
||||
return $this->nodeFactory->createVariable('request');
|
||||
}
|
||||
|
||||
private function isActionWithGetRequestInBody(Node $node): bool
|
||||
{
|
||||
if (! $this->controllerMethodAnalyzer->isAction($node)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/** @var ClassMethod $node */
|
||||
if (! $this->controllerMethodAnalyzer->doesNodeContain($node, '$this->getRequest()')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function isGetRequestInAction(Node $node): bool
|
||||
{
|
||||
if (! $this->methodCallAnalyzer->isMethod($node, 'getRequest')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$scopeNode = $node->getAttribute(Attribute::SCOPE_NODE);
|
||||
|
||||
if (! $this->controllerMethodAnalyzer->isAction($scopeNode)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@ -9,7 +9,7 @@ use Rector\Contract\Bridge\ServiceTypeForNameProviderInterface;
|
||||
use Rector\Naming\PropertyNaming;
|
||||
use Rector\Node\Attribute;
|
||||
use Rector\Node\NodeFactory;
|
||||
use Rector\NodeAnalyzer\SymfonyContainerCallsAnalyzer;
|
||||
use Rector\NodeAnalyzer\Contrib\SymfonyContainerCallsAnalyzer;
|
||||
use Rector\Rector\AbstractRector;
|
||||
|
||||
/**
|
||||
|
83
src/Rector/Dynamic/ClassConstantReplacerRector.php
Normal file
83
src/Rector/Dynamic/ClassConstantReplacerRector.php
Normal file
@ -0,0 +1,83 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\Rector\Dynamic;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\ClassConstFetch;
|
||||
use PhpParser\Node\Identifier;
|
||||
use Rector\NodeAnalyzer\ClassConstAnalyzer;
|
||||
use Rector\Rector\AbstractRector;
|
||||
|
||||
final class ClassConstantReplacerRector extends AbstractRector
|
||||
{
|
||||
/**
|
||||
* class => [
|
||||
* OLD_CONSTANT => NEW_CONSTANT
|
||||
* ]
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
private $oldToNewConstantsByClass = [];
|
||||
|
||||
/**
|
||||
* @var ClassConstAnalyzer
|
||||
*/
|
||||
private $classConstAnalyzer;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $activeType;
|
||||
|
||||
/**
|
||||
* @param string[] $oldToNewConstantsByClass
|
||||
*/
|
||||
public function __construct(array $oldToNewConstantsByClass, ClassConstAnalyzer $classConstAnalyzer)
|
||||
{
|
||||
$this->oldToNewConstantsByClass = $oldToNewConstantsByClass;
|
||||
$this->classConstAnalyzer = $classConstAnalyzer;
|
||||
}
|
||||
|
||||
public function isCandidate(Node $node): bool
|
||||
{
|
||||
$this->activeType = null;
|
||||
|
||||
foreach ($this->oldToNewConstantsByClass as $type => $oldToNewConstants) {
|
||||
$matchedType = $this->classConstAnalyzer->matchTypes($node, $this->getTypes());
|
||||
if ($matchedType) {
|
||||
$this->activeType = $matchedType;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ClassConstFetch $classConstFetchNode
|
||||
*/
|
||||
public function refactor(Node $classConstFetchNode): ?Node
|
||||
{
|
||||
$configuration = $this->oldToNewConstantsByClass[$this->activeType];
|
||||
$constantName = $classConstFetchNode->name->toString();
|
||||
|
||||
if (! isset($configuration[$constantName])) {
|
||||
return $classConstFetchNode;
|
||||
}
|
||||
|
||||
$newConstantName = $configuration[$constantName];
|
||||
|
||||
$classConstFetchNode->name = new Identifier($newConstantName);
|
||||
|
||||
return $classConstFetchNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
private function getTypes(): array
|
||||
{
|
||||
return array_keys($this->oldToNewConstantsByClass);
|
||||
}
|
||||
}
|
27
src/config/level/symfony/symfony30.yml
Normal file
27
src/config/level/symfony/symfony30.yml
Normal file
@ -0,0 +1,27 @@
|
||||
rectors:
|
||||
Rector\Rector\Contrib\Symfony\HttpKernel\GetRequestRector: ~
|
||||
Rector\Rector\Contrib\Symfony\Form\FormTypeGetParentRector: ~
|
||||
Rector\Rector\Contrib\Symfony\Form\OptionNameRector: ~
|
||||
|
||||
Rector\Rector\Dynamic\ClassConstantReplacerRector:
|
||||
# form
|
||||
'Symfony\Component\Form\FormEvents':
|
||||
'PRE_BIND': 'PRE_SUBMIT'
|
||||
'BIND': 'SUBMIT'
|
||||
'POST_BIND': 'POST_SUBMIT'
|
||||
|
||||
Rector\Rector\Dynamic\MethodNameReplacerRector:
|
||||
# form
|
||||
'Symfony\Component\Form\AbstractType':
|
||||
'setDefaultOptions': 'configureOptions'
|
||||
'Symfony\Component\Form\FormTypeInterface':
|
||||
'getName': 'getBlockPrefix'
|
||||
# property access
|
||||
Symfony\Component\PropertyAccess\PropertyAccess:
|
||||
'getPropertyAccessor': 'createPropertyAccessor'
|
||||
|
||||
Rector\Rector\Dynamic\ClassReplacerRector:
|
||||
# console
|
||||
'Symfony\Component\Console\Helper\ProgressHelper': 'Symfony\Component\Console\Helper\ProgressBar'
|
||||
# form
|
||||
'Symfony\Component\Form\Util\VirtualFormAwareIterator': 'Symfony\Component\Form\Util\InheritDataAwareIterator'
|
@ -18,6 +18,8 @@ services:
|
||||
- ['addNodeVisitor', ['@Rector\NodeVisitor\NodeConnector']]
|
||||
# adds current class to all nodes via attribute
|
||||
- ['addNodeVisitor', ['@Rector\NodeTypeResolver\NodeVisitor\ClassResolver']]
|
||||
# adds current method to all nodes via attribute
|
||||
- ['addNodeVisitor', ['@Rector\NodeTypeResolver\NodeVisitor\MethodResolver']]
|
||||
# adds type to variable and property nodes via attribute
|
||||
- ['addNodeVisitor', ['@Rector\NodeTypeResolver\NodeVisitor\TypeResolver']]
|
||||
# adds current namespace to all nodes via attribute
|
||||
|
@ -0,0 +1,16 @@
|
||||
<?php declare (strict_types=1);
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
|
||||
class PermissionCollectionType extends AbstractType
|
||||
{
|
||||
public function getName()
|
||||
{
|
||||
return 'some_name';
|
||||
}
|
||||
|
||||
public function getParent()
|
||||
{
|
||||
return \Symfony\Component\Form\Extension\Core\Type\CollectionType::class;
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\Tests\Rector\Contrib\Symfony\Form\FormTypeGetParentRector;
|
||||
|
||||
use Rector\Rector\Contrib\Symfony\Form\FormTypeGetParentRector;
|
||||
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
|
||||
|
||||
final class Test extends AbstractRectorTestCase
|
||||
{
|
||||
public function test(): void
|
||||
{
|
||||
$this->doTestFileMatchesExpectedContent(
|
||||
__DIR__ . '/Wrong/wrong.php.inc',
|
||||
__DIR__ . '/Correct/correct.php.inc'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
protected function getRectorClasses(): array
|
||||
{
|
||||
return [FormTypeGetParentRector::class];
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
<?php declare (strict_types=1);
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
|
||||
class PermissionCollectionType extends AbstractType
|
||||
{
|
||||
public function getName()
|
||||
{
|
||||
return 'some_name';
|
||||
}
|
||||
|
||||
public function getParent()
|
||||
{
|
||||
return 'collection';
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class RegistrationFormType extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder
|
||||
->add('name', 'text', array('label' => 'form.name'))
|
||||
->add('price1', 'text', array(
|
||||
'label' => 'form.price1',
|
||||
'scale' => 3,
|
||||
))
|
||||
->add('price2', 'text', array(
|
||||
'scale' => 3,
|
||||
))
|
||||
->add('discount', 'integer', [
|
||||
'label' => 'form.email',
|
||||
'inherit_data' => true,
|
||||
])
|
||||
->add('password', 'password')
|
||||
;
|
||||
}
|
||||
}
|
25
tests/Rector/Contrib/Symfony/Form/OptionNameRector/Test.php
Normal file
25
tests/Rector/Contrib/Symfony/Form/OptionNameRector/Test.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\Tests\Rector\Contrib\Symfony\Form\OptionNameRector;
|
||||
|
||||
use Rector\Rector\Contrib\Symfony\Form\OptionNameRector;
|
||||
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
|
||||
|
||||
final class Test extends AbstractRectorTestCase
|
||||
{
|
||||
public function test(): void
|
||||
{
|
||||
$this->doTestFileMatchesExpectedContent(
|
||||
__DIR__ . '/Wrong/wrong.php.inc',
|
||||
__DIR__ . '/Correct/correct.php.inc'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
protected function getRectorClasses(): array
|
||||
{
|
||||
return [OptionNameRector::class];
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class RegistrationFormType extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder
|
||||
->add('name', 'text', array('label' => 'form.name'))
|
||||
->add('price1', 'text', array(
|
||||
'label' => 'form.price1',
|
||||
'precision' => 3,
|
||||
))
|
||||
->add('price2', 'text', array(
|
||||
'precision' => 3,
|
||||
))
|
||||
->add('discount', 'integer', [
|
||||
'label' => 'form.email',
|
||||
'virtual' => true,
|
||||
])
|
||||
->add('password', 'password')
|
||||
;
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
<?php declare (strict_types=1);
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
|
||||
|
||||
class ClassWithNamedService extends Controller
|
||||
{
|
||||
public function someAction(Symfony\Component\HttpFoundation\Request $request)
|
||||
{
|
||||
$request->getSomething();
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\Tests\Rector\Contrib\Symfony\HttpKernel\GetRequestRector;
|
||||
|
||||
use Rector\Rector\Contrib\Symfony\HttpKernel\GetRequestRector;
|
||||
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
|
||||
|
||||
final class Test extends AbstractRectorTestCase
|
||||
{
|
||||
public function test(): void
|
||||
{
|
||||
$this->doTestFileMatchesExpectedContent(
|
||||
__DIR__ . '/Wrong/wrong.php.inc',
|
||||
__DIR__ . '/Correct/correct.php.inc'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
protected function getRectorClasses(): array
|
||||
{
|
||||
return [GetRequestRector::class];
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
<?php declare (strict_types=1);
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
|
||||
|
||||
class ClassWithNamedService extends Controller
|
||||
{
|
||||
public function someAction()
|
||||
{
|
||||
$this->getRequest()->getSomething();
|
||||
}
|
||||
}
|
30
tests/Rector/Dynamic/ClassConstantReplacerRector/Test.php
Normal file
30
tests/Rector/Dynamic/ClassConstantReplacerRector/Test.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\Tests\Rector\Dynamic\ClassConstantReplacerRector;
|
||||
|
||||
use Rector\Rector\Dynamic\ClassConstantReplacerRector;
|
||||
use Rector\Testing\PHPUnit\AbstractConfigurableRectorTestCase;
|
||||
|
||||
final class Test extends AbstractConfigurableRectorTestCase
|
||||
{
|
||||
public function test(): void
|
||||
{
|
||||
$this->doTestFileMatchesExpectedContent(
|
||||
__DIR__ . '/wrong/wrong.php.inc',
|
||||
__DIR__ . '/correct/correct.php.inc'
|
||||
);
|
||||
}
|
||||
|
||||
protected function provideConfig(): string
|
||||
{
|
||||
return __DIR__ . '/config/rector.yml';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
protected function getRectorClasses(): array
|
||||
{
|
||||
return [ClassConstantReplacerRector::class];
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
rectors:
|
||||
Rector\Rector\Dynamic\ClassConstantReplacerRector:
|
||||
'Symfony\Component\Form\FormEvents':
|
||||
'PRE_BIND': 'PRE_SUBMIT'
|
||||
'BIND': 'SUBMIT'
|
||||
'POST_BIND': 'POST_SUBMIT'
|
@ -0,0 +1,13 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
use Symfony\Component\Form\FormEvents;
|
||||
|
||||
class SomeClass
|
||||
{
|
||||
public function subscribe()
|
||||
{
|
||||
return [
|
||||
FormEvents::PRE_SUBMIT
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
use Symfony\Component\Form\FormEvents;
|
||||
|
||||
class SomeClass
|
||||
{
|
||||
public function subscribe()
|
||||
{
|
||||
return [
|
||||
FormEvents::PRE_BIND
|
||||
];
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user