[League event] Dispatch only strings to anonymous class (#6120)

* [League event] Fix: dispatch only strings to anonymous class

* [League event] Dispatch only strings to anonymous class

* Fixed phpstan
This commit is contained in:
Michal Lulco 2021-04-13 19:14:34 +02:00 committed by GitHub
parent a0656b27b9
commit 22d35689bf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 161 additions and 8 deletions

View File

@ -0,0 +1,16 @@
<?php
namespace Rector\Tests\LeagueEvent\Rector\MethodCall\DispatchStringToObjectRector\Fixture;
class EventObject
{
/** @var \League\Event\EventDispatcher */
private $dispatcher;
public function run()
{
$this->dispatcher->dispatch(new \League\Event\Event('my-event'));
}
}
?>

View File

@ -26,11 +26,16 @@ class Fixture
public function run()
{
$this->dispatcher->dispatch(new class implements \League\Event\HasEventName
$this->dispatcher->dispatch(new class('my-event') implements \League\Event\HasEventName
{
private $name;
public function __construct(string $name)
{
$this->name = $name;
}
public function eventName(): string
{
return 'my-event';
return $this->name;
}
});
}

View File

@ -0,0 +1,54 @@
<?php
namespace Rector\Tests\LeagueEvent\Rector\MethodCall\DispatchStringToObjectRector\Fixture;
class MethodCall
{
/** @var \League\Event\EventDispatcher */
private $dispatcher;
public function run()
{
$this->dispatcher->dispatch($this->createEventName());
}
private function createEventName(): string
{
return 'my-event';
}
}
?>
-----
<?php
namespace Rector\Tests\LeagueEvent\Rector\MethodCall\DispatchStringToObjectRector\Fixture;
class MethodCall
{
/** @var \League\Event\EventDispatcher */
private $dispatcher;
public function run()
{
$this->dispatcher->dispatch(new class($this->createEventName()) implements \League\Event\HasEventName
{
private $name;
public function __construct(string $name)
{
$this->name = $name;
}
public function eventName(): string
{
return $this->name;
}
});
}
private function createEventName(): string
{
return 'my-event';
}
}
?>

View File

@ -0,0 +1,46 @@
<?php
namespace Rector\Tests\LeagueEvent\Rector\MethodCall\DispatchStringToObjectRector\Fixture;
class Variable
{
/** @var \League\Event\EventDispatcher */
private $dispatcher;
public function run()
{
$name = 'my-event';
$this->dispatcher->dispatch($name);
}
}
?>
-----
<?php
namespace Rector\Tests\LeagueEvent\Rector\MethodCall\DispatchStringToObjectRector\Fixture;
class Variable
{
/** @var \League\Event\EventDispatcher */
private $dispatcher;
public function run()
{
$name = 'my-event';
$this->dispatcher->dispatch(new class($name) implements \League\Event\HasEventName
{
private $name;
public function __construct(string $name)
{
$this->name = $name;
}
public function eventName(): string
{
return $this->name;
}
});
}
}
?>

View File

@ -5,14 +5,21 @@ namespace Rector\LeagueEvent\Rector\MethodCall;
use PhpParser\Node;
use PhpParser\Node\Arg;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\Assign;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\New_;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Name\FullyQualified;
use PhpParser\Node\Param;
use PhpParser\Node\Stmt;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Expression;
use PhpParser\Node\Stmt\Property;
use PhpParser\Node\Stmt\PropertyProperty;
use PhpParser\Node\Stmt\Return_;
use PHPStan\Type\ObjectType;
use PHPStan\Type\StringType;
use Rector\Core\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
@ -90,10 +97,14 @@ CODE_SAMPLE
return true;
}
return ! $this->nodeTypeResolver->isObjectTypes($methodCall->var, [
if (! $this->nodeTypeResolver->isObjectTypes($methodCall->var, [
new ObjectType('League\Event\EventDispatcher'),
new ObjectType('League\Event\Emitter'),
]);
])) {
return true;
}
return ! $this->getStaticType($methodCall->args[0]->value) instanceof StringType;
}
private function updateNode(MethodCall $methodCall): MethodCall
@ -108,21 +119,42 @@ CODE_SAMPLE
return new New_(new Class_(null, [
'implements' => $implements,
'stmts' => $this->createAnonymousEventClassBody($expr),
]));
'stmts' => $this->createAnonymousEventClassBody(),
]), [new Arg($expr)]);
}
/**
* @return Stmt[]
*/
private function createAnonymousEventClassBody(Expr $expr): array
private function createAnonymousEventClassBody(): array
{
return [
new Property(Class_::MODIFIER_PRIVATE, [new PropertyProperty('name')]),
new ClassMethod('__construct', [
'flags' => Class_::MODIFIER_PUBLIC,
'params' => $this->createConstructParams(),
'stmts' => [new Expression($this->createConstructAssign())],
]),
new ClassMethod('eventName', [
'flags' => Class_::MODIFIER_PUBLIC,
'returnType' => 'string',
'stmts' => [new Return_($expr)],
'stmts' => [new Return_(new Variable('this->name'))],
]),
];
}
/**
* @return Param[]
*/
private function createConstructParams(): array
{
return [
new Param(new Variable('name'), null, 'string')
];
}
private function createConstructAssign(): Assign
{
return new Assign(new Variable('this->name'), new Variable('name'));
}
}