Completed
Push — 2.x ( 144798...0daeb2 )
by Akihito
10s
created

AbstractModule::__toString()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
3
declare(strict_types=1);
4
/**
5
 * This file is part of the Ray.Di package.
6
 *
7
 * @license http://opensource.org/licenses/MIT MIT
8
 */
9
namespace Ray\Di;
10
11
use Ray\Aop\AbstractMatcher;
12
use Ray\Aop\Matcher;
13
use Ray\Aop\PriorityPointcut;
14
15
abstract class AbstractModule
16
{
17
    /**
18
     * @var Matcher
19
     */
20
    protected $matcher;
21
22
    /**
23
     * @var AbstractModule|null
24
     */
25
    protected $lastModule;
26
27
    /**
28
     * @var Container
29
     */
30
    private $container;
31
32 52
    public function __construct(
33
        self $module = null
34
    ) {
35 52
        $this->lastModule = $module;
0 ignored issues
show
Documentation Bug introduced by
It seems like $module can also be of type object<self>. However, the property $lastModule is declared as type object<Ray\Di\AbstractModule>|null. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
36 52
        $this->activate();
37 51
        if ($module instanceof self) {
38 5
            $this->container->merge($module->getContainer());
39
        }
40 51
    }
41
42 1
    public function __toString()
43
    {
44 1
        return (new ModuleString)($this->getContainer(), $this->getContainer()->getPointcuts());
45
    }
46
47
    /**
48
     * Install module
49
     */
50 42
    public function install(self $module)
51
    {
52 42
        $this->getContainer()->merge($module->getContainer());
53 42
    }
54
55
    /**
56
     * Override module
57
     */
58 1
    public function override(self $module)
59
    {
60 1
        $module->getContainer()->merge($this->container);
61 1
        $this->container = $module->getContainer();
62 1
    }
63
64
    /**
65
     * Return container
66
     *
67
     * @return Container
68
     */
69 53
    public function getContainer() : Container
70
    {
71 53
        if (! $this->container) {
72 1
            $this->activate();
73
        }
74
75 53
        return $this->container;
76
    }
77
78
    /**
79
     * Bind interceptor
80
     *
81
     * @param AbstractMatcher $classMatcher
82
     * @param AbstractMatcher $methodMatcher
83
     * @param string[]        $interceptors
84
     */
85 42
    public function bindInterceptor(AbstractMatcher $classMatcher, AbstractMatcher $methodMatcher, array $interceptors)
86
    {
87 42
        $pointcut = new Pointcut($classMatcher, $methodMatcher, $interceptors);
88 42
        $this->container->addPointcut($pointcut);
89 42
        foreach ($interceptors as $interceptor) {
90 42
            (new Bind($this->container, $interceptor))->to($interceptor)->in(Scope::SINGLETON);
91
        }
92 42
    }
93
94
    /**
95
     * Bind interceptor early
96
     *
97
     * @param AbstractMatcher $classMatcher
98
     * @param AbstractMatcher $methodMatcher
99
     * @param array           $interceptors
100
     */
101 1
    public function bindPriorityInterceptor(AbstractMatcher $classMatcher, AbstractMatcher $methodMatcher, array $interceptors)
102
    {
103 1
        $pointcut = new PriorityPointcut($classMatcher, $methodMatcher, $interceptors);
104 1
        $this->container->addPointcut($pointcut);
105 1
        foreach ($interceptors as $interceptor) {
106 1
            (new Bind($this->container, $interceptor))->to($interceptor)->in(Scope::SINGLETON);
107
        }
108 1
    }
109
110
    /**
111
     * Rename binding name
112
     *
113
     * @param string $interface       Interface
114
     * @param string $newName         New binding name
115
     * @param string $sourceName      Original binding name
116
     * @param string $targetInterface Original interface
117
     */
118 1
    public function rename(string $interface, string $newName, string $sourceName = Name::ANY, string $targetInterface = '')
119
    {
120 1
        $targetInterface = $targetInterface ?: $interface;
121 1
        if ($this->lastModule instanceof self) {
122 1
            $this->lastModule->getContainer()->move($interface, $sourceName, $targetInterface, $newName);
123
        }
124 1
    }
125
126
    /**
127
     * Configure binding
128
     */
129
    abstract protected function configure();
130
131
    /**
132
     * Bind interface
133
     */
134 51
    protected function bind(string $interface = '') : Bind
135
    {
136 51
        return new Bind($this->getContainer(), $interface);
137
    }
138
139
    /**
140
     * Activate bindings
141
     */
142 53
    private function activate()
143
    {
144 53
        $this->container = new Container;
145 53
        $this->matcher = new Matcher;
146 53
        $this->configure();
147 52
    }
148
}
149