Completed
Pull Request — 2.x (#172)
by Akihito
01:57
created

AbstractModule   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 129
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 15
lcom 1
cbo 5
dl 0
loc 129
ccs 41
cts 41
cp 1
rs 10
c 0
b 0
f 0

10 Methods

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