292 lines
9.2 KiB
PHP
292 lines
9.2 KiB
PHP
<?php
|
|
|
|
/*
|
|
* This file is part of the Symfony package.
|
|
*
|
|
* (c) Fabien Potencier <fabien@symfony.com>
|
|
*
|
|
* For the full copyright and license information, please view the LICENSE
|
|
* file that was distributed with this source code.
|
|
*/
|
|
|
|
namespace Symfony\Component\HttpKernel;
|
|
|
|
use Symfony\Component\DependencyInjection\Dumper\Preloader;
|
|
use Symfony\Component\DependencyInjection\Kernel\AbstractKernel;
|
|
use Symfony\Component\DependencyInjection\Kernel\KernelTrait;
|
|
use Symfony\Component\HttpFoundation\Request;
|
|
use Symfony\Component\HttpFoundation\Response;
|
|
use Symfony\Component\HttpKernel\Bundle\BundleAdapter;
|
|
use Symfony\Component\HttpKernel\Bundle\BundleInterface;
|
|
use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface;
|
|
|
|
/**
|
|
* The Kernel is the heart of the Symfony system.
|
|
*
|
|
* It manages an environment made of bundles.
|
|
*
|
|
* Environment names must always start with a letter and
|
|
* they must only contain letters and numbers.
|
|
*
|
|
* @author Fabien Potencier <fabien@symfony.com>
|
|
*/
|
|
abstract class Kernel extends AbstractKernel implements KernelInterface, RebootableInterface, TerminableInterface
|
|
{
|
|
use KernelTrait {
|
|
registerBundles as public;
|
|
registerContainerConfiguration as public;
|
|
initializeBundles as protected doInitializeBundles;
|
|
initializeContainer as protected doInitializeContainer;
|
|
getKernelParameters as private doGetKernelParameters;
|
|
}
|
|
|
|
private ?string $warmupDir = null;
|
|
private int $requestStackSize = 0;
|
|
private bool $resetServices = false;
|
|
private bool $handlingHttpCache = false;
|
|
|
|
public const VERSION = '8.1.1';
|
|
public const VERSION_ID = 80101;
|
|
public const MAJOR_VERSION = 8;
|
|
public const MINOR_VERSION = 1;
|
|
public const RELEASE_VERSION = 1;
|
|
public const EXTRA_VERSION = '';
|
|
|
|
public const END_OF_MAINTENANCE = '01/2027';
|
|
public const END_OF_LIFE = '01/2027';
|
|
|
|
public function __clone()
|
|
{
|
|
parent::__clone();
|
|
$this->requestStackSize = 0;
|
|
$this->resetServices = false;
|
|
$this->handlingHttpCache = false;
|
|
}
|
|
|
|
public function boot(): void
|
|
{
|
|
if ($this->booted) {
|
|
if (!$this->requestStackSize && $this->resetServices) {
|
|
if ($this->container->has('services_resetter')) {
|
|
$this->container->get('services_resetter')->reset();
|
|
}
|
|
$this->resetServices = false;
|
|
if ($this->debug) {
|
|
$this->startTime = microtime(true);
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if (!$this->container) {
|
|
$this->preBoot();
|
|
}
|
|
|
|
foreach ($this->getBundles() as $bundle) {
|
|
$bundle->setContainer($this->container);
|
|
$bundle->boot();
|
|
}
|
|
|
|
$this->booted = true;
|
|
}
|
|
|
|
public function reboot(?string $warmupDir): void
|
|
{
|
|
$this->shutdown();
|
|
$this->warmupDir = $warmupDir;
|
|
$this->boot();
|
|
}
|
|
|
|
public function terminate(Request $request, Response $response): void
|
|
{
|
|
if (!$this->booted) {
|
|
return;
|
|
}
|
|
|
|
if ($this->getHttpKernel() instanceof TerminableInterface) {
|
|
$this->getHttpKernel()->terminate($request, $response);
|
|
}
|
|
}
|
|
|
|
public function shutdown(): void
|
|
{
|
|
parent::shutdown();
|
|
$this->requestStackSize = 0;
|
|
$this->resetServices = false;
|
|
}
|
|
|
|
public function handle(Request $request, int $type = HttpKernelInterface::MAIN_REQUEST, bool $catch = true): Response
|
|
{
|
|
if (!$this->container) {
|
|
$this->preBoot();
|
|
}
|
|
|
|
if (HttpKernelInterface::MAIN_REQUEST === $type && !$this->handlingHttpCache && $this->container->has('http_cache')) {
|
|
$this->handlingHttpCache = true;
|
|
|
|
try {
|
|
return $this->container->get('http_cache')->handle($request, $type, $catch);
|
|
} finally {
|
|
$this->handlingHttpCache = false;
|
|
$this->resetServices = true;
|
|
}
|
|
}
|
|
|
|
$this->boot();
|
|
++$this->requestStackSize;
|
|
if (!$this->handlingHttpCache) {
|
|
$this->resetServices = true;
|
|
}
|
|
|
|
try {
|
|
return $this->getHttpKernel()->handle($request, $type, $catch);
|
|
} finally {
|
|
--$this->requestStackSize;
|
|
}
|
|
}
|
|
|
|
protected function getHttpKernel(): HttpKernelInterface
|
|
{
|
|
return $this->container->get('http_kernel');
|
|
}
|
|
|
|
public function getBundle(string $name): BundleInterface
|
|
{
|
|
if (!isset($this->bundles[$name])) {
|
|
throw new \InvalidArgumentException(\sprintf('Bundle "%s" does not exist or it is not enabled. Maybe you forgot to add it in the "registerBundles()" method of your "%s.php" file?', $name, get_debug_type($this)));
|
|
}
|
|
|
|
return $this->bundles[$name];
|
|
}
|
|
|
|
public function getCacheDir(): string
|
|
{
|
|
return $this->getProjectDir().'/var/cache/'.$this->environment;
|
|
}
|
|
|
|
public function getBuildDir(): string
|
|
{
|
|
return $this->getCacheDir();
|
|
}
|
|
|
|
public function getShareDir(): ?string
|
|
{
|
|
return $this->getCacheDir();
|
|
}
|
|
|
|
public function getLogDir(): string
|
|
{
|
|
return $this->getProjectDir().'/var/log';
|
|
}
|
|
|
|
public function getCharset(): string
|
|
{
|
|
return 'UTF-8';
|
|
}
|
|
|
|
protected function initializeBundles(): void
|
|
{
|
|
$this->doInitializeBundles();
|
|
|
|
foreach ($this->bundles as $name => $bundle) {
|
|
$this->bundles[$name] = !$bundle instanceof BundleInterface ? new BundleAdapter($bundle) : $bundle;
|
|
}
|
|
}
|
|
|
|
protected function initializeContainer(): void
|
|
{
|
|
$cachePath = $this->getEffectiveBuildDir().'/'.$this->getContainerClass().'.php';
|
|
$oldMtime = is_file($cachePath) ? filemtime($cachePath) : false;
|
|
|
|
$this->doInitializeContainer();
|
|
|
|
if (false !== $oldMtime && filemtime($cachePath) === $oldMtime) {
|
|
return;
|
|
}
|
|
|
|
$buildDir = $this->container->getParameter('kernel.build_dir');
|
|
$cacheDir = $this->container->getParameter('kernel.cache_dir');
|
|
$preload = $this instanceof WarmableInterface ? $this->warmUp($cacheDir, $buildDir) : [];
|
|
|
|
if ($this->container->has('cache_warmer')) {
|
|
$cacheWarmer = $this->container->get('cache_warmer');
|
|
|
|
if ($cacheDir !== $buildDir) {
|
|
$cacheWarmer->enableOptionalWarmers();
|
|
}
|
|
|
|
$preload = array_merge($preload, $cacheWarmer->warmUp($cacheDir, $buildDir));
|
|
}
|
|
|
|
if ($preload && file_exists($preloadFile = $buildDir.'/'.$this->getContainerClass().'.preload.php')) {
|
|
Preloader::append($preloadFile, $preload);
|
|
}
|
|
}
|
|
|
|
protected function getKernelParameters(): array
|
|
{
|
|
$parameters = $this->doGetKernelParameters() + [
|
|
'kernel.charset' => $this->getCharset(),
|
|
];
|
|
|
|
foreach ($this->bundles as $name => $bundle) {
|
|
$parameters['kernel.bundles_metadata'][$name]['namespace'] = $bundle->getNamespace();
|
|
}
|
|
|
|
return $parameters;
|
|
}
|
|
|
|
private function preBoot(): void
|
|
{
|
|
if ($this->debug) {
|
|
$this->startTime = microtime(true);
|
|
}
|
|
|
|
if ($this->debug && !isset($_ENV['SHELL_VERBOSITY']) && !isset($_SERVER['SHELL_VERBOSITY'])) {
|
|
if (\function_exists('putenv')) {
|
|
putenv('SHELL_VERBOSITY=3');
|
|
}
|
|
$_ENV['SHELL_VERBOSITY'] = 3;
|
|
$_SERVER['SHELL_VERBOSITY'] = 3;
|
|
}
|
|
|
|
$this->initializeBundles();
|
|
$this->initializeContainer();
|
|
|
|
$container = $this->container;
|
|
|
|
if ($container->hasParameter('kernel.trusted_hosts') && $trustedHosts = $container->getParameter('kernel.trusted_hosts')) {
|
|
Request::setTrustedHosts(\is_array($trustedHosts) ? $trustedHosts : preg_split('/\s*+,\s*+(?![^{]*})/', $trustedHosts));
|
|
}
|
|
|
|
if ($container->hasParameter('kernel.trusted_proxies') && $container->hasParameter('kernel.trusted_headers') && $trustedProxies = $container->getParameter('kernel.trusted_proxies')) {
|
|
$trustedHeaders = $container->getParameter('kernel.trusted_headers');
|
|
|
|
if (\is_string($trustedHeaders)) {
|
|
$trustedHeaders = array_map('trim', explode(',', $trustedHeaders));
|
|
}
|
|
|
|
if (\is_array($trustedHeaders)) {
|
|
$trustedHeaderSet = 0;
|
|
|
|
foreach ($trustedHeaders as $header) {
|
|
if (!\defined($const = Request::class.'::HEADER_'.strtr(strtoupper($header), '-', '_'))) {
|
|
throw new \InvalidArgumentException(\sprintf('The trusted header "%s" is not supported.', $header));
|
|
}
|
|
$trustedHeaderSet |= \constant($const);
|
|
}
|
|
} else {
|
|
$trustedHeaderSet = $trustedHeaders ?? (Request::HEADER_X_FORWARDED_FOR | Request::HEADER_X_FORWARDED_PORT | Request::HEADER_X_FORWARDED_PROTO);
|
|
}
|
|
|
|
Request::setTrustedProxies(\is_array($trustedProxies) ? $trustedProxies : array_map('trim', explode(',', $trustedProxies)), $trustedHeaderSet);
|
|
}
|
|
}
|
|
|
|
private function getEffectiveBuildDir(): string
|
|
{
|
|
return $this->warmupDir ?: $this->getBuildDir();
|
|
}
|
|
}
|