|
16 | 16 | use PhpParser\Node\Scalar\Int_; |
17 | 17 | use PhpParser\Node\Stmt; |
18 | 18 | use PhpParser\Node\Stmt\Expression; |
| 19 | +use PhpParser\Node\Stmt\Foreach_; |
19 | 20 | use PhpParser\Node\Stmt\If_; |
20 | 21 | use PhpParser\Node\Stmt\Return_; |
| 22 | +use PHPStan\Type\ObjectType; |
21 | 23 | use Rector\Naming\Naming\VariableNaming; |
22 | 24 | use Rector\PhpParser\Enum\NodeGroup; |
23 | 25 | use Rector\PHPStan\ScopeFetcher; |
@@ -69,6 +71,38 @@ public function run($object) |
69 | 71 | return $reflectionProperty->getValue($object); |
70 | 72 | } |
71 | 73 | } |
| 74 | +CODE_SAMPLE |
| 75 | + ), |
| 76 | + |
| 77 | + new CodeSample( |
| 78 | + <<<'CODE_SAMPLE' |
| 79 | +class SomeClass |
| 80 | +{ |
| 81 | + public function run($object) |
| 82 | + { |
| 83 | + $reflectionObject = new ReflectionObject($object); |
| 84 | + foreach ($reflectionObject->getProperties() as $reflectionProperty) { |
| 85 | + echo $reflectionProperty->getValue($object); |
| 86 | + } |
| 87 | + } |
| 88 | +} |
| 89 | +CODE_SAMPLE |
| 90 | + |
| 91 | + , |
| 92 | + <<<'CODE_SAMPLE' |
| 93 | +class SomeClass |
| 94 | +{ |
| 95 | + public function run($object) |
| 96 | + { |
| 97 | + $reflectionObject = new ReflectionObject($object); |
| 98 | + foreach ($reflectionObject->getProperties() as $reflectionProperty) { |
| 99 | + if (PHP_VERSION_ID < 80100) { |
| 100 | + $reflectionProperty->setAccessible(true); |
| 101 | + } |
| 102 | + echo $reflectionProperty->getValue($object); |
| 103 | + } |
| 104 | + } |
| 105 | +} |
72 | 106 | CODE_SAMPLE |
73 | 107 | ), |
74 | 108 |
|
@@ -96,6 +130,14 @@ public function refactor(Node $node): ?Node |
96 | 130 | $hasChanged = false; |
97 | 131 |
|
98 | 132 | foreach ($node->stmts as $key => $stmt) { |
| 133 | + if ($stmt instanceof Foreach_) { |
| 134 | + if ($this->refactorForeach($stmt)) { |
| 135 | + $hasChanged = true; |
| 136 | + } |
| 137 | + |
| 138 | + continue; |
| 139 | + } |
| 140 | + |
99 | 141 | if (! $stmt instanceof Expression && ! $stmt instanceof Return_) { |
100 | 142 | continue; |
101 | 143 | } |
@@ -158,6 +200,45 @@ public function refactor(Node $node): ?Node |
158 | 200 | return null; |
159 | 201 | } |
160 | 202 |
|
| 203 | + private function refactorForeach(Foreach_ $foreach): bool |
| 204 | + { |
| 205 | + if (! $foreach->valueVar instanceof Variable) { |
| 206 | + return false; |
| 207 | + } |
| 208 | + |
| 209 | + if (! $this->isReflectionMembersCall($foreach->expr)) { |
| 210 | + return false; |
| 211 | + } |
| 212 | + |
| 213 | + $firstStmt = $foreach->stmts[0] ?? null; |
| 214 | + if ($this->isSetAccessibleMethodCall($firstStmt) || $this->isSetAccessibleIfMethodCall($firstStmt)) { |
| 215 | + return false; |
| 216 | + } |
| 217 | + |
| 218 | + array_unshift($foreach->stmts, $this->createSetAccessibleExpression($foreach->valueVar)); |
| 219 | + |
| 220 | + return true; |
| 221 | + } |
| 222 | + |
| 223 | + private function isReflectionMembersCall(Expr $expr): bool |
| 224 | + { |
| 225 | + if (! $expr instanceof MethodCall) { |
| 226 | + return false; |
| 227 | + } |
| 228 | + |
| 229 | + if (! $this->isNames($expr->name, ['getProperties', 'getMethods'])) { |
| 230 | + return false; |
| 231 | + } |
| 232 | + |
| 233 | + $callerType = $this->nodeTypeResolver->getType($expr->var); |
| 234 | + if (! $callerType instanceof ObjectType) { |
| 235 | + return false; |
| 236 | + } |
| 237 | + |
| 238 | + return $callerType->isInstanceOf('ReflectionClass') |
| 239 | + ->yes(); |
| 240 | + } |
| 241 | + |
161 | 242 | private function createSetAccessibleExpression(Expr $expr): If_ |
162 | 243 | { |
163 | 244 | $args = [$this->nodeFactory->createArg($this->nodeFactory->createTrue())]; |
|
0 commit comments