AbstractModule   A
last analyzed

Complexity

Total Complexity 19

Size/Duplication

Total Lines 141
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 19
eloc 35
c 1
b 0
f 0
dl 0
loc 141
rs 10

11 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 3
A __toString() 0 3 1
A override() 0 4 1
A bindPriorityInterceptor() 0 6 2
A bind() 0 3 1
A toJson() 0 3 1
A install() 0 3 1
A getContainer() 0 9 2
A bindInterceptor() 0 13 3
A activate() 0 5 1
A rename() 0 5 3
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Ray\Di;
6
7
use Ray\Aop\AbstractMatcher;
8
use Ray\Aop\Matcher;
9
use Ray\Aop\Pointcut;
10
use Ray\Aop\PriorityPointcut;
0 ignored issues
show
Bug introduced by
The type Ray\Aop\PriorityPointcut was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
11
use Stringable;
12
13
use function assert;
14
use function class_exists;
15
use function interface_exists;
16
17
/**
18
 * @psalm-import-type BindableInterface from Types
19
 * @psalm-import-type PointcutList from Types
20
 * @psalm-import-type InterceptorClassList from Types
21
 */
22
abstract class AbstractModule implements Stringable
23
{
24
    /** @var Matcher */
25
    protected $matcher;
26
27
    /** @var ?AbstractModule */
28
    protected $lastModule;
29
    private ?Container $container = null;
30
31
    public function __construct(
32
        ?self $module = null
33
    ) {
34
        $this->lastModule = $module;
35
        $this->activate();
36
        if ($module instanceof self && $this->container instanceof Container) {
37
            $this->container->merge($module->getContainer());
38
        }
39
    }
40
41
    public function __toString(): string
42
    {
43
        return (new ModuleString())($this->getContainer(), $this->getContainer()->getPointcuts());
44
    }
45
46
    /**
47
     * Return module bindings as JSON string
48
     */
49
    public function toJson(): string
50
    {
51
        return (new ModuleJson())($this->getContainer(), $this->getContainer()->getPointcuts());
52
    }
53
54
    /**
55
     * Install module
56
     */
57
    public function install(self $module): void
58
    {
59
        $this->getContainer()->merge($module->getContainer());
60
    }
61
62
    /**
63
     * Override module
64
     */
65
    public function override(self $module): void
66
    {
67
        $module->getContainer()->merge($this->getContainer());
68
        $this->container = $module->getContainer();
69
    }
70
71
    /**
72
     * Return activated container
73
     */
74
    public function getContainer(): Container
75
    {
76
        if ($this->container === null) {
77
            $this->activate();
78
        }
79
80
        assert($this->container instanceof Container);
81
82
        return $this->container;
83
    }
84
85
    /**
86
     * Bind interceptor
87
     *
88
     * @param InterceptorClassList $interceptors
0 ignored issues
show
Bug introduced by
The type Ray\Di\InterceptorClassList was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
89
     */
90
    public function bindInterceptor(AbstractMatcher $classMatcher, AbstractMatcher $methodMatcher, array $interceptors): void
91
    {
92
        $pointcut = new Pointcut($classMatcher, $methodMatcher, $interceptors);
93
        $this->getContainer()->addPointcut($pointcut);
94
        foreach ($interceptors as $interceptor) {
95
            if (class_exists($interceptor)) {
96
                (new Bind($this->getContainer(), $interceptor))->to($interceptor)->in(Scope::SINGLETON);
97
98
                return;
99
            }
100
101
            assert(interface_exists($interceptor));
102
            (new Bind($this->getContainer(), $interceptor))->in(Scope::SINGLETON);
103
        }
104
    }
105
106
    /**
107
     * Bind interceptor early
108
     *
109
     * @param InterceptorClassList $interceptors
110
     */
111
    public function bindPriorityInterceptor(AbstractMatcher $classMatcher, AbstractMatcher $methodMatcher, array $interceptors): void
112
    {
113
        $pointcut = new PriorityPointcut($classMatcher, $methodMatcher, $interceptors);
114
        $this->getContainer()->addPointcut($pointcut);
115
        foreach ($interceptors as $interceptor) {
116
            (new Bind($this->getContainer(), $interceptor))->to($interceptor)->in(Scope::SINGLETON);
117
        }
118
    }
119
120
    /**
121
     * Rename binding name
122
     *
123
     * @param string $interface       Interface
124
     * @param string $newName         New binding name
125
     * @param string $sourceName      Original binding name
126
     * @param string $targetInterface Original interface
127
     */
128
    public function rename(string $interface, string $newName, string $sourceName = Name::ANY, string $targetInterface = ''): void
129
    {
130
        $targetInterface = $targetInterface ?: $interface;
131
        if ($this->lastModule instanceof self) {
132
            $this->lastModule->getContainer()->move($interface, $sourceName, $targetInterface, $newName);
133
        }
134
    }
135
136
    /**
137
     * Configure binding
138
     *
139
     * @return void
140
     *
141
     * @noinspection ReturnTypeCanBeDeclaredInspection
142
     */
143
    abstract protected function configure();
144
145
    /**
146
     * Bind interface
147
     *
148
     * @param BindableInterface $interface
0 ignored issues
show
Bug introduced by
The type Ray\Di\BindableInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
149
     */
150
    protected function bind(string $interface = ''): Bind
151
    {
152
        return new Bind($this->getContainer(), $interface);
153
    }
154
155
    /**
156
     * Activate bindings
157
     */
158
    private function activate(): void
159
    {
160
        $this->container = new Container();
161
        $this->matcher = new Matcher();
162
        $this->configure();
163
    }
164
}
165