<?php

/**
 * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 *
 * @package fusionLib
 * @copyright Copyright (c) 2007 - 2014 fusionLib. All rights reserved.
 * @link http://fusionlib.com
 */

/**
 * flCacheMemcached Class
 *
 * Class to implement memcached based storage for caching.
 *
 * @see http://www.danga.com/memcached/
 *
 * @package fusionLib
 */
class flCacheMemcached extends flCache {

	/**
	 * The Memcached interface object.
	 *
	 * @var Memcached
	 */
	private $cache = null;

	/**
	 * Construct the memcached cache.
	 *
	 * @param array|Memached $servers Array of host + port pairs e.g. localhost,11211 or Memcached object to use.
	 * @param int $lifetime The default lifetime for objects in seconds.
	 * @param string $prefix Prefix for cache keys.
	 * @throws flCacheException
	 */
	function __construct($servers, $lifetime = 3600, $prefix = '') {
		parent::__construct($lifetime, $prefix);

		if($servers instanceof Memcached)
			$this->cache = $servers;
		else {
			// Test if memcached drivers present
			if(extension_loaded('memcached'))
				$this->cache = new Memcached();
			else
				throw new flCacheException('The memcached extension required by flCacheMemcached is not available.');

			// Connect to servers
			foreach($servers as $server) {
				$d = explode(':', $server);
				if(!isset($d[1])) $d[1] = 11211;
				$this->cache->addServer($d[0], $d[1]);
			}
		}
	}

	/**
	 * Get the inner interface object.
	 *
	 * @return Memcached The inner interface object.
	 */
	function _getInnerObject() {
		return $this->cache;
	}

	/**
	 * Store an element in the cache.
	 *
	 * @param string $id The id to store the element as.
	 * @param mixed $data The data to store.
	 * @param int $lifetime The lifetime of the object in seconds, null to use the default or 0 to never expire.
	 * @return bool true if the data is cached or false if it could not be cached.
	 */
	function store($id, $data, $lifetime = null) {

		// Calculate expire time
		$expire = $lifetime === null ? $this->lifetime : $lifetime;
		if($expire)
			$expire += time();

		return $this->cache->set($this->prefix . $id, serialize($data), $expire);
	}

	/**
	 * Get the element from the cache.
	 *
	 * @param string $id The id of the element to get.
	 * @return mixed false if the element is not cached or has expired; else the cached data.
	 */
	function get($id) {
		if(($d = $this->cache->get($this->prefix . $id)) === false)
			return false;
		else
			return unserialize($d);
	}

	/**
	 * Remove the given element from the cache.
	 *
	 * @param string $id The id of the element to remove.
	 */
	function remove($id) {
		$this->cache->delete($this->prefix . $id);
	}

	/**
	 * Flush the cache.
	 */
	function flush() {
		$this->cache->flush();
	}

	/**
	 * Get the UNIX timestamp according to the server.
	 *
	 * @return int The timestamp.
	 */
	function getServerTime() {
		$stats = $this->cache->getStats();
		if(!isset($stats['time']))
			$stats = reset($stats);
		return $stats['time'] ? $stats['time'] : time();
	}
}
