Completed
Push — dev-master ( 511541...a305b0 )
by Derek Stephen
06:18
created

ApplicationPackage::setupMiddlewareStack()   A

Complexity

Conditions 5
Paths 1

Size

Total Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 6.4222

Importance

Changes 0
Metric Value
dl 0
loc 20
ccs 8
cts 13
cp 0.6153
rs 9.2888
c 0
b 0
f 0
cc 5
nc 1
nop 1
crap 6.4222
1
<?php
2
3
namespace Bone\Mvc;
4
5
use Barnacle\Container;
6
use Barnacle\Exception\NotFoundException;
7
use Barnacle\RegistrationInterface;
8
use Bone\Http\Middleware\Stack;
9
use Bone\I18n\I18nRegistrationInterface;
10
use Bone\Mvc\Controller\DownloadController;
11
use Bone\Mvc\Router;
12
use Bone\Mvc\Router\Decorator\ExceptionDecorator;
13
use Bone\Mvc\Router\Decorator\NotAllowedDecorator;
14
use Bone\Mvc\Router\Decorator\NotFoundDecorator;
15
use Bone\Mvc\Router\PlatesStrategy;
16
use Bone\Mvc\Router\RouterConfigInterface;
17
use Bone\Mvc\View\Extension\Plates\AlertBox;
18
use Bone\Mvc\View\Extension\Plates\LocaleLink;
19
use Bone\Mvc\View\Extension\Plates\Translate;
20
use Bone\Mvc\View\ViewEngine;
21
use Bone\View\Helper\Paginator;
22
use Bone\Mvc\View\PlatesEngine;
23
use Bone\Service\TranslatorFactory;
24
use League\Plates\Template\Folders;
25
use League\Route\Strategy\ApplicationStrategy;
26
use League\Route\Strategy\JsonStrategy;
27
use Locale;
28
use PDO;
29
use Laminas\Diactoros\ResponseFactory;
30
use Laminas\I18n\Translator\Loader\Gettext;
31
use Laminas\I18n\Translator\Translator;
32
use Psr\Http\Server\MiddlewareInterface;
33
34
class ApplicationPackage implements RegistrationInterface
35
{
36
    /** @var array $config */
37
    private $config;
38
39
    /** @var Router $router */
40
    private $router;
41
42
    /** @var bool $i18nEnabledSite */
43
    private $i18nEnabledSite = false;
44
45
    /** @var array $supportedLocales */
46
    private $supportedLocales = [];
47
48
    /**
49
     * ApplicationPackage constructor.
50
     * @param array $config
51
     * @param \Bone\Mvc\Router $router
52
     */
53 9
    public function __construct(array $config, Router $router)
54
    {
55 9
        $this->config = $config;
56 9
        $this->router = $router;
57 9
    }
58
59
    /**
60
     * @param Container $c
61
     */
62 9
    public function addToContainer(Container $c)
63
    {
64 9
        $this->setConfigArray($c);
65 9
        $this->setLocale($c);
66 9
        $this->setupLogs($c);
67 9
        $this->setupPdoConnection($c);
68 9
        $this->setupViewEngine($c);
69 9
        $this->setupTranslator($c);
70 9
        $this->setupModules($c);
71 9
        $this->setupModuleViewOverrides($c);
72 9
        $this->setupDownloadController($c);
73 9
        $this->setupMiddlewareStack($c);
74 9
    }
75
76
    /**
77
     * @param Container $c
78
     */
79 9
    private function setConfigArray(Container $c)
80
    {
81 9
        foreach ($this->config as $key => $value) {
82 9
            $c[$key] = $value;
83
        }
84 9
    }
85
86
    /**
87
     * @param Container $c
88
     */
89 9
    private function setLocale(Container $c)
90
    {
91 9
        $i18n = $c->get('i18n');
92 9
        $this->i18nEnabledSite = $i18n['enabled'];
93 9
        $this->supportedLocales = $i18n['supported_locales'];
94 9
        $defaultLocale = $i18n['default_locale'];
95 9
        Locale::setDefault($defaultLocale);
96 9
    }
97
98
    /**
99
     * @param Container $c
100
     */
101 9
    private function setupViewEngine(Container $c)
102
    {
103
        // set up the view engine dependencies
104 9
        $viewEngine = new PlatesEngine($c->get('viewFolder'));
105 9
        $viewEngine->loadExtension(new AlertBox());
106
107 9
        $c[PlatesEngine::class] = $viewEngine;
108
109 View Code Duplication
        $c[NotFoundDecorator::class] = $c->factory(function (Container $c) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
110 9
            $layout = $c->get('default_layout');
111 9
            $templates = $c->get('error_pages');
112 9
            $viewEngine = $c->get(PlatesEngine::class);
113 9
            $notFoundDecorator = new NotFoundDecorator($viewEngine, $templates);
114 9
            $notFoundDecorator->setLayout($layout);
115
116 9
            return $notFoundDecorator;
117 9
        });
118
119 View Code Duplication
        $c[NotAllowedDecorator::class] = $c->factory(function (Container $c) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
120 9
            $layout = $c->get('default_layout');
121 9
            $templates = $c->get('error_pages');
122 9
            $viewEngine = $c->get(PlatesEngine::class);
123 9
            $notAllowedDecorator = new NotAllowedDecorator($viewEngine, $templates);
124 9
            $notAllowedDecorator->setLayout($layout);
125
126 9
            return $notAllowedDecorator;
127 9
        });
128
129 View Code Duplication
        $c[ExceptionDecorator::class] = $c->factory(function (Container $c) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
130 9
            $viewEngine = $c->get(PlatesEngine::class);
131 9
            $layout = $c->get('default_layout');
132 9
            $templates = $c->get('error_pages');
133 9
            $decorator = new ExceptionDecorator($viewEngine, $templates);
134 9
            $decorator->setLayout($layout);
135
136 9
            return $decorator;
137 9
        });
138
139
        $c[PlatesStrategy::class] = $c->factory(function (Container $c) {
140 9
            $viewEngine = $c->get(PlatesEngine::class);
141 9
            $notFoundDecorator = $c->get(NotFoundDecorator::class);
142 9
            $notAllowedDecorator = $c->get(NotAllowedDecorator::class);
143 9
            $exceptionDecorator = $c->get(ExceptionDecorator::class);
144 9
            $layout = $c->get('default_layout');
145 9
            $strategy = new PlatesStrategy($viewEngine, $notFoundDecorator, $notAllowedDecorator, $layout, $exceptionDecorator);
146
147 9
            return $strategy;
148 9
        });
149
150
        /** @var PlatesStrategy $strategy */
151 9
        $strategy = $c->get(PlatesStrategy::class);
152 9
        $strategy->setContainer($c);
153
154 9
        if ($this->i18nEnabledSite === true) {
155 8
            $strategy->setI18nEnabled(true);
156 8
            $strategy->setSupportedLocales($this->supportedLocales);
157
        }
158
159 9
        $this->router->setStrategy($strategy);
160 9
    }
161
162
    /**
163
     * @param Container $c
164
     */
165 9
    private function setupModules(Container $c)
166
    {
167
        // set up the modules and vendor package modules
168 9
        $packages = $c->get('packages');
169 9
        $i18n = $c->get('i18n');
170
        /** @var Translator $translator */
171 9
        $translator = $c->get(Translator::class);
172
173 9
        foreach ($packages as $packageName) {
174 9
            if (class_exists($packageName)) {
175
                /** @var RegistrationInterface $package */
176 9
                $package = new $packageName();
177
178 9
                if ($package->hasEntityPath()) {
179 9
                    $paths = $c['entity_paths'];
180 9
                    $paths[] = $package->getEntityPath();
181 9
                    $c['entity_paths'] = $paths;
182
                }
183
            }
184
        }
185 9
        reset($packages);
186 9
        foreach ($packages as $packageName) {
187 9
            if (class_exists($packageName)) {
188
                /** @var RegistrationInterface $package */
189 9
                $package = new $packageName();
190 9
                $package->addToContainer($c);
191
192 9
                if ($package instanceof RouterConfigInterface) {
193 9
                    $package->addRoutes($c, $this->router);
194
                }
195
196 9
                if ($package instanceof I18nRegistrationInterface) {
197 9
                    foreach ($i18n['supported_locales'] as $locale) {
198 9
                        $factory = new TranslatorFactory();
199 9
                        $factory->addPackageTranslations($translator, $package, $locale);
200
                    }
201
                }
202
            }
203
        }
204 9
    }
205
206
    /**
207
     * @param Container $c
208
     */
209 9
    private function setupTranslator(Container $c)
210
    {
211 9
        $config = $c->get('i18n');
212 9
        $engine = $c->get(PlatesEngine::class);
213 9
        if (is_array($config)) {
214 9
            $factory = new TranslatorFactory();
215 9
            $translator = $factory->createTranslator($config);
216 9
            $engine->loadExtension(new Translate($translator));
217 9
            $engine->loadExtension(new LocaleLink());
218 9
            $defaultLocale = $config['default_locale'] ?: 'en_GB';
219 9
            $translator->setLocale($defaultLocale);
220 9
            $c[Translator::class] = $translator;
221
        }
222 9
    }
223
224
225
    /**
226
     * @param Container $c
227
     */
228 9
    private function setupPdoConnection(Container $c)
229
    {
230
        // set up a db connection
231
        $c[PDO::class] = $c->factory(function (Container $c): PDO {
232 1
            $credentials = $c->get('db');
233 1
            $host = $credentials['host'];
234 1
            $db = $credentials['database'];
235 1
            $user = $credentials['user'];
236 1
            $pass = $credentials['pass'];
237
238 1
            $dbConnection = new PDO('mysql:host=' . $host . ';dbname=' . $db, $user, $pass, [
239 1
                PDO::ATTR_EMULATE_PREPARES => false,
240
                PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
241
            ]);
242
243 1
            return $dbConnection;
244 9
        });
245 9
    }
246
247
    /**
248
     * @param Container $c
249
     */
250 9
    private function setupDownloadController(Container $c): void
251
    {
252 9
        $uploadDirectory = $c->get('uploads_dir');
253 9
        $c[DownloadController::class] = new DownloadController($uploadDirectory);
254 9
        $strategy = new JsonStrategy(new ResponseFactory());
255 9
        $strategy->setContainer($c);
256 9
        $this->router->map('GET', '/download', [DownloadController::class, 'downloadAction'])->setStrategy($strategy);
257 9
    }
258
259
    /**
260
     * @param Container $c
261
     */
262 9
    private function setupLogs(Container $c)
263
    {
264 9
        if ($c->has('display_errors')) {
265
            ini_set('display_errors', $c->get('display_errors'));
266
        }
267
268 9
        if ($c->has('error_reporting')) {
269
            error_reporting($c->get('error_reporting'));
270
        }
271
272 9
        if ($c->has('error_log')) {
273
            $errorLog = $c->get('error_log');
274
            if (!file_exists($errorLog)) {
275
                file_put_contents($errorLog, '');
276
                chmod($errorLog, 0775);
277
            }
278
            ini_set($c->get('error_log'), $errorLog);
279
        }
280 9
    }
281
282
    /**
283
     * @param Container $c
284
     */
285 9
    private function setupModuleViewOverrides(Container $c): void
286
    {
287
        /** @var PlatesEngine $viewEngine */
288 9
        $viewEngine = $c->get(PlatesEngine::class);
289 9
        $views = $c->get('views');
290 9
        $registeredViews = $viewEngine->getFolders();
291
292 9
        foreach ($views as $view => $folder) {
293 9
            $this->overrideViewFolder($view, $folder, $registeredViews);
294
        }
295 9
    }
296
297
    /**
298
     * @param string $view
299
     * @param string $folder
300
     * @param array $registeredViews
301
     * @param PlatesEngine $viewEngine
0 ignored issues
show
Bug introduced by
There is no parameter named $viewEngine. 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...
302
     */
303 9
    private function overrideViewFolder(string $view, string $folder, Folders $registeredViews): void
304
    {
305 9
        if ($registeredViews->exists($view)) {
306
            /** @var \League\Plates\Template\Folder $currentFolder */
307 1
            $currentFolder = $registeredViews->get($view);
308 1
            $currentFolder->setPath($folder);
309
        }
310 9
    }
311
312
    /**
313
     * @return string
314
     */
315 1
    public function getEntityPath(): string
316
    {
317 1
        return '';
318
    }
319
320
    /**
321
     * @return bool
322
     */
323 1
    public function hasEntityPath(): bool
324
    {
325 1
        return false;
326
    }
327
328
    /**
329
     * @param Container $c
330
     */
331 9
    public function setupMiddlewareStack(Container $c): void
332
    {
333
        $c[Stack::class] = $c->factory(function (Container $c) {
334 8
            $router = $c->get(Router::class);
335 8
            $stack = new Stack($router);
336 8
            $middlewareStack = $c->has('stack') ? $c->get('stack') : [];
337
338 8
            foreach ($middlewareStack as $middleware) {
339
                if ($middleware instanceof MiddlewareInterface) {
340
                    $stack->addMiddleWare($middleware);
341
                } elseif ($c->has($middleware)) {
342
                    $stack->addMiddleWare($c->get($middleware));
343
                } else {
344
                    $stack->addMiddleWare(new $middleware());
345
                }
346
            }
347
348 8
            return $stack;
349 9
        });
350
    }
351
}