Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Symfony 5.1] Add LogoutSuccessHandlerToLogoutEventSubscriberRector #5346

Merged
merged 4 commits into from Jan 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions config/set/symfony51.php
Expand Up @@ -10,6 +10,8 @@
use Rector\Renaming\Rector\String_\RenameStringRector;
use Rector\Renaming\ValueObject\MethodCallRename;
use Rector\Renaming\ValueObject\RenameClassAndConstFetch;
use Rector\Symfony5\Rector\Class_\LogoutHandlerToLogoutEventSubscriberRector;
use Rector\Symfony5\Rector\Class_\LogoutSuccessHandlerToLogoutEventSubscriberRector;
use Rector\Transform\Rector\New_\NewArgToMethodCallRector;
use Rector\Transform\Rector\StaticCall\StaticCallToNewRector;
use Rector\Transform\ValueObject\NewArgToMethodCall;
Expand All @@ -24,6 +26,10 @@
return static function (ContainerConfigurator $containerConfigurator): void {
$services = $containerConfigurator->services();

// see https://github.com/symfony/symfony/pull/36243
$services->set(LogoutHandlerToLogoutEventSubscriberRector::class);
$services->set(LogoutSuccessHandlerToLogoutEventSubscriberRector::class);

$services->set(RenameClassRector::class)
->call('configure', [[
RenameClassRector::OLD_TO_NEW_CLASSES => [
Expand Down
Expand Up @@ -2,7 +2,7 @@

namespace Rector\EarlyReturn\Tests\Rector\Return_\ReturnBinaryAndToEarlyReturnRector\Fixture;

class NotIdentical
final class SomeNotIdentical
{
public function accept($something, $somethingelse)
{
Expand All @@ -16,7 +16,7 @@ class NotIdentical

namespace Rector\EarlyReturn\Tests\Rector\Return_\ReturnBinaryAndToEarlyReturnRector\Fixture;

class NotIdentical
final class SomeNotIdentical
{
public function accept($something, $somethingelse)
{
Expand Down
@@ -0,0 +1,14 @@
<?php

declare(strict_types=1);

namespace Rector\SymfonyCodeQuality\Contract;

use PhpParser\Node\Expr\ClassConstFetch;

interface EventReferenceToMethodNameInterface
{
public function getClassConstFetch(): ClassConstFetch;

public function getMethodName(): string;
}
Expand Up @@ -26,8 +26,9 @@
use Rector\Symfony\ValueObject\ServiceDefinition;
use Rector\Symfony\ValueObject\Tag;
use Rector\Symfony\ValueObject\Tag\EventListenerTag;
use Rector\SymfonyCodeQuality\Contract\EventReferenceToMethodNameInterface;
use Rector\SymfonyCodeQuality\ValueObject\EventNameToClassAndConstant;
use Rector\SymfonyCodeQuality\ValueObject\EventReferenceToMethodName;
use Rector\SymfonyCodeQuality\ValueObject\EventReferenceToMethodNameWithPriority;

final class GetSubscribedEventsClassMethodFactory
{
Expand Down Expand Up @@ -83,7 +84,7 @@ public function __construct(
}

/**
* @param EventReferenceToMethodName[] $eventReferencesToMethodNames
* @param EventReferenceToMethodNameInterface[] $eventReferencesToMethodNames
*/
public function create(array $eventReferencesToMethodNames): ClassMethod
{
Expand All @@ -92,8 +93,10 @@ public function create(array $eventReferencesToMethodNames): ClassMethod
$eventsToMethodsArray = new Array_();

foreach ($eventReferencesToMethodNames as $eventReferencesToMethodName) {
$priority = $eventReferencesToMethodName instanceof EventReferenceToMethodNameWithPriority ? $eventReferencesToMethodName->getPriority() : null;

$eventsToMethodsArray->items[] = $this->createArrayItemFromMethodAndPriority(
null,
$priority,
$eventReferencesToMethodName->getMethodName(),
$eventReferencesToMethodName->getClassConstFetch()
);
Expand Down
Expand Up @@ -5,8 +5,9 @@
namespace Rector\SymfonyCodeQuality\ValueObject;

use PhpParser\Node\Expr\ClassConstFetch;
use Rector\SymfonyCodeQuality\Contract\EventReferenceToMethodNameInterface;

final class EventReferenceToMethodName
final class EventReferenceToMethodName implements EventReferenceToMethodNameInterface
{
/**
* @var ClassConstFetch
Expand Down
@@ -0,0 +1,48 @@
<?php

declare(strict_types=1);

namespace Rector\SymfonyCodeQuality\ValueObject;

use PhpParser\Node\Expr\ClassConstFetch;
use Rector\SymfonyCodeQuality\Contract\EventReferenceToMethodNameInterface;

final class EventReferenceToMethodNameWithPriority implements EventReferenceToMethodNameInterface
{
/**
* @var ClassConstFetch
*/
private $classConstFetch;

/**
* @var string
*/
private $methodName;

/**
* @var int
*/
private $priority;

public function __construct(ClassConstFetch $classConstFetch, string $methodName, int $priority)
{
$this->classConstFetch = $classConstFetch;
$this->methodName = $methodName;
$this->priority = $priority;
}

public function getClassConstFetch(): ClassConstFetch
{
return $this->classConstFetch;
}

public function getMethodName(): string
{
return $this->methodName;
}

public function getPriority(): int
{
return $this->priority;
}
}
55 changes: 55 additions & 0 deletions rules/symfony5/src/NodeFactory/BareLogoutClassMethodFactory.php
@@ -0,0 +1,55 @@
<?php

declare(strict_types=1);

namespace Rector\Symfony5\NodeFactory;

use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Identifier;
use PhpParser\Node\Name\FullyQualified;
use PhpParser\Node\Param;
use PhpParser\Node\Stmt\ClassMethod;
use Rector\Core\Php\PhpVersionProvider;
use Rector\Core\PhpParser\Node\NodeFactory;
use Rector\Core\ValueObject\PhpVersionFeature;

final class BareLogoutClassMethodFactory
{
/**
* @var NodeFactory
*/
private $nodeFactory;

/**
* @var PhpVersionProvider
*/
private $phpVersionProvider;

public function __construct(NodeFactory $nodeFactory, PhpVersionProvider $phpVersionProvider)
{
$this->nodeFactory = $nodeFactory;
$this->phpVersionProvider = $phpVersionProvider;
}

public function create(): ClassMethod
{
$classMethod = $this->nodeFactory->createPublicMethod('onLogout');

$variable = new Variable('logoutEvent');
$classMethod->params[] = $this->createLogoutEventParam($variable);

if ($this->phpVersionProvider->isAtLeastPhpVersion(PhpVersionFeature::VOID_TYPE)) {
$classMethod->returnType = new Identifier('void');
}

return $classMethod;
}

private function createLogoutEventParam(Variable $variable): Param
{
$param = new Param($variable);
$param->type = new FullyQualified('Symfony\Component\Security\Http\Event\LogoutEvent');

return $param;
}
}
73 changes: 33 additions & 40 deletions rules/symfony5/src/NodeFactory/OnLogoutClassMethodFactory.php
Expand Up @@ -7,14 +7,10 @@
use PhpParser\Node\Expr\Assign;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Identifier;
use PhpParser\Node\Name\FullyQualified;
use PhpParser\Node\Param;
use PhpParser\Node\Stmt;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Expression;
use Rector\Core\Php\PhpVersionProvider;
use Rector\Core\PhpParser\Node\NodeFactory;
use Rector\Core\ValueObject\PhpVersionFeature;
use Rector\NetteKdyby\NodeManipulator\ListeningClassMethodArgumentManipulator;
use Rector\NodeNameResolver\NodeNameResolver;

Expand All @@ -29,16 +25,6 @@ final class OnLogoutClassMethodFactory
'token' => 'getToken',
];

/**
* @var NodeFactory
*/
private $nodeFactory;

/**
* @var PhpVersionProvider
*/
private $phpVersionProvider;

/**
* @var ListeningClassMethodArgumentManipulator
*/
Expand All @@ -49,25 +35,45 @@ final class OnLogoutClassMethodFactory
*/
private $nodeNameResolver;

/**
* @var BareLogoutClassMethodFactory
*/
private $bareLogoutClassMethodFactory;

public function __construct(
NodeFactory $nodeFactory,
PhpVersionProvider $phpVersionProvider,
ListeningClassMethodArgumentManipulator $listeningClassMethodArgumentManipulator,
NodeNameResolver $nodeNameResolver
NodeNameResolver $nodeNameResolver,
BareLogoutClassMethodFactory $bareLogoutClassMethodFactory
) {
$this->nodeFactory = $nodeFactory;
$this->phpVersionProvider = $phpVersionProvider;
$this->listeningClassMethodArgumentManipulator = $listeningClassMethodArgumentManipulator;
$this->nodeNameResolver = $nodeNameResolver;
$this->bareLogoutClassMethodFactory = $bareLogoutClassMethodFactory;
}

public function createFromLogoutClassMethod(ClassMethod $logoutClassMethod): ClassMethod
{
$classMethod = $this->nodeFactory->createPublicMethod('onLogout');
$classMethod = $this->bareLogoutClassMethodFactory->create();

$logoutEventVariable = new Variable('logoutEvent');
$classMethod->params[] = $this->createLogoutEventParam($logoutEventVariable);
$assignStmts = $this->createAssignStmtFromOldClassMethod($logoutClassMethod);
$classMethod->stmts = array_merge($assignStmts, (array) $logoutClassMethod->stmts);

return $classMethod;
}

/**
* @return Stmt[]
*/
private function createAssignStmtFromOldClassMethod(ClassMethod $onLogoutSuccessClassMethod): array
{
$usedParams = $this->resolveUsedParams($onLogoutSuccessClassMethod);
return $this->createAssignStmts($usedParams);
}

/**
* @return Param[]
*/
private function resolveUsedParams(ClassMethod $logoutClassMethod): array
{
$usedParams = [];
foreach ($logoutClassMethod->params as $oldParam) {
if (! $this->listeningClassMethodArgumentManipulator->isParamUsedInClassMethodBody(
Expand All @@ -79,30 +85,17 @@ public function createFromLogoutClassMethod(ClassMethod $logoutClassMethod): Cla

$usedParams[] = $oldParam;
}

if ($this->phpVersionProvider->isAtLeastPhpVersion(PhpVersionFeature::VOID_TYPE)) {
$classMethod->returnType = new Identifier('void');
}

$assignStmts = $this->createAssignStmts($usedParams, $logoutEventVariable);
$classMethod->stmts = array_merge($assignStmts, (array) $logoutClassMethod->stmts);

return $classMethod;
}

private function createLogoutEventParam(Variable $logoutEventVariable): Param
{
$param = new Param($logoutEventVariable);
$param->type = new FullyQualified('Symfony\Component\Security\Http\Event\LogoutEvent');
return $param;
return $usedParams;
}

/**
* @param Param[] $params
* @return Expression[]
*/
private function createAssignStmts(array $params, Variable $logoutEventVariable): array
private function createAssignStmts(array $params): array
{
$logoutEventVariable = new Variable('logoutEvent');

$assignStmts = [];
foreach ($params as $param) {
foreach (self::PARAMETER_TO_GETTER_NAMES as $parameterName => $getterName) {
Expand Down