Completed
Push — master ( 85fc43...b5ae43 )
by Derek Stephen
01:43
created

ApplicationPackage   A

Complexity

Total Complexity 42

Size/Duplication

Total Lines 314
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 19

Test Coverage

Coverage 97.86%

Importance

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