Skip to content

Commit a22419a

Browse files
committed
[code-quality] Add RequestIsMasterRector
1 parent 00c1f25 commit a22419a

File tree

8 files changed

+225
-0
lines changed

8 files changed

+225
-0
lines changed

config/sets/symfony/symfony-code-quality.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
declare(strict_types=1);
44

55
use Rector\Config\RectorConfig;
6+
use Rector\Symfony\CodeQuality\Rector\BinaryOp\RequestIsMasterRector;
67
use Rector\Symfony\CodeQuality\Rector\BinaryOp\ResponseStatusCodeRector;
78
use Rector\Symfony\CodeQuality\Rector\Class_\EventListenerToEventSubscriberRector;
89
use Rector\Symfony\CodeQuality\Rector\Class_\InlineClassRoutePrefixRector;
@@ -29,6 +30,9 @@
2930
ActionSuffixRemoverRector::class,
3031
LoadValidatorMetadataToAnnotationRector::class,
3132

33+
// request method
34+
RequestIsMasterRector::class,
35+
3236
// tests
3337
AssertSameResponseCodeWithDebugContentsRector::class,
3438

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
namespace Rector\Symfony\Tests\CodeQuality\Rector\BinaryOp\RequestIsMasterRector\Fixture;
4+
5+
use Symfony\Component\HttpFoundation\Request;
6+
use Symfony\Component\HttpKernel\HttpKernel;
7+
8+
final class SomeController
9+
{
10+
public function index(Request $request)
11+
{
12+
return $request->getRequestType() === HttpKernel::MASTER_REQUEST;
13+
}
14+
15+
public function second(Request $request)
16+
{
17+
return $request->getRequestType() === HttpKernel::MAIN_REQUEST;
18+
}
19+
}
20+
21+
?>
22+
-----
23+
<?php
24+
25+
namespace Rector\Symfony\Tests\CodeQuality\Rector\BinaryOp\RequestIsMasterRector\Fixture;
26+
27+
use Symfony\Component\HttpFoundation\Request;
28+
use Symfony\Component\HttpKernel\HttpKernel;
29+
30+
final class SomeController
31+
{
32+
public function index(Request $request)
33+
{
34+
return $request->isMasterRequest();
35+
}
36+
37+
public function second(Request $request)
38+
{
39+
return $request->isMasterRequest();
40+
}
41+
}
42+
43+
?>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
namespace Rector\Symfony\Tests\CodeQuality\Rector\BinaryOp\RequestIsMasterRector\Fixture;
4+
5+
use Symfony\Component\HttpKernel\HttpKernel;
6+
7+
final class SkipDifferentType
8+
{
9+
public function index(object $request)
10+
{
11+
return $request->getRequestType() === HttpKernel::MASTER_REQUEST;
12+
}
13+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Rector\Symfony\Tests\CodeQuality\Rector\BinaryOp\RequestIsMasterRector;
6+
7+
use Iterator;
8+
use PHPUnit\Framework\Attributes\DataProvider;
9+
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
10+
11+
final class RequestIsMasterRectorTest extends AbstractRectorTestCase
12+
{
13+
#[DataProvider('provideData')]
14+
public function test(string $filePath): void
15+
{
16+
$this->doTestFile($filePath);
17+
}
18+
19+
public static function provideData(): Iterator
20+
{
21+
return self::yieldFilesFromDirectory(__DIR__ . '/Fixture');
22+
}
23+
24+
public function provideConfigFilePath(): string
25+
{
26+
return __DIR__ . '/config/configured_rule.php';
27+
}
28+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use Rector\Config\RectorConfig;
6+
use Rector\Symfony\CodeQuality\Rector\BinaryOp\RequestIsMasterRector;
7+
8+
return static function (RectorConfig $rectorConfig): void {
9+
$rectorConfig->rule(RequestIsMasterRector::class);
10+
};
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Rector\Symfony\CodeQuality\Rector\BinaryOp;
6+
7+
use PhpParser\Node;
8+
use PhpParser\Node\Expr;
9+
use PhpParser\Node\Expr\BinaryOp;
10+
use PhpParser\Node\Expr\ClassConstFetch;
11+
use PhpParser\Node\Expr\MethodCall;
12+
use PHPStan\Type\ObjectType;
13+
use Rector\Rector\AbstractRector;
14+
use Rector\Symfony\Enum\SymfonyClass;
15+
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
16+
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
17+
18+
/**
19+
* @see \Rector\Symfony\Tests\CodeQuality\Rector\BinaryOp\RequestIsMasterRector\RequestIsMasterRectorTest
20+
*/
21+
final class RequestIsMasterRector extends AbstractRector
22+
{
23+
public function getRuleDefinition(): RuleDefinition
24+
{
25+
return new RuleDefinition('Turns status code numbers to constants', [
26+
new CodeSample(
27+
<<<'CODE_SAMPLE'
28+
use Symfony\Component\HttpFoundation\Request;
29+
use Symfony\Component\HttpKernel\HttpKernel;
30+
31+
class SomeController
32+
{
33+
public function index(Request $request): bool
34+
{
35+
return $request->getRequestType() === HttpKernel::MASTER_REQUEST;
36+
}
37+
}
38+
CODE_SAMPLE
39+
,
40+
<<<'CODE_SAMPLE'
41+
use Symfony\Component\HttpFoundation\Request;
42+
use Symfony\Component\HttpKernel\HttpKernel;
43+
44+
class SomeController
45+
{
46+
public function index(Request $request): bool
47+
{
48+
return $request->isMasterRequestType();
49+
}
50+
}
51+
CODE_SAMPLE
52+
),
53+
]);
54+
}
55+
56+
/**
57+
* @return array<class-string<Node>>
58+
*/
59+
public function getNodeTypes(): array
60+
{
61+
return [BinaryOp::class];
62+
}
63+
64+
/**
65+
* @param BinaryOp $node
66+
*/
67+
public function refactor(Node $node): ?Node
68+
{
69+
if (! $node->left instanceof MethodCall) {
70+
return null;
71+
}
72+
73+
$methodCall = $node->left;
74+
if (! $this->isRequestGetRequestType($methodCall)) {
75+
return null;
76+
}
77+
78+
if (! $this->isHttpKernelMainRequestClassConstFetch($node->right)) {
79+
return null;
80+
}
81+
82+
return new MethodCall($methodCall->var, 'isMasterRequest');
83+
}
84+
85+
private function isRequestGetRequestType(MethodCall $methodCall): bool
86+
{
87+
if (! $this->isName($methodCall->name, 'getRequestType')) {
88+
return false;
89+
}
90+
91+
return $this->isObjectType($methodCall->var, new ObjectType(SymfonyClass::REQUEST));
92+
}
93+
94+
private function isHttpKernelMainRequestClassConstFetch(Expr $expr): bool
95+
{
96+
if (! $expr instanceof ClassConstFetch) {
97+
return false;
98+
}
99+
100+
if (! $this->isNames($expr->class, [SymfonyClass::HTTP_KERNEL_INTERFACE, SymfonyClass::HTTP_KERNEL])) {
101+
return false;
102+
}
103+
104+
return $this->isNames($expr->name, ['MASTER_REQUEST', 'MAIN_REQUEST']);
105+
}
106+
}

src/Enum/SymfonyClass.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,4 +75,19 @@ final class SymfonyClass
7575
* @var string
7676
*/
7777
public const TOKEN_STORAGE_INTERFACE = 'Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface';
78+
79+
/**
80+
* @var string
81+
*/
82+
public const HTTP_KERNEL_INTERFACE = 'Symfony\Component\HttpKernel\HttpKernelInterface';
83+
84+
/**
85+
* @var string
86+
*/
87+
public const HTTP_KERNEL = 'Symfony\Component\HttpKernel\HttpKernel';
88+
89+
/**
90+
* @var string
91+
*/
92+
public const REQUEST = 'Symfony\Component\HttpFoundation\Request';
7893
}

stubs/Symfony/Component/HttpFoundation/Request.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,11 @@
1010

1111
final class Request
1212
{
13+
public function getRequestType()
14+
{
15+
}
1316

17+
public function isMasterRequest()
18+
{
19+
}
1420
}

0 commit comments

Comments
 (0)