Completed
Push — phpstan ( 578e3f )
by Akihito
05:32
created

AbstractModule   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 129
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 97.56%

Importance

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

10 Methods

Rating   Name   Duplication   Size   Complexity  
A install() 0 4 1
configure() 0 1 ?
A __construct() 0 9 2
A override() 0 5 1
A bindInterceptor() 0 8 2
A bindPriorityInterceptor() 0 8 2
A activate() 0 6 1
A rename() 0 7 3
A bind() 0 4 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\Pointcut;
14
use Ray\Aop\PriorityPointcut;
15
16
abstract class AbstractModule
17
{
18
    /**
19
     * @var Matcher
20
     */
21
    protected $matcher;
22
23
    /**
24
     * @var AbstractModule|null
25
     */
26
    protected $lastModule;
27
28
    /**
29
     * @var Container
30
     */
31
    private $container;
32
33 49
    public function __construct(
34
        self $module = null
35
    ) {
36 49
        $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...
37 49
        $this->activate();
38 48
        if ($module instanceof self) {
39 5
            $this->container->merge($module->getContainer());
40
        }
41 48
    }
42
43
    /**
44
     * Install module
45
     */
46 41
    public function install(self $module)
47
    {
48 41
        $this->getContainer()->merge($module->getContainer());
49 41
    }
50
51
    /**
52
     * Override module
53
     */
54 1
    public function override(self $module)
55
    {
56 1
        $module->getContainer()->merge($this->container);
57 1
        $this->container = $module->getContainer();
58 1
    }
59
60
    /**
61
     * Return container
62
     *
63
     * @return Container
64
     */
65 49
    public function getContainer() : Container
66
    {
67 49
        if (! $this->container) {
68
            $this->activate();
69
        }
70
71 49
        return $this->container;
72
    }
73
74
    /**
75
     * Bind interceptor
76
     *
77
     * @param AbstractMatcher $classMatcher
78
     * @param AbstractMatcher $methodMatcher
79
     * @param string[]        $interceptors
80
     */
81 40
    public function bindInterceptor(AbstractMatcher $classMatcher, AbstractMatcher $methodMatcher, array $interceptors)
82
    {
83 40
        $pointcut = new Pointcut($classMatcher, $methodMatcher, $interceptors);
0 ignored issues
show
Documentation introduced by
$interceptors is of type array<integer,string>, but the function expects a array<integer,object<Ray\Aop\Interceptor>>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
84 40
        $this->container->addPointcut($pointcut);
85 40
        foreach ($interceptors as $interceptor) {
86 40
            (new Bind($this->container, $interceptor))->to($interceptor)->in(Scope::SINGLETON);
87
        }
88 40
    }
89
90
    /**
91
     * Bind interceptor early
92
     *
93
     * @param AbstractMatcher $classMatcher
94
     * @param AbstractMatcher $methodMatcher
95
     * @param array           $interceptors
96
     */
97 1
    public function bindPriorityInterceptor(AbstractMatcher $classMatcher, AbstractMatcher $methodMatcher, array $interceptors)
98
    {
99 1
        $pointcut = new PriorityPointcut($classMatcher, $methodMatcher, $interceptors);
100 1
        $this->container->addPointcut($pointcut);
101 1
        foreach ($interceptors as $interceptor) {
102 1
            (new Bind($this->container, $interceptor))->to($interceptor)->in(Scope::SINGLETON);
103
        }
104 1
    }
105
106
    /**
107
     * Rename binding name
108
     *
109
     * @param string $interface       Interface
110
     * @param string $newName         New binding name
111
     * @param string $sourceName      Original binding name
112
     * @param string $targetInterface Original interface
113
     */
114 1
    public function rename(string $interface, string $newName, string $sourceName = Name::ANY, string $targetInterface = '')
115
    {
116 1
        $targetInterface = $targetInterface ?: $interface;
117 1
        if ($this->lastModule instanceof self) {
118 1
            $this->lastModule->getContainer()->move($interface, $sourceName, $targetInterface, $newName);
119
        }
120 1
    }
121
122
    /**
123
     * Configure binding
124
     */
125
    abstract protected function configure();
126
127
    /**
128
     * Bind interface
129
     */
130 48
    protected function bind(string $interface = '') : Bind
131
    {
132 48
        return new Bind($this->getContainer(), $interface);
133
    }
134
135
    /**
136
     * Activate bindings
137
     */
138 49
    private function activate()
139
    {
140 49
        $this->container = new Container;
141 49
        $this->matcher = new Matcher;
142 49
        $this->configure();
143 48
    }
144
}
145