diff --git a/AcceptHeader.php b/AcceptHeader.php index bbbd62a6d..c3c8d0c35 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 4906588a7..c72a6d991 100644 --- a/File/File.php +++ b/File/File.php @@ -91,7 +91,7 @@ public function move($directory, $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()); @@ -106,10 +106,10 @@ protected function getTargetFile($directory, $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/MimeType/MimeTypeGuesser.php b/File/MimeType/MimeTypeGuesser.php index ece2109ca..65b4b25be 100644 --- a/File/MimeType/MimeTypeGuesser.php +++ b/File/MimeType/MimeTypeGuesser.php @@ -130,7 +130,7 @@ public function guess($path) } if (2 === \count($this->guessers) && !FileBinaryMimeTypeGuesser::isSupported() && !FileinfoMimeTypeGuesser::isSupported()) { - throw new \LogicException('Unable to guess the mime type as no guessers are available (Did you enable the php_fileinfo extension?)'); + throw new \LogicException('Unable to guess the mime type as no guessers are available (Did you enable the php_fileinfo extension?).'); } return null; diff --git a/File/UploadedFile.php b/File/UploadedFile.php index 0c67f8907..36fd1e65c 100644 --- a/File/UploadedFile.php +++ b/File/UploadedFile.php @@ -208,7 +208,7 @@ public function move($directory, $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 9ffe6f4fe..da794554b 100644 --- a/HeaderBag.php +++ b/HeaderBag.php @@ -219,7 +219,7 @@ public function getDate($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 6690b9b22..a5e50eb79 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. * @@ -725,7 +733,7 @@ public function getSession() if (null === $session) { @trigger_error(sprintf('Calling "%s()" when no session has been set is deprecated since Symfony 4.1 and will throw an exception in 5.0. Use "hasSession()" instead.', __METHOD__), E_USER_DEPRECATED); - // throw new \BadMethodCallException('Session has not been set'); + // throw new \BadMethodCallException('Session has not been set.'); } return $session; diff --git a/Response.php b/Response.php index b267cd8ce..714109d53 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 cdc669904..e71034aba 100644 --- a/ResponseHeaderBag.php +++ b/ResponseHeaderBag.php @@ -252,10 +252,13 @@ public function getCookies($format = self::COOKIES_FLAT) * @param string $domain * @param bool $secure * @param bool $httpOnly + * @param string $sameSite */ - public function clearCookie($name, $path = '/', $domain = null, $secure = false, $httpOnly = true) + public function clearCookie($name, $path = '/', $domain = null, $secure = false, $httpOnly = true/*, $sameSite = null*/) { - $this->setCookie(new Cookie($name, null, 1, $path, $domain, $secure, $httpOnly, false, null)); + $sameSite = \func_num_args() > 5 ? func_get_arg(5) : 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 2192c629e..b6973aaab 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 a399be5fd..6711e0a55 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 27e080021..6cb884778 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 034c02e5c..330ac7f2a 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 e5be90d5f..699d6da6f 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 37b6f145b..db8f85e75 100644 --- a/Session/Storage/MockArraySessionStorage.php +++ b/Session/Storage/MockArraySessionStorage.php @@ -148,7 +148,7 @@ public function setName($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($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 02fe4dad4..c96b3cd9d 100644 --- a/Session/Storage/MockFileSessionStorage.php +++ b/Session/Storage/MockFileSessionStorage.php @@ -37,7 +37,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; @@ -87,7 +87,7 @@ public function regenerate($destroy = false, $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 4085bd6ef..54933d953 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($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 cd0635a16..b9c2682b3 100644 --- a/Session/Storage/Proxy/AbstractProxy.php +++ b/Session/Storage/Proxy/AbstractProxy.php @@ -88,7 +88,7 @@ public function getId() public function setId($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); @@ -114,7 +114,7 @@ public function getName() public function setName($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([]);