Completed
Push — master ( 8863ba...da03d8 )
by Derek Stephen
01:53
created

ApplicationPackage   A

Complexity

Total Complexity 36

Size/Duplication

Total Lines 319
Duplicated Lines 8.46 %

Coupling/Cohesion

Components 1
Dependencies 18

Test Coverage

Coverage 48.73%

Importance

Changes 0
Metric Value
wmc 36
lcom 1
cbo 18
dl 27
loc 319
ccs 77
cts 158
cp 0.4873
rs 9.52
c 0
b 0
f 0

16 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A addToContainer() 0 14 1
A setConfigArray() 0 6 2
A setLocale() 0 8 1
B setupViewEngine() 27 60 2
B setupModules() 0 40 9
A setupPdoConnection() 0 18 1
A setupDownloadController() 0 8 1
A setupRouteFirewall() 0 5 1
A setupLogs() 0 19 5
A setupModuleViewOverrides() 0 11 2
A overrideViewFolder() 0 8 2
A getEntityPath() 0 4 1
A hasEntityPath() 0 4 1
A setupMiddlewareStack() 0 20 5
A setupTranslator() 0 5 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

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