Completed
Push — dev-master ( 0fa404...f1d44b )
by Derek Stephen
01:43
created

ApplicationPackage::setupPdoConnection()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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