Completed
Push — 2.x ( 39dc4e...b7fd10 )
by Akihito
01:28
created

Dependency::injectWithArgs()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 4

Importance

Changes 0
Metric Value
dl 0
loc 17
ccs 9
cts 9
cp 1
rs 9.7
c 0
b 0
f 0
cc 4
nc 3
nop 2
crap 4
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Ray\Di;
6
7
use Ray\Aop\Bind as AopBind;
8
use Ray\Aop\CompilerInterface;
9
use Ray\Aop\MethodInterceptor;
10
use Ray\Aop\WeavedInterface;
11
12
final class Dependency implements DependencyInterface
13
{
14
    /**
15
     * @var NewInstance
16
     */
17
    private $newInstance;
18
19
    /**
20
     * @var null|string
21
     */
22
    private $postConstruct;
23
24
    /**
25
     * @var bool
26
     */
27
    private $isSingleton = false;
28
29
    /**
30
     * @var mixed
31
     */
32
    private $instance;
33
34
    /**
35
     * @var string
36
     */
37
    private $index;
38
39
    /**
40
     * @param \ReflectionMethod $postConstruct
41
     */
42
    public function __construct(NewInstance $newInstance, \ReflectionMethod $postConstruct = null)
43
    {
44
        $this->newInstance = $newInstance;
45
        $this->postConstruct = $postConstruct ? $postConstruct->name : null;
46 70
    }
47
48 70
    public function __sleep()
49 70
    {
50 70
        return ['newInstance', 'postConstruct', 'isSingleton'];
51
    }
52 4
53
    public function __toString()
54 4
    {
55
        return sprintf(
56
            '(dependency) %s',
57 1
            (string) $this->newInstance
58
        );
59 1
    }
60 1
61 1
    /**
62
     * {@inheritdoc}
63
     */
64
    public function register(array &$container, Bind $bind)
65
    {
66
        $this->index = $index = (string) $bind;
67
        $container[$index] = $bind->getBound();
68 62
    }
69
70 62
    /**
71 62
     * {@inheritdoc}
72 62
     */
73
    public function inject(Container $container)
74
    {
75
        // singleton ?
76
        if ($this->isSingleton === true && $this->instance) {
77 58
            return $this->instance;
78
        }
79
80 58
        // create dependency injected instance
81 16
        $this->instance = ($this->newInstance)($container);
82
83
        // @PostConstruct
84
        if ($this->postConstruct) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->postConstruct of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
85 58
            $this->instance->{$this->postConstruct}();
86
        }
87
88 57
        return $this->instance;
89 8
    }
90
91
    /**
92 57
     * {@inheritdoc}
93
     */
94
    public function injectWithArgs(Container $container, array $params)
95
    {
96
        // singleton ?
97
        if ($this->isSingleton === true && $this->instance) {
98 50
            return $this->instance;
99
        }
100 50
101 47
        // create dependency injected instance
102
        $this->instance = $this->newInstance->newInstanceArgs($container, $params);
103 50
104
        // @PostConstruct
105 42
        if ($this->postConstruct) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->postConstruct of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
106
            $this->instance->{$this->postConstruct}();
107 42
        }
108 42
109 42
        return $this->instance;
110 41
    }
111
112 42
    /**
113 42
     * {@inheritdoc}
114 42
     */
115 35
    public function setScope($scope)
116
    {
117 12
        if ($scope === Scope::SINGLETON) {
118 12
            $this->isSingleton = true;
119 12
        }
120
    }
121
122
    public function weaveAspects(CompilerInterface $compiler, array $pointcuts)
123
    {
124
        $class = (string) $this->newInstance;
125
        $isInterceptor = (new \ReflectionClass($class))->implementsInterface(MethodInterceptor::class);
126
        $isWeaved = (new \ReflectionClass($class))->implementsInterface(WeavedInterface::class);
127
        if ($isInterceptor || $isWeaved) {
128
            return;
129
        }
130
        $bind = new AopBind;
131
        $bind->bind((string) $this->newInstance, $pointcuts);
132
        if (! $bind->getBindings()) {
133
            return;
134
        }
135
        $class = $compiler->compile((string) $this->newInstance, $bind);
136
        $this->newInstance->weaveAspects($class, $bind);
137
    }
138
}
139