I've written a fairly small library that abstracts cookie functionality in a way that mimics working with a database model. The repository is on bitbucket and the code is small enough to embed here:
class SimpleCookie {
/**
* Cookie value char limit
* @var int
*/
const valueLimit = 2000;
/**
* Cookie data
* @var array
*/
protected $cookieData = array();
/**
* Cookie name
* @var string
*/
protected $cookieName = null;
/**
* If cookie exists, it get's loaded on construct
*
* @param string $cookieName
*/
public function __construct($cookieName) {
$this->load($cookieName);
}
/**
* @param string $key
* @return mixed
*/
public function __get($key) {
return
isset($this->cookieData[$key])
? $this->cookieData[$key]
: null;
}
/**
* @param string $key
* @param mixed $value
*/
public function __set($key, $value) {
$this->cookieData[$key] = $value;
}
/**
* @param string $key
* @return bool
*/
public function __isset($key) {
return isset($this->cookieData[$key]);
}
/**
* @param string $key
*/
public function __unset($key) {
if(isset($this->cookieData[$key])) {
unset($this->cookieData[$key]);
}
}
/**
* Load a cookie
*
* @param string $cookieName
* @return SimpleCookie|false
*/
public function load($cookieName) {
$this->setName($cookieName);
if(!$data = $this->getCookie($this->cookieName)) {
return false;
}
if(is_array($data)) {
$data = implode("", $data);
}
return $this->setData( $this->getCookieArray( $data ) );
}
/**
* Save a cookie
*
* @param int $expires
* @param string $path
* @param string $domain
* @param bool $secure
* @param bool $httponly
* @return bool
*/
public function save($expires = 0, $path = "/", $domain = null, $secure = false, $httponly = false) {
$value = $this->getCookieString($this->cookieData);
$name = $this->cookieName;
if(strlen($value) > SimpleCookie::valueLimit) {
$value = str_split($value, SimpleCookie::valueLimit);
$result = true;
foreach($value as $k => $v) {
$result = $result && $this->setCookie("{$name}[$k]", $v, $expires, $path, $domain, $secure, $httponly);
}
return $result;
}
return $this->setCookie($name, $value, $expires, $path, $domain, $secure, $httponly);
}
/**
* Set cookie
*
* @since version 0.2
* @param int $expires
* @param string $value
* @param string $path
* @param string $domain
* @param bool $secure
* @param bool $httponly
* @return bool
*/
protected function setCookie($name, $value, $expires = 0, $path = "/", $domain = null, $secure = false, $httponly = false) {
$expires = is_int($expires) || ctype_digit($expires) ? (int) $expires : 0;
$path = is_string($path) ? $path : "/";
$domain = is_string($domain) || is_null($domain) ? $domain : null;
$secure = $secure === true;
$httponly = $httponly === true;
return setcookie($name, $value, $expires, $path, $domain, $secure, $httponly);
}
/**
* Get cookie
*
* @since version 0.2
* @param string $name
* @return mixed|false
*/
protected function getCookie($name) {
return isset($_COOKIE[$name]) && !empty($_COOKIE[$name]) ? $_COOKIE[$name] : false;
}
/**
* Delete a cookie
*
* @param string $path
* @param string $domain
* @param bool $secure
* @param bool $httponly
* @return bool
*/
public function delete($path = "/", $domain = null, $secure = false, $httponly = false) {
$this->setData(array());
return $this->save(time() - 3600, $path, $domain, $secure, $httponly);
}
/**
* Get cookie value from array
*
* Called on save
*
* @param array $data
* @return string
*/
protected function getCookieString(array $data) {
return http_build_query($data);
}
/**
* Get cookie array from cookie value
*
* Called on load
*
* @param string $string
* @throws InvalidArgumentException
* @return array
*/
protected function getCookieArray($string) {
if(!is_string($string)) {
throw new InvalidArgumentException("Cookie string must be a string :)");
}
parse_str($string, $data);
return $data;
}
/**
* Set cookie data
*
* This function updates internal data array,
* it does not save the cookie.
*
* @param array $data
* @return SimpleCookie
*/
public function setData(array $data) {
$this->cookieData = $data;
return $this;
}
/**
* Get data array
*
* @return array
*/
public function getData() {
return $this->cookieData;
}
/**
* Set cookie name
*
* @param string $cookieName
* @throws InvalidArgumentException
* @return SimpleCookie
*/
protected function setName($cookieName) {
if(!is_string($cookieName) || empty($cookieName)) {
throw new InvalidArgumentException("Cookie name must be a non empty string");
}
$this->cookieName = $cookieName;
return $this;
}
}
I would really love to hear your critiques on:
- Code quality
- Code clarity
- Comments sufficiency
I'm more interested in what I'm doing wrong than right. Any opinions on the actual usefulness of the library are welcome, although not central in my question.