diff --git a/Bundle/Bundle.php b/Bundle/Bundle.php index 2ff356c9ff..e8057737ed 100644 --- a/Bundle/Bundle.php +++ b/Bundle/Bundle.php @@ -69,7 +69,7 @@ public function getContainerExtension() if (null !== $extension) { if (!$extension instanceof ExtensionInterface) { - throw new \LogicException(sprintf('Extension %s must implement Symfony\Component\DependencyInjection\Extension\ExtensionInterface.', \get_class($extension))); + throw new \LogicException(sprintf('Extension "%s" must implement Symfony\Component\DependencyInjection\Extension\ExtensionInterface.', \get_class($extension))); } // check naming convention diff --git a/CacheClearer/Psr6CacheClearer.php b/CacheClearer/Psr6CacheClearer.php index 47a6ece5c1..f5670f1b97 100644 --- a/CacheClearer/Psr6CacheClearer.php +++ b/CacheClearer/Psr6CacheClearer.php @@ -31,7 +31,7 @@ public function hasPool($name) public function getPool($name) { if (!$this->hasPool($name)) { - throw new \InvalidArgumentException(sprintf('Cache pool not found: %s.', $name)); + throw new \InvalidArgumentException(sprintf('Cache pool not found: "%s".', $name)); } return $this->pools[$name]; @@ -40,7 +40,7 @@ public function getPool($name) public function clearPool($name) { if (!isset($this->pools[$name])) { - throw new \InvalidArgumentException(sprintf('Cache pool not found: %s.', $name)); + throw new \InvalidArgumentException(sprintf('Cache pool not found: "%s".', $name)); } return $this->pools[$name]->clear(); diff --git a/Controller/ArgumentResolver.php b/Controller/ArgumentResolver.php index 89154ece71..3504ae614f 100644 --- a/Controller/ArgumentResolver.php +++ b/Controller/ArgumentResolver.php @@ -62,7 +62,7 @@ public function getArguments(Request $request, $controller): array } if (!$atLeastOne) { - throw new \InvalidArgumentException(sprintf('%s::resolve() must yield at least one value.', \get_class($resolver))); + throw new \InvalidArgumentException(sprintf('"%s::resolve()" must yield at least one value.', \get_class($resolver))); } // continue to the next controller argument diff --git a/Controller/ContainerControllerResolver.php b/Controller/ContainerControllerResolver.php index 015eea91fa..7eb028de1f 100644 --- a/Controller/ContainerControllerResolver.php +++ b/Controller/ContainerControllerResolver.php @@ -64,7 +64,7 @@ protected function instantiateController($class) throw new \InvalidArgumentException(sprintf('Controller "%s" has required constructor arguments and does not exist in the container. Did you forget to define the controller as a service?', $class), 0, $e); } - throw new \InvalidArgumentException(sprintf('Controller "%s" does neither exist as service nor as class', $class), 0, $e); + throw new \InvalidArgumentException(sprintf('Controller "%s" does neither exist as service nor as class.', $class), 0, $e); } private function throwExceptionIfControllerWasRemoved(string $controller, \Throwable $previous) diff --git a/Controller/ControllerResolver.php b/Controller/ControllerResolver.php index 4bf258416f..feb69e54ac 100644 --- a/Controller/ControllerResolver.php +++ b/Controller/ControllerResolver.php @@ -64,7 +64,7 @@ public function getController(Request $request) } if (!\is_callable($controller)) { - throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable. %s', $request->getPathInfo(), $this->getControllerError($controller))); + throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable. %s.', $request->getPathInfo(), $this->getControllerError($controller))); } return $controller; @@ -72,7 +72,7 @@ public function getController(Request $request) if (\is_object($controller)) { if (!\is_callable($controller)) { - throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable. %s', $request->getPathInfo(), $this->getControllerError($controller))); + throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable. %s.', $request->getPathInfo(), $this->getControllerError($controller))); } return $controller; @@ -85,11 +85,11 @@ public function getController(Request $request) try { $callable = $this->createController($controller); } catch (\InvalidArgumentException $e) { - throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable. %s', $request->getPathInfo(), $e->getMessage()), 0, $e); + throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable. %s.', $request->getPathInfo(), $e->getMessage()), 0, $e); } if (!\is_callable($callable)) { - throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable. %s', $request->getPathInfo(), $this->getControllerError($callable))); + throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable. %s.', $request->getPathInfo(), $this->getControllerError($callable))); } return $callable; diff --git a/ControllerMetadata/ArgumentMetadata.php b/ControllerMetadata/ArgumentMetadata.php index e73b848e60..6fc7e70344 100644 --- a/ControllerMetadata/ArgumentMetadata.php +++ b/ControllerMetadata/ArgumentMetadata.php @@ -99,7 +99,7 @@ public function isNullable() public function getDefaultValue() { if (!$this->hasDefaultValue) { - throw new \LogicException(sprintf('Argument $%s does not have a default value. Use %s::hasDefaultValue() to avoid this exception.', $this->name, __CLASS__)); + throw new \LogicException(sprintf('Argument $%s does not have a default value. Use "%s::hasDefaultValue()" to avoid this exception.', $this->name, __CLASS__)); } return $this->defaultValue; diff --git a/DataCollector/DumpDataCollector.php b/DataCollector/DumpDataCollector.php index 6ed9abea5b..d9f381b3d6 100644 --- a/DataCollector/DumpDataCollector.php +++ b/DataCollector/DumpDataCollector.php @@ -198,7 +198,7 @@ public function getDumps($format, $maxDepthLimit = -1, $maxItemsPerDepth = -1) $dumper = new HtmlDumper($data, $this->charset); $dumper->setDisplayOptions(['fileLinkFormat' => $this->fileLinkFormat]); } else { - throw new \InvalidArgumentException(sprintf('Invalid dump format: %s', $format)); + throw new \InvalidArgumentException(sprintf('Invalid dump format: "%s".', $format)); } $dumps = []; diff --git a/EventListener/TranslatorListener.php b/EventListener/TranslatorListener.php index d28eee2b1a..e276b3bd71 100644 --- a/EventListener/TranslatorListener.php +++ b/EventListener/TranslatorListener.php @@ -40,7 +40,7 @@ class TranslatorListener implements EventSubscriberInterface public function __construct($translator, RequestStack $requestStack) { if (!$translator instanceof TranslatorInterface && !$translator instanceof LocaleAwareInterface) { - throw new \TypeError(sprintf('Argument 1 passed to %s() must be an instance of %s, %s given.', __METHOD__, LocaleAwareInterface::class, \is_object($translator) ? \get_class($translator) : \gettype($translator))); + throw new \TypeError(sprintf('Argument 1 passed to "%s()" must be an instance of "%s", "%s" given.', __METHOD__, LocaleAwareInterface::class, \is_object($translator) ? \get_class($translator) : \gettype($translator))); } $this->translator = $translator; $this->requestStack = $requestStack; diff --git a/Fragment/FragmentHandler.php b/Fragment/FragmentHandler.php index 624f578471..e981291b87 100644 --- a/Fragment/FragmentHandler.php +++ b/Fragment/FragmentHandler.php @@ -98,7 +98,7 @@ public function render($uri, $renderer = 'inline', array $options = []) protected function deliver(Response $response) { if (!$response->isSuccessful()) { - throw new \RuntimeException(sprintf('Error when rendering "%s" (Status code is %s).', $this->requestStack->getCurrentRequest()->getUri(), $response->getStatusCode())); + throw new \RuntimeException(sprintf('Error when rendering "%s" (Status code is %d).', $this->requestStack->getCurrentRequest()->getUri(), $response->getStatusCode())); } if (!$response instanceof StreamedResponse) { diff --git a/Fragment/HIncludeFragmentRenderer.php b/Fragment/HIncludeFragmentRenderer.php index 7859c36844..5b01fec47b 100644 --- a/Fragment/HIncludeFragmentRenderer.php +++ b/Fragment/HIncludeFragmentRenderer.php @@ -57,7 +57,7 @@ public function __construct($templating = null, UriSigner $signer = null, string public function setTemplating($templating) { if (null !== $templating && !$templating instanceof EngineInterface && !$templating instanceof Environment) { - throw new \InvalidArgumentException('The hinclude rendering strategy needs an instance of Twig\Environment or Symfony\Component\Templating\EngineInterface'); + throw new \InvalidArgumentException('The hinclude rendering strategy needs an instance of Twig\Environment or Symfony\Component\Templating\EngineInterface.'); } if ($templating instanceof EngineInterface) { diff --git a/HttpCache/AbstractSurrogate.php b/HttpCache/AbstractSurrogate.php index 9b4541793f..472d87e483 100644 --- a/HttpCache/AbstractSurrogate.php +++ b/HttpCache/AbstractSurrogate.php @@ -96,7 +96,7 @@ public function handle(HttpCache $cache, $uri, $alt, $ignoreErrors) $response = $cache->handle($subRequest, HttpKernelInterface::SUB_REQUEST, true); if (!$response->isSuccessful()) { - throw new \RuntimeException(sprintf('Error when rendering "%s" (Status code is %s).', $subRequest->getUri(), $response->getStatusCode())); + throw new \RuntimeException(sprintf('Error when rendering "%s" (Status code is %d).', $subRequest->getUri(), $response->getStatusCode())); } return $response->getContent(); diff --git a/HttpClientKernel.php b/HttpClientKernel.php index c8421a4b10..912ce313f8 100644 --- a/HttpClientKernel.php +++ b/HttpClientKernel.php @@ -21,6 +21,9 @@ use Symfony\Component\Mime\Part\TextPart; use Symfony\Contracts\HttpClient\HttpClientInterface; +// Help opcache.preload discover always-needed symbols +class_exists(ResponseHeaderBag::class); + /** * An implementation of a Symfony HTTP kernel using a "real" HTTP client. * diff --git a/HttpKernel.php b/HttpKernel.php index f1b601361e..681e96321d 100644 --- a/HttpKernel.php +++ b/HttpKernel.php @@ -33,6 +33,18 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; +// Help opcache.preload discover always-needed symbols +class_exists(LegacyEventDispatcherProxy::class); +class_exists(ControllerArgumentsEvent::class); +class_exists(ControllerEvent::class); +class_exists(ExceptionEvent::class); +class_exists(FinishRequestEvent::class); +class_exists(RequestEvent::class); +class_exists(ResponseEvent::class); +class_exists(TerminateEvent::class); +class_exists(ViewEvent::class); +class_exists(KernelEvents::class); + /** * HttpKernel notifies events to convert a Request object to a Response one. * diff --git a/Kernel.php b/Kernel.php index 0b21ee8996..a559f07288 100644 --- a/Kernel.php +++ b/Kernel.php @@ -76,11 +76,11 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl private static $freshCache = []; - const VERSION = '4.4.5'; - const VERSION_ID = 40405; + const VERSION = '4.4.6'; + const VERSION_ID = 40406; const MAJOR_VERSION = 4; const MINOR_VERSION = 4; - const RELEASE_VERSION = 5; + const RELEASE_VERSION = 6; const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '11/2022'; @@ -231,7 +231,7 @@ public function getBundle($name) $class = static::class; $class = 'c' === $class[0] && 0 === strpos($class, "class@anonymous\0") ? get_parent_class($class).'@anonymous' : $class; - 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, $class)); + 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, $class)); } return $this->bundles[$name]; @@ -449,7 +449,7 @@ protected function initializeBundles() foreach ($this->registerBundles() as $bundle) { $name = $bundle->getName(); if (isset($this->bundles[$name])) { - throw new \LogicException(sprintf('Trying to register two bundles with the same name "%s"', $name)); + throw new \LogicException(sprintf('Trying to register two bundles with the same name "%s".', $name)); } $this->bundles[$name] = $bundle; } @@ -530,47 +530,20 @@ protected function initializeContainer() try { is_dir($cacheDir) ?: mkdir($cacheDir, 0777, true); - if ($lock = fopen($cachePath, 'w')) { - chmod($cachePath, 0666 & ~umask()); + if ($lock = fopen($cachePath.'.lock', 'w')) { flock($lock, LOCK_EX | LOCK_NB, $wouldBlock); if (!flock($lock, $wouldBlock ? LOCK_SH : LOCK_EX)) { fclose($lock); - } else { - $cache = new class($cachePath, $this->debug) extends ConfigCache { - public $lock; - - public function write($content, array $metadata = null) - { - rewind($this->lock); - ftruncate($this->lock, 0); - fwrite($this->lock, $content); - - if (null !== $metadata) { - file_put_contents($this->getPath().'.meta', serialize($metadata)); - @chmod($this->getPath().'.meta', 0666 & ~umask()); - } - - if (\function_exists('opcache_invalidate') && filter_var(ini_get('opcache.enable'), FILTER_VALIDATE_BOOLEAN)) { - @opcache_invalidate($this->getPath(), true); - } - } - - public function release() - { - flock($this->lock, LOCK_UN); - fclose($this->lock); - } - }; - $cache->lock = $lock; - - if (!\is_object($this->container = include $cachePath)) { - $this->container = null; - } elseif (!$oldContainer || \get_class($this->container) !== $oldContainer->name) { - $this->container->set('kernel', $this); - - return; - } + $lock = null; + } elseif (!\is_object($this->container = include $cachePath)) { + $this->container = null; + } elseif (!$oldContainer || \get_class($this->container) !== $oldContainer->name) { + flock($lock, LOCK_UN); + fclose($lock); + $this->container->set('kernel', $this); + + return; } } } catch (\Throwable $e) { @@ -634,8 +607,10 @@ public function release() } $this->dumpContainer($cache, $container, $class, $this->getContainerBaseClass()); - if (method_exists($cache, 'release')) { - $cache->release(); + + if ($lock) { + flock($lock, LOCK_UN); + fclose($lock); } $this->container = require $cachePath; @@ -713,10 +688,10 @@ protected function buildContainer() foreach (['cache' => $this->warmupDir ?: $this->getCacheDir(), 'logs' => $this->getLogDir()] as $name => $dir) { if (!is_dir($dir)) { if (false === @mkdir($dir, 0777, true) && !is_dir($dir)) { - throw new \RuntimeException(sprintf("Unable to create the %s directory (%s)\n", $name, $dir)); + throw new \RuntimeException(sprintf('Unable to create the "%s" directory (%s).', $name, $dir)); } } elseif (!is_writable($dir)) { - throw new \RuntimeException(sprintf("Unable to write in the %s directory (%s)\n", $name, $dir)); + throw new \RuntimeException(sprintf('Unable to write in the "%s" directory (%s).', $name, $dir)); } } @@ -805,6 +780,7 @@ protected function dumpContainer(ConfigCache $cache, ContainerBuilder $container 'as_files' => true, 'debug' => $this->debug, 'build_time' => $container->hasParameter('kernel.container_build_time') ? $container->getParameter('kernel.container_build_time') : time(), + 'preload_classes' => array_map('get_class', $this->bundles), ]); $rootCode = array_pop($content); diff --git a/Tests/CacheClearer/Psr6CacheClearerTest.php b/Tests/CacheClearer/Psr6CacheClearerTest.php index cdf4a97d34..6e0a47e930 100644 --- a/Tests/CacheClearer/Psr6CacheClearerTest.php +++ b/Tests/CacheClearer/Psr6CacheClearerTest.php @@ -40,7 +40,7 @@ public function testClearPool() public function testClearPoolThrowsExceptionOnUnreferencedPool() { $this->expectException('InvalidArgumentException'); - $this->expectExceptionMessage('Cache pool not found: unknown'); + $this->expectExceptionMessage('Cache pool not found: "unknown"'); (new Psr6CacheClearer())->clearPool('unknown'); } }