ApplicationPackage   B
last analyzed

Complexity

Total Complexity 50

Size/Duplication

Total Lines 361
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 6
Bugs 0 Features 0
Metric Value
wmc 50
eloc 120
dl 0
loc 361
c 6
b 0
f 0
ccs 140
cts 140
cp 1
rs 8.4

26 Methods

Rating   Name   Duplication   Size   Complexity  
A setupViewEngine() 0 6 1
A addEntityPathsFromPackages() 0 11 4
A addMiddlewaresToContainer() 0 7 2
A setupMiddlewareStack() 0 12 5
A setupLogs() 0 4 1
A registerPackage() 0 10 1
A setupPdoConnection() 0 4 1
A registerRoutes() 0 4 2
A addMiddlewaresToStack() 0 8 2
A __construct() 0 3 1
A initMiddlewareStack() 0 3 1
A setConfigArray() 0 4 2
A registerTranslations() 0 10 3
A setupTranslator() 0 6 1
A registerViews() 0 14 4
A registerConsoleCommands() 0 13 3
A initConsoleApp() 0 3 1
A overrideViewFolder() 0 6 2
A setupDownloadController() 0 7 1
A setupPackages() 0 12 3
A setupVendorViewOverrides() 0 9 2
A registerMiddleware() 0 8 3
A setupRouteFirewall() 0 6 1
A setupConsoleApp() 0 4 1
A addToContainer() 0 16 1
A setupRouter() 0 5 1

How to fix   Complexity   

Complex Class

Complex classes like ApplicationPackage 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 ApplicationPackage, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Bone;
4
5
use Barnacle\Container;
6
use Barnacle\EntityRegistrationInterface;
7
use Barnacle\RegistrationInterface;
8
use Bone\Console\CommandRegistrationInterface;
9
use Bone\Console\ConsoleApplication;
10
use Bone\Console\ConsolePackage;
11
use Bone\Db\DbPackage;
12
use Bone\Firewall\FirewallPackage;
13
use Bone\Http\GlobalMiddlewareRegistrationInterface;
14
use Bone\Http\Middleware\Stack;
15
use Bone\Http\MiddlewareRegistrationInterface;
16
use Bone\I18n\I18nPackage;
17
use Bone\I18n\I18nRegistrationInterface;
18
use Bone\Log\LogPackage;
19
use Bone\Controller\DownloadController;
20
use Bone\Router\Router;
21
use Bone\Router\RouterConfigInterface;
22
use Bone\Router\RouterPackage;
23
use Bone\View\ViewEngine;
24
use Bone\I18n\Service\TranslatorFactory;
25
use Bone\View\ViewPackage;
26
use Bone\View\ViewRegistrationInterface;
27
use League\Plates\Template\Folders;
28
use League\Route\Strategy\JsonStrategy;
29
use Laminas\Diactoros\ResponseFactory;
30
use Laminas\I18n\Translator\Translator;
31
use Psr\Http\Server\MiddlewareInterface;
32
33
class ApplicationPackage implements RegistrationInterface
34
{
35
    /** @var array $config */
36
    private $config;
37
38
    /** @var Router $router */
39
    private $router;
40
41
    /**
42
     * ApplicationPackage constructor.
43
     * @param array $config
44 10
     * @param Router $router
45
     */
46 10
    public function __construct(array $config)
47 10
    {
48 10
        $this->config = $config;
49
    }
50
51
    /**
52
     * @param Container $c
53
     * @throws \Bone\Exception
54
     * @throws \Exception
55 10
     */
56
    public function addToContainer(Container $c)
57 10
    {
58 10
        $this->setConfigArray($c);
59 10
        $this->setupLogs($c);
60 10
        $this->setupPdoConnection($c);
61 10
        $this->setupRouter($c);
62 10
        $this->initMiddlewareStack($c);
63 10
        $this->setupViewEngine($c);
64 10
        $this->initConsoleApp($c);
65 10
        $this->setupTranslator($c);
66 10
        $this->setupPackages($c);
67 10
        $this->setupVendorViewOverrides($c);
68 10
        $this->setupDownloadController($c);
69 10
        $this->setupRouteFirewall($c);
70 10
        $this->setupMiddlewareStack($c);
71 10
        $this->setupConsoleApp($c);
72
    }
73
74
    /**
75
     * @param Container $c
76 10
     */
77
    private function setConfigArray(Container $c)
78 10
    {
79 10
        foreach ($this->config as $key => $value) {
80
            $c[$key] = $value;
81 10
        }
82
    }
83
84
    /**
85
     * @param Container $c
86 10
     */
87
    private function setupViewEngine(Container $c)
88 10
    {
89 10
        $package = new ViewPackage();
90 10
        $package->addToContainer($c);
91
        $this->addMiddlewaresToContainer($package, $c);
92
        $this->addMiddlewaresToStack($package, $c);
93
    }
94
95 10
    /**
96
     * @param Container $c
97 10
     */
98 10
    private function setupRouter(Container $c)
99 10
    {
100
        $package = new RouterPackage();
101
        $package->addToContainer($c);
102
        $this->router = $c->get(Router::class);
103
    }
104 10
105
    /**
106
     * @param Container $c
107 10
     */
108 10
    private function setupPackages(Container $c)
109 10
    {
110
        // set up the modules and vendor package modules
111 10
        $c['consoleCommands'] = [];
112
        $packages = $c->get('packages');
113 10
        $this->addEntityPathsFromPackages($packages, $c);
114 10
115 10
        reset($packages);
116
117
        foreach ($packages as $packageName) {
118 10
            if (class_exists($packageName)) {
119
                $this->registerPackage($packageName, $c);
120
            }
121
        }
122
    }
123
124 10
    /**
125
     * @param string $packageName
126
     * @param Container $c
127 10
     */
128 10
    private function registerPackage(string $packageName, Container $c): void
129 10
    {
130 10
        /** @var RegistrationInterface $package */
131 10
        $package = new $packageName();
132 10
        $package->addToContainer($c);
133 10
        $this->registerRoutes($package, $c);
134
        $this->registerViews($package, $c);
135
        $this->registerTranslations($package, $c);
136
        $this->registerMiddleware($package, $c);
137
        $this->registerConsoleCommands($package, $c);
138 10
    }
139
140 10
    /**
141
     * @param RegistrationInterface $package
142 10
     */
143 10
    private function registerConsoleCommands(RegistrationInterface $package, Container $c): void
144
    {
145 10
        $consoleCommands = $c->get('consoleCommands');
146 10
147
        if ($package instanceof CommandRegistrationInterface) {
148
            $commands = $package->registerConsoleCommands($c);
149
150 10
            foreach ($commands as $command) {
151 10
                $consoleCommands[] = $command;
152
            }
153
        }
154
155
        $c['consoleCommands'] = $consoleCommands;
156 10
    }
157
158 10
    /**
159 10
     * @param RegistrationInterface $package
160 10
     */
161
    private function registerMiddleware(RegistrationInterface $package, Container $c): void
162 10
    {
163
        if ($package instanceof MiddlewareRegistrationInterface) {
164
            $this->addMiddlewaresToContainer($package, $c);
165
        }
166
167 10
        if ($package instanceof GlobalMiddlewareRegistrationInterface) {
168
            $this->addMiddlewaresToStack($package, $c);
169 10
        }
170 10
    }
171
172 10
    /**
173
     * @param MiddlewareRegistrationInterface $package
174
     * @param Container $c
175
     */
176
    private function addMiddlewaresToContainer(MiddlewareRegistrationInterface $package, Container $c): void
177 10
    {
178
        $middlewares = $package->getMiddleware($c);
179 10
        
180
        foreach ($middlewares as $middleware) {
181 10
            $className = get_class($middleware);
182
            $c[$className] = $middleware;
183 10
        }
184 10
    }
185 10
186 10
    /**
187
     * @param GlobalMiddlewareRegistrationInterface $package
188
     * @param Container $c
189 10
     */
190
    private function addMiddlewaresToStack(GlobalMiddlewareRegistrationInterface $package, Container $c): void
191
    {
192
        /** @var Stack $stack */
193
        $stack = $c->get(Stack::class);
194 10
        $middlewares = $package->getGlobalMiddleware($c);
195
196 10
        foreach ($middlewares as $middleware) {
197 10
            $stack->addMiddleWare($c->get($middleware));
198
        }
199
    }
200
201
    /**
202 10
     * @param RegistrationInterface $package
203
     */
204 10
    private function registerRoutes(RegistrationInterface $package, Container $c): void
205 10
    {
206 10
        if ($package instanceof RouterConfigInterface) {
207
            $package->addRoutes($c, $this->router);
208
        }
209
    }
210
211
    /**
212 10
     * @param RegistrationInterface $package
213
     */
214 10
    private function registerViews(RegistrationInterface $package, Container $c): void
215 10
    {
216
        if ($package instanceof ViewRegistrationInterface) {
217 10
            $views = $package->addViews();
218
            $extensions = $package->addViewExtensions($c);
219 10
            /** @var ViewEngine $engine */
220 10
            $engine = $c->get(ViewEngine::class);
221 10
222 10
            foreach ($views as $name => $folder) {
223
                $engine->addFolder($name, $folder);
224
            }
225
226 10
            foreach ($extensions as $extension) {
227
                $engine->loadExtension($extension);
228
            }
229
        }
230
    }
231
232 10
    /**
233
     * @param RegistrationInterface $package
234 10
     */
235 10
    private function registerTranslations(RegistrationInterface $package, Container $c): void 
236 10
    {
237 10
        $i18n = $c->get('i18n');
238
        /** @var Translator $translator */
239
        $translator = $c->get(Translator::class);
240
241
        if ($package instanceof I18nRegistrationInterface) {
242
            foreach ($i18n['supported_locales'] as $locale) {
243
                $factory = new TranslatorFactory();
244 10
                $factory->addPackageTranslations($translator, $package, $locale);
245
            }
246 10
        }
247 10
    }
248 10
249
    /**
250
     * @param Container $c
251
     */
252
    private function initConsoleApp(Container $c): void
253 10
    {
254
        $c[ConsoleApplication::class] = new ConsoleApplication();
255 10
    }
256 10
257 10
    /**
258 10
     * @param Container $c
259 10
     */
260 10
    private function setupConsoleApp(Container $c): void
261
    {
262
        $package = new ConsolePackage();
263
        $package->addToContainer($c);
264
    }
265 10
266
    /**
267 10
     * @param array $packages
268 10
     * @param Container $c
269 10
     */
270
    private function addEntityPathsFromPackages(array $packages, Container $c): void
271
    {
272
        foreach ($packages as $packageName) {
273
            if (class_exists($packageName)) {
274
                /** @var RegistrationInterface $package */
275 10
                $package = new $packageName();
276
277 10
                if ($package instanceof EntityRegistrationInterface) {
278 10
                    $paths = $c['entity_paths'];
279 10
                    $paths[] = $package->getEntityPath();
280
                    $c['entity_paths'] = $paths;
281
                }
282
            }
283
        }
284 10
    }
285
286
    /**
287 10
     * @param Container $c
288 10
     * @throws \Bone\Exception
289 10
     */
290
    private function setupTranslator(Container $c)
291 10
    {
292 10
        $package = new I18nPackage();
293
        $package->addToContainer($c);
294 10
        $this->addMiddlewaresToContainer($package, $c);
295
        $this->addMiddlewaresToStack($package, $c);
296
    }
297
298
299
    /**
300
     * @param Container $c
301 10
     * @throws \Bone\Exception
302
     */
303 10
    private function setupPdoConnection(Container $c)
304
    {
305 1
        $package = new DbPackage();
306 1
        $package->addToContainer($c);
307
    }
308 10
309
    /**
310
     * @param Container $c
311
     */
312
    private function setupDownloadController(Container $c): void
313 10
    {
314
        $uploadDirectory = $c->get('uploads_dir');
315 10
        $c[DownloadController::class] = new DownloadController($uploadDirectory);
316 10
        $strategy = new JsonStrategy(new ResponseFactory());
317 10
        $strategy->setContainer($c);
318
        $this->router->map('GET', '/download', [DownloadController::class, 'downloadAction'])->setStrategy($strategy);
319
    }
320
321
    /**
322 10
     * @param Container $c
323
     */
324 10
    private function setupRouteFirewall(Container $c): void
325 10
    {
326
        $package = new FirewallPackage();
327 10
        $package->addToContainer($c);
328 10
        $this->addMiddlewaresToContainer($package, $c);
329 10
        $this->addMiddlewaresToStack($package, $c);
330 10
    }
331 10
332
    /**
333 10
     * @param Container $c
334
     * @throws \Exception
335
     */
336 10
    private function  setupLogs(Container $c)
337
    {
338
        $package = new LogPackage();
339
        $package->addToContainer($c);
340
    }
341
342
    /**
343
     * @param Container $c
344
     */
345
    private function setupVendorViewOverrides(Container $c): void
346
    {
347
        /** @var ViewEngine $viewEngine */
348
        $viewEngine = $c->get(ViewEngine::class);
349
        $views = $c->get('views');
350
        $registeredViews = $viewEngine->getFolders();
351
352
        foreach ($views as $view => $folder) {
353
            $this->overrideViewFolder($view, $folder, $registeredViews);
354
        }
355
    }
356
357
    /**
358
     * @param string $view
359
     * @param string $folder
360
     * @param Folders $registeredViews
361
     */
362
    private function overrideViewFolder(string $view, string $folder, Folders $registeredViews): void
363
    {
364
        if ($registeredViews->exists($view)) {
365
            /** @var \League\Plates\Template\Folder $currentFolder */
366
            $currentFolder = $registeredViews->get($view);
367
            $currentFolder->setPath($folder);
368
        }
369
    }
370
371
    /**
372
     * @param Container $c
373
     */
374
    private function initMiddlewareStack(Container $c): void
375
    {
376
        $c[Stack::class] = new Stack($this->router);
377
    }
378
379
    /**
380
     * @param Container $c
381
     */
382
    private function setupMiddlewareStack(Container $c): void
383
    {
384
        $stack = $c->get(Stack::class);
385
        $middlewareStack = $c->has('stack') ? $c->get('stack') : [];
386
387
        foreach ($middlewareStack as $middleware) {
388
            if ($middleware instanceof MiddlewareInterface) {
389
                $stack->addMiddleWare($middleware);
390
            } elseif ($c->has($middleware)) {
391
                $stack->addMiddleWare($c->get($middleware));
392
            } else {
393
                $stack->addMiddleWare(new $middleware());
394
            }
395
        }
396
    }
397
}
398