Passed
Push — master ( db49f9...b5d0c3 )
by Alexander
01:42
created

DefinitionExtractor::fromFunction()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 4
dl 0
loc 7
ccs 5
cts 5
cp 1
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 1
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Factory\Extractors;
6
7
use Yiisoft\Factory\Definitions\ClassDefinition;
8
use Yiisoft\Factory\Definitions\DefinitionInterface;
9
use Yiisoft\Factory\Definitions\ParameterDefinition;
10
use Yiisoft\Factory\Exceptions\NotInstantiableException;
11
12
/**
13
 * Class DefinitionExtractor
14
 * This implementation resolves dependencies by using class type hints.
15
 * Note that service names need not match the parameter names, parameter names are ignored
16
 */
17
class DefinitionExtractor implements ExtractorInterface
18
{
19 12
    public function fromClassName(string $class): array
20
    {
21 12
        $reflectionClass = new \ReflectionClass($class);
22 12
        if (!$reflectionClass->isInstantiable()) {
23 5
            throw new NotInstantiableException($class);
24
        }
25 12
        $constructor = $reflectionClass->getConstructor();
26 12
        return $constructor === null ? [] : $this->fromFunction($constructor);
27
    }
28
29
    /**
30
     * @suppress PhanUndeclaredMethod
31
     */
32 10
    private function fromFunction(\ReflectionFunctionAbstract $reflectionFunction): array
33
    {
34 10
        $result = [];
35 10
        foreach ($reflectionFunction->getParameters() as $parameter) {
36 10
            $result[$parameter->getName()] = $this->fromParameter($parameter);
37
        }
38 10
        return $result;
39
    }
40
41
    /**
42
     * @suppress PhanUndeclaredMethod
43
     */
44 10
    private function fromParameter(\ReflectionParameter $parameter): DefinitionInterface
45
    {
46 10
        $type = $parameter->getType();
47
48
        // PHP 8 union type is used as type hint
49 10
        if ($type instanceof \ReflectionUnionType) {
0 ignored issues
show
Bug introduced by
The type ReflectionUnionType was not found. Maybe you did not declare it correctly or list all dependencies?

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:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
50
            $types = [];
51
            foreach ($type->getTypes() as $unionType) {
0 ignored issues
show
Bug introduced by
The method getTypes() does not exist on ReflectionType. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

51
            foreach ($type->/** @scrutinizer ignore-call */ getTypes() as $unionType) {

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
52
                if (!$unionType->isBuiltin()) {
53
                    $types[] = $unionType->getName();
54
                }
55
            }
56
            return new ClassDefinition(implode('|', $types), $type->allowsNull());
57
        }
58
59
        // Our parameter has a class type hint
60 10
        if ($type !== null && !$type->isBuiltin()) {
61 7
            return new ClassDefinition($type->getName(), $type->allowsNull());
62
        }
63
64
        // Our parameter does not have a class type hint and either has a default value or is nullable.
65 4
        return new ParameterDefinition(
66
            $parameter,
67 4
            $parameter->isDefaultValueAvailable() ? $parameter->getDefaultValue() : null,
68 4
            $type !== null ? $type->getName() : null
69
        );
70
    }
71
72
    public function fromCallable(callable $callable): array
73
    {
74
        return $this->fromFunction(new \ReflectionFunction(\Closure::fromCallable($callable)));
75
    }
76
}
77