| Total Complexity | 184 |
| Total Lines | 619 |
| Duplicated Lines | 0 % |
| Changes | 7 | ||
| Bugs | 0 | Features | 0 |
Complex classes like Resolver often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use Resolver, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 31 | class Resolver |
||
| 32 | { |
||
| 33 | private AbstractContainer $container; |
||
| 34 | private ?BuilderFactory $builder; |
||
| 35 | private bool $strict = true; |
||
| 36 | |||
| 37 | /** @var array<string,\PhpParser\Node> */ |
||
| 38 | private array $literalCache = []; |
||
| 39 | |||
| 40 | public function __construct(AbstractContainer $container, BuilderFactory $builder = null) |
||
| 41 | { |
||
| 42 | $this->builder = $builder; |
||
| 43 | $this->container = $container; |
||
| 44 | } |
||
| 45 | |||
| 46 | /** |
||
| 47 | * The method name generated for a service definition. |
||
| 48 | */ |
||
| 49 | public static function createMethod(string $id): string |
||
| 50 | { |
||
| 51 | return 'get' . \str_replace(['.', '_', '\\'], '', \ucwords($id, '._')); |
||
| 52 | } |
||
| 53 | |||
| 54 | /** |
||
| 55 | * If true, exception will be thrown on resolvable services with are not typed. |
||
| 56 | */ |
||
| 57 | public function setStrictAutowiring(bool $boolean = true): void |
||
| 58 | { |
||
| 59 | $this->strict = $boolean; |
||
| 60 | } |
||
| 61 | |||
| 62 | /** |
||
| 63 | * @param mixed $definition |
||
| 64 | */ |
||
| 65 | public static function autowireService($definition, bool $allTypes = false, AbstractContainer $container = null): array |
||
| 66 | { |
||
| 67 | $types = $autowired = []; |
||
| 68 | |||
| 69 | if (\is_callable($definition)) { |
||
| 70 | $types = \array_filter(self::getTypes(Callback::toReflection($definition)), fn (string $v) => \class_exists($v) || \interface_exists($v) || $allTypes); |
||
| 71 | } elseif (\is_object($definition)) { |
||
| 72 | if ($definition instanceof \stdClass) { |
||
| 73 | return $allTypes ? ['object'] : $types; |
||
| 74 | } |
||
| 75 | |||
| 76 | $types[] = \get_class($definition); |
||
| 77 | } elseif (\is_string($definition)) { |
||
| 78 | if (!(\class_exists($definition) || \interface_exists($definition))) { |
||
| 79 | return $allTypes ? ['string'] : []; |
||
| 80 | } |
||
| 81 | |||
| 82 | $types[] = $definition; |
||
| 83 | } elseif (\is_array($definition)) { |
||
| 84 | if (null !== $container && 2 === \count($definition, \COUNT_RECURSIVE)) { |
||
| 85 | if ($definition[0] instanceof Definitions\Reference) { |
||
| 86 | $def = $container->definition((string) $definition[0]); |
||
| 87 | } elseif ($definition[0] instanceof Expr\BinaryOp\Coalesce) { |
||
| 88 | $def = $container->definition($definition[0]->left->dim->value); |
||
| 89 | } |
||
| 90 | |||
| 91 | if (isset($def)) { |
||
| 92 | if ($def instanceof Definitions\DefinitionInterface) { |
||
| 93 | $class = self::getDefinitionClass($def); |
||
| 94 | |||
| 95 | if (null === $class) { |
||
| 96 | return []; |
||
| 97 | } |
||
| 98 | } |
||
| 99 | $types = self::getTypes(new \ReflectionMethod($class ?? $def, $definition[1])); |
||
| 100 | goto resolve_types; |
||
| 101 | } |
||
| 102 | } |
||
| 103 | |||
| 104 | return $allTypes ? ['array'] : []; |
||
| 105 | } |
||
| 106 | |||
| 107 | resolve_types: |
||
| 108 | foreach ($types as $type) { |
||
| 109 | $autowired[] = $type; |
||
| 110 | |||
| 111 | foreach (\class_implements($type) ?: [] as $interface) { |
||
| 112 | $autowired[] = $interface; |
||
| 113 | } |
||
| 114 | |||
| 115 | foreach (\class_parents($type) ?: [] as $parent) { |
||
| 116 | $autowired[] = $parent; |
||
| 117 | } |
||
| 118 | } |
||
| 119 | |||
| 120 | return $autowired; |
||
| 121 | } |
||
| 122 | |||
| 123 | /** |
||
| 124 | * Resolves arguments for callable. |
||
| 125 | * |
||
| 126 | * @param array<int|string,mixed> $args |
||
| 127 | * |
||
| 128 | * @return array<int,mixed> |
||
| 129 | */ |
||
| 130 | public function autowireArguments(\ReflectionFunctionAbstract $function, array $args = []): array |
||
| 174 | } |
||
| 175 | |||
| 176 | /** |
||
| 177 | * Resolve a service definition, class string, invocable object or callable |
||
| 178 | * using autowiring. |
||
| 179 | * |
||
| 180 | * @param string|callable|object $callback |
||
| 181 | * @param array<int|string,mixed> $args |
||
| 182 | * |
||
| 183 | * @throws ContainerResolutionException|\ReflectionException if unresolvable |
||
| 184 | * |
||
| 185 | * @return mixed |
||
| 186 | */ |
||
| 187 | public function resolve($callback, array $args = []) |
||
| 188 | { |
||
| 189 | if ($callback instanceof Definitions\Statement) { |
||
| 190 | if (Services\ServiceLocator::class == ($value = $callback->getValue())) { |
||
| 191 | $services = []; |
||
| 192 | $args = \array_merge($args, $callback->getArguments()); |
||
| 193 | |||
| 194 | foreach ($args as $name => $service) { |
||
| 195 | $services += $this->resolveServiceSubscriber($name, (string) $service); |
||
| 196 | } |
||
| 197 | $resolved = null === $this->builder ? new Services\ServiceLocator($services) : $this->builder->new('\\' . Services\ServiceLocator::class, [$services]); |
||
| 198 | } else { |
||
| 199 | $resolved = $this->resolve($value, $callback->getArguments() + $args); |
||
| 200 | |||
| 201 | if ($callback->isClosureWrappable()) { |
||
| 202 | $resolved = null === $this->builder ? fn () => $resolved : new Expr\ArrowFunction(['expr' => $resolved]); |
||
| 203 | } |
||
| 204 | } |
||
| 205 | } elseif ($callback instanceof Definitions\Reference) { |
||
| 206 | $resolved = $this->resolveReference((string) $callback); |
||
| 207 | |||
| 208 | if (\is_callable($resolved) || (\is_array($resolved) && 2 === \count($resolved, \COUNT_RECURSIVE))) { |
||
| 209 | $resolved = $this->resolveCallable($resolved, $args); |
||
| 210 | } else { |
||
| 211 | $callback = $resolved; |
||
| 212 | } |
||
| 213 | } elseif ($callback instanceof Definitions\ValueDefinition) { |
||
| 214 | $resolved = $callback->getEntity(); |
||
| 215 | } elseif ($callback instanceof Definitions\TaggedLocator) { |
||
| 216 | $resolved = $this->resolve($callback->resolve($this->container)); |
||
| 217 | } elseif ($callback instanceof Builder\PhpLiteral) { |
||
| 218 | $expression = $this->literalCache[\spl_object_id($callback)] ??= $callback->resolve($this)[0]; |
||
| 219 | $resolved = $expression instanceof Stmt\Expression ? $expression->expr : $expression; |
||
| 220 | } elseif (\is_string($callback)) { |
||
| 221 | if (\str_contains($callback, '%')) { |
||
| 222 | $callback = $this->container->parameter($callback); |
||
| 223 | } |
||
| 224 | |||
| 225 | if (\class_exists($callback)) { |
||
| 226 | return $this->resolveClass($callback, $args); |
||
| 227 | } |
||
| 228 | |||
| 229 | if (\is_callable($callback)) { |
||
| 230 | $resolved = $this->resolveCallable($callback, $args); |
||
| 231 | } |
||
| 232 | } elseif (\is_callable($callback) || \is_array($callback)) { |
||
| 233 | $resolved = $this->resolveCallable($callback, $args); |
||
| 234 | } |
||
| 235 | |||
| 236 | return $resolved ?? (null === $this->builder ? $callback : $this->builder->val($callback)); |
||
| 237 | } |
||
| 238 | |||
| 239 | /** |
||
| 240 | * Resolves callables and array like callables. |
||
| 241 | * |
||
| 242 | * @param callable|array<int,mixed> $callback |
||
| 243 | * @param array<int|string,mixed> $arguments |
||
| 244 | * |
||
| 245 | * @throws \ReflectionException if $callback is not a real callable |
||
| 246 | * |
||
| 247 | * @return mixed |
||
| 248 | */ |
||
| 249 | public function resolveCallable($callback, array $arguments = []) |
||
| 250 | { |
||
| 251 | if (\is_array($callback)) { |
||
| 252 | if (2 === \count($callback, \COUNT_RECURSIVE) && \is_string($callback[1])) { |
||
| 253 | $callback[0] = $this->resolve($callback[0]); |
||
| 254 | |||
| 255 | if ($callback[0] instanceof Expr\BinaryOp\Coalesce) { |
||
| 256 | $class = self::getDefinitionClass($this->container->definition($callback[0]->left->dim->value)); |
||
| 257 | |||
| 258 | if (null !== $class) { |
||
| 259 | $type = [$class, $callback[1]]; |
||
| 260 | } |
||
| 261 | } elseif ($callback[0] instanceof Expr\New_) { |
||
| 262 | $type = [(string) $callback[0]->class, $callback[1]]; |
||
| 263 | } |
||
| 264 | |||
| 265 | if (isset($type) || \is_callable($callback)) { |
||
| 266 | goto create_callable; |
||
| 267 | } |
||
| 268 | } |
||
| 269 | |||
| 270 | $callback = $this->resolveArguments($callback); |
||
| 271 | |||
| 272 | return null === $this->builder ? $callback : $this->builder->val($callback); |
||
| 273 | } |
||
| 274 | |||
| 275 | create_callable: |
||
| 276 | $args = $this->autowireArguments($ref = Callback::toReflection($type ?? $callback), $arguments); |
||
| 277 | |||
| 278 | if ($ref instanceof \ReflectionFunction) { |
||
| 279 | return null === $this->builder ? $ref->invokeArgs($args) : $this->builder->funcCall($callback, $args); |
||
| 280 | } |
||
| 281 | |||
| 282 | if ($ref->isStatic()) { |
||
| 283 | $className = \is_array($callback) ? $callback[0] : $ref->getDeclaringClass()->getName(); |
||
| 284 | |||
| 285 | return null === $this->builder ? $ref->invokeArgs(null, $args) : $this->builder->staticCall($className, $ref->getName(), $args); |
||
| 286 | } |
||
| 287 | |||
| 288 | return null === $this->builder ? $callback(...$args) : $this->builder->methodCall($callback[0], $ref->getName(), $args); |
||
| 289 | } |
||
| 290 | |||
| 291 | /** |
||
| 292 | * @param array<int|string,mixed> $args |
||
| 293 | * |
||
| 294 | * @throws ContainerResolutionException|\ReflectionException if class string unresolvable |
||
| 295 | */ |
||
| 296 | public function resolveClass(string $class, array $args = []): object |
||
| 297 | { |
||
| 298 | /** @var class-string $class */ |
||
| 299 | $reflection = new \ReflectionClass($class); |
||
| 300 | |||
| 301 | if ($reflection->isAbstract() || !$reflection->isInstantiable()) { |
||
| 302 | throw new ContainerResolutionException(\sprintf('Class %s is an abstract type or instantiable.', $class)); |
||
| 303 | } |
||
| 304 | |||
| 305 | if (null === $constructor = $reflection->getConstructor()) { |
||
| 306 | if (!empty($args)) { |
||
| 307 | throw new ContainerResolutionException(\sprintf('Unable to pass arguments, class "%s" has no constructor.', $class)); |
||
| 308 | } |
||
| 309 | |||
| 310 | $service = null === $this->builder ? $reflection->newInstanceWithoutConstructor() : $this->builder->new($class); |
||
| 311 | } else { |
||
| 312 | $args = $this->autowireArguments($constructor, $args); |
||
| 313 | $service = null === $this->builder ? $reflection->newInstanceArgs($args) : $this->builder->new($class, $args); |
||
| 314 | } |
||
| 315 | |||
| 316 | if ($reflection->implementsInterface(Injector\InjectableInterface::class)) { |
||
| 317 | return Injector\Injectable::getProperties($this, $service, $reflection); |
||
| 318 | } |
||
| 319 | |||
| 320 | return $service; |
||
| 321 | } |
||
| 322 | |||
| 323 | /** |
||
| 324 | * @param array<int|string,mixed> $arguments |
||
| 325 | * |
||
| 326 | * @return array<int|string,mixed> |
||
| 327 | */ |
||
| 328 | public function resolveArguments(array $arguments = []): array |
||
| 329 | { |
||
| 330 | foreach ($arguments as $key => $value) { |
||
| 331 | if ($value instanceof \stdClass) { |
||
| 332 | $resolved = null === $this->builder ? $value : new Expr\Cast\Object_($this->builder->val($this->resolveArguments((array) $value))); |
||
| 333 | } elseif (\is_array($value)) { |
||
| 334 | $resolved = $this->resolveArguments($value); |
||
| 335 | } elseif (\is_int($value)) { |
||
| 336 | $resolved = null === $this->builder ? $value : new Scalar\LNumber($value); |
||
| 337 | } elseif (\is_float($value)) { |
||
| 338 | $resolved = null === $this->builder ? (int) $value : new Scalar\DNumber($value); |
||
| 339 | } elseif (\is_numeric($value)) { |
||
| 340 | $resolved = null === $this->builder ? (int) $value : Scalar\LNumber::fromString($value); |
||
| 341 | } elseif (\is_string($value)) { |
||
| 342 | if (\str_contains($value, '%')) { |
||
| 343 | $value = $this->container->parameter($value); |
||
| 344 | } |
||
| 345 | |||
| 346 | $resolved = null === $this->builder ? $value : $this->builder->val($value); |
||
| 347 | } else { |
||
| 348 | $resolved = $this->resolve($value); |
||
| 349 | } |
||
| 350 | |||
| 351 | $arguments[$key] = $resolved; |
||
| 352 | } |
||
| 353 | |||
| 354 | return $arguments; |
||
| 355 | } |
||
| 356 | |||
| 357 | /** |
||
| 358 | * Resolves service by type. |
||
| 359 | * |
||
| 360 | * @param string $id A class or an interface name |
||
| 361 | * |
||
| 362 | * @return mixed |
||
| 363 | */ |
||
| 364 | public function get(string $id, bool $single = false) |
||
| 365 | { |
||
| 366 | if (\is_subclass_of($id, ServiceSubscriberInterface::class)) { |
||
| 367 | static $services = []; |
||
| 368 | |||
| 369 | foreach ($id::getSubscribedServices() as $name => $service) { |
||
| 370 | $services += $this->resolveServiceSubscriber($name, $service); |
||
| 371 | } |
||
| 372 | |||
| 373 | if (null === $builder = $this->builder) { |
||
| 374 | return new Services\ServiceLocator($services); |
||
| 375 | } |
||
| 376 | |||
| 377 | return $builder->new('\\' . Services\ServiceLocator::class, [$services]); |
||
| 378 | } |
||
| 379 | |||
| 380 | if (!$this->strict) { |
||
| 381 | return $this->container->get($id, $single ? $this->container::EXCEPTION_ON_MULTIPLE_SERVICE : $this->container::IGNORE_MULTIPLE_SERVICE); |
||
| 382 | } |
||
| 383 | |||
| 384 | if ($this->container->typed($id)) { |
||
| 385 | return $this->container->autowired($id, $single); |
||
| 386 | } |
||
| 387 | |||
| 388 | throw new NotFoundServiceException(\sprintf('Service of type "%s" not found. Check class name because it cannot be found.', $id)); |
||
| 389 | } |
||
| 390 | |||
| 391 | /** |
||
| 392 | * Gets the PHP's parser builder. |
||
| 393 | */ |
||
| 394 | public function getBuilder(): ?BuilderFactory |
||
| 395 | { |
||
| 396 | return $this->builder; |
||
| 397 | } |
||
| 398 | |||
| 399 | /** |
||
| 400 | * @return mixed |
||
| 401 | */ |
||
| 402 | private function resolveReference(string $reference) |
||
| 403 | { |
||
| 404 | if ('?' === $reference[0]) { |
||
| 405 | $invalidBehavior = $this->container::EXCEPTION_ON_MULTIPLE_SERVICE; |
||
| 406 | $reference = \substr($reference, 1); |
||
| 407 | |||
| 408 | if ($arrayLike = \str_ends_with('[]', $reference)) { |
||
| 409 | $reference = \substr($reference, 0, -2); |
||
| 410 | $invalidBehavior = $this->container::IGNORE_MULTIPLE_SERVICE; |
||
| 411 | } |
||
| 412 | |||
| 413 | if ($this->container->has($reference) || $this->container->typed($reference)) { |
||
| 414 | return $this->container->get($reference, $invalidBehavior); |
||
| 415 | } |
||
| 416 | |||
| 417 | return $arrayLike ? [] : null; |
||
| 418 | } |
||
| 419 | |||
| 420 | if ('[]' === \substr($reference, -2)) { |
||
| 421 | return $this->container->get(\substr($reference, 0, -2), $this->container::IGNORE_MULTIPLE_SERVICE); |
||
| 422 | } |
||
| 423 | |||
| 424 | return $this->container->get($reference); |
||
| 425 | } |
||
| 426 | |||
| 427 | /** |
||
| 428 | * Resolves services for ServiceLocator. |
||
| 429 | * |
||
| 430 | * @param int|string $id |
||
| 431 | * |
||
| 432 | * @return (\Closure|array|mixed|null)[] |
||
| 433 | */ |
||
| 434 | private function resolveServiceSubscriber($id, string $value): array |
||
| 435 | { |
||
| 436 | if ('?' === $value[0]) { |
||
| 437 | $arrayLike = \str_ends_with($value = \substr($value, 1), '[]'); |
||
| 438 | |||
| 439 | if (\is_int($id)) { |
||
| 440 | $id = $arrayLike ? \substr($value, 0, -2) : $value; |
||
| 441 | } |
||
| 442 | |||
| 443 | return ($this->container->has($id) || $this->container->typed($id)) ? $this->resolveServiceSubscriber($id, $value) : [$id => $arrayLike ? [] : null]; |
||
| 444 | } |
||
| 445 | |||
| 446 | $service = function () use ($value) { |
||
| 447 | if ('[]' === \substr($value, -2)) { |
||
| 448 | $service = $this->container->get(\substr($value, 0, -2), $this->container::IGNORE_MULTIPLE_SERVICE); |
||
| 449 | |||
| 450 | return \is_array($service) ? $service : [$service]; |
||
| 451 | } |
||
| 452 | |||
| 453 | return $this->container->get($value); |
||
| 454 | }; |
||
| 455 | |||
| 456 | if (null !== $this->builder) { |
||
| 457 | if ('[]' === \substr($value, -2)) { |
||
| 458 | $returnType = 'array'; |
||
| 459 | } if ($this->container->has($value)) { |
||
| 460 | $returnType = $this->container->definition($value)->getTypes()[0] ?? ( |
||
| 461 | \class_exists($value) || \interface_exists($value) |
||
| 462 | ? $value |
||
| 463 | : (!\is_int($id) && (\class_exists($id) || \interface_exists($id)) ? $id : null) |
||
| 464 | ); |
||
| 465 | } elseif (\class_exists($value) || \interface_exists($value)) { |
||
| 466 | $returnType = $value; |
||
| 467 | } |
||
| 468 | |||
| 469 | $service = new Expr\ArrowFunction(['expr' => $this->builder->val($service()), 'returnType' => $returnType ?? null]); |
||
| 470 | } |
||
| 471 | |||
| 472 | return [\is_int($id) ? \rtrim($value, '[]') : $id => $service]; |
||
| 473 | } |
||
| 474 | |||
| 475 | /** |
||
| 476 | * Resolves missing argument using autowiring. |
||
| 477 | * |
||
| 478 | * @param array<int|string,mixed> $providedParameters |
||
| 479 | * @param array<int,string> $types |
||
| 480 | * |
||
| 481 | * @throws ContainerResolutionException |
||
| 482 | * |
||
| 483 | * @return mixed |
||
| 484 | */ |
||
| 485 | private function autowireArgument(\ReflectionParameter $parameter, array $types, array $providedParameters) |
||
| 486 | { |
||
| 487 | foreach ($types as $typeName) { |
||
| 488 | if (!Reflection::isBuiltinType($typeName)) { |
||
| 489 | try { |
||
| 490 | return $providedParameters[$typeName] ?? $this->get($typeName, !$parameter->isVariadic()); |
||
| 491 | } catch (NotFoundServiceException $e) { |
||
| 492 | // Ignore this exception ... |
||
| 493 | } catch (ContainerResolutionException $e) { |
||
| 494 | $errorException = new ContainerResolutionException(\sprintf("{$e->getMessage()} (needed by %s)", Reflection::toString($parameter))); |
||
| 495 | } |
||
| 496 | |||
| 497 | if ( |
||
| 498 | ServiceProviderInterface::class === $typeName && |
||
| 499 | null !== $class = $parameter->getDeclaringClass() |
||
| 500 | ) { |
||
| 501 | if (!$class->implementsInterface(ServiceSubscriberInterface::class)) { |
||
| 502 | throw new ContainerResolutionException(\sprintf( |
||
| 503 | 'Service of type %s needs parent class %s to implement %s.', |
||
| 504 | $typeName, |
||
| 505 | $class->getName(), |
||
| 506 | ServiceSubscriberInterface::class |
||
| 507 | )); |
||
| 508 | } |
||
| 509 | |||
| 510 | return $this->get($class->getName()); |
||
| 511 | } |
||
| 512 | } |
||
| 513 | |||
| 514 | if (\PHP_MAJOR_VERSION >= 8 && $attributes = $parameter->getAttributes()) { |
||
| 515 | foreach ($attributes as $attribute) { |
||
| 516 | if (Attribute\Inject::class === $attribute->getName()) { |
||
| 517 | if (null === $attrName = $attribute->getArguments()[0] ?? null) { |
||
| 518 | throw new ContainerResolutionException(\sprintf('Using the Inject attribute on parameter %s requires a value to be set.', $parameter->getName())); |
||
| 519 | } |
||
| 520 | |||
| 521 | if ($arrayLike = \str_ends_with($attrName, '[]')) { |
||
| 522 | $attrName = \substr($attrName, 0, -2); |
||
| 523 | } |
||
| 524 | |||
| 525 | try { |
||
| 526 | return $this->get($attrName, !$arrayLike); |
||
| 527 | } catch (NotFoundServiceException $e) { |
||
| 528 | // Ignore this exception ... |
||
| 529 | } |
||
| 530 | } |
||
| 531 | } |
||
| 532 | } |
||
| 533 | |||
| 534 | if ( |
||
| 535 | ($method = $parameter->getDeclaringFunction()) instanceof \ReflectionMethod |
||
| 536 | && \preg_match('#@param[ \t]+([\w\\\\]+)(?:\[\])?[ \t]+\$' . $parameter->name . '#', (string) $method->getDocComment(), $m) |
||
| 537 | && ($itemType = Reflection::expandClassName($m[1], $method->getDeclaringClass())) |
||
| 538 | && (\class_exists($itemType) || \interface_exists($itemType)) |
||
| 539 | ) { |
||
| 540 | try { |
||
| 541 | if (\in_array($typeName, ['array', 'iterable'], true)) { |
||
| 542 | return $this->get($itemType); |
||
| 543 | } |
||
| 544 | |||
| 545 | if ('object' === $typeName || \is_subclass_of($itemType, $typeName)) { |
||
| 546 | return $this->get($itemType, true); |
||
| 547 | } |
||
| 548 | } catch (NotFoundServiceException $e) { |
||
| 549 | // Ignore this exception ... |
||
| 550 | } |
||
| 551 | } |
||
| 552 | |||
| 553 | if (isset($errorException)) { |
||
| 554 | throw $errorException; |
||
| 555 | } |
||
| 556 | } |
||
| 557 | |||
| 558 | return null; |
||
| 559 | } |
||
| 560 | |||
| 561 | /** |
||
| 562 | * Returns an associated type to the given parameter if available. |
||
| 563 | * |
||
| 564 | * @param \ReflectionParameter|\ReflectionFunctionAbstract $reflection |
||
| 565 | * |
||
| 566 | * @return array<int,string> |
||
| 567 | */ |
||
| 568 | private static function getTypes(\Reflector $reflection): array |
||
| 603 | } |
||
| 604 | |||
| 605 | private static function getDefinitionClass(Definitions\DefinitionInterface $def): ?string |
||
| 606 | { |
||
| 607 | if (!\class_exists($class = $def->getEntity())) { |
||
| 608 | if ($def instanceof Definitions\TypedDefinitionInterface) { |
||
| 609 | foreach ($def->getTypes() as $typed) { |
||
| 610 | if (\class_exists($typed)) { |
||
| 611 | return $typed; |
||
| 612 | } |
||
| 613 | } |
||
| 614 | } |
||
| 615 | |||
| 616 | return null; |
||
| 617 | } |
||
| 618 | |||
| 619 | return $class; |
||
| 620 | } |
||
| 621 | |||
| 622 | /** |
||
| 623 | * Get the parameter's allowed null else error. |
||
| 624 | * |
||
| 625 | * @throws \ReflectionException|ContainerResolutionException |
||
| 626 | * |
||
| 627 | * @return null|void |
||
| 628 | */ |
||
| 629 | private static function getParameterDefaultValue(\ReflectionParameter $parameter, array $types) |
||
| 650 | } |
||
| 651 | } |
||
| 652 |
The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g.
excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths