Completed
Push — master ( ae2d8b...c1b50b )
by Derek Stephen
01:39
created

ApplicationPackage::setupModules()   B

Complexity

Conditions 9
Paths 32

Size

Total Lines 40

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 23
CRAP Score 9

Importance

Changes 0
Metric Value
dl 0
loc 40
ccs 23
cts 23
cp 1
rs 7.7244
c 0
b 0
f 0
cc 9
nc 32
nop 1
crap 9
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\Http\MiddlewareAwareInterface;
11
use Bone\I18n\I18nPackage;
12
use Bone\I18n\I18nRegistrationInterface;
13
use Bone\I18n\View\Extension\LocaleLink;
14
use Bone\I18n\View\Extension\Translate;
15
use Bone\Mvc\Controller\DownloadController;
16
use Bone\Mvc\Router;
17
use Bone\Mvc\Router;
0 ignored issues
show
Bug introduced by
This code did not parse for me. Apparently, there is an error somewhere around this line:

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