|
4 | 4 |
|
5 | 5 | namespace LaminasPhpStan\Type\Laminas; |
6 | 6 |
|
7 | | -use Laminas\ServiceManager\AbstractPluginManager; |
8 | 7 | use Laminas\ServiceManager\ServiceLocatorInterface; |
9 | | -use LaminasPhpStan\ServiceManagerLoader; |
10 | | -use PhpParser\Node\Arg; |
11 | | -use PhpParser\Node\Expr\MethodCall; |
12 | | -use PHPStan\Analyser\Scope; |
13 | | -use PHPStan\Reflection\MethodReflection; |
14 | | -use PHPStan\Reflection\ReflectionProvider; |
15 | | -use PHPStan\Type\Constant\ConstantStringType; |
16 | | -use PHPStan\Type\DynamicMethodReturnTypeExtension; |
17 | | -use PHPStan\Type\MixedType; |
18 | | -use PHPStan\Type\NeverType; |
19 | | -use PHPStan\Type\ObjectType; |
20 | | -use PHPStan\Type\Type; |
21 | | -use ReflectionClass; |
22 | 8 |
|
23 | | -final class ServiceManagerGetDynamicReturnTypeExtension implements DynamicMethodReturnTypeExtension |
| 9 | +final class ServiceManagerGetDynamicReturnTypeExtension extends AbstractServiceLocatorGetDynamicReturnTypeExtension |
24 | 10 | { |
25 | | - public function __construct( |
26 | | - private ReflectionProvider $reflectionProvider, |
27 | | - private ServiceManagerLoader $serviceManagerLoader |
28 | | - ) { |
29 | | - } |
30 | | - |
31 | 11 | public function getClass(): string |
32 | 12 | { |
33 | 13 | return ServiceLocatorInterface::class; |
34 | 14 | } |
35 | | - |
36 | | - public function isMethodSupported(MethodReflection $methodReflection): bool |
37 | | - { |
38 | | - return 'get' === $methodReflection->getName(); |
39 | | - } |
40 | | - |
41 | | - public function getTypeFromMethodCall( |
42 | | - MethodReflection $methodReflection, |
43 | | - MethodCall $methodCall, |
44 | | - Scope $scope |
45 | | - ): Type { |
46 | | - $calledOnType = $scope->getType($methodCall->var); |
47 | | - if (! $calledOnType instanceof ObjectType) { |
48 | | - return new MixedType(); |
49 | | - } |
50 | | - |
51 | | - $args = $methodCall->getArgs(); |
52 | | - if (1 !== \count($args)) { |
53 | | - return new MixedType(); |
54 | | - } |
55 | | - |
56 | | - $serviceManager = $this->serviceManagerLoader->getServiceLocator($calledOnType->getClassName()); |
57 | | - |
58 | | - $firstArg = $args[0]; |
59 | | - if (! $firstArg instanceof Arg) { |
60 | | - throw new \PHPStan\ShouldNotHappenException(\sprintf( |
61 | | - 'Argument passed to %s::%s should be a string, %s given', |
62 | | - $methodReflection->getDeclaringClass()->getName(), |
63 | | - $methodReflection->getName(), |
64 | | - $firstArg->getType() |
65 | | - )); |
66 | | - } |
67 | | - $argType = $scope->getType($firstArg->value); |
68 | | - if (! $argType instanceof ConstantStringType) { |
69 | | - if ($serviceManager instanceof AbstractPluginManager) { |
70 | | - $refClass = new ReflectionClass($serviceManager); |
71 | | - $refProperty = $refClass->getProperty('instanceOf'); |
72 | | - $refProperty->setAccessible(true); |
73 | | - $returnedInstance = $refProperty->getValue($serviceManager); |
74 | | - \assert(null === $returnedInstance || \is_string($returnedInstance)); |
75 | | - if (null !== $returnedInstance && $this->reflectionProvider->hasClass($returnedInstance)) { |
76 | | - return new ObjectType($returnedInstance); |
77 | | - } |
78 | | - } |
79 | | - |
80 | | - return new MixedType(); |
81 | | - } |
82 | | - |
83 | | - $serviceName = $argType->getValue(); |
84 | | - if (! $serviceManager->has($serviceName)) { |
85 | | - return new NeverType(); |
86 | | - } |
87 | | - |
88 | | - if (\class_exists($serviceName) || \interface_exists($serviceName)) { |
89 | | - return new ObjectServiceManagerType($serviceName, $serviceName); |
90 | | - } |
91 | | - |
92 | | - $service = $serviceManager->get($serviceName); |
93 | | - if (\is_object($service)) { |
94 | | - $className = $service::class; |
95 | | - $refClass = new ReflectionClass($service); |
96 | | - if ($refClass->isAnonymous()) { |
97 | | - if (false !== ($parentClass = $refClass->getParentClass())) { |
98 | | - $className = $parentClass->getName(); |
99 | | - } elseif ([] !== ($interfaces = $refClass->getInterfaces())) { |
100 | | - $className = \current($interfaces)->getName(); |
101 | | - } |
102 | | - } |
103 | | - |
104 | | - return new ObjectServiceManagerType($className, $serviceName); |
105 | | - } |
106 | | - |
107 | | - return $scope->getTypeFromValue($service); |
108 | | - } |
109 | 15 | } |
0 commit comments