| 
<?phpnamespace GuzzleHttp\Cookie;
 
 use Psr\Http\Message\RequestInterface;
 use Psr\Http\Message\ResponseInterface;
 
 /**
 * Cookie jar that stores cookies an an array
 */
 class CookieJar implements CookieJarInterface
 {
 /** @var SetCookie[] Loaded cookie data */
 private $cookies = [];
 
 /** @var bool */
 private $strictMode;
 
 /**
 * @param bool $strictMode   Set to true to throw exceptions when invalid
 *                           cookies are added to the cookie jar.
 * @param array $cookieArray Array of SetCookie objects or a hash of
 *                           arrays that can be used with the SetCookie
 *                           constructor
 */
 public function __construct($strictMode = false, $cookieArray = [])
 {
 $this->strictMode = $strictMode;
 
 foreach ($cookieArray as $cookie) {
 if (!($cookie instanceof SetCookie)) {
 $cookie = new SetCookie($cookie);
 }
 $this->setCookie($cookie);
 }
 }
 
 /**
 * Create a new Cookie jar from an associative array and domain.
 *
 * @param array  $cookies Cookies to create the jar from
 * @param string $domain  Domain to set the cookies to
 *
 * @return self
 */
 public static function fromArray(array $cookies, $domain)
 {
 $cookieJar = new self();
 foreach ($cookies as $name => $value) {
 $cookieJar->setCookie(new SetCookie([
 'Domain'  => $domain,
 'Name'    => $name,
 'Value'   => $value,
 'Discard' => true
 ]));
 }
 
 return $cookieJar;
 }
 
 /**
 * Quote the cookie value if it is not already quoted and it contains
 * problematic characters.
 *
 * @param string $value Value that may or may not need to be quoted
 *
 * @return string
 */
 public static function getCookieValue($value)
 {
 if (substr($value, 0, 1) !== '"' &&
 substr($value, -1, 1) !== '"' &&
 strpbrk($value, ';,=')
 ) {
 $value = '"' . $value . '"';
 }
 
 return $value;
 }
 
 /**
 * Evaluate if this cookie should be persisted to storage
 * that survives between requests.
 *
 * @param SetCookie $cookie Being evaluated.
 * @param bool $allowSessionCookies If we should persist session cookies
 * @return bool
 */
 public static function shouldPersist(
 SetCookie $cookie,
 $allowSessionCookies = false
 ) {
 if ($cookie->getExpires() || $allowSessionCookies) {
 if (!$cookie->getDiscard()) {
 return true;
 }
 }
 
 return false;
 }
 
 public function toArray()
 {
 return array_map(function (SetCookie $cookie) {
 return $cookie->toArray();
 }, $this->getIterator()->getArrayCopy());
 }
 
 public function clear($domain = null, $path = null, $name = null)
 {
 if (!$domain) {
 $this->cookies = [];
 return;
 } elseif (!$path) {
 $this->cookies = array_filter(
 $this->cookies,
 function (SetCookie $cookie) use ($path, $domain) {
 return !$cookie->matchesDomain($domain);
 }
 );
 } elseif (!$name) {
 $this->cookies = array_filter(
 $this->cookies,
 function (SetCookie $cookie) use ($path, $domain) {
 return !($cookie->matchesPath($path) &&
 $cookie->matchesDomain($domain));
 }
 );
 } else {
 $this->cookies = array_filter(
 $this->cookies,
 function (SetCookie $cookie) use ($path, $domain, $name) {
 return !($cookie->getName() == $name &&
 $cookie->matchesPath($path) &&
 $cookie->matchesDomain($domain));
 }
 );
 }
 }
 
 public function clearSessionCookies()
 {
 $this->cookies = array_filter(
 $this->cookies,
 function (SetCookie $cookie) {
 return !$cookie->getDiscard() && $cookie->getExpires();
 }
 );
 }
 
 public function setCookie(SetCookie $cookie)
 {
 // If the name string is empty (but not 0), ignore the set-cookie
 // string entirely.
 $name = $cookie->getName();
 if (!$name && $name !== '0') {
 return false;
 }
 
 // Only allow cookies with set and valid domain, name, value
 $result = $cookie->validate();
 if ($result !== true) {
 if ($this->strictMode) {
 throw new \RuntimeException('Invalid cookie: ' . $result);
 } else {
 $this->removeCookieIfEmpty($cookie);
 return false;
 }
 }
 
 // Resolve conflicts with previously set cookies
 foreach ($this->cookies as $i => $c) {
 
 // Two cookies are identical, when their path, and domain are
 // identical.
 if ($c->getPath() != $cookie->getPath() ||
 $c->getDomain() != $cookie->getDomain() ||
 $c->getName() != $cookie->getName()
 ) {
 continue;
 }
 
 // The previously set cookie is a discard cookie and this one is
 // not so allow the new cookie to be set
 if (!$cookie->getDiscard() && $c->getDiscard()) {
 unset($this->cookies[$i]);
 continue;
 }
 
 // If the new cookie's expiration is further into the future, then
 // replace the old cookie
 if ($cookie->getExpires() > $c->getExpires()) {
 unset($this->cookies[$i]);
 continue;
 }
 
 // If the value has changed, we better change it
 if ($cookie->getValue() !== $c->getValue()) {
 unset($this->cookies[$i]);
 continue;
 }
 
 // The cookie exists, so no need to continue
 return false;
 }
 
 $this->cookies[] = $cookie;
 
 return true;
 }
 
 public function count()
 {
 return count($this->cookies);
 }
 
 public function getIterator()
 {
 return new \ArrayIterator(array_values($this->cookies));
 }
 
 public function extractCookies(
 RequestInterface $request,
 ResponseInterface $response
 ) {
 if ($cookieHeader = $response->getHeader('Set-Cookie')) {
 foreach ($cookieHeader as $cookie) {
 $sc = SetCookie::fromString($cookie);
 if (!$sc->getDomain()) {
 $sc->setDomain($request->getUri()->getHost());
 }
 $this->setCookie($sc);
 }
 }
 }
 
 public function withCookieHeader(RequestInterface $request)
 {
 $values = [];
 $uri = $request->getUri();
 $scheme = $uri->getScheme();
 $host = $uri->getHost();
 $path = $uri->getPath() ?: '/';
 
 foreach ($this->cookies as $cookie) {
 if ($cookie->matchesPath($path) &&
 $cookie->matchesDomain($host) &&
 !$cookie->isExpired() &&
 (!$cookie->getSecure() || $scheme == 'https')
 ) {
 $values[] = $cookie->getName() . '='
 . self::getCookieValue($cookie->getValue());
 }
 }
 
 return $values
 ? $request->withHeader('Cookie', implode('; ', $values))
 : $request;
 }
 
 /**
 * If a cookie already exists and the server asks to set it again with a
 * null value, the cookie must be deleted.
 *
 * @param SetCookie $cookie
 */
 private function removeCookieIfEmpty(SetCookie $cookie)
 {
 $cookieValue = $cookie->getValue();
 if ($cookieValue === null || $cookieValue === '') {
 $this->clear(
 $cookie->getDomain(),
 $cookie->getPath(),
 $cookie->getName()
 );
 }
 }
 }
 
 |