Passed
Push — master ( d209f7...a05b28 )
by Alexander
07:18
created

ClassDefinition   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 80
Duplicated Lines 0 %

Test Coverage

Coverage 44.12%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 32
c 2
b 0
f 0
dl 0
loc 80
ccs 15
cts 34
cp 0.4412
rs 10
wmc 13

5 Methods

Rating   Name   Duplication   Size   Complexity  
A resolveUnionType() 0 24 5
A resolve() 0 20 5
A __construct() 0 4 1
A getType() 0 3 1
A isUnionType() 0 3 1
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
use function gettype;
10
11
/**
12
 * Reference points to a class name in the container
13
 */
14
class ClassDefinition implements DefinitionInterface
15
{
16
    private string $class;
17
    private bool $optional;
18
19
    /**
20
     * Constructor.
21
     *
22
     * @param string $class the class name
23
     * @param bool $optional if null should be returned instead of throwing an exception
24
     */
25 7
    public function __construct(string $class, bool $optional)
26
    {
27 7
        $this->class = $class;
28 7
        $this->optional = $optional;
29 7
    }
30
31
    public function getType(): string
32
    {
33
        return $this->class;
34
    }
35
36 9
    public function resolve(ContainerInterface $container)
37
    {
38 9
        if ($this->isUnionType()) {
39
            return $this->resolveUnionType($container);
40
        }
41
42
        try {
43 9
            $result = $container->get($this->class);
44 5
        } catch (\Throwable $t) {
45 5
            if ($this->optional) {
46 4
                return null;
47
            }
48 3
            throw $t;
49
        }
50
51 4
        if (!$result instanceof $this->class) {
52
            $actualType = gettype($this->class);
53
            throw new InvalidConfigException("Container returned incorrect type \"$actualType\" for service \"$this->class\".");
54
        }
55 4
        return $result;
56
    }
57
58
    /**
59
     * @param ContainerInterface $container
60
     *
61
     * @throws \Throwable
62
     *
63
     * @return mixed
64
     */
65
    private function resolveUnionType(ContainerInterface $container)
66
    {
67
        $types = explode('|', $this->class);
68
69
        $error = null;
70
71
        foreach ($types as $type) {
72
            try {
73
                $result = $container->get($type);
74
                if (!$result instanceof $type) {
75
                    $actualType = gettype($this->class);
76
                    throw new InvalidConfigException("Container returned incorrect type \"$actualType\" for service \"$this->class\".");
77
                }
78
                return $result;
79
            } catch (\Throwable $t) {
80
                $error = $t;
81
            }
82
        }
83
84
        if ($this->optional) {
85
            return null;
86
        }
87
88
        throw $error;
89
    }
90
91 9
    private function isUnionType(): bool
92
    {
93 9
        return strpos($this->class, '|') !== false;
94
    }
95
}
96