1 | <?php |
||
2 | |||
3 | namespace ForkCMS\App; |
||
4 | |||
5 | use PDOException; |
||
6 | use Spoon; |
||
7 | use SpoonDatabaseException; |
||
8 | use Symfony\Component\DependencyInjection\ContainerBuilder; |
||
9 | use Symfony\Component\Filesystem\Filesystem; |
||
10 | use Symfony\Component\Finder\Finder; |
||
11 | use Symfony\Component\HttpFoundation\Response; |
||
12 | use Symfony\Component\HttpKernel\DependencyInjection\MergeExtensionConfigurationPass; |
||
13 | use Symfony\Component\HttpKernel\Kernel as BaseKernel; |
||
14 | use Symfony\Component\HttpFoundation\Request; |
||
15 | use Symfony\Component\HttpKernel\HttpKernelInterface; |
||
16 | use Backend\DependencyInjection\BackendExtension; |
||
17 | |||
18 | /** |
||
19 | * The Kernel provides a proper way to load an environment and DI container. |
||
20 | * It also handles requests and responses. |
||
21 | */ |
||
22 | abstract class Kernel extends BaseKernel |
||
23 | { |
||
24 | /** @var Request We need this to check if a module is being installed */ |
||
25 | private $request; |
||
26 | |||
27 | /** |
||
28 | * Constructor. |
||
29 | * |
||
30 | * @param string $environment The environment |
||
31 | * @param bool $enableDebug Whether to enable debugging or not |
||
32 | * |
||
33 | * @api |
||
34 | */ |
||
35 | public function __construct(string $environment, bool $enableDebug) |
||
36 | { |
||
37 | $this->request = Request::createFromGlobals(); |
||
38 | |||
39 | parent::__construct($environment, $enableDebug); |
||
40 | $this->boot(); |
||
41 | } |
||
42 | |||
43 | /** |
||
44 | * {@inheritdoc} |
||
45 | * |
||
46 | * @api |
||
47 | */ |
||
48 | public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true): Response |
||
49 | { |
||
50 | // boot if it hasn't booted yet |
||
51 | $this->boot(); |
||
52 | |||
53 | return $this->getHttpKernel()->handle($request, $type, $catch); |
||
54 | } |
||
55 | |||
56 | /** |
||
57 | * Boot and define the Fork Constants. |
||
58 | */ |
||
59 | public function boot(): void |
||
60 | { |
||
61 | if ($this->booted) { |
||
62 | return; |
||
63 | } |
||
64 | |||
65 | parent::boot(); |
||
66 | |||
67 | // define Fork constants |
||
68 | $this->defineForkConstants(); |
||
0 ignored issues
–
show
Deprecated Code
introduced
by
![]() |
|||
69 | } |
||
70 | |||
71 | /** |
||
72 | * This will disappear in time in favour of container-driven parameters. |
||
73 | * |
||
74 | * @deprecated |
||
75 | */ |
||
76 | public function defineForkConstants(): void |
||
77 | { |
||
78 | $container = $this->getContainer(); |
||
79 | |||
80 | Spoon::setDebug($container->getParameter('kernel.debug')); |
||
81 | Spoon::setDebugEmail($container->getParameter('fork.debug_email')); |
||
82 | Spoon::setDebugMessage($container->getParameter('fork.debug_message')); |
||
83 | Spoon::setCharset($container->getParameter('kernel.charset')); |
||
84 | |||
85 | /** |
||
86 | * @deprecated SPOON_* constants are deprecated in favour of Spoon::set*(). |
||
87 | * Will be removed in the next major release. |
||
88 | */ |
||
89 | defined('PATH_WWW') || define('PATH_WWW', realpath($container->getParameter('site.path_www'))); |
||
90 | |||
91 | defined('SITE_DEFAULT_LANGUAGE') || define('SITE_DEFAULT_LANGUAGE', $container->getParameter('site.default_language')); |
||
92 | defined('SITE_DEFAULT_TITLE') || define('SITE_DEFAULT_TITLE', $container->getParameter('site.default_title')); |
||
93 | defined('SITE_MULTILANGUAGE') || define('SITE_MULTILANGUAGE', $container->getParameter('site.multilanguage')); |
||
94 | defined('SITE_DOMAIN') || define('SITE_DOMAIN', $container->getParameter('site.domain')); |
||
95 | defined('SITE_PROTOCOL') || define('SITE_PROTOCOL', $container->getParameter('site.protocol')); |
||
96 | defined('SITE_URL') || define('SITE_URL', SITE_PROTOCOL . '://' . SITE_DOMAIN); |
||
97 | |||
98 | defined('FORK_VERSION') || define('FORK_VERSION', $container->getParameter('fork.version')); |
||
99 | |||
100 | defined('ACTION_GROUP_TAG') || define('ACTION_GROUP_TAG', $container->getParameter('action.group_tag')); |
||
101 | defined('ACTION_RIGHTS_LEVEL') || define('ACTION_RIGHTS_LEVEL', $container->getParameter('action.rights_level')); |
||
102 | |||
103 | defined('BACKEND_PATH') || define('BACKEND_PATH', PATH_WWW . '/src/Backend'); |
||
104 | defined('BACKEND_CACHE_PATH') || define('BACKEND_CACHE_PATH', BACKEND_PATH . '/Cache'); |
||
105 | defined('BACKEND_CORE_PATH') || define('BACKEND_CORE_PATH', BACKEND_PATH . '/Core'); |
||
106 | defined('BACKEND_MODULES_PATH') || define('BACKEND_MODULES_PATH', BACKEND_PATH . '/Modules'); |
||
107 | defined('BACKEND_CORE_URL') || define('BACKEND_CORE_URL', '/src/Backend/Core'); |
||
108 | defined('BACKEND_CACHE_URL') || define('BACKEND_CACHE_URL', '/src/Backend/Cache'); |
||
109 | |||
110 | defined('FRONTEND_PATH') || define('FRONTEND_PATH', PATH_WWW . '/src/Frontend'); |
||
111 | defined('FRONTEND_CACHE_PATH') || define('FRONTEND_CACHE_PATH', FRONTEND_PATH . '/Cache'); |
||
112 | defined('FRONTEND_THEMES_PATH') || define('FRONTEND_THEMES_PATH', FRONTEND_PATH . '/Themes'); |
||
113 | defined('FRONTEND_CORE_PATH') || define('FRONTEND_CORE_PATH', FRONTEND_PATH . '/Core'); |
||
114 | defined('FRONTEND_MODULES_PATH') || define('FRONTEND_MODULES_PATH', FRONTEND_PATH . '/Modules'); |
||
115 | defined('FRONTEND_FILES_PATH') || define('FRONTEND_FILES_PATH', FRONTEND_PATH . '/Files'); |
||
116 | defined('FRONTEND_FILES_URL') || define('FRONTEND_FILES_URL', '/src/Frontend/Files'); |
||
117 | defined('FRONTEND_CORE_URL') || define('FRONTEND_CORE_URL', '/src/Frontend/Core'); |
||
118 | defined('FRONTEND_CACHE_URL') || define('FRONTEND_CACHE_URL', '/src/Frontend/Cache'); |
||
119 | } |
||
120 | |||
121 | /** |
||
122 | * Builds the service container. |
||
123 | * |
||
124 | * @throws \RuntimeException |
||
125 | * |
||
126 | * @return ContainerBuilder The compiled service container |
||
127 | */ |
||
128 | protected function buildContainer() |
||
129 | { |
||
130 | $container = parent::buildContainer(); |
||
131 | |||
132 | $installedModules = $this->getInstalledModules($container); |
||
133 | |||
134 | $container->setParameter('installed_modules', $installedModules); |
||
135 | |||
136 | foreach ($installedModules as $module) { |
||
137 | $class = 'Backend\\Modules\\' . $module . '\\DependencyInjection\\' . $module . 'Extension'; |
||
138 | |||
139 | if (class_exists($class)) { |
||
140 | $container->registerExtension(new $class()); |
||
141 | } |
||
142 | } |
||
143 | |||
144 | $container->registerExtension(new BackendExtension()); |
||
145 | |||
146 | // ensure these extensions are implicitly loaded |
||
147 | $container->getCompilerPassConfig()->setMergePass( |
||
148 | new MergeExtensionConfigurationPass(array_keys($container->getExtensions())) |
||
149 | ); |
||
150 | |||
151 | return $container; |
||
152 | } |
||
153 | |||
154 | private function getInstalledModules(ContainerBuilder $containerBuilder): array |
||
155 | { |
||
156 | // on installation all modules should be loaded |
||
157 | if ($this->environment === 'install' || $this->environment === 'test') { |
||
158 | return $this->getAllPossibleModuleNames(); |
||
159 | } |
||
160 | |||
161 | $moduleNames = []; |
||
162 | if ($this->isInstallingModule()) { |
||
163 | $moduleNames[] = $this->request->query->get('module'); |
||
164 | } |
||
165 | |||
166 | try { |
||
167 | $moduleNames = array_merge( |
||
168 | $moduleNames, |
||
169 | (array) $containerBuilder->get('database')->getColumn( |
||
170 | 'SELECT name FROM modules' |
||
171 | ) |
||
172 | ); |
||
173 | } catch (SpoonDatabaseException $e) { |
||
174 | $moduleNames = []; |
||
175 | } catch (PDOException $e) { |
||
176 | // fork is probably not installed yet |
||
177 | $moduleNames = []; |
||
178 | } |
||
179 | |||
180 | if (empty($moduleNames)) { |
||
181 | return $this->getAllPossibleModuleNames(); |
||
182 | } |
||
183 | |||
184 | return $moduleNames; |
||
185 | } |
||
186 | |||
187 | public function isInstallingModule(): bool |
||
188 | { |
||
189 | return preg_match('/\/private(\/\w\w)?\/extensions\/install_module\?/', $this->request->getRequestUri()) |
||
190 | && $this->request->query->has('module') |
||
191 | && in_array($this->request->query->get('module'), $this->getAllPossibleModuleNames()); |
||
192 | } |
||
193 | |||
194 | private function getAllPossibleModuleNames(): array |
||
195 | { |
||
196 | $moduleNames = []; |
||
197 | $finder = new Finder(); |
||
198 | |||
199 | $directories = $finder->directories()->in(__DIR__ . '/../src/Backend/Modules')->depth(0); |
||
200 | |||
201 | foreach ($directories->getIterator() as $directory) { |
||
202 | $moduleNames[] = $directory->getFilename(); |
||
203 | } |
||
204 | |||
205 | return $moduleNames; |
||
206 | } |
||
207 | |||
208 | protected function initializeContainer(): void |
||
209 | { |
||
210 | // remove the cache dir when installing a module to trigger rebuilding the kernel |
||
211 | if ($this->isInstallingModule()) { |
||
212 | $fileSystem = new Filesystem(); |
||
213 | $fileSystem->remove($this->getCacheDir().'/'.$this->getContainerClass().'.php'); |
||
214 | } |
||
215 | |||
216 | parent::initializeContainer(); |
||
217 | } |
||
218 | |||
219 | public function getLogDir(): string |
||
220 | { |
||
221 | return dirname(__DIR__).'/var/logs/' . $this->environment; |
||
222 | } |
||
223 | |||
224 | public function getCacheDir(): string |
||
225 | { |
||
226 | return dirname(__DIR__) . '/var/cache/' . $this->environment; |
||
227 | } |
||
228 | } |
||
229 |