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

ClassDefinition::resolve()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 19
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 5.1502

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 11
nc 5
nop 1
dl 0
loc 19
ccs 9
cts 11
cp 0.8182
crap 5.1502
rs 9.6111
c 1
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Factory\Definitions;
6
7
use Psr\Container\ContainerInterface;
8
use Yiisoft\Factory\Exceptions\InvalidConfigException;
9
10
/**
11
 * Reference points to a class name in the container
12
 */
13
class ClassDefinition implements DefinitionInterface
14
{
15
    private string $class;
16
    private bool $optional;
17
18
    /**
19
     * Constructor.
20
     * @param string $class the class name
21
     * @param bool $optional if null should be returned instead of throwing an exception
22
     */
23 7
    public function __construct(string $class, bool $optional)
24
    {
25 7
        $this->class = $class;
26 7
        $this->optional = $optional;
27 7
    }
28
29
    public function getType(): string
30
    {
31
        return $this->class;
32
    }
33
34 9
    public function resolve(ContainerInterface $container)
35
    {
36 9
        if ($this->isUnionType()) {
37
            return $this->resolveUnionType($container);
38
        }
39
40
        try {
41 9
            $result = $container->get($this->class);
42 5
        } catch (\Throwable $t) {
43 5
            if ($this->optional) {
44 4
                return null;
45
            }
46 3
            throw $t;
47
        }
48
49 4
        if (!$result instanceof $this->class) {
50
            throw new InvalidConfigException('Container returned incorrect type for service ' . $this->class);
51
        }
52 4
        return $result;
53
    }
54
55
    /**
56
     * @param ContainerInterface $container
57
     * @return mixed
58
     * @throws \Throwable
59
     */
60
    private function resolveUnionType(ContainerInterface $container)
61
    {
62
        $types = explode('|', $this->class);
63
64
        $error = null;
65
66
        foreach ($types as $type) {
67
            try {
68
                $result = $container->get($type);
69
                if (!$result instanceof $type) {
70
                    throw new InvalidConfigException('Container returned incorrect type for service ' . $type);
71
                }
72
                return $result;
73
            } catch (\Throwable $t) {
74
                $error = $t;
75
            }
76
        }
77
78
        if ($this->optional) {
79
            return null;
80
        }
81
82
        throw $error;
83
    }
84
85 9
    private function isUnionType(): bool
86
    {
87 9
        return strpos($this->class, '|') !== false;
88
    }
89
}
90