1 | <?php |
||||
2 | |||||
3 | declare(strict_types=1); |
||||
4 | |||||
5 | namespace Thruster\MikroKernel; |
||||
6 | |||||
7 | use Psr\Http\Message\ResponseInterface; |
||||
8 | use Psr\Http\Message\ServerRequestInterface; |
||||
9 | use Psr\Http\Server\RequestHandlerInterface; |
||||
10 | use Symfony\Bridge\ProxyManager\LazyProxy\Instantiator\RuntimeInstantiator; |
||||
11 | use Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper; |
||||
12 | use Symfony\Component\Config\ConfigCache; |
||||
13 | use Symfony\Component\Config\FileLocator; |
||||
14 | use Symfony\Component\Config\Loader\DelegatingLoader; |
||||
15 | use Symfony\Component\Config\Loader\LoaderResolver; |
||||
16 | use Symfony\Component\Debug\DebugClassLoader; |
||||
17 | use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; |
||||
18 | use Symfony\Component\DependencyInjection\Compiler\PassConfig; |
||||
19 | use Symfony\Component\DependencyInjection\ContainerBuilder; |
||||
20 | use Symfony\Component\DependencyInjection\ContainerInterface; |
||||
21 | use Symfony\Component\DependencyInjection\Dumper\PhpDumper; |
||||
22 | use Symfony\Component\DependencyInjection\Loader\ClosureLoader; |
||||
23 | use Symfony\Component\DependencyInjection\Loader\DirectoryLoader; |
||||
24 | use Symfony\Component\DependencyInjection\Loader\GlobFileLoader; |
||||
25 | use Symfony\Component\DependencyInjection\Loader\IniFileLoader; |
||||
26 | use Symfony\Component\DependencyInjection\Loader\PhpFileLoader; |
||||
27 | use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; |
||||
28 | use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; |
||||
29 | use Symfony\Component\Filesystem\Filesystem; |
||||
30 | use Thruster\HttpFactory\HttpFactoryInterface; |
||||
31 | use Thruster\HttpFactory\ZendDiactorosHttpFactory; |
||||
32 | |||||
33 | /** |
||||
34 | * Class MikroKernel. |
||||
35 | * |
||||
36 | * @author Aurimas Niekis <[email protected]> |
||||
37 | */ |
||||
38 | abstract class MikroKernel implements MikroKernelInterface |
||||
39 | { |
||||
40 | /** @var ContainerInterface */ |
||||
41 | protected $container; |
||||
42 | |||||
43 | /** @var string */ |
||||
44 | protected $environment; |
||||
45 | |||||
46 | /** @var bool */ |
||||
47 | protected $debug; |
||||
48 | |||||
49 | /** @var bool */ |
||||
50 | protected $booted; |
||||
51 | |||||
52 | /** @var int */ |
||||
53 | protected $startTime; |
||||
54 | |||||
55 | /** @var string */ |
||||
56 | private $projectDir; |
||||
57 | |||||
58 | /** @var string */ |
||||
59 | private $warmupDir; |
||||
60 | |||||
61 | /** @var RequestHandlerInterface */ |
||||
62 | private $requestHandler; |
||||
63 | |||||
64 | 24 | public function __construct(string $environment = 'dev', bool $debug = true) |
|||
65 | { |
||||
66 | 24 | $this->environment = $environment; |
|||
67 | 24 | $this->debug = $debug; |
|||
68 | 24 | $this->booted = false; |
|||
69 | 24 | } |
|||
70 | |||||
71 | 3 | public function __clone() |
|||
72 | { |
||||
73 | 3 | $this->booted = false; |
|||
74 | 3 | $this->container = null; |
|||
75 | 3 | $this->startTime = null; |
|||
76 | 3 | } |
|||
77 | |||||
78 | /** |
||||
79 | * {@inheritdoc} |
||||
80 | */ |
||||
81 | 12 | public function boot(): void |
|||
82 | { |
||||
83 | 12 | if ($this->booted) { |
|||
84 | 3 | return; |
|||
85 | } |
||||
86 | |||||
87 | 12 | if ($this->debug) { |
|||
88 | 6 | $this->startTime = time(); |
|||
89 | } |
||||
90 | |||||
91 | 12 | if ($this->debug && !isset($_ENV['SHELL_VERBOSITY']) && !isset($_SERVER['SHELL_VERBOSITY'])) { |
|||
92 | 3 | putenv('SHELL_VERBOSITY=3'); |
|||
93 | 3 | $_ENV['SHELL_VERBOSITY'] = 3; |
|||
94 | 3 | $_SERVER['SHELL_VERBOSITY'] = 3; |
|||
95 | } |
||||
96 | |||||
97 | // init container |
||||
98 | 12 | $this->initializeContainer(); |
|||
99 | |||||
100 | 12 | $this->booted = true; |
|||
101 | 12 | } |
|||
102 | |||||
103 | 6 | public function handle(ServerRequestInterface $request): ResponseInterface |
|||
104 | { |
||||
105 | 6 | $requestHandler = $this->getRequestHandler(); |
|||
106 | |||||
107 | 6 | if (null !== $requestHandler) { |
|||
108 | 3 | return $requestHandler->handle($request); |
|||
109 | } |
||||
110 | |||||
111 | 3 | return $this->getHttpFactory() |
|||
112 | 3 | ->response() |
|||
113 | 3 | ->createResponse() |
|||
114 | 3 | ->withBody($this->getHttpFactory()->stream()->createStream('<h1>It Works!</h1>')); |
|||
115 | } |
||||
116 | |||||
117 | /** |
||||
118 | * {@inheritdoc} |
||||
119 | */ |
||||
120 | 6 | public function getEnvironment(): string |
|||
121 | { |
||||
122 | 6 | return $this->environment; |
|||
123 | } |
||||
124 | |||||
125 | /** |
||||
126 | * {@inheritdoc} |
||||
127 | */ |
||||
128 | 6 | public function isDebug(): bool |
|||
129 | { |
||||
130 | 6 | return $this->debug; |
|||
131 | } |
||||
132 | |||||
133 | /** |
||||
134 | * Gets the application root dir (path of the project's composer file). |
||||
135 | * |
||||
136 | * @return string The project root dir |
||||
137 | */ |
||||
138 | public function getProjectDir(): string |
||||
139 | { |
||||
140 | if (null === $this->projectDir) { |
||||
141 | $r = new \ReflectionObject($this); |
||||
142 | $dir = $rootDir = \dirname($r->getFileName()); |
||||
143 | while (!file_exists($dir . '/composer.json')) { |
||||
144 | if ($dir === \dirname($dir)) { |
||||
145 | return $this->projectDir = $rootDir; |
||||
146 | } |
||||
147 | $dir = \dirname($dir); |
||||
148 | } |
||||
149 | $this->projectDir = $dir; |
||||
150 | } |
||||
151 | |||||
152 | return $this->projectDir; |
||||
153 | } |
||||
154 | |||||
155 | /** |
||||
156 | * {@inheritdoc} |
||||
157 | */ |
||||
158 | 9 | public function getContainer(): ?ContainerInterface |
|||
159 | { |
||||
160 | 9 | return $this->container; |
|||
161 | } |
||||
162 | |||||
163 | 6 | public function getRequestHandler(): ?RequestHandlerInterface |
|||
164 | { |
||||
165 | 6 | if (null !== $this->requestHandler) { |
|||
166 | 3 | return $this->requestHandler; |
|||
167 | } |
||||
168 | |||||
169 | 6 | if (false === $this->container->has(RequestHandlerInterface::class)) { |
|||
170 | 3 | return null; |
|||
171 | } |
||||
172 | |||||
173 | 3 | $this->requestHandler = $this->container->get(RequestHandlerInterface::class); |
|||
174 | |||||
175 | 3 | return $this->requestHandler; |
|||
176 | } |
||||
177 | |||||
178 | /** |
||||
179 | * {@inheritdoc} |
||||
180 | */ |
||||
181 | public function getStartTime(): int |
||||
182 | { |
||||
183 | return $this->debug ? $this->startTime : 0; |
||||
184 | } |
||||
185 | |||||
186 | /** |
||||
187 | * {@inheritdoc} |
||||
188 | */ |
||||
189 | 6 | public function getCacheDir(): string |
|||
190 | { |
||||
191 | 6 | return $this->getProjectDir() . '/var/cache/' . $this->environment; |
|||
192 | } |
||||
193 | |||||
194 | /** |
||||
195 | * Use this method to register compiler passes and manipulate the container during the building process. |
||||
196 | * |
||||
197 | * @param ContainerBuilder $container |
||||
198 | */ |
||||
199 | protected function build(ContainerBuilder $container): void |
||||
200 | { |
||||
201 | } |
||||
202 | |||||
203 | /** |
||||
204 | * Gets the container class. |
||||
205 | * |
||||
206 | * @return string The container class |
||||
207 | */ |
||||
208 | 6 | protected function getContainerClass(): string |
|||
209 | { |
||||
210 | 6 | $class = \get_class($this); |
|||
211 | 6 | if ('c' === $class[0] && 0 === strpos($class, "class@anonymous\0")) { |
|||
212 | $class = \get_parent_class($class) . str_replace('.', '_', ContainerBuilder::hash($class)); |
||||
213 | } |
||||
214 | |||||
215 | 6 | return str_replace('\\', '_', $class) . |
|||
216 | 6 | ucfirst($this->environment) . ($this->debug ? 'Debug' : '') . 'Container'; |
|||
217 | } |
||||
218 | |||||
219 | /** |
||||
220 | * Gets the container's base class. |
||||
221 | * |
||||
222 | * All names except Container must be fully qualified. |
||||
223 | * |
||||
224 | * @return string |
||||
225 | */ |
||||
226 | 3 | protected function getContainerBaseClass(): string |
|||
227 | { |
||||
228 | 3 | return 'Container'; |
|||
229 | } |
||||
230 | |||||
231 | /** |
||||
232 | * Initializes the service container. |
||||
233 | * |
||||
234 | * The cached version of the service container is used when fresh, otherwise the |
||||
235 | * container is built. |
||||
236 | */ |
||||
237 | 6 | protected function initializeContainer(): void |
|||
238 | { |
||||
239 | 6 | $class = $this->getContainerClass(); |
|||
240 | 6 | $cacheDir = $this->warmupDir ?: $this->getCacheDir(); |
|||
241 | 6 | $cache = new ConfigCache($cacheDir . '/' . $class . '.php', $this->debug); |
|||
242 | 6 | $oldContainer = null; |
|||
243 | |||||
244 | 6 | if ($fresh = $cache->isFresh()) { |
|||
245 | // Silence E_WARNING to ignore "include" failures - don't use "@" to prevent silencing fatal errors |
||||
246 | 3 | $errorLevel = error_reporting(\E_ALL ^ \E_WARNING); |
|||
247 | 3 | $fresh = $oldContainer = false; |
|||
248 | |||||
249 | try { |
||||
250 | 3 | if (file_exists($cache->getPath()) && \is_object($this->container = include $cache->getPath())) { |
|||
251 | 3 | $this->container->set('kernel', $this); |
|||
252 | 3 | $oldContainer = $this->container; |
|||
253 | 3 | $fresh = true; |
|||
254 | } |
||||
255 | } catch (\Throwable $e) { |
||||
0 ignored issues
–
show
Coding Style
Comprehensibility
introduced
by
![]() |
|||||
256 | } catch (\Exception $e) { |
||||
0 ignored issues
–
show
Coding Style
Comprehensibility
introduced
by
|
|||||
257 | 3 | } finally { |
|||
258 | 3 | error_reporting($errorLevel); |
|||
259 | } |
||||
260 | } |
||||
261 | |||||
262 | 6 | if ($fresh) { |
|||
263 | 3 | return; |
|||
264 | } |
||||
265 | |||||
266 | 3 | if ($this->debug) { |
|||
267 | 3 | $collectedLogs = []; |
|||
268 | 3 | $previousHandler = \defined('PHPUNIT_COMPOSER_INSTALL'); |
|||
269 | $previousHandler = $previousHandler ?: set_error_handler(function ($type, $message, $file, $line) use ( |
||||
270 | &$collectedLogs, |
||||
271 | &$previousHandler |
||||
272 | ) { |
||||
273 | if (E_USER_DEPRECATED !== $type && E_DEPRECATED !== $type) { |
||||
274 | /* @var callable $previousHandler */ |
||||
275 | return $previousHandler ? $previousHandler($type, $message, $file, $line) : false; |
||||
276 | } |
||||
277 | |||||
278 | if (isset($collectedLogs[$message])) { |
||||
279 | $collectedLogs[$message]['count']++; |
||||
280 | |||||
281 | return; |
||||
282 | } |
||||
283 | |||||
284 | $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 5); |
||||
285 | // Clean the trace by removing first frames added by the error handler itself. |
||||
286 | for ($i = 0; isset($backtrace[$i]); $i++) { |
||||
287 | if ($backtrace[$i]['line'] ?? null === $line && $backtrace[$i]['file'] ?? null === $file) { |
||||
288 | $backtrace = \array_slice($backtrace, 1 + $i); |
||||
289 | break; |
||||
290 | } |
||||
291 | } |
||||
292 | // Remove frames added by DebugClassLoader. |
||||
293 | for ($i = \count($backtrace) - 2; 0 < $i; $i--) { |
||||
294 | if (DebugClassLoader::class === ($backtrace[$i]['class'] ?? null)) { |
||||
295 | $backtrace = [$backtrace[$i + 1]]; |
||||
296 | break; |
||||
297 | } |
||||
298 | } |
||||
299 | |||||
300 | $collectedLogs[$message] = [ |
||||
301 | 'type' => $type, |
||||
302 | 'message' => $message, |
||||
303 | 'file' => $file, |
||||
304 | 'line' => $line, |
||||
305 | 'trace' => [$backtrace[0]], |
||||
306 | 'count' => 1, |
||||
307 | ]; |
||||
308 | 3 | }); |
|||
309 | } |
||||
310 | |||||
311 | try { |
||||
312 | 3 | $container = null; |
|||
0 ignored issues
–
show
|
|||||
313 | 3 | $container = $this->buildContainer(); |
|||
314 | 3 | $container->compile(); |
|||
315 | 3 | } finally { |
|||
316 | 3 | if ($this->debug && true !== $previousHandler) { |
|||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||
317 | restore_error_handler(); |
||||
318 | |||||
319 | file_put_contents( |
||||
320 | $cacheDir . '/' . $class . 'Deprecations.log', |
||||
321 | serialize(array_values($collectedLogs)) |
||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||
322 | ); |
||||
323 | file_put_contents( |
||||
324 | $cacheDir . '/' . $class . 'Compiler.log', |
||||
325 | 3 | null !== $container ? implode("\n", $container->getCompiler()->getLog()) : '' |
|||
326 | ); |
||||
327 | } |
||||
328 | } |
||||
329 | |||||
330 | 3 | if (null === $oldContainer && file_exists($cache->getPath())) { |
|||
331 | 3 | $errorLevel = error_reporting(\E_ALL ^ \E_WARNING); |
|||
332 | |||||
333 | try { |
||||
334 | 3 | $oldContainer = include $cache->getPath(); |
|||
335 | } catch (\Throwable $e) { |
||||
0 ignored issues
–
show
Coding Style
Comprehensibility
introduced
by
|
|||||
336 | } catch (\Exception $e) { |
||||
0 ignored issues
–
show
Coding Style
Comprehensibility
introduced
by
|
|||||
337 | 3 | } finally { |
|||
338 | 3 | error_reporting($errorLevel); |
|||
339 | } |
||||
340 | } |
||||
341 | |||||
342 | 3 | $oldContainer = \is_object($oldContainer) ? new \ReflectionClass($oldContainer) : false; |
|||
343 | |||||
344 | 3 | $this->dumpContainer($cache, $container, $class, $this->getContainerBaseClass()); |
|||
345 | 3 | $this->container = require $cache->getPath(); |
|||
346 | 3 | $this->container->set('kernel', $this); |
|||
347 | |||||
348 | 3 | if ($oldContainer && \get_class($this->container) !== $oldContainer->name) { |
|||
349 | // Because concurrent requests might still be using them, |
||||
350 | // old container files are not removed immediately, |
||||
351 | // but on a next dump of the container. |
||||
352 | 3 | static $legacyContainers = []; |
|||
353 | 3 | $oldContainerDir = \dirname($oldContainer->getFileName()); |
|||
354 | |||||
355 | 3 | $legacyContainers[$oldContainerDir . '.legacy'] = true; |
|||
356 | 3 | foreach (glob(\dirname($oldContainerDir) . \DIRECTORY_SEPARATOR . '*.legacy') as $legacyContainer) { |
|||
357 | 3 | if (!isset($legacyContainers[$legacyContainer]) && @unlink($legacyContainer)) { |
|||
358 | 3 | (new Filesystem())->remove(substr($legacyContainer, 0, -7)); |
|||
359 | } |
||||
360 | } |
||||
361 | |||||
362 | 3 | touch($oldContainerDir . '.legacy'); |
|||
363 | } |
||||
364 | |||||
365 | 3 | if ($this->container->has('cache_warmer')) { |
|||
366 | $this->container->get('cache_warmer')->warmUp($this->container->getParameter('kernel.cache_dir')); |
||||
367 | } |
||||
368 | 3 | } |
|||
369 | |||||
370 | /** |
||||
371 | * Returns the kernel parameters. |
||||
372 | * |
||||
373 | * @return array An array of kernel parameters |
||||
374 | */ |
||||
375 | 3 | protected function getKernelParameters(): array |
|||
376 | { |
||||
377 | return [ |
||||
378 | 3 | 'kernel.project_dir' => realpath($this->getProjectDir()) ?: $this->getProjectDir(), |
|||
379 | 3 | 'kernel.environment' => $this->environment, |
|||
380 | 3 | 'kernel.debug' => $this->debug, |
|||
381 | 3 | 'kernel.cache_dir' => realpath($cacheDir = $this->warmupDir ?: $this->getCacheDir()) ?: $cacheDir, |
|||
382 | 3 | 'kernel.container_class' => $this->getContainerClass(), |
|||
383 | ]; |
||||
384 | } |
||||
385 | |||||
386 | /** |
||||
387 | * Builds the service container. |
||||
388 | * |
||||
389 | * @return ContainerBuilder The compiled service container |
||||
390 | * |
||||
391 | * @throws \RuntimeException |
||||
392 | */ |
||||
393 | 3 | protected function buildContainer() |
|||
394 | { |
||||
395 | 3 | $dir = $this->warmupDir ?: $this->getCacheDir(); |
|||
396 | 3 | if (!is_dir($dir)) { |
|||
397 | if (false === @mkdir($dir, 0777, true) && !is_dir($dir)) { |
||||
398 | throw new \RuntimeException(sprintf("Unable to create the cache directory (%s)\n", $dir)); |
||||
399 | } |
||||
400 | 3 | } elseif (!is_writable($dir)) { |
|||
401 | throw new \RuntimeException(sprintf("Unable to write in the cache directory (%s)\n", $dir)); |
||||
402 | } |
||||
403 | |||||
404 | 3 | $container = $this->getContainerBuilder(); |
|||
405 | 3 | $container->addObjectResource($this); |
|||
406 | 3 | $this->build($container); |
|||
407 | |||||
408 | 3 | $this->registerContainerConfiguration($this->getContainerLoader($container)); |
|||
409 | |||||
410 | 3 | return $container; |
|||
411 | } |
||||
412 | |||||
413 | /** |
||||
414 | * Gets a new ContainerBuilder instance used to build the service container. |
||||
415 | * |
||||
416 | * @return ContainerBuilder |
||||
417 | */ |
||||
418 | 3 | protected function getContainerBuilder(): ContainerBuilder |
|||
419 | { |
||||
420 | 3 | $container = new ContainerBuilder(); |
|||
421 | 3 | $container->getParameterBag()->add($this->getKernelParameters()); |
|||
422 | |||||
423 | 3 | if ($this instanceof CompilerPassInterface) { |
|||
424 | $container->addCompilerPass($this, PassConfig::TYPE_BEFORE_OPTIMIZATION, -10000); |
||||
425 | } |
||||
426 | |||||
427 | 3 | if (class_exists('ProxyManager\Configuration') && |
|||
428 | 3 | class_exists('Symfony\Bridge\ProxyManager\LazyProxy\Instantiator\RuntimeInstantiator') |
|||
429 | ) { |
||||
430 | 3 | $container->setProxyInstantiator(new RuntimeInstantiator()); |
|||
431 | } |
||||
432 | |||||
433 | 3 | $container->register(HttpFactoryInterface::class, $this->getHttpFactoryClass()) |
|||
434 | 3 | ->setPublic(true); |
|||
435 | |||||
436 | 3 | $container->setAlias('http_factory', HttpFactoryInterface::class); |
|||
437 | |||||
438 | 3 | return $container; |
|||
439 | } |
||||
440 | |||||
441 | 3 | public function getHttpFactory(): HttpFactoryInterface |
|||
442 | { |
||||
443 | 3 | return $this->container->get(HttpFactoryInterface::class); |
|||
444 | } |
||||
445 | |||||
446 | 3 | public function getHttpFactoryClass(): string |
|||
447 | { |
||||
448 | 3 | return ZendDiactorosHttpFactory::class; |
|||
449 | } |
||||
450 | |||||
451 | /** |
||||
452 | * Dumps the service container to PHP code in the cache. |
||||
453 | * |
||||
454 | * @param ConfigCache $cache The config cache |
||||
455 | * @param ContainerBuilder $container The service container |
||||
456 | * @param string $class The name of the class to generate |
||||
457 | * @param string $baseClass The name of the container's base class |
||||
458 | */ |
||||
459 | 3 | protected function dumpContainer(ConfigCache $cache, ContainerBuilder $container, $class, $baseClass): void |
|||
460 | { |
||||
461 | // cache the container |
||||
462 | 3 | $dumper = new PhpDumper($container); |
|||
463 | |||||
464 | 3 | if (class_exists('ProxyManager\Configuration') && |
|||
465 | 3 | class_exists('Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper') |
|||
466 | ) { |
||||
467 | 3 | $dumper->setProxyDumper(new ProxyDumper()); |
|||
468 | } |
||||
469 | |||||
470 | 3 | if ($container->hasParameter('kernel.container_build_time')) { |
|||
471 | $buildTime = $container->getParameter('kernel.container_build_time'); |
||||
472 | } |
||||
473 | |||||
474 | 3 | $content = $dumper->dump([ |
|||
475 | 3 | 'class' => $class, |
|||
476 | 3 | 'base_class' => $baseClass, |
|||
477 | 3 | 'file' => $cache->getPath(), |
|||
478 | 'as_files' => true, |
||||
479 | 3 | 'debug' => $this->debug, |
|||
480 | 3 | 'build_time' => $buildTime ?? time(), |
|||
481 | ]); |
||||
482 | |||||
483 | 3 | $rootCode = array_pop($content); |
|||
0 ignored issues
–
show
It seems like
$content can also be of type string ; however, parameter $array of array_pop() does only seem to accept array , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
484 | 3 | $dir = \dirname($cache->getPath()) . '/'; |
|||
485 | 3 | $fs = new Filesystem(); |
|||
486 | |||||
487 | 3 | foreach ($content as $file => $code) { |
|||
488 | 3 | $fs->dumpFile($dir . $file, $code); |
|||
489 | 3 | @chmod($dir . $file, 0666 & ~umask()); |
|||
0 ignored issues
–
show
It seems like you do not handle an error condition for
chmod() . This can introduce security issues, and is generally not recommended.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||||
490 | } |
||||
491 | |||||
492 | 3 | $legacyFile = \dirname($dir . $file) . '.legacy'; |
|||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||
493 | 3 | if (file_exists($legacyFile)) { |
|||
494 | @unlink($legacyFile); |
||||
0 ignored issues
–
show
It seems like you do not handle an error condition for
unlink() . This can introduce security issues, and is generally not recommended.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||||
495 | } |
||||
496 | |||||
497 | 3 | $cache->write($rootCode, $container->getResources()); |
|||
498 | 3 | } |
|||
499 | |||||
500 | /** |
||||
501 | * Returns a loader for the container. |
||||
502 | * |
||||
503 | * @param ContainerInterface $container |
||||
504 | * |
||||
505 | * @return DelegatingLoader The loader |
||||
506 | */ |
||||
507 | 3 | protected function getContainerLoader(ContainerInterface $container) |
|||
508 | { |
||||
509 | 3 | $locator = new FileLocator($this); |
|||
0 ignored issues
–
show
$this of type Thruster\MikroKernel\MikroKernel is incompatible with the type string|string[] expected by parameter $paths of Symfony\Component\Config...eLocator::__construct() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
510 | 3 | $resolver = new LoaderResolver([ |
|||
511 | 3 | new XmlFileLoader($container, $locator), |
|||
512 | 3 | new YamlFileLoader($container, $locator), |
|||
513 | 3 | new IniFileLoader($container, $locator), |
|||
514 | 3 | new PhpFileLoader($container, $locator), |
|||
515 | 3 | new GlobFileLoader($container, $locator), |
|||
516 | 3 | new DirectoryLoader($container, $locator), |
|||
517 | 3 | new ClosureLoader($container), |
|||
518 | ]); |
||||
519 | |||||
520 | 3 | return new DelegatingLoader($resolver); |
|||
521 | } |
||||
522 | |||||
523 | 3 | public function serialize() |
|||
524 | { |
||||
525 | 3 | return serialize([$this->environment, $this->debug]); |
|||
526 | } |
||||
527 | |||||
528 | public function unserialize($data): void |
||||
529 | { |
||||
530 | [$environment, $debug] = unserialize($data, ['allowed_classes' => false]); |
||||
531 | |||||
532 | $this->__construct($environment, $debug); |
||||
533 | } |
||||
534 | } |
||||
535 |