Completed
Push — master ( a305b0...f627c0 )
by Derek Stephen
01:40
created

ApplicationPackage::setupRouteFirewall()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

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