diff --git a/AcceptHeader.php b/AcceptHeader.php index 90f9f479d..057c6b530 100644 --- a/AcceptHeader.php +++ b/AcceptHeader.php @@ -11,6 +11,9 @@ namespace Symfony\Component\HttpFoundation; +// Help opcache.preload discover always-needed symbols +class_exists(AcceptHeaderItem::class); + /** * Represents an Accept-* header. * diff --git a/File/File.php b/File/File.php index d79c27f68..82d964cab 100644 --- a/File/File.php +++ b/File/File.php @@ -88,7 +88,7 @@ public function move(string $directory, string $name = null) $renamed = rename($this->getPathname(), $target); restore_error_handler(); if (!$renamed) { - throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $target, strip_tags($error))); + throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s).', $this->getPathname(), $target, strip_tags($error))); } @chmod($target, 0666 & ~umask()); @@ -103,10 +103,10 @@ protected function getTargetFile(string $directory, string $name = null) { if (!is_dir($directory)) { if (false === @mkdir($directory, 0777, true) && !is_dir($directory)) { - throw new FileException(sprintf('Unable to create the "%s" directory', $directory)); + throw new FileException(sprintf('Unable to create the "%s" directory.', $directory)); } } elseif (!is_writable($directory)) { - throw new FileException(sprintf('Unable to write in the "%s" directory', $directory)); + throw new FileException(sprintf('Unable to write in the "%s" directory.', $directory)); } $target = rtrim($directory, '/\\').\DIRECTORY_SEPARATOR.(null === $name ? $this->getBasename() : $this->getName($name)); diff --git a/File/UploadedFile.php b/File/UploadedFile.php index 3a258e29c..fa13b01e0 100644 --- a/File/UploadedFile.php +++ b/File/UploadedFile.php @@ -181,7 +181,7 @@ public function move(string $directory, string $name = null) $moved = move_uploaded_file($this->getPathname(), $target); restore_error_handler(); if (!$moved) { - throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $target, strip_tags($error))); + throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s).', $this->getPathname(), $target, strip_tags($error))); } @chmod($target, 0666 & ~umask()); diff --git a/HeaderBag.php b/HeaderBag.php index 9c7273a73..d45d95e09 100644 --- a/HeaderBag.php +++ b/HeaderBag.php @@ -199,7 +199,7 @@ public function getDate(string $key, \DateTime $default = null) } if (false === $date = \DateTime::createFromFormat(DATE_RFC2822, $value)) { - throw new \RuntimeException(sprintf('The %s HTTP header is not parseable (%s).', $key, $value)); + throw new \RuntimeException(sprintf('The "%s" HTTP header is not parseable (%s).', $key, $value)); } return $date; diff --git a/Request.php b/Request.php index 21cb15744..b72d9a949 100644 --- a/Request.php +++ b/Request.php @@ -15,6 +15,14 @@ use Symfony\Component\HttpFoundation\Exception\SuspiciousOperationException; use Symfony\Component\HttpFoundation\Session\SessionInterface; +// Help opcache.preload discover always-needed symbols +class_exists(AcceptHeader::class); +class_exists(FileBag::class); +class_exists(HeaderBag::class); +class_exists(HeaderUtils::class); +class_exists(ParameterBag::class); +class_exists(ServerBag::class); + /** * Request represents an HTTP request. * diff --git a/Response.php b/Response.php index 4a331954b..4bbef581e 100644 --- a/Response.php +++ b/Response.php @@ -11,6 +11,9 @@ namespace Symfony\Component\HttpFoundation; +// Help opcache.preload discover always-needed symbols +class_exists(ResponseHeaderBag::class); + /** * Response represents an HTTP response. * diff --git a/ResponseHeaderBag.php b/ResponseHeaderBag.php index 56b9245f9..5acefc9c9 100644 --- a/ResponseHeaderBag.php +++ b/ResponseHeaderBag.php @@ -239,9 +239,9 @@ public function getCookies(string $format = self::COOKIES_FLAT) /** * Clears a cookie in the browser. */ - public function clearCookie(string $name, ?string $path = '/', string $domain = null, bool $secure = false, bool $httpOnly = true) + public function clearCookie(string $name, ?string $path = '/', string $domain = null, bool $secure = false, bool $httpOnly = true, string $sameSite = null) { - $this->setCookie(new Cookie($name, null, 1, $path, $domain, $secure, $httpOnly, false, null)); + $this->setCookie(new Cookie($name, null, 1, $path, $domain, $secure, $httpOnly, false, $sameSite)); } /** diff --git a/Session/Session.php b/Session/Session.php index 89071b861..8b02d2d0d 100644 --- a/Session/Session.php +++ b/Session/Session.php @@ -18,6 +18,11 @@ use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage; use Symfony\Component\HttpFoundation\Session\Storage\SessionStorageInterface; +// Help opcache.preload discover always-needed symbols +class_exists(AttributeBag::class); +class_exists(FlashBag::class); +class_exists(SessionBagProxy::class); + /** * @author Fabien Potencier * @author Drak diff --git a/Session/Storage/Handler/MemcachedSessionHandler.php b/Session/Storage/Handler/MemcachedSessionHandler.php index 8896964ee..828d29eb5 100644 --- a/Session/Storage/Handler/MemcachedSessionHandler.php +++ b/Session/Storage/Handler/MemcachedSessionHandler.php @@ -47,7 +47,7 @@ public function __construct(\Memcached $memcached, array $options = []) $this->memcached = $memcached; if ($diff = array_diff(array_keys($options), ['prefix', 'expiretime'])) { - throw new \InvalidArgumentException(sprintf('The following options are not supported "%s"', implode(', ', $diff))); + throw new \InvalidArgumentException(sprintf('The following options are not supported "%s".', implode(', ', $diff))); } $this->ttl = isset($options['expiretime']) ? (int) $options['expiretime'] : 86400; diff --git a/Session/Storage/Handler/MongoDbSessionHandler.php b/Session/Storage/Handler/MongoDbSessionHandler.php index a6889e40c..9a2d7919a 100644 --- a/Session/Storage/Handler/MongoDbSessionHandler.php +++ b/Session/Storage/Handler/MongoDbSessionHandler.php @@ -66,7 +66,7 @@ class MongoDbSessionHandler extends AbstractSessionHandler public function __construct(\MongoDB\Client $mongo, array $options) { if (!isset($options['database']) || !isset($options['collection'])) { - throw new \InvalidArgumentException('You must provide the "database" and "collection" option for MongoDBSessionHandler'); + throw new \InvalidArgumentException('You must provide the "database" and "collection" option for MongoDBSessionHandler.'); } $this->mongo = $mongo; diff --git a/Session/Storage/Handler/NativeFileSessionHandler.php b/Session/Storage/Handler/NativeFileSessionHandler.php index bdfc9d819..effc9db54 100644 --- a/Session/Storage/Handler/NativeFileSessionHandler.php +++ b/Session/Storage/Handler/NativeFileSessionHandler.php @@ -38,7 +38,7 @@ public function __construct(string $savePath = null) if ($count = substr_count($savePath, ';')) { if ($count > 2) { - throw new \InvalidArgumentException(sprintf('Invalid argument $savePath \'%s\'', $savePath)); + throw new \InvalidArgumentException(sprintf('Invalid argument $savePath \'%s\'.', $savePath)); } // characters after last ';' are the path @@ -46,7 +46,7 @@ public function __construct(string $savePath = null) } if ($baseDir && !is_dir($baseDir) && !@mkdir($baseDir, 0777, true) && !is_dir($baseDir)) { - throw new \RuntimeException(sprintf('Session Storage was not able to create directory "%s"', $baseDir)); + throw new \RuntimeException(sprintf('Session Storage was not able to create directory "%s".', $baseDir)); } ini_set('session.save_path', $savePath); diff --git a/Session/Storage/Handler/PdoSessionHandler.php b/Session/Storage/Handler/PdoSessionHandler.php index 74412e008..a301e9f05 100644 --- a/Session/Storage/Handler/PdoSessionHandler.php +++ b/Session/Storage/Handler/PdoSessionHandler.php @@ -174,7 +174,7 @@ public function __construct($pdoOrDsn = null, array $options = []) { if ($pdoOrDsn instanceof \PDO) { if (\PDO::ERRMODE_EXCEPTION !== $pdoOrDsn->getAttribute(\PDO::ATTR_ERRMODE)) { - throw new \InvalidArgumentException(sprintf('"%s" requires PDO error mode attribute be set to throw Exceptions (i.e. $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION))', __CLASS__)); + throw new \InvalidArgumentException(sprintf('"%s" requires PDO error mode attribute be set to throw Exceptions (i.e. $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)).', __CLASS__)); } $this->pdo = $pdoOrDsn; @@ -468,7 +468,7 @@ private function buildDsnFromUrl(string $dsnOrUrl): string } if (!isset($params['scheme'])) { - throw new \InvalidArgumentException('URLs without scheme are not supported to configure the PdoSessionHandler'); + throw new \InvalidArgumentException('URLs without scheme are not supported to configure the PdoSessionHandler.'); } $driverAliasMap = [ diff --git a/Session/Storage/Handler/RedisSessionHandler.php b/Session/Storage/Handler/RedisSessionHandler.php index b9ca28f59..d6c37c430 100644 --- a/Session/Storage/Handler/RedisSessionHandler.php +++ b/Session/Storage/Handler/RedisSessionHandler.php @@ -54,11 +54,11 @@ public function __construct($redis, array $options = []) !$redis instanceof RedisProxy && !$redis instanceof RedisClusterProxy ) { - throw new \InvalidArgumentException(sprintf('%s() expects parameter 1 to be Redis, RedisArray, RedisCluster or Predis\ClientInterface, %s given', __METHOD__, \is_object($redis) ? \get_class($redis) : \gettype($redis))); + throw new \InvalidArgumentException(sprintf('"%s()" expects parameter 1 to be Redis, RedisArray, RedisCluster or Predis\ClientInterface, "%s" given.', __METHOD__, \is_object($redis) ? \get_class($redis) : \gettype($redis))); } if ($diff = array_diff(array_keys($options), ['prefix', 'ttl'])) { - throw new \InvalidArgumentException(sprintf('The following options are not supported "%s"', implode(', ', $diff))); + throw new \InvalidArgumentException(sprintf('The following options are not supported "%s".', implode(', ', $diff))); } $this->redis = $redis; diff --git a/Session/Storage/Handler/SessionHandlerFactory.php b/Session/Storage/Handler/SessionHandlerFactory.php index b92bd0ffd..a5ebd29eb 100644 --- a/Session/Storage/Handler/SessionHandlerFactory.php +++ b/Session/Storage/Handler/SessionHandlerFactory.php @@ -27,7 +27,7 @@ class SessionHandlerFactory public static function createHandler($connection): AbstractSessionHandler { if (!\is_string($connection) && !\is_object($connection)) { - throw new \TypeError(sprintf('Argument 1 passed to %s() must be a string or a connection object, %s given.', __METHOD__, \gettype($connection))); + throw new \TypeError(sprintf('Argument 1 passed to "%s()" must be a string or a connection object, "%s" given.', __METHOD__, \gettype($connection))); } switch (true) { @@ -46,7 +46,7 @@ public static function createHandler($connection): AbstractSessionHandler return new PdoSessionHandler($connection); case !\is_string($connection): - throw new \InvalidArgumentException(sprintf('Unsupported Connection: %s.', \get_class($connection))); + throw new \InvalidArgumentException(sprintf('Unsupported Connection: "%s".', \get_class($connection))); case 0 === strpos($connection, 'file://'): return new StrictSessionHandler(new NativeFileSessionHandler(substr($connection, 7))); @@ -80,6 +80,6 @@ public static function createHandler($connection): AbstractSessionHandler return new PdoSessionHandler($connection); } - throw new \InvalidArgumentException(sprintf('Unsupported Connection: %s.', $connection)); + throw new \InvalidArgumentException(sprintf('Unsupported Connection: "%s".', $connection)); } } diff --git a/Session/Storage/MockArraySessionStorage.php b/Session/Storage/MockArraySessionStorage.php index 4662bd864..0201504c9 100644 --- a/Session/Storage/MockArraySessionStorage.php +++ b/Session/Storage/MockArraySessionStorage.php @@ -148,7 +148,7 @@ public function setName(string $name) public function save() { if (!$this->started || $this->closed) { - throw new \RuntimeException('Trying to save a session that was not started yet or was already closed'); + throw new \RuntimeException('Trying to save a session that was not started yet or was already closed.'); } // nothing to do since we don't persist the session data $this->closed = false; @@ -186,7 +186,7 @@ public function registerBag(SessionBagInterface $bag) public function getBag(string $name) { if (!isset($this->bags[$name])) { - throw new \InvalidArgumentException(sprintf('The SessionBagInterface %s is not registered.', $name)); + throw new \InvalidArgumentException(sprintf('The SessionBagInterface "%s" is not registered.', $name)); } if (!$this->started) { diff --git a/Session/Storage/MockFileSessionStorage.php b/Session/Storage/MockFileSessionStorage.php index 019a63484..ab8b86402 100644 --- a/Session/Storage/MockFileSessionStorage.php +++ b/Session/Storage/MockFileSessionStorage.php @@ -36,7 +36,7 @@ public function __construct(string $savePath = null, string $name = 'MOCKSESSID' } if (!is_dir($savePath) && !@mkdir($savePath, 0777, true) && !is_dir($savePath)) { - throw new \RuntimeException(sprintf('Session Storage was not able to create directory "%s"', $savePath)); + throw new \RuntimeException(sprintf('Session Storage was not able to create directory "%s".', $savePath)); } $this->savePath = $savePath; @@ -86,7 +86,7 @@ public function regenerate(bool $destroy = false, int $lifetime = null) public function save() { if (!$this->started) { - throw new \RuntimeException('Trying to save a session that was not started yet or was already closed'); + throw new \RuntimeException('Trying to save a session that was not started yet or was already closed.'); } $data = $this->data; diff --git a/Session/Storage/NativeSessionStorage.php b/Session/Storage/NativeSessionStorage.php index 792bacf4e..268f9784e 100644 --- a/Session/Storage/NativeSessionStorage.php +++ b/Session/Storage/NativeSessionStorage.php @@ -17,6 +17,11 @@ use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy; use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy; +// Help opcache.preload discover always-needed symbols +class_exists(MetadataBag::class); +class_exists(StrictSessionHandler::class); +class_exists(SessionHandlerProxy::class); + /** * This provides a base class for session attribute storage. * @@ -149,7 +154,7 @@ public function start() // ok to try and start the session if (!session_start()) { - throw new \RuntimeException('Failed to start the session'); + throw new \RuntimeException('Failed to start the session.'); } if (null !== $this->emulateSameSite) { @@ -311,7 +316,7 @@ public function registerBag(SessionBagInterface $bag) public function getBag(string $name) { if (!isset($this->bags[$name])) { - throw new \InvalidArgumentException(sprintf('The SessionBagInterface %s is not registered.', $name)); + throw new \InvalidArgumentException(sprintf('The SessionBagInterface "%s" is not registered.', $name)); } if (!$this->started && $this->saveHandler->isActive()) { diff --git a/Session/Storage/Proxy/AbstractProxy.php b/Session/Storage/Proxy/AbstractProxy.php index 38f7dede6..e7be22c01 100644 --- a/Session/Storage/Proxy/AbstractProxy.php +++ b/Session/Storage/Proxy/AbstractProxy.php @@ -86,7 +86,7 @@ public function getId() public function setId(string $id) { if ($this->isActive()) { - throw new \LogicException('Cannot change the ID of an active session'); + throw new \LogicException('Cannot change the ID of an active session.'); } session_id($id); @@ -110,7 +110,7 @@ public function getName() public function setName(string $name) { if ($this->isActive()) { - throw new \LogicException('Cannot change the name of an active session'); + throw new \LogicException('Cannot change the name of an active session.'); } session_name($name); diff --git a/Tests/ResponseHeaderBagTest.php b/Tests/ResponseHeaderBagTest.php index 4d9244122..18b3c36a6 100644 --- a/Tests/ResponseHeaderBagTest.php +++ b/Tests/ResponseHeaderBagTest.php @@ -128,6 +128,14 @@ public function testClearCookieSecureNotHttpOnly() $this->assertSetCookieHeader('foo=deleted; expires='.gmdate('D, d-M-Y H:i:s T', time() - 31536001).'; Max-Age=0; path=/; secure', $bag); } + public function testClearCookieSamesite() + { + $bag = new ResponseHeaderBag([]); + + $bag->clearCookie('foo', '/', null, true, false, 'none'); + $this->assertSetCookieHeader('foo=deleted; expires='.gmdate('D, d-M-Y H:i:s T', time() - 31536001).'; Max-Age=0; path=/; secure; samesite=none', $bag); + } + public function testReplace() { $bag = new ResponseHeaderBag([]);