<?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) 2013 fusionLib. All rights reserved.
 * @link http://fusionlib.com
 */

/**
 * flCacheDb Class
 *
 * Implementation of database based cache engine.
 *
 * @package fusionLib
 */
class flCacheDb extends flCache {

	/**
	 * The database object
	 *
	 * @var flDb
	 */
	private $db;

	/**
	 * Construct the cache
	 *
	 * @param flDb $db The database object to use.
	 * @param int $lifetime The default lifetime for objects in seconds.
	 * @param string $prefix Prefix for cache keys.
	 */
	function __construct($db, $lifetime = 3600, $prefix = '') {
		parent::__construct($lifetime, $prefix);
		$this->db = $db;
	}

	/**
	 * 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() + $expire;

		// Cache the data
		$result = $this->db->replace('fl_cache', array('id' => md5($id), 'expireat' => $expire, 'content' => serialize($data)));

		// Randomly choose to clean cache
		static $autoClean = true;
		if($autoClean && mt_rand(1, 100) == 1) {
			$autoClean = false;
			$this->db->delete('fl_cache', 'expireat AND expireat<?', time());
		}

		return $result;
	}

	/**
	 * 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) {
		$result = $this->db->fetchOne('SELECT content FROM fl_cache WHERE id=? AND (expireat==0 OR expireat>=?)', md5($id), time());
		return $result ? unserialize($result) : false;
	}

	/**
	 * Remove the given element from the cache.
	 *
	 * @param string $id The id of the element to remove.
	 */
	function remove($id) {
		$this->db->delete('fl_cache', 'id=?', md5($id));
	}

	/**
	 * Flush the cache.
	 */
	function flush() {
		$this->db->query('TRUNCATE TABLE fl_cache');
	}

	/**
	 * Get the UNIX timestamp according to the server.
	 *
	 * @return int The timestamp.
	 */
	function getServerTime() {
		return $this->db->fetchOne('SELECT UNIX_TIMESTAMP()');
	}
}
