Aggiornato Composer

This commit is contained in:
Paolo A
2024-05-17 12:24:19 +00:00
parent 4ac62108b5
commit ec201d75b2
2238 changed files with 38684 additions and 59785 deletions

View File

@@ -29,7 +29,7 @@ class CacheWarmerAggregate implements CacheWarmerInterface
/**
* @param iterable<mixed, CacheWarmerInterface> $warmers
*/
public function __construct(iterable $warmers = [], bool $debug = false, string $deprecationLogsFilepath = null)
public function __construct(iterable $warmers = [], bool $debug = false, ?string $deprecationLogsFilepath = null)
{
$this->warmers = $warmers;
$this->debug = $debug;

View File

@@ -33,7 +33,7 @@ class FileLocator extends BaseFileLocator
/**
* {@inheritdoc}
*/
public function locate(string $file, string $currentPath = null, bool $first = true)
public function locate(string $file, ?string $currentPath = null, bool $first = true)
{
if (isset($file[0]) && '@' === $file[0]) {
$resource = $this->kernel->locateResource($file);

View File

@@ -33,7 +33,7 @@ final class ArgumentResolver implements ArgumentResolverInterface
/**
* @param iterable<mixed, ArgumentValueResolverInterface> $argumentValueResolvers
*/
public function __construct(ArgumentMetadataFactoryInterface $argumentMetadataFactory = null, iterable $argumentValueResolvers = [])
public function __construct(?ArgumentMetadataFactoryInterface $argumentMetadataFactory = null, iterable $argumentValueResolvers = [])
{
$this->argumentMetadataFactory = $argumentMetadataFactory ?? new ArgumentMetadataFactory();
$this->argumentValueResolvers = $argumentValueResolvers ?: self::getDefaultArgumentValueResolvers();

View File

@@ -69,8 +69,9 @@ final class NotTaggedControllerValueResolver implements ArgumentValueResolverInt
}
if (!$this->container->has($controller)) {
$i = strrpos($controller, ':');
$controller = substr($controller, 0, $i).strtolower(substr($controller, $i));
$controller = (false !== $i = strrpos($controller, ':'))
? substr($controller, 0, $i).strtolower(substr($controller, $i))
: $controller.'::__invoke';
}
$what = sprintf('argument $%s of "%s()"', $argument->getName(), $controller);

View File

@@ -25,7 +25,7 @@ class ContainerControllerResolver extends ControllerResolver
{
protected $container;
public function __construct(ContainerInterface $container, LoggerInterface $logger = null)
public function __construct(ContainerInterface $container, ?LoggerInterface $logger = null)
{
$this->container = $container;

View File

@@ -25,7 +25,7 @@ class ControllerResolver implements ControllerResolverInterface
{
private $logger;
public function __construct(LoggerInterface $logger = null)
public function __construct(?LoggerInterface $logger = null)
{
$this->logger = $logger;
}

View File

@@ -35,10 +35,10 @@ class TraceableArgumentResolver implements ArgumentResolverInterface
{
$e = $this->stopwatch->start('controller.get_arguments');
$ret = $this->resolver->getArguments($request, $controller);
$e->stop();
return $ret;
try {
return $this->resolver->getArguments($request, $controller);
} finally {
$e->stop();
}
}
}

View File

@@ -35,10 +35,10 @@ class TraceableControllerResolver implements ControllerResolverInterface
{
$e = $this->stopwatch->start('controller.get_callable');
$ret = $this->resolver->getController($request);
$e->stop();
return $ret;
try {
return $this->resolver->getController($request);
} finally {
$e->stop();
}
}
}

View File

@@ -107,9 +107,9 @@ class ArgumentMetadata
/**
* Returns the default value of the argument.
*
* @throws \LogicException if no default value is present; {@see self::hasDefaultValue()}
*
* @return mixed
*
* @throws \LogicException if no default value is present; {@see self::hasDefaultValue()}
*/
public function getDefaultValue()
{
@@ -137,7 +137,7 @@ class ArgumentMetadata
/**
* @return object[]
*/
public function getAttributes(string $name = null, int $flags = 0): array
public function getAttributes(?string $name = null, int $flags = 0): array
{
if (!$name) {
return $this->attributes;

View File

@@ -33,7 +33,7 @@ final class ArgumentMetadataFactory implements ArgumentMetadataFactoryInterface
$class = $reflection->class;
} else {
$reflection = new \ReflectionFunction($controller);
if ($class = str_contains($reflection->name, '{closure}') ? null : $reflection->getClosureScopeClass()) {
if ($class = str_contains($reflection->name, '{closure') ? null : (\PHP_VERSION_ID >= 80111 ? $reflection->getClosureCalledClass() : $reflection->getClosureScopeClass())) {
$class = $class->name;
}
}

View File

@@ -21,7 +21,7 @@ use Symfony\Component\HttpFoundation\Response;
*/
class AjaxDataCollector extends DataCollector
{
public function collect(Request $request, Response $response, \Throwable $exception = null)
public function collect(Request $request, Response $response, ?\Throwable $exception = null)
{
// all collecting is done client side
}

View File

@@ -32,7 +32,7 @@ class ConfigDataCollector extends DataCollector implements LateDataCollectorInte
/**
* Sets the Kernel associated with this Request.
*/
public function setKernel(KernelInterface $kernel = null)
public function setKernel(?KernelInterface $kernel = null)
{
$this->kernel = $kernel;
}
@@ -40,7 +40,7 @@ class ConfigDataCollector extends DataCollector implements LateDataCollectorInte
/**
* {@inheritdoc}
*/
public function collect(Request $request, Response $response, \Throwable $exception = null)
public function collect(Request $request, Response $response, ?\Throwable $exception = null)
{
$eom = \DateTime::createFromFormat('d/m/Y', '01/'.Kernel::END_OF_MAINTENANCE);
$eol = \DateTime::createFromFormat('d/m/Y', '01/'.Kernel::END_OF_LIFE);
@@ -60,8 +60,8 @@ class ConfigDataCollector extends DataCollector implements LateDataCollectorInte
'php_intl_locale' => class_exists(\Locale::class, false) && \Locale::getDefault() ? \Locale::getDefault() : 'n/a',
'php_timezone' => date_default_timezone_get(),
'xdebug_enabled' => \extension_loaded('xdebug'),
'apcu_enabled' => \extension_loaded('apcu') && filter_var(ini_get('apc.enabled'), \FILTER_VALIDATE_BOOLEAN),
'zend_opcache_enabled' => \extension_loaded('Zend OPcache') && filter_var(ini_get('opcache.enable'), \FILTER_VALIDATE_BOOLEAN),
'apcu_enabled' => \extension_loaded('apcu') && filter_var(\ini_get('apc.enabled'), \FILTER_VALIDATE_BOOLEAN),
'zend_opcache_enabled' => \extension_loaded('Zend OPcache') && filter_var(\ini_get('opcache.enable'), \FILTER_VALIDATE_BOOLEAN),
'bundles' => [],
'sapi_name' => \PHP_SAPI,
];

View File

@@ -70,9 +70,21 @@ abstract class DataCollector implements DataCollectorInterface
$casters = [
'*' => function ($v, array $a, Stub $s, $isNested) {
if (!$v instanceof Stub) {
$b = $a;
foreach ($a as $k => $v) {
if (\is_object($v) && !$v instanceof \DateTimeInterface && !$v instanceof Stub) {
$a[$k] = new CutStub($v);
if (!\is_object($v) || $v instanceof \DateTimeInterface || $v instanceof Stub) {
continue;
}
try {
$a[$k] = $s = new CutStub($v);
if ($b[$k] === $s) {
// we've hit a non-typed reference
$a[$k] = $v;
}
} catch (\TypeError $e) {
// we've hit a typed reference
}
}
}

View File

@@ -25,7 +25,7 @@ interface DataCollectorInterface extends ResetInterface
/**
* Collects data for the given Request and Response.
*/
public function collect(Request $request, Response $response, \Throwable $exception = null);
public function collect(Request $request, Response $response, ?\Throwable $exception = null);
/**
* Returns the name of the collector.

View File

@@ -47,11 +47,12 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
* @param string|FileLinkFormatter|null $fileLinkFormat
* @param DataDumperInterface|Connection|null $dumper
*/
public function __construct(Stopwatch $stopwatch = null, $fileLinkFormat = null, string $charset = null, RequestStack $requestStack = null, $dumper = null)
public function __construct(?Stopwatch $stopwatch = null, $fileLinkFormat = null, ?string $charset = null, ?RequestStack $requestStack = null, $dumper = null)
{
$fileLinkFormat = $fileLinkFormat ?: \ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');
$this->stopwatch = $stopwatch;
$this->fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');
$this->charset = $charset ?: ini_get('php.output_encoding') ?: ini_get('default_charset') ?: 'UTF-8';
$this->fileLinkFormat = $fileLinkFormat instanceof FileLinkFormatter && false === $fileLinkFormat->format('', 0) ? false : $fileLinkFormat;
$this->charset = $charset ?: \ini_get('php.output_encoding') ?: \ini_get('default_charset') ?: 'UTF-8';
$this->requestStack = $requestStack;
$this->dumper = $dumper;
@@ -100,7 +101,7 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
}
}
public function collect(Request $request, Response $response, \Throwable $exception = null)
public function collect(Request $request, Response $response, ?\Throwable $exception = null)
{
if (!$this->dataCount) {
$this->data = [];
@@ -115,11 +116,11 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
if (!$this->requestStack
|| !$response->headers->has('X-Debug-Token')
|| $response->isRedirection()
|| ($response->headers->has('Content-Type') && !str_contains($response->headers->get('Content-Type'), 'html'))
|| ($response->headers->has('Content-Type') && !str_contains($response->headers->get('Content-Type') ?? '', 'html'))
|| 'html' !== $request->getRequestFormat()
|| false === strripos($response->getContent(), '</body>')
) {
if ($response->headers->has('Content-Type') && str_contains($response->headers->get('Content-Type'), 'html')) {
if ($response->headers->has('Content-Type') && str_contains($response->headers->get('Content-Type') ?? '', 'html')) {
$dumper = new HtmlDumper('php://output', $this->charset);
$dumper->setDisplayOptions(['fileLinkFormat' => $this->fileLinkFormat]);
} else {
@@ -232,7 +233,7 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
$h = headers_list();
$i = \count($h);
array_unshift($h, 'Content-Type: '.ini_get('default_mimetype'));
array_unshift($h, 'Content-Type: '.\ini_get('default_mimetype'));
while (0 !== stripos($h[$i], 'Content-Type:')) {
--$i;
}

View File

@@ -30,7 +30,7 @@ class EventDataCollector extends DataCollector implements LateDataCollectorInter
private $requestStack;
private $currentRequest;
public function __construct(EventDispatcherInterface $dispatcher = null, RequestStack $requestStack = null)
public function __construct(?EventDispatcherInterface $dispatcher = null, ?RequestStack $requestStack = null)
{
$this->dispatcher = $dispatcher;
$this->requestStack = $requestStack;
@@ -39,7 +39,7 @@ class EventDataCollector extends DataCollector implements LateDataCollectorInter
/**
* {@inheritdoc}
*/
public function collect(Request $request, Response $response, \Throwable $exception = null)
public function collect(Request $request, Response $response, ?\Throwable $exception = null)
{
$this->currentRequest = $this->requestStack && $this->requestStack->getMainRequest() !== $request ? $request : null;
$this->data = [

View File

@@ -25,7 +25,7 @@ class ExceptionDataCollector extends DataCollector
/**
* {@inheritdoc}
*/
public function collect(Request $request, Response $response, \Throwable $exception = null)
public function collect(Request $request, Response $response, ?\Throwable $exception = null)
{
if (null !== $exception) {
$this->data = [

View File

@@ -30,7 +30,7 @@ class LoggerDataCollector extends DataCollector implements LateDataCollectorInte
private $requestStack;
private $processedLogs;
public function __construct(object $logger = null, string $containerPathPrefix = null, RequestStack $requestStack = null)
public function __construct(?object $logger = null, ?string $containerPathPrefix = null, ?RequestStack $requestStack = null)
{
if (null !== $logger && $logger instanceof DebugLoggerInterface) {
$this->logger = $logger;
@@ -43,7 +43,7 @@ class LoggerDataCollector extends DataCollector implements LateDataCollectorInte
/**
* {@inheritdoc}
*/
public function collect(Request $request, Response $response, \Throwable $exception = null)
public function collect(Request $request, Response $response, ?\Throwable $exception = null)
{
$this->currentRequest = $this->requestStack && $this->requestStack->getMainRequest() !== $request ? $request : null;
}
@@ -144,7 +144,7 @@ class LoggerDataCollector extends DataCollector implements LateDataCollectorInte
$allChannels = [];
foreach ($this->getProcessedLogs() as $log) {
if ('' === trim($log['channel'])) {
if ('' === trim($log['channel'] ?? '')) {
continue;
}
@@ -222,9 +222,9 @@ class LoggerDataCollector extends DataCollector implements LateDataCollectorInte
return $logs;
}
private function getContainerCompilerLogs(string $compilerLogsFilepath = null): array
private function getContainerCompilerLogs(?string $compilerLogsFilepath = null): array
{
if (!is_file($compilerLogsFilepath)) {
if (!$compilerLogsFilepath || !is_file($compilerLogsFilepath)) {
return [];
}

View File

@@ -29,7 +29,7 @@ class MemoryDataCollector extends DataCollector implements LateDataCollectorInte
/**
* {@inheritdoc}
*/
public function collect(Request $request, Response $response, \Throwable $exception = null)
public function collect(Request $request, Response $response, ?\Throwable $exception = null)
{
$this->updateMemoryUsage();
}
@@ -41,7 +41,7 @@ class MemoryDataCollector extends DataCollector implements LateDataCollectorInte
{
$this->data = [
'memory' => 0,
'memory_limit' => $this->convertToBytes(ini_get('memory_limit')),
'memory_limit' => $this->convertToBytes(\ini_get('memory_limit')),
];
}
@@ -100,11 +100,11 @@ class MemoryDataCollector extends DataCollector implements LateDataCollectorInte
switch (substr($memoryLimit, -1)) {
case 't': $max *= 1024;
// no break
// no break
case 'g': $max *= 1024;
// no break
// no break
case 'm': $max *= 1024;
// no break
// no break
case 'k': $max *= 1024;
}

View File

@@ -38,7 +38,7 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter
private $sessionUsages = [];
private $requestStack;
public function __construct(RequestStack $requestStack = null)
public function __construct(?RequestStack $requestStack = null)
{
$this->controllers = new \SplObjectStorage();
$this->requestStack = $requestStack;
@@ -47,7 +47,7 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter
/**
* {@inheritdoc}
*/
public function collect(Request $request, Response $response, \Throwable $exception = null)
public function collect(Request $request, Response $response, ?\Throwable $exception = null)
{
// attributes are serialized and as they can be anything, they need to be converted to strings.
$attributes = [];
@@ -110,7 +110,7 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter
'session_metadata' => $sessionMetadata,
'session_attributes' => $sessionAttributes,
'session_usages' => array_values($this->sessionUsages),
'stateless_check' => $this->requestStack && $this->requestStack->getMainRequest()->attributes->get('_stateless', false),
'stateless_check' => $this->requestStack && ($mainRequest = $this->requestStack->getMainRequest()) && $mainRequest->attributes->get('_stateless', false),
'flashes' => $flashes,
'path_info' => $request->getPathInfo(),
'controller' => 'n/a',
@@ -474,12 +474,12 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter
'line' => $r->getStartLine(),
];
if (str_contains($r->name, '{closure}')) {
if (str_contains($r->name, '{closure')) {
return $controller;
}
$controller['method'] = $r->name;
if ($class = $r->getClosureScopeClass()) {
if ($class = \PHP_VERSION_ID >= 80111 ? $r->getClosureCalledClass() : $r->getClosureScopeClass()) {
$controller['class'] = $class->name;
} else {
return $r->name;

View File

@@ -36,7 +36,7 @@ class RouterDataCollector extends DataCollector
*
* @final
*/
public function collect(Request $request, Response $response, \Throwable $exception = null)
public function collect(Request $request, Response $response, ?\Throwable $exception = null)
{
if ($response instanceof RedirectResponse) {
$this->data['redirect'] = true;

View File

@@ -27,16 +27,17 @@ class TimeDataCollector extends DataCollector implements LateDataCollectorInterf
private $kernel;
private $stopwatch;
public function __construct(KernelInterface $kernel = null, Stopwatch $stopwatch = null)
public function __construct(?KernelInterface $kernel = null, ?Stopwatch $stopwatch = null)
{
$this->kernel = $kernel;
$this->stopwatch = $stopwatch;
$this->data = ['events' => [], 'stopwatch_installed' => false, 'start_time' => 0];
}
/**
* {@inheritdoc}
*/
public function collect(Request $request, Response $response, \Throwable $exception = null)
public function collect(Request $request, Response $response, ?\Throwable $exception = null)
{
if (null !== $this->kernel) {
$startTime = $this->kernel->getStartTime();
@@ -57,7 +58,7 @@ class TimeDataCollector extends DataCollector implements LateDataCollectorInterf
*/
public function reset()
{
$this->data = [];
$this->data = ['events' => [], 'stopwatch_installed' => false, 'start_time' => 0];
if (null !== $this->stopwatch) {
$this->stopwatch->reset();

View File

@@ -40,12 +40,12 @@ class FileLinkFormatter
private $urlFormat;
/**
* @param string|\Closure $urlFormat the URL format, or a closure that returns it on-demand
* @param string|array|null $fileLinkFormat
* @param string|\Closure $urlFormat the URL format, or a closure that returns it on-demand
*/
public function __construct(string $fileLinkFormat = null, RequestStack $requestStack = null, string $baseDir = null, $urlFormat = null)
public function __construct($fileLinkFormat = null, ?RequestStack $requestStack = null, ?string $baseDir = null, $urlFormat = null)
{
$fileLinkFormat = (self::FORMATS[$fileLinkFormat] ?? $fileLinkFormat) ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');
if ($fileLinkFormat && !\is_array($fileLinkFormat)) {
if (!\is_array($fileLinkFormat) && $fileLinkFormat = (self::FORMATS[$fileLinkFormat] ?? $fileLinkFormat) ?: \ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format')) {
$i = strpos($f = $fileLinkFormat, '&', max(strrpos($f, '%f'), strrpos($f, '%l'))) ?: \strlen($f);
$fileLinkFormat = [substr($f, 0, $i)] + preg_split('/&([^>]++)>/', substr($f, $i), -1, \PREG_SPLIT_DELIM_CAPTURE);
}

View File

@@ -24,6 +24,7 @@ use Symfony\Component\DependencyInjection\LazyProxy\ProxyHelper;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\TypedReference;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
/**
@@ -69,6 +70,7 @@ class RegisterControllerArgumentLocatorsPass implements CompilerPassInterface
foreach ($container->findTaggedServiceIds($this->controllerTag, true) as $id => $tags) {
$def = $container->getDefinition($id);
$def->setPublic(true);
$def->setLazy(false);
$class = $def->getClass();
$autowire = $def->isAutowired();
$bindings = $def->getBindings();
@@ -174,7 +176,7 @@ class RegisterControllerArgumentLocatorsPass implements CompilerPassInterface
$invalidBehavior = ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE;
}
if (Request::class === $type || SessionInterface::class === $type) {
if (Request::class === $type || SessionInterface::class === $type || Response::class === $type) {
continue;
}

View File

@@ -36,13 +36,15 @@ use Symfony\Contracts\Service\ResetInterface;
*
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
* @author Tobias Schultze <http://tobion.de>
*
* @internal
*/
abstract class AbstractSessionListener implements EventSubscriberInterface, ResetInterface
{
public const NO_AUTO_CACHE_CONTROL_HEADER = 'Symfony-Session-NoAutoCacheControl';
/**
* @internal
*/
protected $container;
private $sessionUsageStack = [];
private $debug;
@@ -52,13 +54,19 @@ abstract class AbstractSessionListener implements EventSubscriberInterface, Rese
*/
private $sessionOptions;
public function __construct(ContainerInterface $container = null, bool $debug = false, array $sessionOptions = [])
/**
* @internal
*/
public function __construct(?ContainerInterface $container = null, bool $debug = false, array $sessionOptions = [])
{
$this->container = $container;
$this->debug = $debug;
$this->sessionOptions = $sessionOptions;
}
/**
* @internal
*/
public function onKernelRequest(RequestEvent $event)
{
if (!$event->isMainRequest()) {
@@ -72,6 +80,7 @@ abstract class AbstractSessionListener implements EventSubscriberInterface, Rese
$request->setSessionFactory(function () use (&$sess, $request) {
if (!$sess) {
$sess = $this->getSession();
$request->setSession($sess);
/*
* For supporting sessions in php runtime with runners like roadrunner or swoole, the session
@@ -93,6 +102,9 @@ abstract class AbstractSessionListener implements EventSubscriberInterface, Rese
$this->sessionUsageStack[] = $session instanceof Session ? $session->getUsageIndex() : 0;
}
/**
* @internal
*/
public function onKernelResponse(ResponseEvent $event)
{
if (!$event->isMainRequest() || (!$this->container->has('initialized_session') && !$event->getRequest()->hasSession())) {
@@ -104,7 +116,7 @@ abstract class AbstractSessionListener implements EventSubscriberInterface, Rese
// Always remove the internal header if present
$response->headers->remove(self::NO_AUTO_CACHE_CONTROL_HEADER);
if (!$session = $this->container && $this->container->has('initialized_session') ? $this->container->get('initialized_session') : $event->getRequest()->getSession()) {
if (!$session = $this->container && $this->container->has('initialized_session') ? $this->container->get('initialized_session') : ($event->getRequest()->hasSession() ? $event->getRequest()->getSession() : null)) {
return;
}
@@ -158,6 +170,11 @@ abstract class AbstractSessionListener implements EventSubscriberInterface, Rese
$isSessionEmpty = $session->isEmpty() && empty($_SESSION); // checking $_SESSION to keep compatibility with native sessions
if ($requestSessionCookieId && $isSessionEmpty) {
// PHP internally sets the session cookie value to "deleted" when setcookie() is called with empty string $value argument
// which happens in \Symfony\Component\HttpFoundation\Session\Storage\Handler\AbstractSessionHandler::destroy
// when the session gets invalidated (for example on logout) so we must handle this case here too
// otherwise we would send two Set-Cookie headers back with the response
SessionUtils::popSessionCookie($sessionName, 'deleted');
$response->headers->clearCookie(
$sessionName,
$sessionCookiePath,
@@ -195,10 +212,11 @@ abstract class AbstractSessionListener implements EventSubscriberInterface, Rese
}
if ($autoCacheControl) {
$maxAge = $response->headers->hasCacheControlDirective('public') ? 0 : (int) $response->getMaxAge();
$response
->setExpires(new \DateTime())
->setExpires(new \DateTimeImmutable('+'.$maxAge.' seconds'))
->setPrivate()
->setMaxAge(0)
->setMaxAge($maxAge)
->headers->addCacheControlDirective('must-revalidate');
}
@@ -215,6 +233,9 @@ abstract class AbstractSessionListener implements EventSubscriberInterface, Rese
}
}
/**
* @internal
*/
public function onFinishRequest(FinishRequestEvent $event)
{
if ($event->isMainRequest()) {
@@ -222,6 +243,9 @@ abstract class AbstractSessionListener implements EventSubscriberInterface, Rese
}
}
/**
* @internal
*/
public function onSessionUsage(): void
{
if (!$this->debug) {
@@ -257,6 +281,9 @@ abstract class AbstractSessionListener implements EventSubscriberInterface, Rese
throw new UnexpectedSessionUsageException('Session was used while the request was declared stateless.');
}
/**
* @internal
*/
public static function getSubscribedEvents(): array
{
return [
@@ -267,6 +294,9 @@ abstract class AbstractSessionListener implements EventSubscriberInterface, Rese
];
}
/**
* @internal
*/
public function reset(): void
{
if (\PHP_SESSION_ACTIVE === session_status()) {
@@ -284,6 +314,8 @@ abstract class AbstractSessionListener implements EventSubscriberInterface, Rese
/**
* Gets the session object.
*
* @internal
*
* @return SessionInterface|null
*/
abstract protected function getSession();

View File

@@ -49,7 +49,7 @@ class DebugHandlersListener implements EventSubscriberInterface
* @param bool $scream Enables/disables screaming mode, where even silenced errors are logged
* @param bool $scope Enables/disables scoping mode
*/
public function __construct(callable $exceptionHandler = null, LoggerInterface $logger = null, $levels = \E_ALL, ?int $throwAt = \E_ALL, bool $scream = true, $scope = true, $deprecationLogger = null, $fileLinkFormat = null)
public function __construct(?callable $exceptionHandler = null, ?LoggerInterface $logger = null, $levels = \E_ALL, ?int $throwAt = \E_ALL, bool $scream = true, $scope = true, $deprecationLogger = null, $fileLinkFormat = null)
{
if (!\is_bool($scope)) {
trigger_deprecation('symfony/http-kernel', '5.4', 'Passing a $fileLinkFormat is deprecated.');
@@ -57,7 +57,7 @@ class DebugHandlersListener implements EventSubscriberInterface
$deprecationLogger = $fileLinkFormat;
}
$handler = set_exception_handler('var_dump');
$handler = set_exception_handler('is_int');
$this->earlyHandler = \is_array($handler) ? $handler[0] : null;
restore_exception_handler();
@@ -73,7 +73,7 @@ class DebugHandlersListener implements EventSubscriberInterface
/**
* Configures the error handler.
*/
public function configure(object $event = null)
public function configure(?object $event = null)
{
if ($event instanceof ConsoleEvent && !\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true)) {
return;
@@ -83,7 +83,7 @@ class DebugHandlersListener implements EventSubscriberInterface
}
$this->firstCall = $this->hasTerminatedWithException = false;
$handler = set_exception_handler('var_dump');
$handler = set_exception_handler('is_int');
$handler = \is_array($handler) ? $handler[0] : null;
restore_exception_handler();

View File

@@ -29,7 +29,7 @@ class DumpListener implements EventSubscriberInterface
private $dumper;
private $connection;
public function __construct(ClonerInterface $cloner, DataDumperInterface $dumper, Connection $connection = null)
public function __construct(ClonerInterface $cloner, DataDumperInterface $dumper, ?Connection $connection = null)
{
$this->cloner = $cloner;
$this->dumper = $dumper;

View File

@@ -33,9 +33,15 @@ class ErrorListener implements EventSubscriberInterface
protected $controller;
protected $logger;
protected $debug;
/**
* @var array<class-string, array{log_level: string|null, status_code: int<100,599>|null}>
*/
protected $exceptionsMapping;
public function __construct($controller, LoggerInterface $logger = null, bool $debug = false, array $exceptionsMapping = [])
/**
* @param array<class-string, array{log_level: string|null, status_code: int<100,599>|null}> $exceptionsMapping
*/
public function __construct($controller, ?LoggerInterface $logger = null, bool $debug = false, array $exceptionsMapping = [])
{
$this->controller = $controller;
$this->logger = $logger;
@@ -149,7 +155,7 @@ class ErrorListener implements EventSubscriberInterface
/**
* Logs an exception.
*/
protected function logException(\Throwable $exception, string $message, string $logLevel = null): void
protected function logException(\Throwable $exception, string $message, ?string $logLevel = null): void
{
if (null !== $this->logger) {
if (null !== $logLevel) {

View File

@@ -35,7 +35,7 @@ class LocaleListener implements EventSubscriberInterface
private $useAcceptLanguageHeader;
private $enabledLocales;
public function __construct(RequestStack $requestStack, string $defaultLocale = 'en', RequestContextAwareInterface $router = null, bool $useAcceptLanguageHeader = false, array $enabledLocales = [])
public function __construct(RequestStack $requestStack, string $defaultLocale = 'en', ?RequestContextAwareInterface $router = null, bool $useAcceptLanguageHeader = false, array $enabledLocales = [])
{
$this->defaultLocale = $defaultLocale;
$this->requestStack = $requestStack;
@@ -68,8 +68,10 @@ class LocaleListener implements EventSubscriberInterface
{
if ($locale = $request->attributes->get('_locale')) {
$request->setLocale($locale);
} elseif ($this->useAcceptLanguageHeader && $this->enabledLocales && ($preferredLanguage = $request->getPreferredLanguage($this->enabledLocales))) {
$request->setLocale($preferredLanguage);
} elseif ($this->useAcceptLanguageHeader && $this->enabledLocales) {
if ($request->getLanguages() && $preferredLanguage = $request->getPreferredLanguage($this->enabledLocales)) {
$request->setLocale($preferredLanguage);
}
$request->attributes->set('_vary_by_language', true);
}
}

View File

@@ -15,6 +15,7 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestMatcherInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
use Symfony\Component\HttpKernel\Event\TerminateEvent;
@@ -47,7 +48,7 @@ class ProfilerListener implements EventSubscriberInterface
* @param bool $onlyException True if the profiler only collects data when an exception occurs, false otherwise
* @param bool $onlyMainRequests True if the profiler only collects data when the request is the main request, false otherwise
*/
public function __construct(Profiler $profiler, RequestStack $requestStack, RequestMatcherInterface $matcher = null, bool $onlyException = false, bool $onlyMainRequests = false, string $collectParameter = null)
public function __construct(Profiler $profiler, RequestStack $requestStack, ?RequestMatcherInterface $matcher = null, bool $onlyException = false, bool $onlyMainRequests = false, ?string $collectParameter = null)
{
$this->profiler = $profiler;
$this->matcher = $matcher;
@@ -96,8 +97,21 @@ class ProfilerListener implements EventSubscriberInterface
return;
}
if (!$profile = $this->profiler->collect($request, $event->getResponse(), $exception)) {
return;
$session = $request->hasPreviousSession() && $request->hasSession() ? $request->getSession() : null;
if ($session instanceof Session) {
$usageIndexValue = $usageIndexReference = &$session->getUsageIndex();
$usageIndexReference = \PHP_INT_MIN;
}
try {
if (!$profile = $this->profiler->collect($request, $event->getResponse(), $exception)) {
return;
}
} finally {
if ($session instanceof Session) {
$usageIndexReference = $usageIndexValue;
}
}
$this->profiles[$request] = $profile;

View File

@@ -55,7 +55,7 @@ class RouterListener implements EventSubscriberInterface
*
* @throws \InvalidArgumentException
*/
public function __construct($matcher, RequestStack $requestStack, RequestContext $context = null, LoggerInterface $logger = null, string $projectDir = null, bool $debug = true)
public function __construct($matcher, RequestStack $requestStack, ?RequestContext $context = null, ?LoggerInterface $logger = null, ?string $projectDir = null, bool $debug = true)
{
if (!$matcher instanceof UrlMatcherInterface && !$matcher instanceof RequestMatcherInterface) {
throw new \InvalidArgumentException('Matcher must either implement UrlMatcherInterface or RequestMatcherInterface.');
@@ -73,7 +73,7 @@ class RouterListener implements EventSubscriberInterface
$this->debug = $debug;
}
private function setCurrentRequest(Request $request = null)
private function setCurrentRequest(?Request $request = null)
{
if (null !== $request) {
try {

View File

@@ -28,7 +28,7 @@ class SurrogateListener implements EventSubscriberInterface
{
private $surrogate;
public function __construct(SurrogateInterface $surrogate = null)
public function __construct(?SurrogateInterface $surrogate = null)
{
$this->surrogate = $surrogate;
}

View File

@@ -22,7 +22,7 @@ class AccessDeniedHttpException extends HttpException
* @param \Throwable|null $previous The previous exception
* @param int $code The internal exception code
*/
public function __construct(?string $message = '', \Throwable $previous = null, int $code = 0, array $headers = [])
public function __construct(?string $message = '', ?\Throwable $previous = null, int $code = 0, array $headers = [])
{
if (null === $message) {
trigger_deprecation('symfony/http-kernel', '5.3', 'Passing null as $message to "%s()" is deprecated, pass an empty string instead.', __METHOD__);

View File

@@ -21,7 +21,7 @@ class BadRequestHttpException extends HttpException
* @param \Throwable|null $previous The previous exception
* @param int $code The internal exception code
*/
public function __construct(?string $message = '', \Throwable $previous = null, int $code = 0, array $headers = [])
public function __construct(?string $message = '', ?\Throwable $previous = null, int $code = 0, array $headers = [])
{
if (null === $message) {
trigger_deprecation('symfony/http-kernel', '5.3', 'Passing null as $message to "%s()" is deprecated, pass an empty string instead.', __METHOD__);

View File

@@ -21,7 +21,7 @@ class ConflictHttpException extends HttpException
* @param \Throwable|null $previous The previous exception
* @param int $code The internal exception code
*/
public function __construct(?string $message = '', \Throwable $previous = null, int $code = 0, array $headers = [])
public function __construct(?string $message = '', ?\Throwable $previous = null, int $code = 0, array $headers = [])
{
if (null === $message) {
trigger_deprecation('symfony/http-kernel', '5.3', 'Passing null as $message to "%s()" is deprecated, pass an empty string instead.', __METHOD__);

View File

@@ -21,7 +21,7 @@ class GoneHttpException extends HttpException
* @param \Throwable|null $previous The previous exception
* @param int $code The internal exception code
*/
public function __construct(?string $message = '', \Throwable $previous = null, int $code = 0, array $headers = [])
public function __construct(?string $message = '', ?\Throwable $previous = null, int $code = 0, array $headers = [])
{
if (null === $message) {
trigger_deprecation('symfony/http-kernel', '5.3', 'Passing null as $message to "%s()" is deprecated, pass an empty string instead.', __METHOD__);

View File

@@ -21,7 +21,7 @@ class HttpException extends \RuntimeException implements HttpExceptionInterface
private $statusCode;
private $headers;
public function __construct(int $statusCode, ?string $message = '', \Throwable $previous = null, array $headers = [], ?int $code = 0)
public function __construct(int $statusCode, ?string $message = '', ?\Throwable $previous = null, array $headers = [], ?int $code = 0)
{
if (null === $message) {
trigger_deprecation('symfony/http-kernel', '5.3', 'Passing null as $message to "%s()" is deprecated, pass an empty string instead.', __METHOD__);

View File

@@ -21,7 +21,7 @@ class LengthRequiredHttpException extends HttpException
* @param \Throwable|null $previous The previous exception
* @param int $code The internal exception code
*/
public function __construct(?string $message = '', \Throwable $previous = null, int $code = 0, array $headers = [])
public function __construct(?string $message = '', ?\Throwable $previous = null, int $code = 0, array $headers = [])
{
if (null === $message) {
trigger_deprecation('symfony/http-kernel', '5.3', 'Passing null as $message to "%s()" is deprecated, pass an empty string instead.', __METHOD__);

View File

@@ -22,7 +22,7 @@ class MethodNotAllowedHttpException extends HttpException
* @param \Throwable|null $previous The previous exception
* @param int|null $code The internal exception code
*/
public function __construct(array $allow, ?string $message = '', \Throwable $previous = null, ?int $code = 0, array $headers = [])
public function __construct(array $allow, ?string $message = '', ?\Throwable $previous = null, ?int $code = 0, array $headers = [])
{
if (null === $message) {
trigger_deprecation('symfony/http-kernel', '5.3', 'Passing null as $message to "%s()" is deprecated, pass an empty string instead.', __METHOD__);

View File

@@ -21,7 +21,7 @@ class NotAcceptableHttpException extends HttpException
* @param \Throwable|null $previous The previous exception
* @param int $code The internal exception code
*/
public function __construct(?string $message = '', \Throwable $previous = null, int $code = 0, array $headers = [])
public function __construct(?string $message = '', ?\Throwable $previous = null, int $code = 0, array $headers = [])
{
if (null === $message) {
trigger_deprecation('symfony/http-kernel', '5.3', 'Passing null as $message to "%s()" is deprecated, pass an empty string instead.', __METHOD__);

View File

@@ -21,7 +21,7 @@ class NotFoundHttpException extends HttpException
* @param \Throwable|null $previous The previous exception
* @param int $code The internal exception code
*/
public function __construct(?string $message = '', \Throwable $previous = null, int $code = 0, array $headers = [])
public function __construct(?string $message = '', ?\Throwable $previous = null, int $code = 0, array $headers = [])
{
if (null === $message) {
trigger_deprecation('symfony/http-kernel', '5.3', 'Passing null as $message to "%s()" is deprecated, pass an empty string instead.', __METHOD__);

View File

@@ -21,7 +21,7 @@ class PreconditionFailedHttpException extends HttpException
* @param \Throwable|null $previous The previous exception
* @param int $code The internal exception code
*/
public function __construct(?string $message = '', \Throwable $previous = null, int $code = 0, array $headers = [])
public function __construct(?string $message = '', ?\Throwable $previous = null, int $code = 0, array $headers = [])
{
if (null === $message) {
trigger_deprecation('symfony/http-kernel', '5.3', 'Passing null as $message to "%s()" is deprecated, pass an empty string instead.', __METHOD__);

View File

@@ -23,7 +23,7 @@ class PreconditionRequiredHttpException extends HttpException
* @param \Throwable|null $previous The previous exception
* @param int $code The internal exception code
*/
public function __construct(?string $message = '', \Throwable $previous = null, int $code = 0, array $headers = [])
public function __construct(?string $message = '', ?\Throwable $previous = null, int $code = 0, array $headers = [])
{
if (null === $message) {
trigger_deprecation('symfony/http-kernel', '5.3', 'Passing null as $message to "%s()" is deprecated, pass an empty string instead.', __METHOD__);

View File

@@ -22,7 +22,7 @@ class ServiceUnavailableHttpException extends HttpException
* @param \Throwable|null $previous The previous exception
* @param int|null $code The internal exception code
*/
public function __construct($retryAfter = null, ?string $message = '', \Throwable $previous = null, ?int $code = 0, array $headers = [])
public function __construct($retryAfter = null, ?string $message = '', ?\Throwable $previous = null, ?int $code = 0, array $headers = [])
{
if (null === $message) {
trigger_deprecation('symfony/http-kernel', '5.3', 'Passing null as $message to "%s()" is deprecated, pass an empty string instead.', __METHOD__);

View File

@@ -24,7 +24,7 @@ class TooManyRequestsHttpException extends HttpException
* @param \Throwable|null $previous The previous exception
* @param int|null $code The internal exception code
*/
public function __construct($retryAfter = null, ?string $message = '', \Throwable $previous = null, ?int $code = 0, array $headers = [])
public function __construct($retryAfter = null, ?string $message = '', ?\Throwable $previous = null, ?int $code = 0, array $headers = [])
{
if (null === $message) {
trigger_deprecation('symfony/http-kernel', '5.3', 'Passing null as $message to "%s()" is deprecated, pass an empty string instead.', __METHOD__);

View File

@@ -22,7 +22,7 @@ class UnauthorizedHttpException extends HttpException
* @param \Throwable|null $previous The previous exception
* @param int|null $code The internal exception code
*/
public function __construct(string $challenge, ?string $message = '', \Throwable $previous = null, ?int $code = 0, array $headers = [])
public function __construct(string $challenge, ?string $message = '', ?\Throwable $previous = null, ?int $code = 0, array $headers = [])
{
if (null === $message) {
trigger_deprecation('symfony/http-kernel', '5.3', 'Passing null as $message to "%s()" is deprecated, pass an empty string instead.', __METHOD__);

View File

@@ -21,7 +21,7 @@ class UnprocessableEntityHttpException extends HttpException
* @param \Throwable|null $previous The previous exception
* @param int $code The internal exception code
*/
public function __construct(?string $message = '', \Throwable $previous = null, int $code = 0, array $headers = [])
public function __construct(?string $message = '', ?\Throwable $previous = null, int $code = 0, array $headers = [])
{
if (null === $message) {
trigger_deprecation('symfony/http-kernel', '5.3', 'Passing null as $message to "%s()" is deprecated, pass an empty string instead.', __METHOD__);

View File

@@ -21,7 +21,7 @@ class UnsupportedMediaTypeHttpException extends HttpException
* @param \Throwable|null $previous The previous exception
* @param int $code The internal exception code
*/
public function __construct(?string $message = '', \Throwable $previous = null, int $code = 0, array $headers = [])
public function __construct(?string $message = '', ?\Throwable $previous = null, int $code = 0, array $headers = [])
{
if (null === $message) {
trigger_deprecation('symfony/http-kernel', '5.3', 'Passing null as $message to "%s()" is deprecated, pass an empty string instead.', __METHOD__);

View File

@@ -34,7 +34,7 @@ abstract class AbstractSurrogateFragmentRenderer extends RoutableFragmentRendere
*
* @param FragmentRendererInterface $inlineStrategy The inline strategy to use when the surrogate is not supported
*/
public function __construct(SurrogateInterface $surrogate = null, FragmentRendererInterface $inlineStrategy, UriSigner $signer = null)
public function __construct(?SurrogateInterface $surrogate, FragmentRendererInterface $inlineStrategy, ?UriSigner $signer = null)
{
$this->surrogate = $surrogate;
$this->inlineStrategy = $inlineStrategy;
@@ -89,9 +89,11 @@ abstract class AbstractSurrogateFragmentRenderer extends RoutableFragmentRendere
private function containsNonScalars(array $values): bool
{
foreach ($values as $value) {
if (\is_array($value)) {
return $this->containsNonScalars($value);
} elseif (!is_scalar($value) && null !== $value) {
if (\is_scalar($value) || null === $value) {
continue;
}
if (!\is_array($value) || $this->containsNonScalars($value)) {
return true;
}
}

View File

@@ -28,7 +28,7 @@ final class FragmentUriGenerator implements FragmentUriGeneratorInterface
private $signer;
private $requestStack;
public function __construct(string $fragmentPath, UriSigner $signer = null, RequestStack $requestStack = null)
public function __construct(string $fragmentPath, ?UriSigner $signer = null, ?RequestStack $requestStack = null)
{
$this->fragmentPath = $fragmentPath;
$this->signer = $signer;
@@ -38,7 +38,7 @@ final class FragmentUriGenerator implements FragmentUriGeneratorInterface
/**
* {@inheritDoc}
*/
public function generate(ControllerReference $controller, Request $request = null, bool $absolute = false, bool $strict = true, bool $sign = true): string
public function generate(ControllerReference $controller, ?Request $request = null, bool $absolute = false, bool $strict = true, bool $sign = true): string
{
if (null === $request && (null === $this->requestStack || null === $request = $this->requestStack->getCurrentRequest())) {
throw new \LogicException('Generating a fragment URL can only be done when handling a Request.');
@@ -85,7 +85,7 @@ final class FragmentUriGenerator implements FragmentUriGeneratorInterface
foreach ($values as $key => $value) {
if (\is_array($value)) {
$this->checkNonScalar($value);
} elseif (!is_scalar($value) && null !== $value) {
} elseif (!\is_scalar($value) && null !== $value) {
throw new \LogicException(sprintf('Controller attributes cannot contain non-scalar/non-null values (value for key "%s" is not a scalar or null).', $key));
}
}

View File

@@ -28,5 +28,5 @@ interface FragmentUriGeneratorInterface
* @param bool $strict Whether to allow non-scalar attributes or not
* @param bool $sign Whether to sign the URL or not
*/
public function generate(ControllerReference $controller, Request $request = null, bool $absolute = false, bool $strict = true, bool $sign = true): string;
public function generate(ControllerReference $controller, ?Request $request = null, bool $absolute = false, bool $strict = true, bool $sign = true): string;
}

View File

@@ -30,9 +30,9 @@ class HIncludeFragmentRenderer extends RoutableFragmentRenderer
private $charset;
/**
* @param string $globalDefaultTemplate The global default content (it can be a template name or the content)
* @param string|null $globalDefaultTemplate The global default content (it can be a template name or the content)
*/
public function __construct(Environment $twig = null, UriSigner $signer = null, string $globalDefaultTemplate = null, string $charset = 'utf-8')
public function __construct(?Environment $twig = null, ?UriSigner $signer = null, ?string $globalDefaultTemplate = null, string $charset = 'utf-8')
{
$this->twig = $twig;
$this->globalDefaultTemplate = $globalDefaultTemplate;

View File

@@ -30,7 +30,7 @@ class InlineFragmentRenderer extends RoutableFragmentRenderer
private $kernel;
private $dispatcher;
public function __construct(HttpKernelInterface $kernel, EventDispatcherInterface $dispatcher = null)
public function __construct(HttpKernelInterface $kernel, ?EventDispatcherInterface $dispatcher = null)
{
$this->kernel = $kernel;
$this->dispatcher = $dispatcher;

View File

@@ -95,7 +95,7 @@ abstract class AbstractSurrogate implements SurrogateInterface
try {
$response = $cache->handle($subRequest, HttpKernelInterface::SUB_REQUEST, true);
if (!$response->isSuccessful()) {
if (!$response->isSuccessful() && Response::HTTP_NOT_MODIFIED !== $response->getStatusCode()) {
throw new \RuntimeException(sprintf('Error when rendering "%s" (Status code is %d).', $subRequest->getUri(), $response->getStatusCode()));
}
@@ -133,4 +133,15 @@ abstract class AbstractSurrogate implements SurrogateInterface
$response->headers->set('Surrogate-Control', preg_replace(sprintf('#content="%s/1.0",\s*#', $upperName), '', $value));
}
}
protected static function generateBodyEvalBoundary(): string
{
static $cookie;
$cookie = hash('md5', $cookie ?? $cookie = random_bytes(16), true);
$boundary = base64_encode($cookie);
\assert(HttpCache::BODY_EVAL_BOUNDARY_LENGTH === \strlen($boundary));
return $boundary;
}
}

View File

@@ -45,7 +45,7 @@ class Esi extends AbstractSurrogate
/**
* {@inheritdoc}
*/
public function renderIncludeTag(string $uri, string $alt = null, bool $ignoreErrors = true, string $comment = '')
public function renderIncludeTag(string $uri, ?string $alt = null, bool $ignoreErrors = true, string $comment = '')
{
$html = sprintf('<esi:include src="%s"%s%s />',
$uri,
@@ -80,8 +80,8 @@ class Esi extends AbstractSurrogate
$content = preg_replace('#<esi\:remove>.*?</esi\:remove>#s', '', $content);
$content = preg_replace('#<esi\:comment[^>]+>#s', '', $content);
$boundary = self::generateBodyEvalBoundary();
$chunks = preg_split('#<esi\:include\s+(.*?)\s*(?:/|</esi\:include)>#', $content, -1, \PREG_SPLIT_DELIM_CAPTURE);
$chunks[0] = str_replace($this->phpEscapeMap[0], $this->phpEscapeMap[1], $chunks[0]);
$i = 1;
while (isset($chunks[$i])) {
@@ -95,16 +95,10 @@ class Esi extends AbstractSurrogate
throw new \RuntimeException('Unable to process an ESI tag without a "src" attribute.');
}
$chunks[$i] = sprintf('<?php echo $this->surrogate->handle($this, %s, %s, %s) ?>'."\n",
var_export($options['src'], true),
var_export($options['alt'] ?? '', true),
isset($options['onerror']) && 'continue' === $options['onerror'] ? 'true' : 'false'
);
++$i;
$chunks[$i] = str_replace($this->phpEscapeMap[0], $this->phpEscapeMap[1], $chunks[$i]);
++$i;
$chunks[$i] = $boundary.$options['src']."\n".($options['alt'] ?? '')."\n".('continue' === ($options['onerror'] ?? ''))."\n";
$i += 2;
}
$content = implode('', $chunks);
$content = $boundary.implode('', $chunks).$boundary;
$response->setContent($content);
$response->headers->set('X-Body-Eval', 'ESI');

View File

@@ -29,6 +29,8 @@ use Symfony\Component\HttpKernel\TerminableInterface;
*/
class HttpCache implements HttpKernelInterface, TerminableInterface
{
public const BODY_EVAL_BOUNDARY_LENGTH = 24;
private $kernel;
private $store;
private $request;
@@ -79,7 +81,7 @@ class HttpCache implements HttpKernelInterface, TerminableInterface
* This setting is overridden by the stale-if-error HTTP Cache-Control extension
* (see RFC 5861).
*/
public function __construct(HttpKernelInterface $kernel, StoreInterface $store, SurrogateInterface $surrogate = null, array $options = [])
public function __construct(HttpKernelInterface $kernel, StoreInterface $store, ?SurrogateInterface $surrogate = null, array $options = [])
{
$this->store = $store;
$this->kernel = $kernel;
@@ -469,7 +471,7 @@ class HttpCache implements HttpKernelInterface, TerminableInterface
*
* @return Response
*/
protected function forward(Request $request, bool $catch = false, Response $entry = null)
protected function forward(Request $request, bool $catch = false, ?Response $entry = null)
{
if ($this->surrogate) {
$this->surrogate->addSurrogateCapability($request);
@@ -631,12 +633,22 @@ class HttpCache implements HttpKernelInterface, TerminableInterface
private function restoreResponseBody(Request $request, Response $response)
{
if ($response->headers->has('X-Body-Eval')) {
\assert(self::BODY_EVAL_BOUNDARY_LENGTH === 24);
ob_start();
if ($response->headers->has('X-Body-File')) {
include $response->headers->get('X-Body-File');
} else {
eval('; ?>'.$response->getContent().'<?php ;');
$content = $response->getContent();
$boundary = substr($content, 0, 24);
$j = strpos($content, $boundary, 24);
echo substr($content, 24, $j - 24);
$i = $j + 24;
while (false !== $j = strpos($content, $boundary, $i)) {
[$uri, $alt, $ignoreErrors, $part] = explode("\n", substr($content, $i, $j - $i), 4);
$i = $j + 24;
echo $this->surrogate->handle($this, $uri, $alt, $ignoreErrors);
echo $part;
}
$response->setContent(ob_get_clean());
@@ -718,7 +730,11 @@ class HttpCache implements HttpKernelInterface, TerminableInterface
$timeout = $this->options['stale_while_revalidate'];
}
return abs($entry->getTtl()) < $timeout;
$age = $entry->getAge();
$maxAge = $entry->getMaxAge() ?? 0;
$ttl = $maxAge - $age;
return abs($ttl) < $timeout;
}
/**

View File

@@ -147,7 +147,7 @@ class ResponseCacheStrategy implements ResponseCacheStrategyInterface
if (is_numeric($this->ageDirectives['expires'])) {
$date = clone $response->getDate();
$date->modify('+'.($this->ageDirectives['expires'] + $this->age).' seconds');
$date = $date->modify('+'.($this->ageDirectives['expires'] + $this->age).' seconds');
$response->setExpires($date);
}
}

View File

@@ -42,7 +42,7 @@ class Ssi extends AbstractSurrogate
/**
* {@inheritdoc}
*/
public function renderIncludeTag(string $uri, string $alt = null, bool $ignoreErrors = true, string $comment = '')
public function renderIncludeTag(string $uri, ?string $alt = null, bool $ignoreErrors = true, string $comment = '')
{
return sprintf('<!--#include virtual="%s" -->', $uri);
}
@@ -64,9 +64,8 @@ class Ssi extends AbstractSurrogate
// we don't use a proper XML parser here as we can have SSI tags in a plain text response
$content = $response->getContent();
$boundary = self::generateBodyEvalBoundary();
$chunks = preg_split('#<!--\#include\s+(.*?)\s*-->#', $content, -1, \PREG_SPLIT_DELIM_CAPTURE);
$chunks[0] = str_replace($this->phpEscapeMap[0], $this->phpEscapeMap[1], $chunks[0]);
$i = 1;
while (isset($chunks[$i])) {
@@ -80,14 +79,10 @@ class Ssi extends AbstractSurrogate
throw new \RuntimeException('Unable to process an SSI tag without a "virtual" attribute.');
}
$chunks[$i] = sprintf('<?php echo $this->surrogate->handle($this, %s, \'\', false) ?>'."\n",
var_export($options['virtual'], true)
);
++$i;
$chunks[$i] = str_replace($this->phpEscapeMap[0], $this->phpEscapeMap[1], $chunks[$i]);
++$i;
$chunks[$i] = $boundary.$options['virtual']."\n\n\n";
$i += 2;
}
$content = implode('', $chunks);
$content = $boundary.implode('', $chunks).$boundary;
$response->setContent($content);
$response->headers->set('X-Body-Eval', 'SSI');

View File

@@ -29,17 +29,28 @@ class Store implements StoreInterface
private $keyCache;
/** @var array<string, resource> */
private $locks = [];
private $options;
/**
* Constructor.
*
* The available options are:
*
* * private_headers Set of response headers that should not be stored
* when a response is cached. (default: Set-Cookie)
*
* @throws \RuntimeException
*/
public function __construct(string $root)
public function __construct(string $root, array $options = [])
{
$this->root = $root;
if (!is_dir($this->root) && !@mkdir($this->root, 0777, true) && !is_dir($this->root)) {
throw new \RuntimeException(sprintf('Unable to create the store directory (%s).', $this->root));
}
$this->keyCache = new \SplObjectStorage();
$this->options = array_merge([
'private_headers' => ['Set-Cookie'],
], $options);
}
/**
@@ -186,7 +197,7 @@ class Store implements StoreInterface
if ($this->getPath($digest) !== $response->headers->get('X-Body-File')) {
throw new \RuntimeException('X-Body-File and X-Content-Digest do not match.');
}
// Everything seems ok, omit writing content to disk
// Everything seems ok, omit writing content to disk
} else {
$digest = $this->generateContentDigest($response);
$response->headers->set('X-Content-Digest', $digest);
@@ -216,6 +227,10 @@ class Store implements StoreInterface
$headers = $this->persistResponse($response);
unset($headers['age']);
foreach ($this->options['private_headers'] as $h) {
unset($headers[strtolower($h)]);
}
array_unshift($entries, [$storedEnv, $headers]);
if (!$this->save($key, serialize($entries))) {
@@ -460,15 +475,25 @@ class Store implements StoreInterface
/**
* Restores a Response from the HTTP headers and body.
*/
private function restoreResponse(array $headers, string $path = null): Response
private function restoreResponse(array $headers, ?string $path = null): ?Response
{
$status = $headers['X-Status'][0];
unset($headers['X-Status']);
$content = null;
if (null !== $path) {
$headers['X-Body-File'] = [$path];
unset($headers['x-body-file']);
if ($headers['X-Body-Eval'] ?? $headers['x-body-eval'] ?? false) {
$content = file_get_contents($path);
\assert(HttpCache::BODY_EVAL_BOUNDARY_LENGTH === 24);
if (48 > \strlen($content) || substr($content, -24) !== substr($content, 0, 24)) {
return null;
}
}
}
return new Response($path, $status, $headers);
return new Response($content, $status, $headers);
}
}

View File

@@ -59,12 +59,12 @@ interface SurrogateInterface
/**
* Renders a Surrogate tag.
*
* @param string $alt An alternate URI
* @param string $comment A comment to add as an esi:include tag
* @param string|null $alt An alternate URI
* @param string $comment A comment to add as an esi:include tag
*
* @return string
*/
public function renderIncludeTag(string $uri, string $alt = null, bool $ignoreErrors = true, string $comment = '');
public function renderIncludeTag(string $uri, ?string $alt = null, bool $ignoreErrors = true, string $comment = '');
/**
* Replaces a Response Surrogate tags with the included resource content.

View File

@@ -33,7 +33,7 @@ final class HttpClientKernel implements HttpKernelInterface
{
private $client;
public function __construct(HttpClientInterface $client = null)
public function __construct(?HttpClientInterface $client = null)
{
if (null === $client && !class_exists(HttpClient::class)) {
throw new \LogicException(sprintf('You cannot use "%s" as the HttpClient component is not installed. Try running "composer require symfony/http-client".', __CLASS__));

View File

@@ -55,7 +55,7 @@ class HttpKernel implements HttpKernelInterface, TerminableInterface
protected $requestStack;
private $argumentResolver;
public function __construct(EventDispatcherInterface $dispatcher, ControllerResolverInterface $resolver, RequestStack $requestStack = null, ArgumentResolverInterface $argumentResolver = null)
public function __construct(EventDispatcherInterface $dispatcher, ControllerResolverInterface $resolver, ?RequestStack $requestStack = null, ?ArgumentResolverInterface $argumentResolver = null)
{
$this->dispatcher = $dispatcher;
$this->resolver = $resolver;
@@ -70,6 +70,7 @@ class HttpKernel implements HttpKernelInterface, TerminableInterface
{
$request->headers->set('X-Php-Ob-Level', (string) ob_get_level());
$this->requestStack->push($request);
try {
return $this->handleRaw($request, $type);
} catch (\Exception $e) {
@@ -83,6 +84,8 @@ class HttpKernel implements HttpKernelInterface, TerminableInterface
}
return $this->handleThrowable($e, $request, $type);
} finally {
$this->requestStack->pop();
}
}
@@ -97,13 +100,23 @@ class HttpKernel implements HttpKernelInterface, TerminableInterface
/**
* @internal
*/
public function terminateWithException(\Throwable $exception, Request $request = null)
public function terminateWithException(\Throwable $exception, ?Request $request = null)
{
if (!$request = $request ?: $this->requestStack->getMainRequest()) {
throw $exception;
}
$response = $this->handleThrowable($exception, $request, self::MAIN_REQUEST);
if ($pop = $request !== $this->requestStack->getMainRequest()) {
$this->requestStack->push($request);
}
try {
$response = $this->handleThrowable($exception, $request, self::MAIN_REQUEST);
} finally {
if ($pop) {
$this->requestStack->pop();
}
}
$response->sendHeaders();
$response->sendContent();
@@ -121,8 +134,6 @@ class HttpKernel implements HttpKernelInterface, TerminableInterface
*/
private function handleRaw(Request $request, int $type = self::MAIN_REQUEST): Response
{
$this->requestStack->push($request);
// request
$event = new RequestEvent($this, $request, $type);
$this->dispatcher->dispatch($event, KernelEvents::REQUEST);
@@ -199,7 +210,6 @@ class HttpKernel implements HttpKernelInterface, TerminableInterface
private function finishRequest(Request $request, int $type)
{
$this->dispatcher->dispatch(new FinishRequestEvent($this, $request, $type), KernelEvents::FINISH_REQUEST);
$this->requestStack->pop();
}
/**

View File

@@ -36,7 +36,7 @@ class HttpKernelBrowser extends AbstractBrowser
/**
* @param array $server The server parameters (equivalent of $_SERVER)
*/
public function __construct(HttpKernelInterface $kernel, array $server = [], History $history = null, CookieJar $cookieJar = null)
public function __construct(HttpKernelInterface $kernel, array $server = [], ?History $history = null, ?CookieJar $cookieJar = null)
{
// These class properties must be set before calling the parent constructor, as it may depend on it.
$this->kernel = $kernel;

View File

@@ -78,11 +78,11 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl
*/
private static $freshCache = [];
public const VERSION = '5.4.8';
public const VERSION_ID = 50408;
public const VERSION = '5.4.39';
public const VERSION_ID = 50439;
public const MAJOR_VERSION = 5;
public const MINOR_VERSION = 4;
public const RELEASE_VERSION = 8;
public const RELEASE_VERSION = 39;
public const EXTRA_VERSION = '';
public const END_OF_MAINTENANCE = '11/2024';
@@ -404,9 +404,9 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl
/**
* Gets the container class.
*
* @throws \InvalidArgumentException If the generated classname is invalid
*
* @return string
*
* @throws \InvalidArgumentException If the generated classname is invalid
*/
protected function getContainerClass()
{
@@ -467,7 +467,7 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl
try {
is_dir($buildDir) ?: mkdir($buildDir, 0777, true);
if ($lock = fopen($cachePath.'.lock', 'w')) {
if ($lock = fopen($cachePath.'.lock', 'w+')) {
if (!flock($lock, \LOCK_EX | \LOCK_NB, $wouldBlock) && !flock($lock, $wouldBlock ? \LOCK_SH : \LOCK_EX)) {
fclose($lock);
$lock = null;
@@ -778,7 +778,9 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl
$this->startTime = microtime(true);
}
if ($this->debug && !isset($_ENV['SHELL_VERBOSITY']) && !isset($_SERVER['SHELL_VERBOSITY'])) {
putenv('SHELL_VERBOSITY=3');
if (\function_exists('putenv')) {
putenv('SHELL_VERBOSITY=3');
}
$_ENV['SHELL_VERBOSITY'] = 3;
$_SERVER['SHELL_VERBOSITY'] = 3;
}

View File

@@ -1,4 +1,4 @@
Copyright (c) 2004-2022 Fabien Potencier
Copyright (c) 2004-present Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -29,14 +29,14 @@ interface DebugLoggerInterface
*
* @return array
*/
public function getLogs(Request $request = null);
public function getLogs(?Request $request = null);
/**
* Returns the number of errors.
*
* @return int
*/
public function countErrors(Request $request = null);
public function countErrors(?Request $request = null);
/**
* Removes all log records.

View File

@@ -42,17 +42,21 @@ class Logger extends AbstractLogger
/**
* @param string|resource|null $output
*/
public function __construct(string $minLevel = null, $output = null, callable $formatter = null)
public function __construct(?string $minLevel = null, $output = null, ?callable $formatter = null)
{
if (null === $minLevel) {
$minLevel = null === $output || 'php://stdout' === $output || 'php://stderr' === $output ? LogLevel::ERROR : LogLevel::WARNING;
if (isset($_ENV['SHELL_VERBOSITY']) || isset($_SERVER['SHELL_VERBOSITY'])) {
switch ((int) ($_ENV['SHELL_VERBOSITY'] ?? $_SERVER['SHELL_VERBOSITY'])) {
case -1: $minLevel = LogLevel::ERROR; break;
case 1: $minLevel = LogLevel::NOTICE; break;
case 2: $minLevel = LogLevel::INFO; break;
case 3: $minLevel = LogLevel::DEBUG; break;
case -1: $minLevel = LogLevel::ERROR;
break;
case 1: $minLevel = LogLevel::NOTICE;
break;
case 2: $minLevel = LogLevel::INFO;
break;
case 3: $minLevel = LogLevel::DEBUG;
break;
}
}
}
@@ -85,7 +89,7 @@ class Logger extends AbstractLogger
$formatter = $this->formatter;
if ($this->handle) {
@fwrite($this->handle, $formatter($level, $message, $context));
@fwrite($this->handle, $formatter($level, $message, $context).\PHP_EOL);
} else {
error_log($formatter($level, $message, $context, false));
}
@@ -96,7 +100,7 @@ class Logger extends AbstractLogger
if (str_contains($message, '{')) {
$replacements = [];
foreach ($context as $key => $val) {
if (null === $val || is_scalar($val) || (\is_object($val) && method_exists($val, '__toString'))) {
if (null === $val || \is_scalar($val) || (\is_object($val) && method_exists($val, '__toString'))) {
$replacements["{{$key}}"] = $val;
} elseif ($val instanceof \DateTimeInterface) {
$replacements["{{$key}}"] = $val->format(\DateTime::RFC3339);
@@ -110,7 +114,7 @@ class Logger extends AbstractLogger
$message = strtr($message, $replacements);
}
$log = sprintf('[%s] %s', $level, $message).\PHP_EOL;
$log = sprintf('[%s] %s', $level, $message);
if ($prefixDate) {
$log = date(\DateTime::RFC3339).' '.$log;
}

View File

@@ -47,7 +47,7 @@ class FileProfilerStorage implements ProfilerStorageInterface
/**
* {@inheritdoc}
*/
public function find(?string $ip, ?string $url, ?int $limit, ?string $method, int $start = null, int $end = null, string $statusCode = null): array
public function find(?string $ip, ?string $url, ?int $limit, ?string $method, ?int $start = null, ?int $end = null, ?string $statusCode = null): array
{
$file = $this->getIndexFilename();
@@ -61,6 +61,12 @@ class FileProfilerStorage implements ProfilerStorageInterface
$result = [];
while (\count($result) < $limit && $line = $this->readLineFromFile($file)) {
$values = str_getcsv($line);
if (7 !== \count($values)) {
// skip invalid lines
continue;
}
[$csvToken, $csvIp, $csvMethod, $csvUrl, $csvTime, $csvParent, $csvStatusCode] = $values;
$csvTime = (int) $csvTime;
@@ -115,19 +121,7 @@ class FileProfilerStorage implements ProfilerStorageInterface
*/
public function read(string $token): ?Profile
{
if (!$token || !file_exists($file = $this->getFilename($token))) {
return null;
}
if (\function_exists('gzcompress')) {
$file = 'compress.zlib://'.$file;
}
if (!$data = unserialize(file_get_contents($file))) {
return null;
}
return $this->createProfileFromData($token, $data);
return $this->doRead($token);
}
/**
@@ -169,14 +163,13 @@ class FileProfilerStorage implements ProfilerStorageInterface
'status_code' => $profile->getStatusCode(),
];
$context = stream_context_create();
$data = serialize($data);
if (\function_exists('gzcompress')) {
$file = 'compress.zlib://'.$file;
stream_context_set_option($context, 'zlib', 'level', 3);
if (\function_exists('gzencode')) {
$data = gzencode($data, 3);
}
if (false === file_put_contents($file, serialize($data), 0, $context)) {
if (false === file_put_contents($file, $data, \LOCK_EX)) {
return false;
}
@@ -272,7 +265,7 @@ class FileProfilerStorage implements ProfilerStorageInterface
return '' === $line ? null : $line;
}
protected function createProfileFromData(string $token, array $data, Profile $parent = null)
protected function createProfileFromData(string $token, array $data, ?Profile $parent = null)
{
$profile = new Profile($token);
$profile->setIp($data['ip']);
@@ -291,21 +284,34 @@ class FileProfilerStorage implements ProfilerStorageInterface
}
foreach ($data['children'] as $token) {
if (!$token || !file_exists($file = $this->getFilename($token))) {
continue;
if (null !== $childProfile = $this->doRead($token, $profile)) {
$profile->addChild($childProfile);
}
if (\function_exists('gzcompress')) {
$file = 'compress.zlib://'.$file;
}
if (!$childData = unserialize(file_get_contents($file))) {
continue;
}
$profile->addChild($this->createProfileFromData($token, $childData, $profile));
}
return $profile;
}
private function doRead($token, ?Profile $profile = null): ?Profile
{
if (!$token || !file_exists($file = $this->getFilename($token))) {
return null;
}
$h = fopen($file, 'r');
flock($h, \LOCK_SH);
$data = stream_get_contents($h);
flock($h, \LOCK_UN);
fclose($h);
if (\function_exists('gzdecode')) {
$data = @gzdecode($data) ?: $data;
}
if (!$data = unserialize($data)) {
return null;
}
return $this->createProfileFromData($token, $data, $profile);
}
}

View File

@@ -37,7 +37,7 @@ class Profiler implements ResetInterface
private $initiallyEnabled = true;
private $enabled = true;
public function __construct(ProfilerStorageInterface $storage, LoggerInterface $logger = null, bool $enable = true)
public function __construct(ProfilerStorageInterface $storage, ?LoggerInterface $logger = null, bool $enable = true)
{
$this->storage = $storage;
$this->logger = $logger;
@@ -116,7 +116,7 @@ class Profiler implements ResetInterface
/**
* Finds profiler tokens for the given criteria.
*
* @param string|null $limit The maximum number of tokens to return
* @param int|null $limit The maximum number of tokens to return
* @param string|null $start The start date to search from
* @param string|null $end The end date to search to
*
@@ -124,7 +124,7 @@ class Profiler implements ResetInterface
*
* @see https://php.net/datetime.formats for the supported date/time formats
*/
public function find(?string $ip, ?string $url, ?string $limit, ?string $method, ?string $start, ?string $end, string $statusCode = null)
public function find(?string $ip, ?string $url, ?int $limit, ?string $method, ?string $start, ?string $end, ?string $statusCode = null)
{
return $this->storage->find($ip, $url, $limit, $method, $this->getTimestamp($start), $this->getTimestamp($end), $statusCode);
}
@@ -134,7 +134,7 @@ class Profiler implements ResetInterface
*
* @return Profile|null
*/
public function collect(Request $request, Response $response, \Throwable $exception = null)
public function collect(Request $request, Response $response, ?\Throwable $exception = null)
{
if (false === $this->enabled) {
return null;

View File

@@ -33,7 +33,7 @@ interface ProfilerStorageInterface
* @param int|null $start The start date to search from
* @param int|null $end The end date to search to
*/
public function find(?string $ip, ?string $url, ?int $limit, ?string $method, int $start = null, int $end = null): array;
public function find(?string $ip, ?string $url, ?int $limit, ?string $method, ?int $start = null, ?int $end = null): array;
/**
* Reads data associated with the given token.

View File

@@ -20,7 +20,7 @@
"symfony/deprecation-contracts": "^2.1|^3",
"symfony/error-handler": "^4.4|^5.0|^6.0",
"symfony/event-dispatcher": "^5.0|^6.0",
"symfony/http-foundation": "^5.3.7|^6.0",
"symfony/http-foundation": "^5.4.21|^6.2.7",
"symfony/polyfill-ctype": "^1.8",
"symfony/polyfill-php73": "^1.9",
"symfony/polyfill-php80": "^1.16",
@@ -41,6 +41,7 @@
"symfony/stopwatch": "^4.4|^5.0|^6.0",
"symfony/translation": "^4.4|^5.0|^6.0",
"symfony/translation-contracts": "^1.1|^2|^3",
"symfony/var-dumper": "^4.4.31|^5.4",
"psr/cache": "^1.0|^2.0|^3.0",
"twig/twig": "^2.13|^3.0.4"
},