Passed
Pull Request — master (#78)
by Dmitriy
02:32
created

ClassDefinition::resolve()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 23
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 5.7283

Importance

Changes 0
Metric Value
eloc 13
dl 0
loc 23
ccs 9
cts 13
cp 0.6923
rs 9.5222
c 0
b 0
f 0
cc 5
nc 5
nop 1
crap 5.7283
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Factory\Definition;
6
7
use Psr\Container\ContainerInterface;
8
use Throwable;
9
use Yiisoft\Factory\Exception\InvalidConfigException;
10
11
use function gettype;
12
13
/**
14
 * Reference points to a class name in the container
15
 */
16
class ClassDefinition implements DefinitionInterface
17
{
18
    private string $class;
19
    private bool $optional;
20
21
    /**
22
     * Constructor.
23
     *
24
     * @param string $class the class name
25
     * @param bool $optional if null should be returned instead of throwing an exception
26
     */
27 7
    public function __construct(string $class, bool $optional)
28
    {
29 7
        $this->class = $class;
30 7
        $this->optional = $optional;
31 7
    }
32
33
    public function getType(): string
34
    {
35
        return $this->class;
36
    }
37
38 7
    public function resolve(ContainerInterface $container)
39
    {
40 7
        if ($this->isUnionType()) {
41
            return $this->resolveUnionType($container);
42
        }
43
44
        try {
45
            /** @var mixed */
46 7
            $result = $container->get($this->class);
47 5
        } catch (Throwable $t) {
48 5
            if ($this->optional) {
49 4
                return null;
50
            }
51 3
            throw $t;
52
        }
53
54 2
        if (!$result instanceof $this->class) {
55
            $actualType = gettype($this->class);
56
            throw new InvalidConfigException(
57
                "Container returned incorrect type \"$actualType\" for service \"$this->class\"."
58
            );
59
        }
60 2
        return $result;
61
    }
62
63
    /**
64
     * @throws Throwable
65
     *
66
     * @return mixed
67
     */
68
    private function resolveUnionType(ContainerInterface $container)
69
    {
70
        $types = explode('|', $this->class);
71
72
        foreach ($types as $type) {
73
            try {
74
                /** @var mixed */
75
                $result = $container->get($type);
76
                if (!$result instanceof $type) {
77
                    $actualType = gettype($this->class);
78
                    throw new InvalidConfigException(
79
                        "Container returned incorrect type \"$actualType\" for service \"$this->class\"."
80
                    );
81
                }
82
                return $result;
83
            } catch (Throwable $t) {
84
                $error = $t;
85
            }
86
        }
87
88
        if ($this->optional) {
89
            return null;
90
        }
91
92
        throw $error;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $error seems to be defined by a foreach iteration on line 72. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
93
    }
94
95 7
    private function isUnionType(): bool
96
    {
97 7
        return strpos($this->class, '|') !== false;
98
    }
99
}
100