Completed
Push — 0.x ( fce172...24652b )
by Andrew
01:16
created

ModuleLoader   B

Complexity

Total Complexity 38

Size/Duplication

Total Lines 192
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 38
lcom 1
cbo 5
dl 0
loc 192
ccs 105
cts 105
cp 1
rs 8.3999
c 0
b 0
f 0

13 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A define() 0 9 3
A modify() 0 9 3
A loaded() 0 5 1
A isEnv() 0 4 1
A isContext() 0 4 1
C resolveDependencies() 0 57 10
A injectRequiredModule() 0 14 4
A resolveRequire() 0 5 1
A resolveRequireEnv() 0 10 3
A resolveConflict() 0 10 3
A resolveReplace() 0 21 4
A getModule() 0 14 3
1
<?php
2
namespace Cadre\Module;
3
4
use Aura\Di\Container;
5
use Aura\Di\ContainerConfigInterface;
6
7
class ModuleLoader implements ModuleLoaderInterface
8
{
9
    protected $modules = [];
10
    protected $environment;
11
    protected $context;
12
    protected $isResolved = false;
13
    protected $containerConfigs = [];
14
    protected $conflictsWith = [];
15
    protected $replacedWith = [];
16
    protected $touchedModules = [];
17
18 18
    public function __construct(array $modules, $environment = '', $context = '')
19
    {
20 18
        $this->modules = $modules;
21 18
        $this->environment = $environment;
22 18
        $this->context = $context;
23 18
    }
24
25 16
    public function define(Container $di)
26
    {
27 16
        $this->resolveDependencies();
28 10
        foreach ($this->containerConfigs as $containerConfig) {
29 10
            if ($containerConfig instanceof ContainerConfigInterface) {
0 ignored issues
show
Bug introduced by
The class Aura\Di\ContainerConfigInterface does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
30 10
                $containerConfig->define($di);
31
            }
32
        }
33 10
    }
34
35 10
    public function modify(Container $di)
36
    {
37 10
        $this->resolveDependencies();
38 10
        foreach ($this->containerConfigs as $containerConfig) {
39 10
            if ($containerConfig instanceof ContainerConfigInterface) {
0 ignored issues
show
Bug introduced by
The class Aura\Di\ContainerConfigInterface does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
40 10
                $containerConfig->modify($di);
41
            }
42
        }
43 10
    }
44
45 2
    public function loaded($name)
46
    {
47 2
        $this->resolveDependencies();
48 2
        return isset($this->containerConfigs[$name]);
49
    }
50
51 1
    public function isEnv($environment)
52
    {
53 1
        return 0 === strcmp($environment, $this->environment);
54
    }
55
56 1
    public function isContext($context)
57
    {
58 1
        return 0 === strcmp($context, $this->context);
59
    }
60
61 16
    protected function resolveDependencies()
62
    {
63 16
        if ($this->isResolved) {
64 10
            return;
65
        }
66
67 16
        $idx = 0;
68
69 16
        while ($idx < count($this->modules)) {
70 16
            $module = $this->getModule($this->modules[$idx]);
71 15
            $name = get_class($module);
72
73 15
            if (isset($this->containerConfigs[$name])) {
74 1
                $idx++;
75 1
                continue;
76
            }
77
78 15
            if (isset($this->replacedWith[$name])) {
79 1
                $idx++;
80 1
                continue;
81
            }
82
83 15
            if (isset($this->conflictsWith[$name])) {
84 1
                throw new ConflictingModuleException($name, $this->conflictsWith[$name]);
85
            }
86
87 15
            if (empty($this->touchedModules[$name])) {
88 15
                $this->touchedModules[$name] = 0;
89
            }
90
91 15
            if (1 < $this->touchedModules[$name]) {
92 1
                throw new CircularReferenceException($name, $this->touchedModules[$name]);
93
            }
94
95 15
            $this->touchedModules[$name]++;
96
97 15
            if ($module instanceof ModuleInterface) {
98 14
                $this->resolveRequire($idx, $module);
99 14
                $this->resolveRequireEnv($idx, $module);
100 14
                $this->resolveConflict($module, $name);
101 14
                $this->resolveReplace($module, $name);
102
            }
103
104 15
            $module = $this->getModule($this->modules[$idx]);
105 15
            if (0 === strcmp($name, get_class($module))) {
106
                // No new modules were inserted
107 14
                $this->containerConfigs[$name] = $module;
108
            } else {
109
                // Do not increment $idx, reprocess this $idx
110 7
                continue;
111
            }
112
113 14
            $idx++;
114
        }
115
116 10
        $this->isResolved = true;
117 10
    }
118
119 14
    protected function injectRequiredModule($idx, $requiredModules)
120
    {
121 14
        foreach ($requiredModules as $requiredModule) {
122 7
            $foundIdx = array_search($requiredModule, $this->modules);
123 7
            if (false === $foundIdx) {
124
                // New module, not found yet
125 5
                array_splice($this->modules, $idx, 0, $requiredModule);
126 7
            } elseif ($idx < $foundIdx) {
127
                // Found module after us in list. Move up
128 2
                array_splice($this->modules, $foundIdx, 1);
129 7
                array_splice($this->modules, $idx, 0, $requiredModule);
130
            }
131
        }
132 14
    }
133
134 14
    protected function resolveRequire($idx, ModuleInterface $module)
135
    {
136 14
        $requiredModules = $module->require();
137 14
        $this->injectRequiredModule($idx, $requiredModules);
138 14
    }
139
140 14
    protected function resolveRequireEnv($idx, ModuleInterface $module)
141
    {
142 14
        $envMethod = 'require' . str_replace(' ', '', ucwords(
143 14
            strtolower(str_replace('_', ' ', trim($this->environment)))
144
        ));
145 14
        if ('require' !== $envMethod && method_exists($module, $envMethod)) {
146 2
            $requiredModules = $module->$envMethod();
147 2
            $this->injectRequiredModule($idx, $requiredModules);
148
        }
149 14
    }
150
151 14
    protected function resolveConflict(ModuleInterface $module, $name)
152
    {
153 14
        $conflictingModules = $module->conflict();
154 14
        foreach ($conflictingModules as $conflictingModule) {
155 3
            $this->conflictsWith[$conflictingModule] = $name;
156 3
            if (isset($this->containerConfigs[$conflictingModule])) {
157 3
                throw new ConflictingModuleException($conflictingModule, $name);
158
            }
159
        }
160 14
    }
161
162 14
    protected function resolveReplace(ModuleInterface $module, $name)
163
    {
164 14
        $replacesModules = $module->replace();
165 14
        foreach ($replacesModules as $replacesModule) {
166 3
            if (isset($this->replacedWith[$replacesModule])) {
167 1
                throw new AlreadyReplacedException(
168 1
                    $name,
169 1
                    $replacesModule,
170 1
                    $this->replacedWith[$replacesModule]
171
                );
172
            }
173 3
            if (isset($this->containerConfigs[$replacesModule])) {
174 1
                throw new AlreadyLoadedException(
175 1
                    $name,
176 1
                    'replace',
177 1
                    $replacesModule
178
                );
179
            }
180 2
            $this->replacedWith[$replacesModule] = $name;
181
        }
182 14
    }
183
184 16
    protected function getModule($module)
185
    {
186 16
        if (is_string($module)) {
187 16
            $module = new $module($this);
188
        }
189
190 16
        if (! $module instanceof ContainerConfigInterface) {
0 ignored issues
show
Bug introduced by
The class Aura\Di\ContainerConfigInterface does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
191 1
            throw new \InvalidArgumentException(
192 1
                'Modules must implement ModuleInterface or ContainerConfigInterface'
193
            );
194
        }
195
196 15
        return $module;
197
    }
198
}
199