Completed
Push — master ( 1d4cea...b63ce5 )
by Derek Stephen
05:14
created

ApplicationPackage   A

Complexity

Total Complexity 42

Size/Duplication

Total Lines 314
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 17

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 42
lcom 1
cbo 17
dl 0
loc 314
ccs 140
cts 140
cp 1
rs 9.0399
c 0
b 0
f 0

24 Methods

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

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. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

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