Completed
Push — master ( c1b50b...72ef67 )
by Derek Stephen
01:55 queued 39s
created

ApplicationPackage::setConfigArray()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 4
cts 4
cp 1
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 1
crap 2
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\Decorator\ExceptionDecorator;
18
use Bone\Mvc\Router\Decorator\NotAllowedDecorator;
19
use Bone\Mvc\Router\Decorator\NotFoundDecorator;
20
use Bone\Mvc\Router\PlatesStrategy;
21
use Bone\Mvc\Router\RouterConfigInterface;
22
use Bone\Mvc\View\Extension\Plates\AlertBox;
23
use Bone\Mvc\View\ViewEngine;
24
use Bone\View\Helper\Paginator;
25
use Bone\Mvc\View\PlatesEngine;
26
use Bone\I18n\Service\TranslatorFactory;
27
use League\Plates\Template\Folders;
28
use League\Route\Strategy\ApplicationStrategy;
29
use League\Route\Strategy\JsonStrategy;
30
use Locale;
31
use PDO;
32
use Laminas\Diactoros\ResponseFactory;
33
use Laminas\I18n\Translator\Loader\Gettext;
34
use Laminas\I18n\Translator\Translator;
35
use Psr\Http\Server\MiddlewareInterface;
36
37
class ApplicationPackage implements RegistrationInterface
38
{
39
    /** @var array $config */
40
    private $config;
41
42
    /** @var Router $router */
43
    private $router;
44
45
    /** @var bool $i18nEnabledSite */
46
    private $i18nEnabledSite = false;
47
48
    /** @var array $supportedLocales */
49
    private $supportedLocales = [];
50
51
    /**
52
     * ApplicationPackage constructor.
53
     * @param array $config
54
     * @param Router $router
55
     */
56 9
    public function __construct(array $config, Router $router)
57
    {
58 9
        $this->config = $config;
59 9
        $this->router = $router;
60 9
    }
61
62
    /**
63
     * @param Container $c
64
     */
65 9
    public function addToContainer(Container $c)
66
    {
67 9
        $this->setConfigArray($c);
68 9
        $this->setLocale($c);
69 9
        $this->setupLogs($c);
70 9
        $this->setupPdoConnection($c);
71 9
        $this->setupViewEngine($c);
72 9
        $this->initMiddlewareStack($c);
73 9
        $this->setupTranslator($c);
74 9
        $this->setupModules($c);
75 9
        $this->setupModuleViewOverrides($c);
76 9
        $this->setupDownloadController($c);
77 9
        $this->setupRouteFirewall($c);
78 9
        $this->setupMiddlewareStack($c);
79 9
    }
80
81
    /**
82
     * @param Container $c
83
     */
84 9
    private function setConfigArray(Container $c)
85
    {
86 9
        foreach ($this->config as $key => $value) {
87 9
            $c[$key] = $value;
88
        }
89 9
    }
90
91
    /**
92
     * @param Container $c
93
     */
94 9
    private function setLocale(Container $c)
95
    {
96 9
        $i18n = $c->get('i18n');
97 9
        $this->i18nEnabledSite = $i18n['enabled'];
98 9
        $this->supportedLocales = $i18n['supported_locales'];
99 9
        $defaultLocale = $i18n['default_locale'];
100 9
        Locale::setDefault($defaultLocale);
101 9
    }
102
103
    /**
104
     * @param Container $c
105
     */
106 9
    private function setupViewEngine(Container $c)
107
    {
108
        // set up the view engine dependencies
109 9
        $viewEngine = new PlatesEngine($c->get('viewFolder'));
110 9
        $viewEngine->loadExtension(new AlertBox());
111
112 9
        $c[PlatesEngine::class] = $viewEngine;
113
114 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...
115 9
            $layout = $c->get('default_layout');
116 9
            $templates = $c->get('error_pages');
117 9
            $viewEngine = $c->get(PlatesEngine::class);
118 9
            $notFoundDecorator = new NotFoundDecorator($viewEngine, $templates);
119 9
            $notFoundDecorator->setLayout($layout);
120
121 9
            return $notFoundDecorator;
122 9
        });
123
124 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...
125 9
            $layout = $c->get('default_layout');
126 9
            $templates = $c->get('error_pages');
127 9
            $viewEngine = $c->get(PlatesEngine::class);
128 9
            $notAllowedDecorator = new NotAllowedDecorator($viewEngine, $templates);
129 9
            $notAllowedDecorator->setLayout($layout);
130
131 9
            return $notAllowedDecorator;
132 9
        });
133
134 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...
135 9
            $viewEngine = $c->get(PlatesEngine::class);
136 9
            $layout = $c->get('default_layout');
137 9
            $templates = $c->get('error_pages');
138 9
            $decorator = new ExceptionDecorator($viewEngine, $templates);
139 9
            $decorator->setLayout($layout);
140
141 9
            return $decorator;
142 9
        });
143
144
        $c[PlatesStrategy::class] = $c->factory(function (Container $c) {
145 9
            $viewEngine = $c->get(PlatesEngine::class);
146 9
            $notFoundDecorator = $c->get(NotFoundDecorator::class);
147 9
            $notAllowedDecorator = $c->get(NotAllowedDecorator::class);
148 9
            $exceptionDecorator = $c->get(ExceptionDecorator::class);
149 9
            $layout = $c->get('default_layout');
150 9
            $strategy = new PlatesStrategy($viewEngine, $notFoundDecorator, $notAllowedDecorator, $layout, $exceptionDecorator);
151
152 9
            return $strategy;
153 9
        });
154
155
        /** @var PlatesStrategy $strategy */
156 9
        $strategy = $c->get(PlatesStrategy::class);
157 9
        $strategy->setContainer($c);
158
159 9
        if ($this->i18nEnabledSite === true) {
160 8
            $strategy->setI18nEnabled(true);
161 8
            $strategy->setSupportedLocales($this->supportedLocales);
162
        }
163
164 9
        $this->router->setStrategy($strategy);
165 9
    }
166
167
    /**
168
     * @param Container $c
169
     */
170 9
    private function setupModules(Container $c)
171
    {
172
        // set up the modules and vendor package modules
173 9
        $packages = $c->get('packages');
174 9
        $i18n = $c->get('i18n');
175
        /** @var Translator $translator */
176 9
        $translator = $c->get(Translator::class);
177
178 9
        foreach ($packages as $packageName) {
179 9
            if (class_exists($packageName)) {
180
                /** @var RegistrationInterface $package */
181 9
                $package = new $packageName();
182
183 9
                if ($package->hasEntityPath()) {
184 9
                    $paths = $c['entity_paths'];
185 9
                    $paths[] = $package->getEntityPath();
186 9
                    $c['entity_paths'] = $paths;
187
                }
188
            }
189
        }
190 9
        reset($packages);
191 9
        foreach ($packages as $packageName) {
192 9
            if (class_exists($packageName)) {
193
                /** @var RegistrationInterface $package */
194 9
                $package = new $packageName();
195 9
                $package->addToContainer($c);
196
197 9
                if ($package instanceof RouterConfigInterface) {
198 9
                    $package->addRoutes($c, $this->router);
199
                }
200
201 9
                if ($package instanceof I18nRegistrationInterface) {
0 ignored issues
show
Bug introduced by
The class Bone\I18n\I18nRegistrationInterface does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
202 9
                    foreach ($i18n['supported_locales'] as $locale) {
203 9
                        $factory = new TranslatorFactory();
204 9
                        $factory->addPackageTranslations($translator, $package, $locale);
205
                    }
206
                }
207
208 9
                if ($package instanceof MiddlewareAwareInterface) {
209
                    $stack = $c->get(Stack::class);
210
                    $package->addMiddleware($stack);
211
                }
212
            }
213
        }
214 9
    }
215
216
    /**
217
     * @param Container $c
218
     */
219 9
    private function setupTranslator(Container $c)
220
    {
221 9
        $package = new I18nPackage();
222 9
        $package->addToContainer($c);
223 9
    }
224
225
226
    /**
227
     * @param Container $c
228
     */
229 9
    private function setupPdoConnection(Container $c)
230
    {
231
        // set up a db connection
232
        $c[PDO::class] = $c->factory(function (Container $c): PDO {
233 1
            $credentials = $c->get('db');
234 1
            $host = $credentials['host'];
235 1
            $db = $credentials['database'];
236 1
            $user = $credentials['user'];
237 1
            $pass = $credentials['pass'];
238
239 1
            $dbConnection = new PDO('mysql:host=' . $host . ';dbname=' . $db, $user, $pass, [
240 1
                PDO::ATTR_EMULATE_PREPARES => false,
241
                PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
242
            ]);
243
244 1
            return $dbConnection;
245 9
        });
246 9
    }
247
248
    /**
249
     * @param Container $c
250
     */
251 9
    private function setupDownloadController(Container $c): void
252
    {
253 9
        $uploadDirectory = $c->get('uploads_dir');
254 9
        $c[DownloadController::class] = new DownloadController($uploadDirectory);
255 9
        $strategy = new JsonStrategy(new ResponseFactory());
256 9
        $strategy->setContainer($c);
257 9
        $this->router->map('GET', '/download', [DownloadController::class, 'downloadAction'])->setStrategy($strategy);
258 9
    }
259
260
    /**
261
     * @param Container $c
262
     */
263 9
    private function setupRouteFirewall(Container $c): void
264
    {
265 9
        $firewallPackage = new FirewallPackage();
266 9
        $firewallPackage->addToContainer($c);
267 9
    }
268
269
    /**
270
     * @param Container $c
271
     */
272 9
    private function setupLogs(Container $c)
273
    {
274 9
        if ($c->has('display_errors')) {
275
            ini_set('display_errors', $c->get('display_errors'));
276
        }
277
278 9
        if ($c->has('error_reporting')) {
279
            error_reporting($c->get('error_reporting'));
280
        }
281
282 9
        if ($c->has('error_log')) {
283
            $errorLog = $c->get('error_log');
284
            if (!file_exists($errorLog)) {
285
                file_put_contents($errorLog, '');
286
                chmod($errorLog, 0775);
287
            }
288
            ini_set($c->get('error_log'), $errorLog);
289
        }
290 9
    }
291
292
    /**
293
     * @param Container $c
294
     */
295 9
    private function setupModuleViewOverrides(Container $c): void
296
    {
297
        /** @var PlatesEngine $viewEngine */
298 9
        $viewEngine = $c->get(PlatesEngine::class);
299 9
        $views = $c->get('views');
300 9
        $registeredViews = $viewEngine->getFolders();
301
302 9
        foreach ($views as $view => $folder) {
303 9
            $this->overrideViewFolder($view, $folder, $registeredViews);
304
        }
305 9
    }
306
307
    /**
308
     * @param string $view
309
     * @param string $folder
310
     * @param array $registeredViews
311
     * @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...
312
     */
313 9
    private function overrideViewFolder(string $view, string $folder, Folders $registeredViews): void
314
    {
315 9
        if ($registeredViews->exists($view)) {
316
            /** @var \League\Plates\Template\Folder $currentFolder */
317 1
            $currentFolder = $registeredViews->get($view);
318 1
            $currentFolder->setPath($folder);
319
        }
320 9
    }
321
322
    /**
323
     * @return string
324
     */
325 1
    public function getEntityPath(): string
326
    {
327 1
        return '';
328
    }
329
330
    /**
331
     * @return bool
332
     */
333 1
    public function hasEntityPath(): bool
334
    {
335 1
        return false;
336
    }
337
338
    /**
339
     * @param Container $c
340
     */
341 9
    private function initMiddlewareStack(Container $c): void
342
    {
343 9
        $router = $c->get(Router::class);
344 9
        $c[Stack::class] = new Stack($router);
345 9
    }
346
347
    /**
348
     * @param Container $c
349
     */
350 9
    private function setupMiddlewareStack(Container $c): void
351
    {
352 9
        $stack = $c->get(Stack::class);
353 9
        $middlewareStack = $c->has('stack') ? $c->get('stack') : [];
354
355 9
        foreach ($middlewareStack as $middleware) {
356
            if ($middleware instanceof MiddlewareInterface) {
357
                $stack->addMiddleWare($middleware);
358
            } elseif ($c->has($middleware)) {
359
                $stack->addMiddleWare($c->get($middleware));
360
            } else {
361
                $stack->addMiddleWare(new $middleware());
362
            }
363
        }
364
    }
365
}