Passed
Push — master ( e6f0f4...5106e0 )
by Gilles
07:43
created

Thelia::checkMySQLConfigurations()   C

Complexity

Conditions 15
Paths 109

Size

Total Lines 65
Code Lines 36

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 36
dl 0
loc 65
rs 5.8416
c 0
b 0
f 0
cc 15
nc 109
nop 1

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/*************************************************************************************/
3
/*      This file is part of the Thelia package.                                     */
4
/*                                                                                   */
5
/*      Copyright (c) OpenStudio                                                     */
6
/*      email : [email protected]                                                       */
7
/*      web : http://www.thelia.net                                                  */
8
/*                                                                                   */
9
/*      For the full copyright and license information, please view the LICENSE.txt  */
10
/*      file that was distributed with this source code.                             */
11
/*************************************************************************************/
12
13
namespace Thelia\Core;
14
15
/**
16
 * Root class of Thelia
17
 *
18
 * It extends Symfony\Component\HttpKernel\Kernel for changing some features
19
 *
20
 *
21
 * @author Manuel Raynaud <[email protected]>
22
 */
23
24
use Propel\Runtime\Connection\ConnectionInterface;
25
use Propel\Runtime\DataFetcher\PDODataFetcher;
26
use Propel\Runtime\Propel;
27
use Symfony\Component\Config\FileLocator;
28
use Symfony\Component\Config\Loader\LoaderInterface;
29
use Symfony\Component\Debug\Debug;
30
use Symfony\Component\DependencyInjection\ContainerBuilder;
31
use Symfony\Component\DependencyInjection\Definition;
32
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
33
use Symfony\Component\DependencyInjection\Reference;
34
use Symfony\Component\Finder\Finder;
35
use Symfony\Component\HttpKernel\Kernel;
36
use Thelia\Core\DependencyInjection\Loader\XmlFileLoader;
37
use Thelia\Core\Event\TheliaEvents;
38
use Thelia\Core\Propel\Schema\SchemaLocator;
39
use Thelia\Core\Template\TemplateDefinition;
40
use Thelia\Core\Template\TemplateHelperInterface;
41
use Thelia\Core\Translation\Translator;
42
use Thelia\Log\Tlog;
43
use Thelia\Model\Module;
44
use Thelia\Model\ModuleQuery;
45
46
class Thelia extends Kernel
47
{
48
    const THELIA_VERSION = '2.4.0-alpha2';
49
50
    public function __construct($environment, $debug)
51
    {
52
        parent::__construct($environment, $debug);
53
54
        if ($debug) {
55
            Debug::enable();
56
        }
57
    }
58
59
    public static function isInstalled()
60
    {
61
        return file_exists(THELIA_CONF_DIR . 'database.yml');
62
    }
63
64
    protected function checkMySQLConfigurations(ConnectionInterface $con)
65
    {
66
        // TODO : add cache for this test
67
        /** @var  PDODataFetcher $result */
68
        $result = $con->query("SELECT VERSION() as version, @@SESSION.sql_mode as session_sql_mode");
69
70
        if ($result && $data = $result->fetch(\PDO::FETCH_ASSOC)) {
71
            $sessionSqlMode = explode(',', $data['session_sql_mode']);
72
            if (empty($sessionSqlMode[0])) {
73
                unset($sessionSqlMode[0]);
74
            }
75
            $canUpdate = false;
76
77
            // MariaDB is not impacted by this problem
78
            if (false === strpos($data['version'], 'MariaDB')) {
79
                // MySQL 5.6+ compatibility
80
                if (version_compare($data['version'], '5.6.0', '>=')) {
81
                    // add NO_ENGINE_SUBSTITUTION
82
                    if (!in_array('NO_ENGINE_SUBSTITUTION', $sessionSqlMode)) {
83
                        $sessionSqlMode[] = 'NO_ENGINE_SUBSTITUTION';
84
                        $canUpdate = true;
85
                        Tlog::getInstance()->addWarning("Add sql_mode NO_ENGINE_SUBSTITUTION. Please configure your MySQL server.");
86
                    }
87
88
                    // remove STRICT_TRANS_TABLES
89
                    if (($key = array_search('STRICT_TRANS_TABLES', $sessionSqlMode)) !== false) {
90
                        unset($sessionSqlMode[$key]);
91
                        $canUpdate = true;
92
                        Tlog::getInstance()->addWarning("Remove sql_mode STRICT_TRANS_TABLES. Please configure your MySQL server.");
93
                    }
94
95
                    // remove ONLY_FULL_GROUP_BY
96
                    if (($key = array_search('ONLY_FULL_GROUP_BY', $sessionSqlMode)) !== false) {
97
                        unset($sessionSqlMode[$key]);
98
                        $canUpdate = true;
99
                        Tlog::getInstance()->addWarning("Remove sql_mode ONLY_FULL_GROUP_BY. Please configure your MySQL server.");
100
                    }
101
                }
102
            } else {
103
                // MariaDB 10.2.4+ compatibility
104
                if (version_compare($data['version'], '10.2.4', '>=')) {
105
                    // remove STRICT_TRANS_TABLES
106
                    if (($key = array_search('STRICT_TRANS_TABLES', $sessionSqlMode)) !== false) {
107
                        unset($sessionSqlMode[$key]);
108
                        $canUpdate = true;
109
                        Tlog::getInstance()->addWarning("Remove sql_mode STRICT_TRANS_TABLES. Please configure your MySQL server.");
110
                    }
111
                }
112
113
                if (version_compare($data['version'], '10.1.7', '>=')) {
114
                    if (!in_array('NO_ENGINE_SUBSTITUTION', $sessionSqlMode)) {
115
                        $sessionSqlMode[] = 'NO_ENGINE_SUBSTITUTION';
116
                        $canUpdate = true;
117
                        Tlog::getInstance()->addWarning("Add sql_mode NO_ENGINE_SUBSTITUTION. Please configure your MySQL server.");
118
                    }
119
                }
120
            }
121
122
            if (! empty($canUpdate)) {
123
                if (null === $con->query("SET SESSION sql_mode='" . implode(',', $sessionSqlMode) . "';")) {
124
                    throw new \RuntimeException('Failed to set MySQL global and session sql_mode');
125
                }
126
            }
127
        } else {
128
            Tlog::getInstance()->addWarning("Failed to get MySQL version and sql_mode");
129
        }
130
    }
131
132
    /**
133
     * Gets the container's base class.
134
     *
135
     * All names except Container must be fully qualified.
136
     *
137
     * @return string
138
     */
139
    protected function getContainerBaseClass()
140
    {
141
        return '\Thelia\Core\DependencyInjection\TheliaContainer';
142
    }
143
144
    /**
145
     * @inheritDoc
146
     * @throws \Exception
147
     */
148
    public function boot()
149
    {
150
        // initialize Propel, building its cache if necessary
151
        $propelSchemaLocator = new SchemaLocator(
152
            THELIA_CONF_DIR,
153
            THELIA_MODULE_DIR
154
        );
155
        $propelInitService = new PropelInitService(
156
            $this->getEnvironment(),
157
            $this->isDebug(),
158
            $this->getEnvParameters(),
159
            $propelSchemaLocator
160
        );
161
        $propelConnectionAvailable = $propelInitService->init();
162
163
        if ($propelConnectionAvailable) {
164
            $theliaDatabaseConnection = Propel::getConnection('thelia');
165
            $this->checkMySQLConfigurations($theliaDatabaseConnection);
166
        }
167
168
        parent::boot();
169
170
        $this->getContainer()->set('thelia.propel.schema.locator', $propelSchemaLocator);
171
        $this->getContainer()->set('thelia.propel.init', $propelInitService);
172
173
        if ($propelConnectionAvailable) {
174
            $theliaDatabaseConnection->setEventDispatcher($this->getContainer()->get('event_dispatcher'));
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $theliaDatabaseConnection does not seem to be defined for all execution paths leading up to this point.
Loading history...
175
        }
176
177
        if (self::isInstalled()) {
178
            $this->getContainer()->get('event_dispatcher')->dispatch(TheliaEvents::BOOT);
179
        }
180
    }
181
182
    /**
183
     * Add all module's standard templates to the parser environment
184
     *
185
     * @param Definition $parser the parser
186
     * @param Module     $module the Module.
187
     */
188
    protected function addStandardModuleTemplatesToParserEnvironment($parser, $module)
189
    {
190
        $stdTpls = TemplateDefinition::getStandardTemplatesSubdirsIterator();
191
192
        foreach ($stdTpls as $templateType => $templateSubdirName) {
193
            $this->addModuleTemplateToParserEnvironment($parser, $module, $templateType, $templateSubdirName);
194
        }
195
    }
196
197
    /**
198
     * Add a module template directory to the parser environment
199
     *
200
     * @param Definition $parser             the parser
201
     * @param Module     $module             the Module.
202
     * @param string     $templateType       the template type (one of the TemplateDefinition type constants)
203
     * @param string     $templateSubdirName the template subdirectory name (one of the TemplateDefinition::XXX_SUBDIR constants)
204
     */
205
    protected function addModuleTemplateToParserEnvironment($parser, $module, $templateType, $templateSubdirName)
206
    {
207
        // Get template path
208
        $templateDirectory = $module->getAbsoluteTemplateDirectoryPath($templateSubdirName);
209
        try {
210
            $templateDirBrowser = new \DirectoryIterator($templateDirectory);
211
212
            $code = ucfirst($module->getCode());
213
214
            /* browse the directory */
215
            foreach ($templateDirBrowser as $templateDirContent) {
216
                /* is it a directory which is not . or .. ? */
217
                if ($templateDirContent->isDir() && ! $templateDirContent->isDot()) {
218
                    $parser->addMethodCall(
219
                        'addTemplateDirectory',
220
                        array(
221
                            $templateType,
222
                            $templateDirContent->getFilename(),
223
                            $templateDirContent->getPathName(),
224
                            $code
225
                        )
226
                    );
227
                }
228
            }
229
        } catch (\UnexpectedValueException $ex) {
230
            // The directory does not exists, ignore it.
231
        }
232
    }
233
234
    /**
235
     * Load some configuration
236
     * Initialize all plugins
237
     *
238
     * @param ContainerBuilder $container
239
     * @throws \Exception
240
     */
241
    protected function loadConfiguration(ContainerBuilder $container)
242
    {
243
        $loader = new XmlFileLoader($container, new FileLocator(__DIR__ . "/../Config/Resources"));
244
        $finder = Finder::create()
245
            ->name('*.xml')
246
            ->depth(0)
247
            ->in(__DIR__ . "/../Config/Resources");
248
249
        /** @var \SplFileInfo $file */
250
        foreach ($finder as $file) {
251
            $loader->load($file->getBaseName());
252
        }
253
254
        if (defined("THELIA_INSTALL_MODE") === false) {
255
            $modules = ModuleQuery::getActivated();
256
257
            $translationDirs = array();
258
259
260
261
            /** @var Module $module */
262
            foreach ($modules as $module) {
263
                try {
264
                    $definition = new Definition();
265
                    $definition->setClass($module->getFullNamespace());
266
                    $definition->addMethodCall("setContainer", array(new Reference('service_container')));
267
268
                    $container->setDefinition(
269
                        "module." . $module->getCode(),
270
                        $definition
271
                    );
272
273
                    $compilers = call_user_func(array($module->getFullNamespace(), 'getCompilers'));
274
275
                    foreach ($compilers as $compiler) {
276
                        if (is_array($compiler)) {
277
                            $container->addCompilerPass($compiler[0], $compiler[1]);
278
                        } else {
279
                            $container->addCompilerPass($compiler);
280
                        }
281
                    }
282
283
                    $loader = new XmlFileLoader($container, new FileLocator($module->getAbsoluteConfigPath()));
284
                    $loader->load("config.xml", "module." . $module->getCode());
285
286
                    $envConfigFileName = sprintf("config_%s.xml", $this->environment);
287
                    $envConfigFile = sprintf('%s%s%s', $module->getAbsoluteConfigPath(), DS, $envConfigFileName);
288
289
                    if (is_file($envConfigFile) && is_readable($envConfigFile)) {
290
                        $loader->load($envConfigFileName, "module." . $module->getCode());
291
                    }
292
                } catch (\Exception $e) {
293
                    Tlog::getInstance()->addError(
294
                        sprintf("Failed to load module %s: %s", $module->getCode(), $e->getMessage()),
295
                        $e
296
                    );
297
                }
298
            }
299
300
            $parser = $container->getDefinition('thelia.parser');
301
302
            /** @var \Thelia\Core\Template\TemplateHelperInterface $templateHelper */
303
            $templateHelper = $container->get('thelia.template_helper');
304
305
            /** @var Module $module */
306
            foreach ($modules as $module) {
307
                try {
308
                    $this->loadModuleTranslationDirectories($module, $translationDirs, $templateHelper);
309
310
                    $this->addStandardModuleTemplatesToParserEnvironment($parser, $module);
311
                } catch (\Exception $e) {
312
                    Tlog::getInstance()->addError(
313
                        sprintf("Failed to load module %s: %s", $module->getCode(), $e->getMessage()),
314
                        $e
315
                    );
316
                }
317
            }
318
319
            // Load core translation
320
            $translationDirs['core'] = THELIA_LIB . 'Config' . DS . 'I18n';
321
322
            // Load core translation
323
            $translationDirs[Translator::GLOBAL_FALLBACK_DOMAIN] = THELIA_LOCAL_DIR . 'I18n';
324
325
            // Standard templates (front, back, pdf, mail)
326
            /** @var TemplateDefinition $templateDefinition */
327
            foreach ($templateHelper->getStandardTemplateDefinitions() as $templateDefinition) {
328
                // Load parent templates transaltions, the current template translations.
329
                $templateList = array_merge(
330
                    $templateDefinition->getParentList(),
331
                    [ $templateDefinition ]
332
                );
333
334
                /** @var TemplateDefinition $tplDef */
335
                foreach ($templateList as $tplDef) {
336
                    if (is_dir($dir = $tplDef->getAbsoluteI18nPath())) {
337
                        $translationDirs[$tplDef->getTranslationDomain()] = $dir;
338
                    }
339
                }
340
            }
341
342
            if ($translationDirs) {
343
                $this->loadTranslation($container, $translationDirs);
344
            }
345
        }
346
    }
347
348
    /**
349
     * @param Module $module
350
     * @param array $translationDirs
351
     * @param TemplateHelperInterface $templateHelper
352
     */
353
    private function loadModuleTranslationDirectories(Module $module, array &$translationDirs, $templateHelper)
354
    {
355
        // Core module translation
356
        if (is_dir($dir = $module->getAbsoluteI18nPath())) {
357
            $translationDirs[$module->getTranslationDomain()] = $dir;
358
        }
359
360
        // Admin includes translation
361
        if (is_dir($dir = $module->getAbsoluteAdminIncludesI18nPath())) {
362
            $translationDirs[$module->getAdminIncludesTranslationDomain()] = $dir;
363
        }
364
365
        // Module back-office template, if any
366
        $templates =
367
            $templateHelper->getList(
368
                TemplateDefinition::BACK_OFFICE,
369
                $module->getAbsoluteTemplateBasePath()
370
            );
371
372
        foreach ($templates as $template) {
373
            $translationDirs[$module->getBackOfficeTemplateTranslationDomain($template->getName())] =
374
                $module->getAbsoluteBackOfficeI18nTemplatePath($template->getName());
375
        }
376
377
        // Module front-office template, if any
378
        $templates =
379
            $templateHelper->getList(
380
                TemplateDefinition::FRONT_OFFICE,
381
                $module->getAbsoluteTemplateBasePath()
382
            );
383
384
        foreach ($templates as $template) {
385
            $translationDirs[$module->getFrontOfficeTemplateTranslationDomain($template->getName())] =
386
                $module->getAbsoluteFrontOfficeI18nTemplatePath($template->getName());
387
        }
388
389
        // Module pdf template, if any
390
        $templates =
391
            $templateHelper->getList(
392
                TemplateDefinition::PDF,
393
                $module->getAbsoluteTemplateBasePath()
394
            );
395
396
        foreach ($templates as $template) {
397
            $translationDirs[$module->getPdfTemplateTranslationDomain($template->getName())] =
398
                $module->getAbsolutePdfI18nTemplatePath($template->getName());
399
        }
400
401
        // Module email template, if any
402
        $templates =
403
            $templateHelper->getList(
404
                TemplateDefinition::EMAIL,
405
                $module->getAbsoluteTemplateBasePath()
406
            );
407
408
        foreach ($templates as $template) {
409
            $translationDirs[$module->getEmailTemplateTranslationDomain($template->getName())] =
410
                $module->getAbsoluteEmailI18nTemplatePath($template->getName());
411
        }
412
    }
413
414
    private function loadTranslation(ContainerBuilder $container, array $dirs)
415
    {
416
        $translator = $container->getDefinition('thelia.translator');
417
418
        foreach ($dirs as $domain => $dir) {
419
            try {
420
                $finder = Finder::create()
421
                    ->files()
422
                    ->depth(0)
423
                    ->in($dir);
424
425
                /** @var \DirectoryIterator $file */
426
                foreach ($finder as $file) {
427
                    list($locale, $format) = explode('.', $file->getBaseName(), 2);
428
429
                    $translator->addMethodCall('addResource', array($format, (string) $file, $locale, $domain));
430
                }
431
            } catch (\InvalidArgumentException $ex) {
432
                // Ignore missing I18n directories
433
                Tlog::getInstance()->addWarning("loadTranslation: missing $dir directory");
434
            }
435
        }
436
    }
437
438
    /**
439
     *
440
     * initialize session in Request object
441
     *
442
     * All param must be change in Config table
443
     *
444
     * @param \Symfony\Component\HttpFoundation\Request $request
445
     */
446
447
    /**
448
     * Gets a new ContainerBuilder instance used to build the service container.
449
     *
450
     * @return ContainerBuilder
451
     */
452
    protected function getContainerBuilder()
453
    {
454
        return new TheliaContainerBuilder(new ParameterBag($this->getKernelParameters()));
455
    }
456
457
    /**
458
     * Builds the service container.
459
     *
460
     * @return ContainerBuilder The compiled service container
461
     * @throws \Exception
462
     */
463
    protected function buildContainer()
464
    {
465
        /** @var TheliaContainerBuilder $container */
466
        $container = parent::buildContainer();
467
468
        $this->loadConfiguration($container);
469
        $container->customCompile();
470
471
        return $container;
472
    }
473
474
    /**
475
     * Gets the cache directory.
476
     *
477
     * @return string The cache directory
478
     *
479
     * @api
480
     */
481
    public function getCacheDir()
482
    {
483
        if (defined('THELIA_ROOT')) {
484
            return THELIA_CACHE_DIR . $this->environment;
485
        } else {
486
            return parent::getCacheDir();
487
        }
488
    }
489
490
    /**
491
     * Gets the log directory.
492
     *
493
     * @return string The log directory
494
     *
495
     * @api
496
     */
497
    public function getLogDir()
498
    {
499
        if (defined('THELIA_ROOT')) {
500
            return THELIA_LOG_DIR;
501
        } else {
502
            return parent::getLogDir();
503
        }
504
    }
505
506
    /**
507
     * Returns the kernel parameters.
508
     *
509
     * @return array An array of kernel parameters
510
     */
511
    protected function getKernelParameters()
512
    {
513
        $parameters = parent::getKernelParameters();
514
515
        $parameters["thelia.root_dir"] = THELIA_ROOT;
516
        $parameters["thelia.core_dir"] = dirname(__DIR__); // This class is in core/lib/Thelia/Core.
517
        $parameters["thelia.module_dir"] = THELIA_MODULE_DIR;
518
519
        return $parameters;
520
    }
521
522
    /**
523
     * return available bundle
524
     *
525
     * Part of Symfony\Component\HttpKernel\KernelInterface
526
     *
527
     * @return Bundle\TheliaBundle[] An array of bundle instances.
528
     */
529
    public function registerBundles()
530
    {
531
        $bundles = array(
532
            /* TheliaBundle contain all the dependency injection description */
533
            new Bundle\TheliaBundle(),
534
        );
535
536
        /**
537
         * OTHER CORE BUNDLE CAN BE DECLARE HERE AND INITIALIZE WITH SPECIFIC CONFIGURATION
538
         *
539
         * HOW TO DECLARE OTHER BUNDLE ? ETC
540
         */
541
542
        return $bundles;
543
    }
544
545
    /**
546
     * Loads the container configuration
547
     *
548
     * part of Symfony\Component\HttpKernel\KernelInterface
549
     *
550
     * @param LoaderInterface $loader A LoaderInterface instance
551
     *
552
     * @api
553
     */
554
    public function registerContainerConfiguration(LoaderInterface $loader)
555
    {
556
        // Nothing is load here but it's possible to load container configuration here.
557
        // exemple in sf2 : $loader->load(__DIR__.'/config/config_'.$this->getEnvironment().'.yml');
558
    }
559
}
560