Skip to content

Commit a2a7f52

Browse files
authored
Fix FactoryDefinitionRector to work with arrow functions (#214)
1 parent 415aa9a commit a2a7f52

File tree

3 files changed

+71
-18
lines changed

3 files changed

+71
-18
lines changed

src/NodeFactory/ModelFactoryNodeFactory.php

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use PhpParser\Node;
1010
use PhpParser\Node\Arg;
1111
use PhpParser\Node\Expr;
12+
use PhpParser\Node\Expr\ArrowFunction;
1213
use PhpParser\Node\Expr\Closure;
1314
use PhpParser\Node\Expr\MethodCall;
1415
use PhpParser\Node\Expr\PropertyFetch;
@@ -66,13 +67,13 @@ public function createEmptyFactory(string $name, Expr $expr): Class_
6667
return $class;
6768
}
6869

69-
public function createDefinition(Closure $closure): ClassMethod
70+
public function createDefinition(Closure|ArrowFunction $callable): ClassMethod
7071
{
71-
if (isset($closure->params[0])) {
72-
$this->fakerVariableToPropertyFetch($closure->stmts, $closure->params[0]);
72+
if (isset($callable->params[0])) {
73+
$this->fakerVariableToPropertyFetch($callable->getStmts(), $callable->params[0]);
7374
}
7475

75-
return $this->createPublicMethod('definition', $closure->stmts);
76+
return $this->createPublicMethod('definition', $callable->getStmts());
7677
}
7778

7879
public function createStateMethod(MethodCall $methodCall): ?ClassMethod
@@ -87,8 +88,8 @@ public function createStateMethod(MethodCall $methodCall): ?ClassMethod
8788

8889
$thirdArgValue = $methodCall->args[2]->value;
8990
// the third argument may be closure or array
90-
if ($thirdArgValue instanceof Closure && isset($thirdArgValue->params[0])) {
91-
$this->fakerVariableToPropertyFetch($thirdArgValue->stmts, $thirdArgValue->params[0]);
91+
if (($thirdArgValue instanceof Closure || $thirdArgValue instanceof ArrowFunction) && isset($thirdArgValue->params[0])) {
92+
$this->fakerVariableToPropertyFetch($thirdArgValue->getStmts(), $thirdArgValue->params[0]);
9293
unset($thirdArgValue->params[0]);
9394
}
9495

@@ -117,11 +118,11 @@ public function createEmptyConfigure(): ClassMethod
117118
return $this->createPublicMethod('configure', [$return]);
118119
}
119120

120-
public function appendConfigure(ClassMethod $classMethod, string $name, Closure $closure): void
121+
public function appendConfigure(ClassMethod $classMethod, string $name, Closure|ArrowFunction $callable): void
121122
{
122123
$this->simpleCallableNodeTraverser->traverseNodesWithCallable(
123124
(array) $classMethod->stmts,
124-
function (Node $node) use ($closure, $name): ?Return_ {
125+
function (Node $node) use ($callable, $name): ?Return_ {
125126
if (! $node instanceof Return_) {
126127
return null;
127128
}
@@ -130,13 +131,13 @@ function (Node $node) use ($closure, $name): ?Return_ {
130131
return null;
131132
}
132133

133-
if (isset($closure->params[1])) {
134-
$this->fakerVariableToPropertyFetch($closure->stmts, $closure->params[1]);
134+
if (isset($callable->params[1])) {
135+
$this->fakerVariableToPropertyFetch($callable->getStmts(), $callable->params[1]);
135136
// remove argument $faker
136-
unset($closure->params[1]);
137+
unset($callable->params[1]);
137138
}
138139

139-
$node->expr = $this->nodeFactory->createMethodCall($node->expr, $name, [$closure]);
140+
$node->expr = $this->nodeFactory->createMethodCall($node->expr, $name, [$callable]);
140141

141142
return $node;
142143
}

src/Rector/Namespace_/FactoryDefinitionRector.php

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use PhpParser\Node;
88
use PhpParser\Node\Arg;
99
use PhpParser\Node\Expr;
10+
use PhpParser\Node\Expr\ArrowFunction;
1011
use PhpParser\Node\Expr\Assign;
1112
use PhpParser\Node\Expr\ClassConstFetch;
1213
use PhpParser\Node\Expr\Closure;
@@ -207,12 +208,12 @@ private function addDefinition(Class_ $class, MethodCall $methodCall): void
207208
return;
208209
}
209210

210-
$callback = $methodCall->args[1]->value;
211-
if (! $callback instanceof Closure) {
211+
$callable = $methodCall->args[1]->value;
212+
if (! $callable instanceof Closure && ! $callable instanceof ArrowFunction) {
212213
return;
213214
}
214215

215-
$class->stmts[] = $this->modelFactoryNodeFactory->createDefinition($callback);
216+
$class->stmts[] = $this->modelFactoryNodeFactory->createDefinition($callable);
216217
}
217218

218219
private function addState(Class_ $class, MethodCall $methodCall): void
@@ -235,8 +236,8 @@ private function appendAfterCalling(Class_ $class, MethodCall $methodCall, strin
235236
return;
236237
}
237238

238-
$closure = $methodCall->args[1]->value;
239-
if (! $closure instanceof Closure) {
239+
$callable = $methodCall->args[1]->value;
240+
if (! $callable instanceof Closure && ! $callable instanceof ArrowFunction) {
240241
return;
241242
}
242243

@@ -246,6 +247,6 @@ private function appendAfterCalling(Class_ $class, MethodCall $methodCall, strin
246247
$class->stmts[] = $method;
247248
}
248249

249-
$this->modelFactoryNodeFactory->appendConfigure($method, $name, $closure);
250+
$this->modelFactoryNodeFactory->appendConfigure($method, $name, $callable);
250251
}
251252
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
3+
namespace RectorLaravel\Tests\Rector\Namespace_\FactoryDefinitionRector\Fixture;
4+
5+
use RectorLaravel\Tests\Rector\Namespace_\FactoryDefinitionRector\Source\Model;
6+
7+
$factory->define(Model::class, fn ($faker) => [
8+
'name' => $faker->name,
9+
'email' => $faker->unique()->safeEmail,
10+
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
11+
]);
12+
13+
$factory->state(Model::class, 'address', fn ($faker) => [
14+
'address' => $faker->address,
15+
]);
16+
17+
$factory->afterMaking(Model::class, fn (Model $user, $faker) => $user->name = $faker->name);
18+
19+
$factory->afterCreating(Model::class, fn (Model $user, $faker) => $user->name = $faker->name);
20+
21+
?>
22+
-----
23+
<?php
24+
25+
namespace RectorLaravel\Tests\Rector\Namespace_\FactoryDefinitionRector\Fixture;
26+
27+
use RectorLaravel\Tests\Rector\Namespace_\FactoryDefinitionRector\Source\Model;
28+
class ModelFactory extends \Illuminate\Database\Eloquent\Factories\Factory
29+
{
30+
protected $model = Model::class;
31+
public function definition()
32+
{
33+
return [
34+
'name' => $this->faker->name,
35+
'email' => $this->faker->unique()->safeEmail,
36+
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
37+
];
38+
}
39+
public function address()
40+
{
41+
return $this->state(fn() => [
42+
'address' => $this->faker->address,
43+
]);
44+
}
45+
public function configure()
46+
{
47+
return $this->afterMaking(fn (Model $user) => $user->name = $this->faker->name)->afterCreating(fn (Model $user) => $user->name = $this->faker->name);
48+
}
49+
}
50+
51+
?>

0 commit comments

Comments
 (0)