1<?php
2/**
3 * Copyright since 2007 PrestaShop SA and Contributors
4 * PrestaShop is an International Registered Trademark & Property of PrestaShop SA
5 *
6 * NOTICE OF LICENSE
7 *
8 * This source file is subject to the Open Software License (OSL 3.0)
9 * that is bundled with this package in the file LICENSE.md.
10 * It is also available through the world-wide-web at this URL:
11 * https://opensource.org/licenses/OSL-3.0
12 * If you did not receive a copy of the license and are unable to
13 * obtain it through the world-wide-web, please send an email
14 * to license@prestashop.com so we can send you a copy immediately.
15 *
16 * DISCLAIMER
17 *
18 * Do not edit or add to this file if you wish to upgrade PrestaShop to newer
19 * versions in the future. If you wish to customize PrestaShop for your
20 * needs please refer to https://devdocs.prestashop.com/ for more information.
21 *
22 * @author    PrestaShop SA and Contributors <contact@prestashop.com>
23 * @copyright Since 2007 PrestaShop SA and Contributors
24 * @license   https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
25 */
26
27use PrestaShop\PrestaShop\Adapter\Module\Repository\ModuleRepository;
28use PrestaShop\PrestaShop\Adapter\SymfonyContainer;
29use Symfony\Component\Config\Loader\LoaderInterface;
30use Symfony\Component\DependencyInjection\ContainerBuilder;
31use Symfony\Component\HttpKernel\Kernel;
32
33class AppKernel extends Kernel
34{
35    const VERSION = '1.7.8.2';
36    const MAJOR_VERSION_STRING = '1.7';
37    const MAJOR_VERSION = 17;
38    const MINOR_VERSION = 8;
39    const RELEASE_VERSION = 2;
40
41    /**
42     * {@inheritdoc}
43     */
44    public function registerBundles()
45    {
46        $bundles = array(
47            new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
48            new Symfony\Bundle\SecurityBundle\SecurityBundle(),
49            new Symfony\Bundle\TwigBundle\TwigBundle(),
50            new Symfony\Bundle\MonologBundle\MonologBundle(),
51            new Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle(),
52            new Doctrine\Bundle\DoctrineBundle\DoctrineBundle(),
53            new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(),
54            // PrestaShop Core bundle
55            new PrestaShopBundle\PrestaShopBundle(),
56            // PrestaShop Translation parser
57            new PrestaShop\TranslationToolsBundle\TranslationToolsBundle(),
58            // REST API consumer
59            new Csa\Bundle\GuzzleBundle\CsaGuzzleBundle(),
60            new League\Tactician\Bundle\TacticianBundle(),
61            new FOS\JsRoutingBundle\FOSJsRoutingBundle(),
62        );
63
64        if (in_array($this->getEnvironment(), array('dev', 'test'), true)) {
65            $bundles[] = new Symfony\Bundle\DebugBundle\DebugBundle();
66            $bundles[] = new Symfony\Bundle\WebProfilerBundle\WebProfilerBundle();
67            $bundles[] = new Sensio\Bundle\DistributionBundle\SensioDistributionBundle();
68        }
69
70        if ('dev' === $this->getEnvironment()) {
71            $bundles[] = new Symfony\Bundle\WebServerBundle\WebServerBundle();
72        }
73
74        /* Will not work until PrestaShop is installed */
75        $activeModules = $this->getActiveModules();
76        if (!empty($activeModules)) {
77            try {
78                $this->enableComposerAutoloaderOnModules($activeModules);
79            } catch (\Exception $e) {
80            }
81        }
82
83        return $bundles;
84    }
85
86    /**
87     * {@inheritdoc}
88     */
89    public function reboot($warmupDir)
90    {
91        parent::reboot($warmupDir);
92
93        // We have classes to access the container from legacy code, they need to be cleaned after reboot
94        Context::getContext()->container = null;
95        SymfonyContainer::resetStaticCache();
96        // @todo: do not want to risk right now but maybe Context::getContext()->controller->container needs refreshing
97        //        but only if it is a Symfony container (do not override front legacy container)
98    }
99
100    /**
101     * {@inheritdoc}
102     */
103    protected function getKernelParameters()
104    {
105        $kernelParameters = parent::getKernelParameters();
106
107        return array_merge(
108            $kernelParameters,
109            array('kernel.active_modules' => $this->getActiveModules())
110        );
111    }
112
113    /**
114     * {@inheritdoc}
115     */
116    public function getRootDir()
117    {
118        return __DIR__;
119    }
120
121    /**
122     * {@inheritdoc}
123     */
124    public function getCacheDir()
125    {
126        return _PS_CACHE_DIR_;
127    }
128
129    /**
130     * {@inheritdoc}
131     */
132    public function getLogDir()
133    {
134        return dirname(__DIR__) . '/var/logs';
135    }
136
137    /**
138     * {@inheritdoc}
139     *
140     * @throws \Exception
141     */
142    public function registerContainerConfiguration(LoaderInterface $loader)
143    {
144        $loader->load(function (ContainerBuilder $container) {
145            $container->setParameter('container.autowiring.strict_mode', true);
146            $container->setParameter('container.dumper.inline_class_loader', false);
147            $container->addObjectResource($this);
148        });
149
150        $loader->load($this->getRootDir() . '/config/config_' . $this->getEnvironment() . '.yml');
151
152        // Add translation paths to load into the translator. The paths are loaded by the Symfony's FrameworkExtension
153        $loader->load(function (ContainerBuilder $container) {
154            $moduleTranslationsPaths = $container->getParameter('modules_translation_paths');
155            foreach ($this->getActiveModules() as $activeModulePath) {
156                $translationsDir = _PS_MODULE_DIR_ . $activeModulePath . '/translations';
157                if (is_dir($translationsDir)) {
158                    $moduleTranslationsPaths[] = $translationsDir;
159                }
160            }
161            $container->setParameter('modules_translation_paths', $moduleTranslationsPaths);
162        });
163    }
164
165    /**
166     * Enable auto loading of module Composer autoloader if needed.
167     * Need to be done as earlier as possible in application lifecycle.
168     *
169     * Note: this feature is also manage in PrestaShop\PrestaShop\Adapter\ContainerBuilder
170     * for non Symfony environments.
171     *
172     * @param array $modules the list of modules
173     */
174    private function enableComposerAutoloaderOnModules($modules)
175    {
176        $moduleDirectoryPath = rtrim(_PS_MODULE_DIR_, '/') . '/';
177        foreach ($modules as $module) {
178            $autoloader = $moduleDirectoryPath . $module . '/vendor/autoload.php';
179
180            if (file_exists($autoloader)) {
181                include_once $autoloader;
182            }
183        }
184    }
185
186    /**
187     * Gets the application root dir.
188     * Override Kernel due to the fact that we remove the composer.json in
189     * downloaded package. More we are not a framework and the root directory
190     * should always be the parent of this file.
191     *
192     * @return string The project root dir
193     */
194    public function getProjectDir()
195    {
196        return realpath(__DIR__ . '/..');
197    }
198
199    private function getActiveModules(): array
200    {
201        $activeModules = [];
202        try {
203            $activeModules = (new ModuleRepository())->getActiveModules();
204        } catch (\Exception $e) {
205            //Do nothing because the modules retrieval must not block the kernel, and it won't work
206            //during the installation process
207        }
208
209        return $activeModules;
210    }
211}
212