BootstrapRegistrarService   B
last analyzed

Complexity

Total Complexity 50

Size/Duplication

Total Lines 309
Duplicated Lines 0 %

Test Coverage

Coverage 86.03%

Importance

Changes 0
Metric Value
eloc 95
dl 0
loc 309
ccs 117
cts 136
cp 0.8603
rs 8.4
c 0
b 0
f 0
wmc 50

32 Methods

Rating   Name   Duplication   Size   Complexity  
A storeInCache() 0 3 1
A bootstrapFactories() 0 4 1
A bootstrapSeeders() 0 5 2
A bootstrapConfigs() 0 6 2
A bootstrapModels() 0 9 2
A bootstrapMigrations() 0 4 1
A getConfigs() 0 3 1
A bootstrapCommands() 0 5 2
A bootstrapEvents() 0 12 4
A extractPoliciesFromModel() 0 10 3
A getMigrations() 0 3 1
A bootstrapProviders() 0 6 3
A getModels() 0 3 1
A getCommands() 0 3 1
A loadNewBootstrap() 0 5 1
A getCachePath() 0 3 1
A bootstrapRoutes() 0 9 2
A getPolicies() 0 3 1
A bootstrap() 0 12 2
A getFactories() 0 3 1
A extractObserversFromModel() 0 10 3
A recache() 0 5 1
A getProviders() 0 3 1
A getEvents() 0 3 1
A passedRegistrationCondition() 0 7 2
A getRoutes() 0 3 1
A generateRoutePrefixFromFileName() 0 7 1
A getSeeders() 0 3 1
A clearCache() 0 3 1
A cacheExists() 0 3 1
A readFromCache() 0 3 1
A loadBootstrapFromCache() 0 11 3

How to fix   Complexity   

Complex Class

Complex classes like BootstrapRegistrarService often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use BootstrapRegistrarService, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * Created by PhpStorm.
4
 * User: arthur
5
 * Date: 04.10.18
6
 * Time: 02:13.
7
 */
8
9
namespace Foundation\Services;
10
11
use Foundation\Abstracts\Listeners\Listener;
12
use Foundation\Abstracts\Observers\Observer;
13
use Foundation\Abstracts\Policies\Policy;
14
use Foundation\Contracts\ConditionalAutoRegistration;
15
use Foundation\Contracts\Ownable;
16
use Foundation\Core\Larapi;
17
use Foundation\Traits\Cacheable;
18
19
class BootstrapRegistrarService
20
{
21
    /**
22
     * @var string
23
     */
24
    protected $cacheFile = 'bootstrap.php';
25
26
    /**
27
     * @var
28
     */
29
    protected $bootstrap;
30
31 43
    public function recache()
32
    {
33 43
        $this->bootstrap();
34
35 43
        $this->storeInCache($this->bootstrap);
36 43
    }
37
38
    /**
39
     * @param $data
40
     */
41 43
    private function storeInCache($data)
42
    {
43 43
        file_put_contents($this->getCachePath(), '<?php return '.var_export($data, true).';');
44 43
    }
45
46
    /**
47
     * @return mixed
48
     */
49
    public function readFromCache()
50
    {
51
        return include $this->getCachePath();
52
    }
53
54
    public function clearCache()
55
    {
56
        unlink($this->getCachePath());
57
    }
58
59
    /**
60
     * @return bool
61
     */
62
    public function cacheExists()
63
    {
64
        return file_exists($this->getCachePath());
65
    }
66
67
    /**
68
     * @return string
69
     */
70 43
    private function getCachePath(): string
71
    {
72 43
        return app()->bootstrapPath().'/cache/'.$this->cacheFile;
73
    }
74
75 43
    public function bootstrap()
76
    {
77 43
        foreach (Larapi::getModules() as $module) {
78 43
            $this->bootstrapCommands($module);
79 43
            $this->bootstrapRoutes($module);
80 43
            $this->bootstrapConfigs($module);
81 43
            $this->bootstrapFactories($module);
82 43
            $this->bootstrapMigrations($module);
83 43
            $this->bootstrapModels($module);
84 43
            $this->bootstrapSeeders($module);
85 43
            $this->bootstrapProviders($module);
86 43
            $this->bootstrapEvents($module);
87
        }
88 43
    }
89
90 43
    private function bootstrapCommands(\Foundation\Core\Module $module)
91
    {
92 43
        foreach ($module->getCommands()->getClasses() as $commandClass) {
93 43
            $this->bootstrap['commands'][] = [
94 43
                'class' => $commandClass,
95
            ];
96
        }
97 43
    }
98
99 43
    private function bootstrapRoutes(\Foundation\Core\Module $module)
100
    {
101 43
        foreach ($module->getRoutes()->getFiles() as $file) {
102 43
            $this->bootstrap['routes'][] = [
103 43
                'prefix' => $this->generateRoutePrefixFromFileName($file->getFileName()),
104 43
                'controller_namespace' => $module->getControllers()->getNamespace(),
105 43
                'domain' => Larapi::getApiDomainName(),
106 43
                'path' => $file->getPath(),
107 43
                'module_model' => $module->getMainModel(),
108
            ];
109
        }
110 43
    }
111
112 43
    private function generateRoutePrefixFromFileName(string $fileName)
113
    {
114 43
        $prefixArray = explode('.', $fileName);
115 43
        $prefixVersion = $prefixArray[1];
116 43
        $prefixRoute = $prefixArray[0];
117
118 43
        return $prefixVersion.'/'.$prefixRoute;
119
    }
120
121 43
    private function bootstrapConfigs(\Foundation\Core\Module $module)
122
    {
123 43
        foreach ($module->getConfigs()->getFiles() as $file) {
124 43
            $this->bootstrap['configs'][] = [
125 43
                'name' => $file->getName(),
126 43
                'path' => $file->getPath(),
127
            ];
128
        }
129 43
    }
130
131 43
    private function bootstrapFactories(\Foundation\Core\Module $module)
132
    {
133 43
        $this->bootstrap['factories'][] = [
134 43
            'path' => $module->getFactories()->getPath(),
135
        ];
136 43
    }
137
138 43
    private function bootstrapMigrations(\Foundation\Core\Module $module)
139
    {
140 43
        $this->bootstrap['migrations'][] = [
141 43
            'path' => $module->getMigrations()->getPath(),
142
        ];
143 43
    }
144
145 43
    private function bootstrapSeeders(\Foundation\Core\Module $module)
146
    {
147 43
        foreach ($module->getSeeders()->getClasses() as $seederClass) {
148 43
            $this->bootstrap['seeders'][] = [
149 43
                'class' => $seederClass,
150
            ];
151
        }
152 43
    }
153
154 43
    private function bootstrapModels(\Foundation\Core\Module $module)
155
    {
156 43
        foreach ($module->getModels()->getClasses() as $modelClass) {
157 43
            $this->bootstrap['models'][] = [
158 43
                'class' => $modelClass,
159 43
                'observers' => $this->extractObserversFromModel($modelClass),
160 43
                'policies' => $this->extractPoliciesFromModel($modelClass),
161 43
                'cacheable' => class_uses_trait($modelClass, Cacheable::class),
162 43
                'ownable' => class_implements_interface($modelClass, Ownable::class),
163
            ];
164
        }
165 43
    }
166
167 43
    private function extractObserversFromModel(string $modelClass)
168
    {
169 43
        $observers = [];
170 43
        foreach (get_class_property($modelClass, 'observers') ?? [] as $observerClass) {
171
            if (instance_without_constructor($observerClass) instanceof Observer) {
172
                $observers[] = $observerClass;
173
            }
174
        }
175
176 43
        return $observers;
177
    }
178
179 43
    private function extractPoliciesFromModel(string $modelClass)
180
    {
181 43
        $policies = [];
182 43
        foreach (get_class_property($modelClass, 'policies') ?? [] as $policyClass) {
183 43
            if (instance_without_constructor($policyClass) instanceof Policy) {
184 43
                $policies[] = $policyClass;
185
            }
186
        }
187
188 43
        return $policies;
189
    }
190
191 43
    private function bootstrapProviders(\Foundation\Core\Module $module)
192
    {
193 43
        foreach ($module->getServiceProviders()->getClasses() as $serviceProviderClass) {
194 43
            if ($this->passedRegistrationCondition($serviceProviderClass)) {
195 43
                $this->bootstrap['providers'][] = [
196 43
                    'class' => $serviceProviderClass,
197
                ];
198
            }
199
        }
200 43
    }
201
202 43
    private function passedRegistrationCondition($class)
203
    {
204 43
        if (! class_implements_interface($class, ConditionalAutoRegistration::class)) {
205 43
            return true;
206
        }
207
208 43
        return call_class_function($class, 'registrationCondition');
209
    }
210
211 43
    private function bootstrapEvents(\Foundation\Core\Module $module)
212
    {
213 43
        foreach ($module->getEvents()->getClasses() as $eventClass) {
214 43
            $listeners = [];
215 43
            foreach (get_class_property($eventClass, 'listeners') ?? [] as $listenerClass) {
216 43
                if (instance_without_constructor($listenerClass) instanceof Listener) {
217 43
                    $listeners[] = $listenerClass;
218
                }
219
            }
220 43
            $this->bootstrap['events'][] = [
221 43
                'class' => $eventClass,
222 43
                'listeners' => $listeners,
223
            ];
224
        }
225 43
    }
226
227
    /**
228
     * @return mixed
229
     */
230 43
    public function loadBootstrapFromCache()
231
    {
232 43
        if (! isset($this->bootstrap)) {
233
            if ($this->cacheExists()) {
234
                $this->bootstrap = $this->readFromCache();
235
            } else {
236
                $this->recache();
237
            }
238
        }
239
240 43
        return $this->bootstrap;
241
    }
242
243
    public function loadNewBootstrap()
244
    {
245
        $this->bootstrap();
246
247
        return $this->bootstrap;
248
    }
249
250
    /**
251
     * @return array
252
     */
253 43
    public function getCommands(): array
254
    {
255 43
        return $this->loadBootstrapFromCache()['commands'] ?? [];
256
    }
257
258
    /**
259
     * @return array
260
     */
261 43
    public function getRoutes(): array
262
    {
263 43
        return $this->loadBootstrapFromCache()['routes'] ?? [];
264
    }
265
266
    /**
267
     * @return array
268
     */
269 43
    public function getConfigs(): array
270
    {
271 43
        return $this->loadBootstrapFromCache()['configs'] ?? [];
272
    }
273
274
    /**
275
     * @return array
276
     */
277 43
    public function getFactories(): array
278
    {
279 43
        return $this->loadBootstrapFromCache()['factories'] ?? [];
280
    }
281
282
    /**
283
     * @return array
284
     */
285 43
    public function getMigrations(): array
286
    {
287 43
        return $this->loadBootstrapFromCache()['migrations'] ?? [];
288
    }
289
290
    /**
291
     * @return array
292
     */
293
    public function getSeeders(): array
294
    {
295
        return $this->loadBootstrapFromCache()['seeders'] ?? [];
296
    }
297
298
    /**
299
     * @return array
300
     */
301 43
    public function getModels(): array
302
    {
303 43
        return $this->loadBootstrapFromCache()['models'] ?? [];
304
    }
305
306
    /**
307
     * @return array
308
     */
309
    public function getPolicies(): array
310
    {
311
        return $this->loadBootstrapFromCache()['policies'] ?? [];
312
    }
313
314
    /**
315
     * @return array
316
     */
317 43
    public function getProviders(): array
318
    {
319 43
        return $this->loadBootstrapFromCache()['providers'] ?? [];
320
    }
321
322
    /**
323
     * @return array
324
     */
325 43
    public function getEvents(): array
326
    {
327 43
        return $this->loadBootstrapFromCache()['events'] ?? [];
328
    }
329
}
330