Completed
Push — master ( 42eb1d...46b99f )
by Derek Stephen
09:11
created

ApplicationPackage::addMiddlewaresToStack()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 10
ccs 3
cts 3
cp 1
rs 9.9332
c 0
b 0
f 0
cc 2
nc 2
nop 2
crap 2
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
0 ignored issues
show
Bug introduced by
There is no parameter named $router. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
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 View Code Duplication
    private function setupViewEngine(Container $c)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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 View Code Duplication
    private function setupTranslator(Container $c)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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