<?php
namespace Yurun\Util\YurunHttp\Cookie;
use Yurun\Util\YurunHttp\Http\Psr7\Uri;
class CookieManager
{
protected $cookieList;
protected $relationMap;
protected $autoIncrementId;
public function __construct($cookieList = [])
{
$this->setCookieList($cookieList);
}
public function setCookieList($cookieList)
{
$this->autoIncrementId = 1;
$this->cookieList = [];
$this->relationMap = [];
foreach($cookieList as $item)
{
$item = CookieItem::newInstance($item);
$this->insertCookie($item);
}
}
public function getCookieList()
{
return $this->cookieList;
}
public function addSetCookie($setCookie)
{
$item = CookieItem::fromSetCookie($setCookie);
if(($id = $this->findCookie($item)) > 0)
{
$this->updateCookie($id, $item);
}
else
{
$this->insertCookie($item);
}
return $item;
}
public function setCookie($name, $value, $expires = 0, $path = '/', $domain = '', $secure = false, $httpOnly = false)
{
$item = new CookieItem($name, $value, $expires, $path, $domain, $secure, $httpOnly);
if(($id = $this->findCookie($item)) > 0)
{
$this->updateCookie($id, $item);
}
else
{
$this->insertCookie($item);
}
return $item;
}
public function count()
{
return count($this->cookieList);
}
public function getRequestCookies($uri)
{
if(defined('SWOOLE_VERSION') && SWOOLE_VERSION < 4.4)
{
$result = json_decode('[]', true);
}
else
{
$result = [];
}
$uriDomain = Uri::getDomain($uri);
$uriPath = $uri->getPath();
foreach($this->relationMap as $relationDomain => $list1)
{
if('' === $relationDomain || $this->checkDomain($uriDomain, $relationDomain))
{
foreach($list1 as $path => $idList)
{
if($this->checkPath($uriPath, $path))
{
foreach($idList as $id)
{
$cookieItem = $this->cookieList[$id];
if((0 === $cookieItem->expires || $cookieItem->expires > time()) && (!$cookieItem->secure || 'https' === $uri->getScheme() || 'wss' === $uri->getScheme()) )
{
$result[$cookieItem->name] = $cookieItem->value;
}
}
}
}
}
}
return $result;
}
public function getRequestCookieString($uri)
{
$content = '';
foreach($this->getRequestCookies($uri) as $name => $value)
{
$content .= "{$name}={$value}; ";
}
return $content;
}
public function getCookieItem($name, $domain = '', $path = '/')
{
if(isset($this->relationMap[$domain][$path][$name]))
{
$id = $this->relationMap[$domain][$path][$name];
return $this->cookieList[$id];
}
return null;
}
private function checkDomain($uriDomain, $cookieDomain)
{
return ($uriDomain === $cookieDomain)
|| (isset($cookieDomain[0]) && '.' === $cookieDomain[0] && substr($uriDomain, -strlen($cookieDomain) - 1) === '.' . $cookieDomain)
;
}
private function checkPath($uriPath, $cookiePath)
{
$uriPath = rtrim($uriPath, '/');
$cookiePath = rtrim($cookiePath, '/');
if($uriPath === $cookiePath)
{
return true;
}
$uriPathDSCount = substr_count($uriPath, '/');
$cookiePathDSCount = substr_count($cookiePath, '/');
if('' === $uriPath)
{
$uriPath = '/';
}
if('' === $cookiePath)
{
$cookiePath = '/';
}
if($uriPathDSCount > $cookiePathDSCount)
{
$path = dirname($uriPath, $uriPathDSCount - $cookiePathDSCount);
if('\\' === DIRECTORY_SEPARATOR && false !== strpos($path, DIRECTORY_SEPARATOR))
{
$path = str_replace(DIRECTORY_SEPARATOR, '/', $path);
}
return $path === $cookiePath;
}
else
{
return false;
}
}
private function updateCookie($id, $item)
{
if(isset($this->cookieList[$id]))
{
$object = $this->cookieList[$id];
}
foreach($item as $k => $v)
{
$object->$k = $v;
}
}
private function insertCookie($item)
{
$id = $this->autoIncrementId++;
$this->cookieList[$id] = $item;
$this->relationMap[$item->domain][$item->path][$item->name] = $id;
return $id;
}
private function findCookie($item)
{
if(isset($this->relationMap[$item->domain][$item->path][$item->name]))
{
return $this->relationMap[$item->domain][$item->path][$item->name];
}
else
{
return null;
}
}
}