<?php

class FileCache {
    const CACHE_DIR = 1;
    const DEFAULT_LIFETIME = 2;

    protected $_cacheDir;
    protected $_defaultLifeTime;

    /**
     * Create a FileCache instance with given options.
     *
     * To define the options please use the constants. Example:
     * $fileCache = new FileCache(array(
     *   FileCache::CACHE_DIR => '/tmp/cache',
     *   FileCache::DEFAULT_LIFETIME => 3600
     * ));
     *
     * @param array $options
     */
    public function __construct($options = array()) {
        $this->_cacheDir = __DIR__ . '/cache';

        if (!empty($options[self::CACHE_DIR])) {
            $this->_cacheDir = $options[self::CACHE_DIR];
        }

        $this->_defaultLifeTime = 3600;
        if (!empty($options[self::DEFAULT_LIFETIME])) {
            $this->_defaultLifeTime = $options[self::DEFAULT_LIFETIME];
        }
    }

    /**
     * Load cached value by $id. Returns null when cache does not exist or is invalid.
     *
     * @param string $id
     * @return mixed|null
     */
    public function load($id) {
        $file = $this->_cacheDir . '/' . md5($id) . '.cache';
        if (!file_exists($file)) {
            return null;
        }

        if (!is_readable($file) || !($fh = fopen($file, 'r'))) {
            return null;
        }

        $cache = unserialize(fread($fh, filesize($file)));

        if ($cache['valid'] < time()) {
            return null;
        }

        return unserialize($cache['data']);
    }

    /**
     * Save a value $data identified by $id in cache. If you omit $lifeTime
     * the default lifetime will be used.
     *
     * @param string  $id
     * @param mixed   $data
     * @param integer $lifeTime
     * @return bool
     */
    public function save($id, $data, $lifeTime = null) {

        if (!$id) {
            return false;
        }

        if (!file_exists($this->_cacheDir)) {
            mkdir($this->_cacheDir, 0777, true);
        }

        if(!$lifeTime || !is_int($lifeTime)) {
            $lifeTime = $this->_defaultLifeTime;
        }

        $fh = fopen($this->_cacheDir. '/' .md5($id). '.cache', 'w');

        $result = fwrite($fh, serialize([
            'valid' => time() + $lifeTime,
            'data' => serialize($data)
        ]));

        fclose($fh);

        return !!$result;
    }
}