| Total Complexity | 186 |
| Total Lines | 623 |
| Duplicated Lines | 0 % |
| Changes | 18 | ||
| Bugs | 1 | 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 |
||
| 32 | class Resolver |
||
| 33 | { |
||
| 34 | private AbstractContainer $container; |
||
| 35 | private ?BuilderFactory $builder; |
||
| 36 | private bool $strict = true; |
||
| 37 | |||
| 38 | /** @var array<string,\PhpParser\Node> */ |
||
| 39 | private array $literalCache = []; |
||
| 40 | |||
| 41 | public function __construct(AbstractContainer $container, BuilderFactory $builder = null) |
||
| 42 | { |
||
| 43 | $this->builder = $builder; |
||
| 44 | $this->container = $container; |
||
| 45 | } |
||
| 46 | |||
| 47 | /** |
||
| 48 | * The method name generated for a service definition. |
||
| 49 | */ |
||
| 50 | public static function createMethod(string $id): string |
||
| 51 | { |
||
| 52 | return 'get' . \str_replace(['.', '_', '\\'], '', \ucwords($id, '._')); |
||
| 53 | } |
||
| 54 | |||
| 55 | /** |
||
| 56 | * If true, exception will be thrown on resolvable services with are not typed. |
||
| 57 | */ |
||
| 58 | public function setStrictAutowiring(bool $boolean = true): void |
||
| 59 | { |
||
| 60 | $this->strict = $boolean; |
||
| 61 | } |
||
| 62 | |||
| 63 | /** |
||
| 64 | * @param mixed $definition |
||
| 65 | */ |
||
| 66 | public static function autowireService($definition, bool $allTypes = false, AbstractContainer $container = null): array |
||
| 67 | { |
||
| 68 | $types = $autowired = []; |
||
| 69 | |||
| 70 | if (\is_callable($definition)) { |
||
| 71 | $types = \array_filter(self::getTypes(Callback::toReflection($definition)), fn (string $v) => \class_exists($v) || \interface_exists($v) || $allTypes); |
||
| 72 | } elseif (\is_object($definition)) { |
||
| 73 | if ($definition instanceof \stdClass) { |
||
| 74 | return $allTypes ? ['object'] : $types; |
||
| 75 | } |
||
| 76 | |||
| 77 | $types[] = \get_class($definition); |
||
| 78 | } elseif (\is_string($definition)) { |
||
| 79 | if (!(\class_exists($definition) || \interface_exists($definition))) { |
||
| 80 | return $allTypes ? ['string'] : []; |
||
| 81 | } |
||
| 82 | |||
| 83 | $types[] = $definition; |
||
| 84 | } elseif (\is_array($definition)) { |
||
| 85 | if (null !== $container && 2 === \count($definition, \COUNT_RECURSIVE)) { |
||
| 86 | if ($definition[0] instanceof Definitions\Reference) { |
||
| 87 | $def = $container->definition((string) $definition[0]); |
||
| 88 | } elseif ($definition[0] instanceof Expr\BinaryOp\Coalesce) { |
||
| 89 | $def = $container->definition($definition[0]->left->dim->value); |
||
| 90 | } |
||
| 91 | |||
| 92 | if (isset($def)) { |
||
| 93 | if ($def instanceof Definitions\DefinitionInterface) { |
||
| 94 | $class = self::getDefinitionClass($def); |
||
| 95 | |||
| 96 | if (null === $class) { |
||
| 97 | return []; |
||
| 98 | } |
||
| 99 | } |
||
| 100 | $types = self::getTypes(new \ReflectionMethod($class ?? $def, $definition[1])); |
||
| 101 | goto resolve_types; |
||
| 102 | } |
||
| 103 | } |
||
| 104 | |||
| 105 | return $allTypes ? ['array'] : []; |
||
| 106 | } |
||
| 107 | |||
| 108 | resolve_types: |
||
| 109 | foreach ($types as $type) { |
||
| 110 | $autowired[] = $type; |
||
| 111 | |||
| 112 | foreach (\class_implements($type) ?: [] as $interface) { |
||
| 113 | $autowired[] = $interface; |
||
| 114 | } |
||
| 115 | |||
| 116 | foreach (\class_parents($type) ?: [] as $parent) { |
||
| 117 | $autowired[] = $parent; |
||
| 118 | } |
||
| 119 | } |
||
| 120 | |||
| 121 | return $autowired; |
||
| 122 | } |
||
| 123 | |||
| 124 | /** |
||
| 125 | * Resolves arguments for callable. |
||
| 126 | * |
||
| 127 | * @param array<int|string,mixed> $args |
||
| 128 | * |
||
| 129 | * @return array<int,mixed> |
||
| 130 | */ |
||
| 131 | public function autowireArguments(\ReflectionFunctionAbstract $function, array $args = []): array |
||
| 132 | { |
||
| 133 | $resolvedParameters = []; |
||
| 134 | $nullValuesFound = 0; |
||
| 135 | $args = $this->resolveArguments($args); // Resolves provided arguments. |
||
| 136 | |||
| 137 | foreach ($function->getParameters() as $offset => $parameter) { |
||
| 138 | $position = 0 === $nullValuesFound ? $offset : $parameter->name; |
||
| 139 | $resolved = $args[$offset] ?? $args[$parameter->name] ?? null; |
||
| 140 | $types = self::getTypes($parameter) ?: ['null']; |
||
| 141 | |||
| 142 | if (\PHP_VERSION_ID >= 80100 && (\count($types) >= 1 && \is_subclass_of($enumType = $types[0], \BackedEnum::class))) { |
||
|
|
|||
| 143 | if (null === $resolved = ($resolved ?? $args[$enumType] ?? null)) { |
||
| 144 | throw new ContainerResolutionException(\sprintf('Missing value for enum parameter %s.', Reflection::toString($parameter))); |
||
| 145 | } |
||
| 146 | |||
| 147 | try { |
||
| 148 | $resolvedParameters[$position] = $enumType::from($resolved); |
||
| 149 | } catch (\ValueError $e) { |
||
| 150 | throw new ContainerResolutionException(\sprintf('The "%s" value could not be resolved for enum parameter %s.', $resolved, Reflection::toString($parameter)), 0, $e); |
||
| 151 | } |
||
| 152 | continue; |
||
| 153 | } |
||
| 154 | |||
| 155 | if (null === ($resolved = $resolved ?? $this->autowireArgument($parameter, $types, $args))) { |
||
| 156 | if ($parameter->isDefaultValueAvailable()) { |
||
| 157 | if (\PHP_MAJOR_VERSION < 8) { |
||
| 158 | $resolvedParameters[$position] = Reflection::getParameterDefaultValue($parameter); |
||
| 159 | } else { |
||
| 160 | ++$nullValuesFound; |
||
| 161 | } |
||
| 162 | } elseif (!$parameter->isVariadic()) { |
||
| 163 | $resolvedParameters[$position] = self::getParameterDefaultValue($parameter, $types); |
||
| 164 | } |
||
| 165 | |||
| 166 | continue; |
||
| 167 | } |
||
| 168 | |||
| 169 | if ($parameter->isVariadic() && \is_array($resolved)) { |
||
| 170 | $resolvedParameters = \array_merge($resolvedParameters, $resolved); |
||
| 171 | continue; |
||
| 172 | } |
||
| 173 | |||
| 174 | $resolvedParameters[$position] = $resolved; |
||
| 175 | } |
||
| 176 | |||
| 177 | return $resolvedParameters; |
||
| 178 | } |
||
| 179 | |||
| 180 | /** |
||
| 181 | * Resolve a service definition, class string, invocable object or callable |
||
| 182 | * using autowiring. |
||
| 183 | * |
||
| 184 | * @param string|callable|object $callback |
||
| 185 | * @param array<int|string,mixed> $args |
||
| 186 | * |
||
| 187 | * @throws ContainerResolutionException|\ReflectionException if unresolvable |
||
| 188 | * |
||
| 189 | * @return mixed |
||
| 190 | */ |
||
| 191 | public function resolve($callback, array $args = []) |
||
| 192 | { |
||
| 193 | if ($callback instanceof Definitions\Parameter) { |
||
| 194 | if (!\array_key_exists($param = (string) $callback, $this->container->parameters)) { |
||
| 195 | if (!$callback->shouldResolve()) { |
||
| 196 | throw new ContainerResolutionException(\sprintf('The parameter "%s" is not defined.', $param)); |
||
| 197 | } |
||
| 198 | |||
| 199 | return null === $this->builder ? $this->container->parameter($param) : $this->builder->methodCall(new Expr\Variable('this'), 'parameter', [$param]); |
||
| 200 | } |
||
| 201 | |||
| 202 | if (null !== $this->builder) { |
||
| 203 | return $resolved = new Expr\ArrayDimFetch($this->builder->propertyFetch(new Expr\Variable('this'), 'parameters'), new String_($param)); |
||
| 204 | } |
||
| 205 | |||
| 206 | $resolved = $this->container->parameters[$param]; |
||
| 207 | } elseif ($callback instanceof Definitions\Statement) { |
||
| 208 | $resolved = $this->resolve($callback->getValue(), $callback->getArguments() + $args); |
||
| 209 | |||
| 210 | if ($callback->isClosureWrappable()) { |
||
| 211 | $resolved = null === $this->builder ? fn () => $resolved : new Expr\ArrowFunction(['expr' => $resolved]); |
||
| 212 | } |
||
| 213 | } elseif ($callback instanceof Definitions\Reference) { |
||
| 214 | $resolved = $this->resolveReference((string) $callback); |
||
| 215 | |||
| 216 | if (\is_callable($resolved) || (\is_array($resolved) && 2 === \count($resolved, \COUNT_RECURSIVE))) { |
||
| 217 | $resolved = $this->resolveCallable($resolved, $args); |
||
| 218 | } else { |
||
| 219 | $callback = $resolved; |
||
| 220 | } |
||
| 221 | } elseif ($callback instanceof Definitions\ValueDefinition) { |
||
| 222 | $resolved = $callback->getEntity(); |
||
| 223 | } elseif ($callback instanceof Definitions\TaggedLocator) { |
||
| 224 | $resolved = $this->resolve($callback->resolve($this->container)); |
||
| 225 | } elseif ($callback instanceof Builder\PhpLiteral) { |
||
| 226 | $expression = $this->literalCache[\spl_object_id($callback)] ??= $callback->resolve($this)[0]; |
||
| 227 | $resolved = $expression instanceof Stmt\Expression ? $expression->expr : $expression; |
||
| 228 | } elseif (Services\ServiceLocator::class === $callback) { |
||
| 229 | $services = []; |
||
| 230 | |||
| 231 | foreach ($args as $name => $service) { |
||
| 232 | $services += $this->resolveServiceSubscriber($name, (string) $service); |
||
| 233 | } |
||
| 234 | $resolved = null === $this->builder ? new Services\ServiceLocator($services) : $this->builder->new('\\' . Services\ServiceLocator::class, [$services]); |
||
| 235 | } elseif (\is_string($callback)) { |
||
| 236 | if (\str_contains($callback, '%')) { |
||
| 237 | $callback = $this->container->parameter($callback); |
||
| 238 | } |
||
| 239 | |||
| 240 | if (\class_exists($callback)) { |
||
| 241 | return $this->resolveClass($callback, $args); |
||
| 242 | } |
||
| 243 | |||
| 244 | if (\is_callable($callback)) { |
||
| 245 | $resolved = $this->resolveCallable($callback, $args); |
||
| 246 | } |
||
| 247 | } elseif (\is_callable($callback) || \is_array($callback)) { |
||
| 248 | $resolved = $this->resolveCallable($callback, $args); |
||
| 249 | } |
||
| 250 | |||
| 251 | return $resolved ?? (null === $this->builder ? $callback : $this->builder->val($callback)); |
||
| 252 | } |
||
| 253 | |||
| 254 | /** |
||
| 255 | * Resolves callables and array like callables. |
||
| 256 | * |
||
| 257 | * @param callable|array<int,mixed> $callback |
||
| 258 | * @param array<int|string,mixed> $arguments |
||
| 259 | * |
||
| 260 | * @throws \ReflectionException if $callback is not a real callable |
||
| 261 | * |
||
| 262 | * @return mixed |
||
| 263 | */ |
||
| 264 | public function resolveCallable($callback, array $arguments = []) |
||
| 265 | { |
||
| 266 | if (\is_array($callback)) { |
||
| 267 | if ((2 === \count($callback) && \array_is_list($callback)) && \is_string($callback[1])) { |
||
| 268 | $callback[0] = $this->resolve($callback[0]); |
||
| 269 | |||
| 270 | if ($callback[0] instanceof Expr\BinaryOp\Coalesce) { |
||
| 271 | $class = self::getDefinitionClass($this->container->definition($callback[0]->left->dim->value)); |
||
| 272 | |||
| 273 | if (null !== $class) { |
||
| 274 | $type = [$class, $callback[1]]; |
||
| 275 | } |
||
| 276 | } elseif ($callback[0] instanceof Expr\New_) { |
||
| 277 | $type = [(string) $callback[0]->class, $callback[1]]; |
||
| 278 | } |
||
| 279 | |||
| 280 | if (isset($type) || \is_callable($callback)) { |
||
| 281 | goto create_callable; |
||
| 282 | } |
||
| 283 | } |
||
| 284 | |||
| 285 | $callback = $this->resolveArguments($callback); |
||
| 286 | |||
| 287 | return null === $this->builder ? $callback : $this->builder->val($callback); |
||
| 288 | } |
||
| 289 | |||
| 290 | create_callable: |
||
| 291 | $args = $this->autowireArguments($ref = Callback::toReflection($type ?? $callback), $arguments); |
||
| 292 | |||
| 293 | if ($ref instanceof \ReflectionFunction) { |
||
| 294 | return null === $this->builder ? $ref->invokeArgs($args) : $this->builder->funcCall($callback, $args); |
||
| 295 | } |
||
| 296 | |||
| 297 | if ($ref->isStatic()) { |
||
| 298 | $className = \is_array($callback) ? $callback[0] : $ref->getDeclaringClass()->getName(); |
||
| 299 | |||
| 300 | return null === $this->builder ? $ref->invokeArgs(null, $args) : $this->builder->staticCall($className, $ref->getName(), $args); |
||
| 301 | } |
||
| 302 | |||
| 303 | return null === $this->builder ? $callback(...$args) : $this->builder->methodCall($callback[0], $ref->getName(), $args); |
||
| 304 | } |
||
| 305 | |||
| 306 | /** |
||
| 307 | * @param array<int|string,mixed> $args |
||
| 308 | * |
||
| 309 | * @throws ContainerResolutionException|\ReflectionException if class string unresolvable |
||
| 310 | */ |
||
| 311 | public function resolveClass(string $class, array $args = []): object |
||
| 336 | } |
||
| 337 | |||
| 338 | /** |
||
| 339 | * @param array<int|string,mixed> $arguments |
||
| 340 | * |
||
| 341 | * @return array<int|string,mixed> |
||
| 342 | */ |
||
| 343 | public function resolveArguments(array $arguments = []): array |
||
| 370 | } |
||
| 371 | |||
| 372 | /** |
||
| 373 | * Resolves service by type. |
||
| 374 | * |
||
| 375 | * @param string $id A class or an interface name |
||
| 376 | * |
||
| 377 | * @return mixed |
||
| 378 | */ |
||
| 379 | public function get(string $id, bool $single = false) |
||
| 404 | } |
||
| 405 | |||
| 406 | /** |
||
| 407 | * Gets the PHP's parser builder. |
||
| 408 | */ |
||
| 409 | public function getBuilder(): ?BuilderFactory |
||
| 412 | } |
||
| 413 | |||
| 414 | /** |
||
| 415 | * @return mixed |
||
| 416 | */ |
||
| 417 | public function resolveReference(string $reference) |
||
| 418 | { |
||
| 419 | $invalidBehavior = $this->container::EXCEPTION_ON_MULTIPLE_SERVICE; |
||
| 420 | |||
| 421 | if ('?' === $reference[0]) { |
||
| 422 | $invalidBehavior = $this->container::NULL_ON_INVALID_SERVICE; |
||
| 423 | $reference = \substr($reference, 1); |
||
| 424 | } |
||
| 425 | |||
| 426 | if (1 === \preg_match('/\[(.*?)?\]$/', $reference, $matches, \PREG_UNMATCHED_AS_NULL)) { |
||
| 427 | $reference = \str_replace($matches[0], '', $reference); |
||
| 428 | $autowired = $this->container->typed($reference, true); |
||
| 429 | |||
| 430 | if (\is_numeric($k = $matches[1] ?? null) && isset($autowired[$k])) { |
||
| 431 | return $this->container->get($autowired[$k], $invalidBehavior); |
||
| 432 | } |
||
| 433 | |||
| 434 | if (!empty($autowired)) { |
||
| 435 | return \array_map([$this->container, 'get'], $autowired); |
||
| 436 | } |
||
| 437 | |||
| 438 | if (null === $service = $this->container->get($reference, $invalidBehavior)) { |
||
| 439 | return []; |
||
| 440 | } |
||
| 441 | |||
| 442 | return [$service]; |
||
| 443 | } |
||
| 444 | |||
| 445 | return $this->container->get($reference, $invalidBehavior); |
||
| 446 | } |
||
| 447 | |||
| 448 | /** |
||
| 449 | * Resolves services for ServiceLocator. |
||
| 450 | * |
||
| 451 | * @param int|string $id |
||
| 452 | * |
||
| 453 | * @return (\Closure|array|mixed|null)[] |
||
| 454 | */ |
||
| 455 | public function resolveServiceSubscriber($id, string $value): array |
||
| 456 | { |
||
| 457 | $service = fn () => $this->resolveReference($value); |
||
| 458 | |||
| 459 | if (null !== $this->builder) { |
||
| 460 | $type = \rtrim(\ltrim($value, '?'), '[]'); |
||
| 461 | |||
| 462 | if ('[]' === \substr($value, -2)) { |
||
| 463 | $returnType = 'array'; |
||
| 464 | } elseif ($this->container->has($type) && ($def = $this->container->definition($type)) instanceof Definitions\TypedDefinitionInterface) { |
||
| 465 | $returnType = $def->getTypes()[0] ?? ( |
||
| 466 | \class_exists($type) || \interface_exists($type) |
||
| 467 | ? $type |
||
| 468 | : (!\is_int($id) && (\class_exists($id) || \interface_exists($id)) ? $id : null) |
||
| 469 | ); |
||
| 470 | } elseif (\class_exists($type) || \interface_exists($type)) { |
||
| 471 | $returnType = $type; |
||
| 472 | } |
||
| 473 | |||
| 474 | $service = new Expr\ArrowFunction(['expr' => $this->builder->val($service()), 'returnType' => $returnType ?? null]); |
||
| 475 | } |
||
| 476 | |||
| 477 | return [\is_int($id) ? ($type ?? \rtrim(\ltrim($value, '?'), '[]')) : $id => $service]; |
||
| 478 | } |
||
| 479 | |||
| 480 | /** |
||
| 481 | * Resolves missing argument using autowiring. |
||
| 482 | * |
||
| 483 | * @param array<int|string,mixed> $providedParameters |
||
| 484 | * @param array<int,string> $types |
||
| 485 | * |
||
| 486 | * @throws ContainerResolutionException |
||
| 487 | * |
||
| 488 | * @return mixed |
||
| 489 | */ |
||
| 490 | public function autowireArgument(\ReflectionParameter $parameter, array $types, array $providedParameters) |
||
| 491 | { |
||
| 492 | foreach ($types as $typeName) { |
||
| 493 | if (\PHP_MAJOR_VERSION >= 8 && $attributes = $parameter->getAttributes()) { |
||
| 494 | foreach ($attributes as $attribute) { |
||
| 495 | if (Attribute\Inject::class === $attribute->getName()) { |
||
| 496 | try { |
||
| 497 | return $attribute->newInstance()->resolve($this, $typeName); |
||
| 498 | } catch (NotFoundServiceException $e) { |
||
| 499 | // Ignore this exception ... |
||
| 500 | } |
||
| 501 | } |
||
| 502 | |||
| 503 | if (Attribute\Tagged::class === $attribute->getName()) { |
||
| 504 | return $this->resolveArguments($attribute->newInstance()->getValues($this->container)); |
||
| 505 | } |
||
| 506 | } |
||
| 507 | } |
||
| 508 | |||
| 509 | if (!Reflection::isBuiltinType($typeName)) { |
||
| 510 | try { |
||
| 511 | return $providedParameters[$typeName] ?? $this->get($typeName, !$parameter->isVariadic()); |
||
| 512 | } catch (NotFoundServiceException $e) { |
||
| 513 | // Ignore this exception ... |
||
| 514 | } catch (ContainerResolutionException $e) { |
||
| 515 | $errorException = new ContainerResolutionException(\sprintf("{$e->getMessage()} (needed by %s)", Reflection::toString($parameter))); |
||
| 516 | } |
||
| 517 | |||
| 518 | if ( |
||
| 519 | ServiceProviderInterface::class === $typeName && |
||
| 520 | null !== $class = $parameter->getDeclaringClass() |
||
| 521 | ) { |
||
| 522 | if (!$class->implementsInterface(ServiceSubscriberInterface::class)) { |
||
| 523 | throw new ContainerResolutionException(\sprintf( |
||
| 524 | 'Service of type %s needs parent class %s to implement %s.', |
||
| 525 | $typeName, |
||
| 526 | $class->getName(), |
||
| 527 | ServiceSubscriberInterface::class |
||
| 528 | )); |
||
| 529 | } |
||
| 530 | |||
| 531 | return $this->get($class->getName()); |
||
| 532 | } |
||
| 533 | } |
||
| 534 | |||
| 535 | if ( |
||
| 536 | ($method = $parameter->getDeclaringFunction()) instanceof \ReflectionMethod |
||
| 537 | && \preg_match('#@param[ \t]+([\w\\\\]+)(?:\[\])?[ \t]+\$' . $parameter->name . '#', (string) $method->getDocComment(), $m) |
||
| 538 | && ($itemType = Reflection::expandClassName($m[1], $method->getDeclaringClass())) |
||
| 539 | && (\class_exists($itemType) || \interface_exists($itemType)) |
||
| 540 | ) { |
||
| 541 | try { |
||
| 542 | if (\in_array($typeName, ['array', 'iterable'], true)) { |
||
| 543 | return $this->get($itemType); |
||
| 544 | } |
||
| 545 | |||
| 546 | if ('object' === $typeName || \is_subclass_of($itemType, $typeName)) { |
||
| 547 | return $this->get($itemType, true); |
||
| 548 | } |
||
| 549 | } catch (NotFoundServiceException $e) { |
||
| 550 | // Ignore this exception ... |
||
| 551 | } |
||
| 552 | } |
||
| 553 | |||
| 554 | if (isset($errorException)) { |
||
| 555 | throw $errorException; |
||
| 556 | } |
||
| 557 | } |
||
| 558 | |||
| 559 | return null; |
||
| 560 | } |
||
| 561 | |||
| 562 | /** |
||
| 563 | * Returns an associated type to the given parameter if available. |
||
| 564 | * |
||
| 565 | * @param \ReflectionParameter|\ReflectionFunctionAbstract $reflection |
||
| 566 | * |
||
| 567 | * @return array<int,string> |
||
| 568 | */ |
||
| 569 | public static function getTypes(\Reflector $reflection): array |
||
| 604 | } |
||
| 605 | |||
| 606 | private static function getDefinitionClass(Definitions\DefinitionInterface $def): ?string |
||
| 607 | { |
||
| 608 | if (!\is_string($class = $def->getEntity())) { |
||
| 609 | return null; |
||
| 610 | } |
||
| 611 | |||
| 612 | if (!\class_exists($class)) { |
||
| 613 | if ($def instanceof Definitions\TypedDefinitionInterface) { |
||
| 614 | foreach ($def->getTypes() as $typed) { |
||
| 615 | if (\class_exists($typed)) { |
||
| 616 | return $typed; |
||
| 617 | } |
||
| 618 | } |
||
| 619 | } |
||
| 620 | |||
| 621 | return null; |
||
| 622 | } |
||
| 623 | |||
| 624 | return $class; |
||
| 625 | } |
||
| 626 | |||
| 627 | /** |
||
| 628 | * Get the parameter's allowed null else error. |
||
| 629 | * |
||
| 630 | * @throws \ReflectionException|ContainerResolutionException |
||
| 631 | * |
||
| 632 | * @return void|null |
||
| 633 | */ |
||
| 634 | private static function getParameterDefaultValue(\ReflectionParameter $parameter, array $types) |
||
| 655 | } |
||
| 656 | } |
||
| 657 |
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