Completed
Push — master ( 92f9f2...364227 )
by Ryuichi
03:12 queued 01:49
created

Injector::strictInject()   B

Complexity

Conditions 5
Paths 13

Size

Total Lines 23
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 5

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 23
ccs 12
cts 12
cp 1
rs 8.5906
cc 5
eloc 16
nc 13
nop 2
crap 5
1
<?php
2
namespace WebStream\DI;
3
4
use WebStream\Container\Container;
5
use WebStream\Exception\Extend\AnnotationException;
6
use PhpDocReader\PhpDocReader;
7
8
/**
9
 * Injector
10
 * @author Ryuichi TANAKA.
11
 * @since 2015/12/26
12
 * @version 0.7
13
 */
14
trait Injector
15
{
16
    /**
17
     * @var Container プロパティコンテナ
18
     */
19
    private $__propertyContainer;
20
21
    /**
22
     * オブジェクトを注入する
23
     * @param string プロパティ名
24
     * @param mixed オブジェクト
25
     * @return Injector
0 ignored issues
show
Comprehensibility Bug introduced by
The return type Injector is a trait, and thus cannot be used for type-hinting in PHP. Maybe consider adding an interface and use that for type-hinting?

In PHP traits cannot be used for type-hinting as they do not define a well-defined structure. This is because any class that uses a trait can rename that trait’s methods.

If you would like to return an object that has a guaranteed set of methods, you could create a companion interface that lists these methods explicitly.

Loading history...
26
     */
27 3
    public function inject(string $name, $object)
28
    {
29 3
        $this->{$name} = $object;
30
31 3
        return $this;
32
    }
33
34
    /**
35
     * 型指定されたオブジェクトを注入する
36
     * @param string プロパティ名
37
     * @param mixed オブジェクト
38
     * @return Injector
0 ignored issues
show
Comprehensibility Bug introduced by
The return type Injector is a trait, and thus cannot be used for type-hinting in PHP. Maybe consider adding an interface and use that for type-hinting?

In PHP traits cannot be used for type-hinting as they do not define a well-defined structure. This is because any class that uses a trait can rename that trait’s methods.

If you would like to return an object that has a guaranteed set of methods, you could create a companion interface that lists these methods explicitly.

Loading history...
39
     */
40 4
    public function strictInject(string $name, $object)
41
    {
42 4
        $reader = new PhpDocReader();
43
        try {
44 4
            $refClass = new \ReflectionClass($this);
45 4
            while ($refClass !== false) {
46 4
                if ($refClass->hasProperty($name)) {
47 3
                    $refProperty = $refClass->getProperty($name);
48 3
                    $classpath = $reader->getPropertyClass($refProperty);
49 3
                    if ($object instanceof $classpath) {
50 2
                        $this->inject($name, $object);
51
                    } else {
52 1
                        throw new AnnotationException("The type of injected property must be instance of ${classpath}");
53
                    }
54
                }
55 3
                $refClass = $refClass->getParentClass();
56
            }
57 1
        } catch (\ReflectionException $e) {
58
            throw new AnnotationException($e);
59
        }
60
61
        return $this;
62
    }
63
64
    /**
65
     * overload setter
66
     */
67
    public function __set($name, $value)
68
    {
69 1
        if ($this->__propertyContainer === null) {
70 1
            $this->__propertyContainer = new Container(false);
71
        }
72 1
        $this->__propertyContainer->{$name} = $value;
73 1
    }
74
75
    /**
76
     * overload setter
77
     */
78
    public function __get($name)
79
    {
80 1
        return $this->__propertyContainer !== null ? $this->__propertyContainer->{$name} : null;
81
    }
82
83
    /**
84
     * overload isset
85
     */
86
    public function __isset($name)
87
    {
88
        return $__propertyContainer === null || $__propertyContainer->{$name} === null;
0 ignored issues
show
Bug introduced by
The variable $__propertyContainer does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
89
    }
90
91
    /**
92
     * overload unset
93
     */
94
    public function __unset($name)
95
    {
96
        $this->__propertyContainer->remove($name);
97
    }
98
99
    /**
100
     * コンテナクリア
101
     */
102
    public function __clear()
103
    {
104
        $this->__propertyContainer = null;
105
    }
106
}
107