Skip to content

Commit 48d2318

Browse files
committed
Refactored ModelBehaviorsExtension to reduce class complexity
1 parent 6f6a547 commit 48d2318

File tree

2 files changed

+121
-88
lines changed

2 files changed

+121
-88
lines changed
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace ARiddlestone\PHPStanCakePHP2;
6+
7+
use PHPStan\BetterReflection\Reflection\Adapter\ReflectionMethod;
8+
use PHPStan\Reflection\ClassReflection;
9+
use PHPStan\Reflection\ExtendedMethodReflection;
10+
use PHPStan\Reflection\MethodReflection;
11+
use PHPStan\Reflection\ParameterReflection;
12+
use PHPStan\Reflection\ParametersAcceptor;
13+
use PHPStan\Type\ObjectType;
14+
15+
final class ModelBehaviorMethodExtractor
16+
{
17+
/**
18+
* @var ClassReflection
19+
*/
20+
private $classReflection;
21+
22+
public function __construct(ClassReflection $classReflection)
23+
{
24+
$this->classReflection = $classReflection;
25+
}
26+
27+
/**
28+
* Returns all methods for the class which have a first parameter of Model,
29+
* with that parameter removed.
30+
*
31+
* Also filters out private, protected, and static methods.
32+
*
33+
* @return array<MethodReflection>
34+
*/
35+
public function getModelBehaviorMethods(): array
36+
{
37+
$methodNames = array_map(
38+
[$this, 'getMethodReflectionName'],
39+
$this->classReflection->getNativeReflection()->getMethods()
40+
);
41+
/** @var array<ExtendedMethodReflection> $methodReflections */
42+
$methodReflections = array_filter(
43+
array_map(
44+
[$this->classReflection, 'getNativeMethod'],
45+
$methodNames
46+
),
47+
[$this, 'filterBehaviorMethods']
48+
);
49+
return array_map([$this, 'wrapBehaviorMethod'], $methodReflections);
50+
}
51+
52+
/**
53+
* Returns the name of a method from its reflection.
54+
*/
55+
private function getMethodReflectionName(
56+
ReflectionMethod $methodReflection
57+
): string {
58+
return $methodReflection->getName();
59+
}
60+
61+
/**
62+
* Returns true if the given method would be made available as a behavior
63+
* method.
64+
*
65+
* Specifically it must meet the following conditions:
66+
* * Be public
67+
* * Not be static
68+
* * Have at least one variant which accepts a Model as its first parameter
69+
*/
70+
private function filterBehaviorMethods(
71+
ExtendedMethodReflection $methodReflection
72+
): bool {
73+
return $methodReflection->isPublic()
74+
&& ! $methodReflection->isStatic()
75+
&& array_filter(
76+
$methodReflection->getVariants(),
77+
[$this, 'filterBehaviorMethodVariants']
78+
);
79+
}
80+
81+
/**
82+
* Returns true if the given method variant accepts a Model as its first
83+
* parameter.
84+
*/
85+
private function filterBehaviorMethodVariants(
86+
ParametersAcceptor $parametersAcceptor
87+
): bool {
88+
$parameters = $parametersAcceptor->getParameters();
89+
/** @var ParameterReflection|null $firstParameter */
90+
$firstParameter = array_shift($parameters);
91+
92+
if (! $firstParameter) {
93+
return false;
94+
}
95+
96+
if (
97+
$firstParameter->getType()
98+
->isSuperTypeOf(new ObjectType('Model'))
99+
->no()
100+
) {
101+
return false;
102+
}
103+
104+
return true;
105+
}
106+
107+
/**
108+
* Wraps a method reflection in a wrapper which removes the first parameter.
109+
*/
110+
private function wrapBehaviorMethod(
111+
MethodReflection $methodReflection
112+
): MethodReflection {
113+
return new ModelBehaviorMethodWrapper($methodReflection);
114+
}
115+
}

src/ModelBehaviorsExtension.php

Lines changed: 6 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,10 @@
55
namespace ARiddlestone\PHPStanCakePHP2;
66

77
use Exception;
8-
use PHPStan\BetterReflection\Reflection\Adapter\ReflectionMethod;
98
use PHPStan\Reflection\ClassReflection;
10-
use PHPStan\Reflection\ExtendedMethodReflection;
119
use PHPStan\Reflection\MethodReflection;
1210
use PHPStan\Reflection\MethodsClassReflectionExtension;
13-
use PHPStan\Reflection\ParameterReflection;
14-
use PHPStan\Reflection\ParametersAcceptor;
1511
use PHPStan\Reflection\ReflectionProvider;
16-
use PHPStan\Type\ObjectType;
1712

1813
/**
1914
* Adds methods to {@link Model}s from {@link ModelBehavior} classes.
@@ -100,100 +95,23 @@ private function getBehaviorMethods(): array
10095
);
10196
$this->behaviorMethods = [];
10297
foreach ($classReflections as $classReflection) {
98+
$modelBehaviorMethodExtractor =
99+
new ModelBehaviorMethodExtractor($classReflection);
103100
$this->behaviorMethods = array_merge(
104101
$this->behaviorMethods,
105-
$this->getModelBehaviorMethods($classReflection)
102+
$modelBehaviorMethodExtractor->getModelBehaviorMethods()
106103
);
107104
}
108105
}
109106
return $this->behaviorMethods;
110107
}
111108

112-
/**
113-
* Returns all methods for the class which have a first parameter of Model,
114-
* with that parameter removed.
115-
*
116-
* Also filters out private, protected, and static methods.
117-
*
118-
* @return array<MethodReflection>
119-
*/
120-
private function getModelBehaviorMethods(
121-
ClassReflection $classReflection
122-
): array {
123-
$methodNames = array_map(
124-
[$this, 'getMethodReflectionName'],
125-
$classReflection->getNativeReflection()->getMethods()
126-
);
127-
/** @var array<ExtendedMethodReflection> $methodReflections */
128-
$methodReflections = array_filter(
129-
array_map([$classReflection, 'getNativeMethod'], $methodNames),
130-
[$this, 'filterBehaviorMethods']
131-
);
132-
return array_map([$this, 'wrapBehaviorMethod'], $methodReflections);
133-
}
134-
135-
/**
136-
* Returns true if the given method would be made available as a behavior
137-
* method.
138-
*
139-
* Specifically it must meet the following conditions:
140-
* * Be public
141-
* * Not be static
142-
* * Have at least one variant which accepts a Model as its first parameter
143-
*/
144-
private function filterBehaviorMethods(
145-
ExtendedMethodReflection $methodReflection
146-
): bool {
147-
return $methodReflection->isPublic()
148-
&& ! $methodReflection->isStatic()
149-
&& array_filter(
150-
$methodReflection->getVariants(),
151-
[$this, 'filterBehaviorMethodVariants']
152-
);
153-
}
154-
155-
/**
156-
* Returns true if the given method variant accepts a Model as its first
157-
* parameter.
158-
*/
159-
private function filterBehaviorMethodVariants(
160-
ParametersAcceptor $parametersAcceptor
161-
): bool {
162-
$parameters = $parametersAcceptor->getParameters();
163-
/** @var ParameterReflection|null $firstParameter */
164-
$firstParameter = array_shift($parameters);
165-
166-
if (! $firstParameter) {
167-
return false;
168-
}
169-
170-
if (
171-
$firstParameter->getType()
172-
->isSuperTypeOf(new ObjectType('Model'))
173-
->no()
174-
) {
175-
return false;
176-
}
177-
178-
return true;
179-
}
180-
181-
/**
182-
* Wraps a method reflection in a wrapper which removes the first parameter.
183-
*/
184-
private function wrapBehaviorMethod(
185-
MethodReflection $methodReflection
186-
): MethodReflection {
187-
return new ModelBehaviorMethodWrapper($methodReflection);
188-
}
189-
190109
/**
191110
* Returns the name of a method from its reflection.
192-
*
193-
* @param MethodReflection|ReflectionMethod $methodReflection
194111
*/
195-
private function getMethodReflectionName($methodReflection): string
196-
{
112+
private function getMethodReflectionName(
113+
MethodReflection $methodReflection
114+
): string {
197115
return $methodReflection->getName();
198116
}
199117
}

0 commit comments

Comments
 (0)