Chris@0: Chris@0: * Chris@0: * For the full copyright and license information, please view the LICENSE Chris@0: * file that was distributed with this source code. Chris@0: */ Chris@0: Chris@0: namespace Symfony\Component\HttpFoundation; Chris@0: Chris@0: /** Chris@0: * Represents a cookie. Chris@0: * Chris@0: * @author Johannes M. Schmitt Chris@0: */ Chris@0: class Cookie Chris@0: { Chris@0: protected $name; Chris@0: protected $value; Chris@0: protected $domain; Chris@0: protected $expire; Chris@0: protected $path; Chris@0: protected $secure; Chris@0: protected $httpOnly; Chris@0: private $raw; Chris@0: private $sameSite; Chris@0: Chris@0: const SAMESITE_LAX = 'lax'; Chris@0: const SAMESITE_STRICT = 'strict'; Chris@0: Chris@0: /** Chris@0: * Constructor. Chris@0: * Chris@0: * @param string $name The name of the cookie Chris@0: * @param string $value The value of the cookie Chris@0: * @param int|string|\DateTimeInterface $expire The time the cookie expires Chris@0: * @param string $path The path on the server in which the cookie will be available on Chris@0: * @param string $domain The domain that the cookie is available to Chris@0: * @param bool $secure Whether the cookie should only be transmitted over a secure HTTPS connection from the client Chris@0: * @param bool $httpOnly Whether the cookie will be made accessible only through the HTTP protocol Chris@0: * @param bool $raw Whether the cookie value should be sent with no url encoding Chris@0: * @param string|null $sameSite Whether the cookie will be available for cross-site requests Chris@0: * Chris@0: * @throws \InvalidArgumentException Chris@0: */ Chris@0: public function __construct($name, $value = null, $expire = 0, $path = '/', $domain = null, $secure = false, $httpOnly = true, $raw = false, $sameSite = null) Chris@0: { Chris@0: // from PHP source code Chris@0: if (preg_match("/[=,; \t\r\n\013\014]/", $name)) { Chris@0: throw new \InvalidArgumentException(sprintf('The cookie name "%s" contains invalid characters.', $name)); Chris@0: } Chris@0: Chris@0: if (empty($name)) { Chris@0: throw new \InvalidArgumentException('The cookie name cannot be empty.'); Chris@0: } Chris@0: Chris@0: // convert expiration time to a Unix timestamp Chris@0: if ($expire instanceof \DateTimeInterface) { Chris@0: $expire = $expire->format('U'); Chris@0: } elseif (!is_numeric($expire)) { Chris@0: $expire = strtotime($expire); Chris@0: Chris@0: if (false === $expire) { Chris@0: throw new \InvalidArgumentException('The cookie expiration time is not valid.'); Chris@0: } Chris@0: } Chris@0: Chris@0: $this->name = $name; Chris@0: $this->value = $value; Chris@0: $this->domain = $domain; Chris@0: $this->expire = 0 < $expire ? (int) $expire : 0; Chris@0: $this->path = empty($path) ? '/' : $path; Chris@0: $this->secure = (bool) $secure; Chris@0: $this->httpOnly = (bool) $httpOnly; Chris@0: $this->raw = (bool) $raw; Chris@0: Chris@12: if (null !== $sameSite) { Chris@12: $sameSite = strtolower($sameSite); Chris@12: } Chris@12: Chris@0: if (!in_array($sameSite, array(self::SAMESITE_LAX, self::SAMESITE_STRICT, null), true)) { Chris@0: throw new \InvalidArgumentException('The "sameSite" parameter value is not valid.'); Chris@0: } Chris@0: Chris@0: $this->sameSite = $sameSite; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Returns the cookie as a string. Chris@0: * Chris@0: * @return string The cookie Chris@0: */ Chris@0: public function __toString() Chris@0: { Chris@0: $str = ($this->isRaw() ? $this->getName() : urlencode($this->getName())).'='; Chris@0: Chris@0: if ('' === (string) $this->getValue()) { Chris@0: $str .= 'deleted; expires='.gmdate('D, d-M-Y H:i:s T', time() - 31536001); Chris@0: } else { Chris@12: $str .= $this->isRaw() ? $this->getValue() : rawurlencode($this->getValue()); Chris@0: Chris@0: if (0 !== $this->getExpiresTime()) { Chris@0: $str .= '; expires='.gmdate('D, d-M-Y H:i:s T', $this->getExpiresTime()); Chris@0: } Chris@0: } Chris@0: Chris@0: if ($this->getPath()) { Chris@0: $str .= '; path='.$this->getPath(); Chris@0: } Chris@0: Chris@0: if ($this->getDomain()) { Chris@0: $str .= '; domain='.$this->getDomain(); Chris@0: } Chris@0: Chris@0: if (true === $this->isSecure()) { Chris@0: $str .= '; secure'; Chris@0: } Chris@0: Chris@0: if (true === $this->isHttpOnly()) { Chris@0: $str .= '; httponly'; Chris@0: } Chris@0: Chris@0: if (null !== $this->getSameSite()) { Chris@0: $str .= '; samesite='.$this->getSameSite(); Chris@0: } Chris@0: Chris@0: return $str; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Gets the name of the cookie. Chris@0: * Chris@0: * @return string Chris@0: */ Chris@0: public function getName() Chris@0: { Chris@0: return $this->name; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Gets the value of the cookie. Chris@0: * Chris@0: * @return string|null Chris@0: */ Chris@0: public function getValue() Chris@0: { Chris@0: return $this->value; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Gets the domain that the cookie is available to. Chris@0: * Chris@0: * @return string|null Chris@0: */ Chris@0: public function getDomain() Chris@0: { Chris@0: return $this->domain; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Gets the time the cookie expires. Chris@0: * Chris@0: * @return int Chris@0: */ Chris@0: public function getExpiresTime() Chris@0: { Chris@0: return $this->expire; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Gets the path on the server in which the cookie will be available on. Chris@0: * Chris@0: * @return string Chris@0: */ Chris@0: public function getPath() Chris@0: { Chris@0: return $this->path; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Checks whether the cookie should only be transmitted over a secure HTTPS connection from the client. Chris@0: * Chris@0: * @return bool Chris@0: */ Chris@0: public function isSecure() Chris@0: { Chris@0: return $this->secure; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Checks whether the cookie will be made accessible only through the HTTP protocol. Chris@0: * Chris@0: * @return bool Chris@0: */ Chris@0: public function isHttpOnly() Chris@0: { Chris@0: return $this->httpOnly; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Whether this cookie is about to be cleared. Chris@0: * Chris@0: * @return bool Chris@0: */ Chris@0: public function isCleared() Chris@0: { Chris@0: return $this->expire < time(); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Checks if the cookie value should be sent with no url encoding. Chris@0: * Chris@0: * @return bool Chris@0: */ Chris@0: public function isRaw() Chris@0: { Chris@0: return $this->raw; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Gets the SameSite attribute. Chris@0: * Chris@0: * @return string|null Chris@0: */ Chris@0: public function getSameSite() Chris@0: { Chris@0: return $this->sameSite; Chris@0: } Chris@0: }