mirror of
https://github.com/rectorphp/rector.git
synced 2024-06-26 20:53:31 +00:00
[Nette Kdyby] Add ReplaceEventManagerWithEventSubscriberRector
This commit is contained in:
parent
d40cdeafc6
commit
f0a67edb7e
|
@ -4,3 +4,4 @@ services:
|
|||
Rector\NetteKdyby\Rector\Class_\KdybyEventSubscriberToContributteEventSubscriberRector: null
|
||||
Rector\NetteKdyby\Rector\MethodCall\ReplaceMagicPropertyEventWithEventClassRector: null
|
||||
Rector\NetteKdyby\Rector\ClassMethod\ReplaceMagicEventPropertySubscriberWithEventClassSubscriberRector: null
|
||||
Rector\NetteKdyby\Rector\MethodCall\ReplaceEventManagerWithEventSubscriberRector: null
|
||||
|
|
|
@ -309,3 +309,4 @@ parameters:
|
|||
- '#Cognitive complexity for "Rector\\TypeDeclaration\\PHPStan\\Type\\ObjectTypeSpecifier\:\:matchShortenedObjectType\(\)" is 10, keep it under 9#'
|
||||
- '#Parameter \#1 \$objectType of method Rector\\Core\\Naming\\PropertyNaming\:\:fqnToVariableName\(\) expects PHPStan\\Type\\ObjectType\|string, PHPStan\\Type\\Type given#'
|
||||
- '#Parameter \#1 \$type of method PhpParser\\Builder\\FunctionLike\:\:setReturnType\(\) expects PhpParser\\Node\\Name\|PhpParser\\Node\\NullableType\|string, PhpParser\\Node\\Identifier\|PhpParser\\Node\\Name\|PhpParser\\Node\\NullableType\|PhpParser\\Node\\UnionType given#'
|
||||
- '#Cognitive complexity for "Rector\\Core\\PhpParser\\Node\\Value\\ValueResolver\:\:getValue\(\)" is \d+, keep it under 9#'
|
||||
|
|
|
@ -251,7 +251,7 @@ PHP
|
|||
string $name,
|
||||
ObjectType $objectType
|
||||
): void {
|
||||
$assign = $this->createSameNameThisAssign($name);
|
||||
$assign = $this->nodeFactory->createPropertyAssignment($name);
|
||||
$classMethod->stmts[] = new Expression($assign);
|
||||
|
||||
$this->addPropertyToClass($class, $objectType, $name);
|
||||
|
@ -296,16 +296,6 @@ PHP
|
|||
return $this->isName($assign->expr->name, self::GET_MANAGER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates: "$this->value = $value;"
|
||||
*/
|
||||
private function createSameNameThisAssign(string $name): Assign
|
||||
{
|
||||
$propertyFetch = new PropertyFetch(new Variable('this'), $name);
|
||||
|
||||
return new Assign($propertyFetch, new Variable($name));
|
||||
}
|
||||
|
||||
private function removeManagerRegistryProperty(Class_ $class, Assign $assign): void
|
||||
{
|
||||
$managerRegistryPropertyName = $this->getName($assign->var);
|
||||
|
|
|
@ -54,12 +54,28 @@ final class EventClassNaming
|
|||
return $fileInfo->getPath() . DIRECTORY_SEPARATOR . 'Event' . DIRECTORY_SEPARATOR . $shortEventClassName . '.php';
|
||||
}
|
||||
|
||||
public function createEventClassNameFromClassAndProperty(string $className, string $methodName): string
|
||||
{
|
||||
$shortEventClass = $this->createShortEventClassNameFromClassAndProperty($className, $methodName);
|
||||
|
||||
return $this->prependShortClassEventWithNamespace($shortEventClass, $className);
|
||||
}
|
||||
|
||||
public function createEventClassNameFromClassPropertyReference(string $classAndPropertyName): string
|
||||
{
|
||||
[$class, $property] = Strings::split($classAndPropertyName, '#::#');
|
||||
|
||||
$shortEventClass = $this->createShortEventClassNameFromClassAndProperty($class, $property);
|
||||
|
||||
return $this->prependShortClassEventWithNamespace($shortEventClass, $class);
|
||||
}
|
||||
|
||||
/**
|
||||
* TomatoMarket, onBuy
|
||||
* ↓
|
||||
* TomatoMarketBuyEvent
|
||||
*/
|
||||
public function createShortEventClassNameFromClassAndProperty(string $class, string $property): string
|
||||
private function createShortEventClassNameFromClassAndProperty(string $class, string $property): string
|
||||
{
|
||||
$shortClassName = $this->classNaming->getShortName($class);
|
||||
|
||||
|
@ -69,13 +85,6 @@ final class EventClassNaming
|
|||
return $shortClassName . $shortPropertyName . 'Event';
|
||||
}
|
||||
|
||||
public function createEventClassNameFromClassAndProperty(string $className, string $methodName): string
|
||||
{
|
||||
$shortEventClass = $this->createShortEventClassNameFromClassAndProperty($className, $methodName);
|
||||
|
||||
return $this->prependShortClassEventWithNamespace($shortEventClass, $className);
|
||||
}
|
||||
|
||||
private function getShortEventClassName(MethodCall $methodCall): string
|
||||
{
|
||||
/** @var string $methodName */
|
||||
|
|
|
@ -159,14 +159,13 @@ PHP
|
|||
return null;
|
||||
}
|
||||
|
||||
[$class, $property] = Strings::split($eventPropertyReferenceName, '#::#');
|
||||
|
||||
if (! property_exists($class, $property)) {
|
||||
$eventClassName = $this->eventClassNaming->createEventClassNameFromClassPropertyReference(
|
||||
$eventPropertyReferenceName
|
||||
);
|
||||
if ($eventClassName === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$eventClassName = $this->eventClassNaming->createEventClassNameFromClassAndProperty($class, $property);
|
||||
|
||||
$node->key = $this->createClassConstantReference($eventClassName);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -0,0 +1,137 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\NetteKdyby\Rector\MethodCall;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Arg;
|
||||
use PhpParser\Node\Expr\Array_;
|
||||
use PhpParser\Node\Expr\MethodCall;
|
||||
use PhpParser\Node\Expr\New_;
|
||||
use PhpParser\Node\Identifier;
|
||||
use PhpParser\Node\Name\FullyQualified;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\Core\RectorDefinition\CodeSample;
|
||||
use Rector\Core\RectorDefinition\RectorDefinition;
|
||||
use Rector\NetteKdyby\Naming\EventClassNaming;
|
||||
|
||||
/**
|
||||
* @see \Rector\NetteKdyby\Tests\Rector\MethodCall\ReplaceEventManagerWithEventSubscriberRector\ReplaceEventManagerWithEventSubscriberRectorTest
|
||||
*/
|
||||
final class ReplaceEventManagerWithEventSubscriberRector extends AbstractRector
|
||||
{
|
||||
/**
|
||||
* @var EventClassNaming
|
||||
*/
|
||||
private $eventClassNaming;
|
||||
|
||||
public function __construct(EventClassNaming $eventClassNaming)
|
||||
{
|
||||
$this->eventClassNaming = $eventClassNaming;
|
||||
}
|
||||
|
||||
public function getDefinition(): RectorDefinition
|
||||
{
|
||||
return new RectorDefinition('Change Kdyby EventManager to EventDispatcher', [
|
||||
new CodeSample(
|
||||
<<<'PHP'
|
||||
use Kdyby\Events\EventManager;
|
||||
|
||||
final class SomeClass
|
||||
{
|
||||
/**
|
||||
* @var EventManager
|
||||
*/
|
||||
private $eventManager;
|
||||
|
||||
public function __construct(EventManager $eventManager)
|
||||
{
|
||||
$this->eventManager = eventManager;
|
||||
}
|
||||
|
||||
public function run()
|
||||
{
|
||||
$key = '2000';
|
||||
$this->eventManager->dispatchEvent(static::class . '::onCopy', new EventArgsList([$this, $key]));
|
||||
}
|
||||
}
|
||||
PHP
|
||||
,
|
||||
<<<'PHP'
|
||||
use Kdyby\Events\EventManager;
|
||||
|
||||
final class SomeClass
|
||||
{
|
||||
/**
|
||||
* @var EventManager
|
||||
*/
|
||||
private $eventManager;
|
||||
|
||||
public function __construct(EventManager $eventManager)
|
||||
{
|
||||
$this->eventManager = eventManager;
|
||||
}
|
||||
|
||||
public function run()
|
||||
{
|
||||
$key = '2000';
|
||||
$this->eventManager->dispatch(new SomeClassCopyEvent($this, $key));
|
||||
}
|
||||
}
|
||||
PHP
|
||||
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getNodeTypes(): array
|
||||
{
|
||||
return [MethodCall::class];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param MethodCall $node
|
||||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
if (! $this->isObjectType($node->var, 'Kdyby\Events\EventManager')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (! $this->isName($node->name, 'dispatchEvent')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$node->name = new Identifier('dispatch');
|
||||
|
||||
$oldArgs = $node->args;
|
||||
$node->args = [];
|
||||
|
||||
$eventReference = $oldArgs[0]->value;
|
||||
|
||||
$classAndStaticProperty = $this->getValue($eventReference, true);
|
||||
$eventCass = $this->eventClassNaming->createEventClassNameFromClassPropertyReference($classAndStaticProperty);
|
||||
|
||||
$args = [];
|
||||
if ($oldArgs[1]->value instanceof New_) {
|
||||
/** @var New_ $new */
|
||||
$new = $oldArgs[1]->value;
|
||||
|
||||
$array = $new->args[0]->value;
|
||||
if ($array instanceof Array_) {
|
||||
foreach ($array->items as $arrayItem) {
|
||||
$args[] = new Arg($arrayItem->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$class = new New_(new FullyQualified($eventCass), $args);
|
||||
$node->args[] = new Arg($class);
|
||||
|
||||
return $node;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\NetteKdyby\Tests\Rector\MethodCall\ReplaceEventManagerWithEventSubscriberRector\Fixture;
|
||||
|
||||
use Kdyby\Events\EventManager;
|
||||
|
||||
final class SomeClass
|
||||
{
|
||||
/**
|
||||
* @var EventManager
|
||||
*/
|
||||
private $eventManager;
|
||||
|
||||
public function __construct(EventManager $eventManager)
|
||||
{
|
||||
$this->eventManager = eventManager;
|
||||
}
|
||||
|
||||
public function run()
|
||||
{
|
||||
$key = '2000';
|
||||
$this->eventManager->dispatchEvent(static::class . '::onCopy', new EventArgsList([$this, $key]));
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\NetteKdyby\Tests\Rector\MethodCall\ReplaceEventManagerWithEventSubscriberRector\Fixture;
|
||||
|
||||
use Kdyby\Events\EventManager;
|
||||
|
||||
final class SomeClass
|
||||
{
|
||||
/**
|
||||
* @var EventManager
|
||||
*/
|
||||
private $eventManager;
|
||||
|
||||
public function __construct(EventManager $eventManager)
|
||||
{
|
||||
$this->eventManager = eventManager;
|
||||
}
|
||||
|
||||
public function run()
|
||||
{
|
||||
$key = '2000';
|
||||
$this->eventManager->dispatch(new \Rector\NetteKdyby\Tests\Rector\MethodCall\ReplaceEventManagerWithEventSubscriberRector\Fixture\Event\SomeClassCopyEvent($this, $key));
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\NetteKdyby\Tests\Rector\MethodCall\ReplaceEventManagerWithEventSubscriberRector;
|
||||
|
||||
use Iterator;
|
||||
use Rector\Core\Testing\PHPUnit\AbstractRectorTestCase;
|
||||
use Rector\NetteKdyby\Rector\MethodCall\ReplaceEventManagerWithEventSubscriberRector;
|
||||
|
||||
final class ReplaceEventManagerWithEventSubscriberRectorTest extends AbstractRectorTestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider provideData()
|
||||
*/
|
||||
public function test(string $file): void
|
||||
{
|
||||
$this->doTestFile($file);
|
||||
}
|
||||
|
||||
public function provideData(): Iterator
|
||||
{
|
||||
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
|
||||
}
|
||||
|
||||
protected function getRectorClass(): string
|
||||
{
|
||||
return ReplaceEventManagerWithEventSubscriberRector::class;
|
||||
}
|
||||
}
|
|
@ -150,8 +150,7 @@ PHP
|
|||
$paramBuilder->setType(new FullyQualified($staticType));
|
||||
$param = $paramBuilder->getNode();
|
||||
|
||||
$propertyFetch = new PropertyFetch(new Variable('this'), $variableName);
|
||||
$assign = new Assign($propertyFetch, new Variable($variableName));
|
||||
$assign = $this->nodeFactory->createPropertyAssignment($variableName);
|
||||
|
||||
$setEntityFactoryMethod = $this->createSetEntityFactoryClassMethod($variableName, $param, $assign);
|
||||
|
||||
|
|
|
@ -6,15 +6,13 @@ namespace Rector\SOLID\NodeFactory;
|
|||
|
||||
use PhpParser\Builder\Method;
|
||||
use PhpParser\Builder\Param;
|
||||
use PhpParser\Node\Expr\Assign;
|
||||
use PhpParser\Node\Expr\PropertyFetch;
|
||||
use PhpParser\Node\Expr\Variable;
|
||||
use PhpParser\Node\Name\FullyQualified;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use PHPStan\Type\ObjectType;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
|
||||
use Rector\CodingStyle\Naming\ClassNaming;
|
||||
use Rector\Core\Naming\PropertyNaming;
|
||||
use Rector\Core\PhpParser\Node\NodeFactory;
|
||||
use Rector\NodeTypeResolver\PHPStan\Type\TypeFactory;
|
||||
use Rector\SOLID\Rector\Class_\MultiParentingToAbstractDependencyRector;
|
||||
|
||||
|
@ -40,16 +38,23 @@ final class InjectMethodFactory
|
|||
*/
|
||||
private $typeFactory;
|
||||
|
||||
/**
|
||||
* @var NodeFactory
|
||||
*/
|
||||
private $nodeFactory;
|
||||
|
||||
public function __construct(
|
||||
PhpDocInfoFactory $phpDocInfoFactory,
|
||||
PropertyNaming $propertyNaming,
|
||||
ClassNaming $classNaming,
|
||||
TypeFactory $typeFactory
|
||||
TypeFactory $typeFactory,
|
||||
NodeFactory $nodeFactory
|
||||
) {
|
||||
$this->phpDocInfoFactory = $phpDocInfoFactory;
|
||||
$this->propertyNaming = $propertyNaming;
|
||||
$this->classNaming = $classNaming;
|
||||
$this->typeFactory = $typeFactory;
|
||||
$this->nodeFactory = $nodeFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -72,8 +77,8 @@ final class InjectMethodFactory
|
|||
$param->setType(new FullyQualified($objectType->getClassName()));
|
||||
$methodBuilder->addParam($param);
|
||||
|
||||
$propertyFetch = new PropertyFetch(new Variable('this'), $propertyName);
|
||||
$assign = new Assign($propertyFetch, new Variable($propertyName));
|
||||
$assign = $this->nodeFactory->createPropertyAssignment($propertyName);
|
||||
|
||||
$methodBuilder->addStmt($assign);
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ namespace Rector\Core\PhpParser\Node\Value;
|
|||
use PhpParser\ConstExprEvaluationException;
|
||||
use PhpParser\ConstExprEvaluator;
|
||||
use PhpParser\Node\Expr;
|
||||
use PhpParser\Node\Expr\BinaryOp\Concat;
|
||||
use PhpParser\Node\Expr\ClassConstFetch;
|
||||
use PhpParser\Node\Expr\ConstFetch;
|
||||
use PhpParser\Node\Scalar\MagicConst\Dir;
|
||||
|
@ -63,8 +64,24 @@ final class ValueResolver
|
|||
/**
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function getValue(Expr $expr)
|
||||
public function getValue(Expr $expr, bool $resolvedClassReference = false)
|
||||
{
|
||||
if ($expr instanceof Concat) {
|
||||
return $this->processConcat($expr, $resolvedClassReference);
|
||||
}
|
||||
|
||||
if ($expr instanceof ClassConstFetch && $resolvedClassReference) {
|
||||
$class = $this->nodeNameResolver->getName($expr->class);
|
||||
|
||||
if (in_array($class, ['self', 'static'], true)) {
|
||||
return $expr->getAttribute(AttributeKey::CLASS_NAME);
|
||||
}
|
||||
|
||||
if ($this->nodeNameResolver->isName($expr->name, 'class')) {
|
||||
return $class;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$value = $this->getConstExprEvaluator()->evaluateDirectly($expr);
|
||||
} catch (ConstExprEvaluationException $constExprEvaluationException) {
|
||||
|
@ -201,4 +218,12 @@ final class ValueResolver
|
|||
|
||||
return $this->constExprEvaluator->evaluateDirectly($classConstNode->consts[0]->value);
|
||||
}
|
||||
|
||||
private function processConcat($expr, bool $resolvedClassReference): string
|
||||
{
|
||||
return $this->getValue($expr->left, $resolvedClassReference) . $this->getValue(
|
||||
$expr->right,
|
||||
$resolvedClassReference
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,9 +26,9 @@ trait ValueResolverTrait
|
|||
$this->valueResolver = $valueResolver;
|
||||
}
|
||||
|
||||
protected function getValue(Expr $expr)
|
||||
protected function getValue(Expr $expr, bool $resolvedClassReference = false)
|
||||
{
|
||||
return $this->valueResolver->getValue($expr);
|
||||
return $this->valueResolver->getValue($expr, $resolvedClassReference);
|
||||
}
|
||||
|
||||
protected function isValue(Expr $expr, $expectedValue): bool
|
||||
|
|
Loading…
Reference in New Issue
Block a user