Skip to content

Commit 5cafba7

Browse files
authored
Handle JSON GET calls with the route helper (#231)
1 parent 0565543 commit 5cafba7

File tree

5 files changed

+132
-27
lines changed

5 files changed

+132
-27
lines changed

src/Rector/MethodCall/JsonCallToExplicitJsonCallRector.php

Lines changed: 66 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
namespace RectorLaravel\Rector\MethodCall;
66

77
use PhpParser\Node;
8+
use PhpParser\Node\Arg;
9+
use PhpParser\Node\Expr\FuncCall;
810
use PhpParser\Node\Expr\MethodCall;
911
use PhpParser\Node\Identifier;
1012
use PhpParser\Node\Scalar\String_;
@@ -77,19 +79,78 @@ private function updateCall(MethodCall $methodCall): ?MethodCall
7779
return null;
7880
}
7981

80-
$supportedMethods = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'];
82+
$lowercaseMethodName = strtolower($firstArg->value);
8183

82-
if (! in_array($firstArg->value, $supportedMethods, true)) {
84+
$supportedMethods = ['get', 'post', 'put', 'patch', 'delete', 'options'];
85+
86+
if (! in_array($lowercaseMethodName, $supportedMethods, true)) {
8387
return null;
8488
}
8589

86-
if ($firstArg->value === 'GET' && count($methodCallArgs) > 2) {
87-
return null;
90+
if ($lowercaseMethodName === 'get' && count($methodCallArgs) > 2) {
91+
return $this->refactorGetMethodCall($methodCall);
8892
}
8993

90-
$methodCall->name = new Identifier(strtolower($firstArg->value) . 'Json');
94+
$methodCall->name = $this->getMethodCallName($lowercaseMethodName);
9195
$methodCall->args = array_slice($methodCall->args, 1);
9296

9397
return $methodCall;
9498
}
99+
100+
/**
101+
* Set the $data argument from the json('GET') call (3rd argument)
102+
* as the route() helper second argument
103+
*/
104+
private function refactorGetMethodCall(MethodCall $methodCall): ?MethodCall
105+
{
106+
if (! $this->isUsingChangeableRouteHelper($methodCall)) {
107+
return null;
108+
}
109+
110+
$thirdArg = $methodCall->getArgs()[2];
111+
112+
// If it's a named argument, and it's not $data, we won't refactor
113+
if ($thirdArg->name !== null && ! $this->isName($thirdArg, 'data')) {
114+
return null;
115+
}
116+
117+
/** @var FuncCall $routeHelperCall */
118+
$routeHelperCall = $methodCall->getArgs()[1]->value;
119+
120+
$routeHelperCall->args = [
121+
$routeHelperCall->args[0],
122+
new Arg($thirdArg->value),
123+
];
124+
125+
$methodCall->name = $this->getMethodCallName('get');
126+
$methodCall->args = [new Arg($routeHelperCall)];
127+
128+
return $methodCall;
129+
}
130+
131+
private function isUsingChangeableRouteHelper(MethodCall $methodCall): bool
132+
{
133+
$methodCallArgs = $methodCall->getArgs();
134+
135+
// More than 3 arguments means we loose $headers or $options if we refactor
136+
if (count($methodCallArgs) !== 3) {
137+
return false;
138+
}
139+
140+
$secondArg = $methodCallArgs[1]->value;
141+
142+
if (! ($secondArg instanceof FuncCall && $this->isName($secondArg, 'route'))) {
143+
return false;
144+
}
145+
146+
// If there is more than 1 argument in the route() helper
147+
// we have to take into account merging the $data argument,
148+
// but it's too unpredictable to refactor
149+
return count($secondArg->args) === 1;
150+
}
151+
152+
private function getMethodCallName(string $lowercaseMethodName): Identifier
153+
{
154+
return new Identifier("{$lowercaseMethodName}Json");
155+
}
95156
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
namespace Illuminate\Foundation\Testing\Concerns;
4+
5+
if (class_exists('Illuminate\Foundation\Testing\Concerns\MakesHttpRequests')) {
6+
return;
7+
}
8+
9+
class MakesHttpRequests
10+
{
11+
}

tests/Rector/MethodCall/JsonCallToExplicitJsonCallRector/Fixture/fixture_with_json_calls.php.inc

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,77 +2,96 @@
22

33
namespace RectorLaravel\Tests\Rector\MethodCall\JsonCallToExplicitJsonCallRector\Fixture;
44

5+
use Illuminate\Foundation\Testing\Concerns\MakesHttpRequests;
6+
57
class FixtureWithJsonCalls
68
{
7-
public function testGet(\Illuminate\Foundation\Testing\Concerns\MakesHttpRequests $http)
9+
public function testGet(MakesHttpRequests $http)
810
{
911
$http->json('get', '/');
1012
}
1113

12-
public function testPost(\Illuminate\Foundation\Testing\Concerns\MakesHttpRequests $http)
14+
public function testGetWithRouteHelper(MakesHttpRequests $http)
15+
{
16+
$http->json('GET', route('home'));
17+
$http->json('GET', route('home'), ['payload']);
18+
$http->json('GET', route('home'), data: ['payload']);
19+
$http->json('GET', route('home', 'some arg'), ['payload']);
20+
}
21+
22+
public function testPost(MakesHttpRequests $http)
1323
{
1424
$http->json('post', '/');
1525
}
1626

17-
public function testPut(\Illuminate\Foundation\Testing\Concerns\MakesHttpRequests $http)
27+
public function testPut(MakesHttpRequests $http)
1828
{
1929
$http->json('put', '/');
2030
}
2131

22-
public function testPatch(\Illuminate\Foundation\Testing\Concerns\MakesHttpRequests $http)
32+
public function testPatch(MakesHttpRequests $http)
2333
{
2434
$http->json('patch', '/');
2535
}
2636

27-
public function testDelete(\Illuminate\Foundation\Testing\Concerns\MakesHttpRequests $http)
37+
public function testDelete(MakesHttpRequests $http)
2838
{
2939
$http->json('delete', '/');
3040
}
3141

32-
public function testOptions(\Illuminate\Foundation\Testing\Concerns\MakesHttpRequests $http)
42+
public function testOptions(MakesHttpRequests $http)
3343
{
3444
$http->json('options', '/');
3545
}
3646
}
3747

3848
?>
39-
---
49+
-----
4050
<?php
4151

42-
namespace RectorLaravel\Tests\Rector\MethodCall\AssertStatusToAssertMethodRector\Fixture;
52+
namespace RectorLaravel\Tests\Rector\MethodCall\JsonCallToExplicitJsonCallRector\Fixture;
53+
54+
use Illuminate\Foundation\Testing\Concerns\MakesHttpRequests;
4355

4456
class FixtureWithJsonCalls
4557
{
46-
public function testGet(\Illuminate\Foundation\Testing\Concerns\MakesHttpRequests $http)
58+
public function testGet(MakesHttpRequests $http)
4759
{
4860
$http->getJson('/');
4961
}
5062

51-
public function testPost(\Illuminate\Foundation\Testing\Concerns\MakesHttpRequests $http)
63+
public function testGetWithRouteHelper(MakesHttpRequests $http)
64+
{
65+
$http->getJson(route('home'));
66+
$http->getJson(route('home', ['payload']));
67+
$http->getJson(route('home', ['payload']));
68+
$http->json('GET', route('home', 'some arg'), ['payload']);
69+
}
70+
71+
public function testPost(MakesHttpRequests $http)
5272
{
5373
$http->postJson('/');
5474
}
5575

56-
public function testPut(\Illuminate\Foundation\Testing\Concerns\MakesHttpRequests $http)
76+
public function testPut(MakesHttpRequests $http)
5777
{
5878
$http->putJson('/');
5979
}
6080

61-
public function testPatch(\Illuminate\Foundation\Testing\Concerns\MakesHttpRequests $http)
81+
public function testPatch(MakesHttpRequests $http)
6282
{
6383
$http->patchJson('/');
6484
}
6585

66-
public function testDelete(\Illuminate\Foundation\Testing\Concerns\MakesHttpRequests $http)
86+
public function testDelete(MakesHttpRequests $http)
6787
{
6888
$http->deleteJson('/');
6989
}
7090

71-
public function testOptions(\Illuminate\Foundation\Testing\Concerns\MakesHttpRequests $http)
91+
public function testOptions(MakesHttpRequests $http)
7292
{
7393
$http->optionsJson('/');
7494
}
7595
}
7696

7797
?>
78-

tests/Rector/MethodCall/JsonCallToExplicitJsonCallRector/Fixture/fixture_with_json_calls_to_skip.php.inc

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,26 @@
22

33
namespace RectorLaravel\Tests\Rector\MethodCall\JsonCallToExplicitJsonCallRector\Fixture;
44

5+
use Illuminate\Foundation\Testing\Concerns\MakesHttpRequests;
6+
57
class FixtureWithJsonCalls
68
{
7-
public function testHead(\Illuminate\Foundation\Testing\Concerns\MakesHttpRequests $http)
9+
public function testHead(MakesHttpRequests $http)
810
{
911
$http->json('head', '/');
1012
}
1113

12-
public function testTrace(\Illuminate\Foundation\Testing\Concerns\MakesHttpRequests $http)
14+
public function testTrace(MakesHttpRequests $http)
1315
{
1416
$http->json('trace', '/');
1517
}
1618

17-
public function testConnect(\Illuminate\Foundation\Testing\Concerns\MakesHttpRequests $http)
19+
public function testConnect(MakesHttpRequests $http)
1820
{
1921
$http->json('connect', '/');
2022
}
2123

22-
public function testNotEnoughArgs(\Illuminate\Foundation\Testing\Concerns\MakesHttpRequests $http)
24+
public function testNotEnoughArgs(MakesHttpRequests $http)
2325
{
2426
$http->json('GET');
2527
$http->json();

tests/Rector/MethodCall/JsonCallToExplicitJsonCallRector/Fixture/skip_invalid_get_json_calls.php.inc

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,34 @@
22

33
namespace RectorLaravel\Tests\Rector\MethodCall\JsonCallToExplicitJsonCallRector\Fixture;
44

5+
use Illuminate\Foundation\Testing\Concerns\MakesHttpRequests;
6+
57
class FixtureWithGetJsonCalls
68
{
7-
public function testGetWithAllParams(\Illuminate\Foundation\Testing\Concerns\MakesHttpRequests $http)
9+
public function testGetWithAllParams(MakesHttpRequests $http)
810
{
911
$http->json('GET', '/', ['data'], ['headers'], 1);
1012
}
1113

12-
public function testGetWithoutOptions(\Illuminate\Foundation\Testing\Concerns\MakesHttpRequests $http)
14+
public function testGetWithoutOptions(MakesHttpRequests $http)
1315
{
1416
$http->json('GET', '/', ['data'], ['headers']);
1517
}
1618

17-
public function testGetWithoutHeaders(\Illuminate\Foundation\Testing\Concerns\MakesHttpRequests $http)
19+
public function testGetWithoutHeaders(MakesHttpRequests $http)
1820
{
1921
$http->json('GET', '/', ['data']);
2022
}
23+
24+
public function testGetWithNamedHeaders(MakesHttpRequests $http)
25+
{
26+
$http->json('GET', route('home'), headers: ['payload']);
27+
}
28+
29+
public function testGetWithNamedOptions(MakesHttpRequests $http)
30+
{
31+
$http->json('GET', route('home'), options: 1);
32+
}
2133
}
2234

2335
?>

0 commit comments

Comments
 (0)