Completed
Push — 2.x ( c48035...86395f )
by Akihito
14s queued 10s
created

Dependency::setScope()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 0
cts 0
cp 0
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 1
crap 6
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 70
     */
42
    public function __construct(NewInstance $newInstance, \ReflectionMethod $postConstruct = null)
43 70
    {
44 70
        $this->newInstance = $newInstance;
45 70
        $this->postConstruct = $postConstruct ? $postConstruct->name : null;
46
    }
47 4
48
    public function __sleep()
49 4
    {
50
        return ['newInstance', 'postConstruct', 'isSingleton'];
51
    }
52 1
53
    public function __toString()
54 1
    {
55 1
        return sprintf(
56 1
            '(dependency) %s',
57
            (string) $this->newInstance
58
        );
59
    }
60
61
    /**
62
     * {@inheritdoc}
63 62
     */
64
    public function register(array &$container, Bind $bind)
65 62
    {
66 62
        $this->index = $index = (string) $bind;
67 62
        $container[$index] = $bind->getBound();
68
    }
69
70
    /**
71
     * {@inheritdoc}
72 58
     */
73
    public function inject(Container $container)
74
    {
75 58
        // singleton ?
76 16
        if ($this->isSingleton === true && $this->instance) {
77
            return $this->instance;
78
        }
79
80 58
        // create dependency injected instance
81
        $this->instance = ($this->newInstance)($container);
82
83 57
        // @PostConstruct
84 8
        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
            $this->instance->{$this->postConstruct}();
86
        }
87 57
88
        return $this->instance;
89
    }
90
91
    /**
92
     * {@inheritdoc}
93 50
     */
94
    public function injectWithArgs(Container $container, array $params)
95 50
    {
96 47
        // singleton ?
97
        if ($this->isSingleton === true && $this->instance) {
98 50
            return $this->instance;
99
        }
100 42
101
        // create dependency injected instance
102 42
        $this->instance = $this->newInstance->newInstanceArgs($container, $params);
103 42
104 42
        // @PostConstruct
105 41
        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 35
    }
111
112 12
    /**
113 12
     * {@inheritdoc}
114 12
     */
115
    public function setScope($scope)
116
    {
117
        if ($scope === Scope::SINGLETON) {
118
            $this->isSingleton = true;
119
        }
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