romanitalian
5/14/2015 - 7:52 PM

Fcache Caching to files in /tmp

Fcache Caching to files in /tmp

<?php

class Fcache
{
    protected $path = '/tmp/fcache';
    protected $content = null;
    protected $time_limit = 3600;
    protected $prefix_file = 'fcache_';
    public static $inst = null;
    protected $out;

    /**
     * Кеширует результат вызова метода стороннего класса
     * @param $obj Object объект для которого будет вызван $method и результат будет кеширован
     * @param $method String существующий метод объекта $class
     * @param null $args
     */
    public function __construct($obj, $method, $args = null, $postfix = '') {
        if(is_string($obj)) { // for: Fcache::get('key_cache_lalala', $data);
            $key = md5($obj.$postfix);
            $this->content = $this->_get($key);
            if(!$this->content) {
                $this->content = $method;
                $this->set($this->content, $key);
            }
        } else if(is_object($obj)) { // for: Fcache::get($this, 'getData');
            if(!is_null($obj) && !is_null($method)) {
                $key = md5((string)$method.serialize($args).$postfix);
                $this->content = $this->_get($key);
                if(!$this->content) {
                    if(is_null($args)) {
                        $this->content = call_user_func(array($obj, $method));
                    } else {
                        $this->content = call_user_func_array(array($obj, $method), $args);
                    }
                    $this->set($this->content, $key);
                }
            }
        }
    }

    public static function getInstance($class = null, $method = null, $args = null, $postfix = '') {
        if(is_null(self::$inst) || $postfix != '') {
            self::$inst = new self($class, $method, $args, $postfix);
        }
        return self::$inst;
    }

    /**
     * Кешировать результат вызова метода $method объекта $class
     * @param $class
     * @param $method
     * @param null $args
     * @return mixed
     */
    public static function get($class, $method, $args = null, $postfix = '') {
        //return self::getInstance($class, $method)->_get(md5((string)$method));
        return self::getInstance($class, $method, $args, $postfix)->content;
    }

    public function _get($file_name) {
        $_file_path = $this->getFilePath($file_name);
        $is_file_exists = file_exists($_file_path) && is_readable($_file_path);
        if($is_file_exists && $this->isElapsedTime($_file_path)) {
            unlink($_file_path);
        }
        return $is_file_exists && !$this->isElapsedTime($_file_path)
            ? $content = unserialize(file_get_contents($_file_path))
            //? $this->content = include($_file_path)
            : null;
    }

    /**
     * Прошло ли время актуальности кешированных данных
     * @param $file_name
     * @return bool
     */
    protected function isElapsedTime($file_name) {
        return time() - filemtime($file_name) > $this->time_limit;
    }

    public function set($data, $file_name, $time = false) {
        if(!file_exists($this->path)) {
            mkdir($this->path);
        }
        file_put_contents($this->getFilePath($file_name), serialize($data));
        //file_put_contents($this->getFilePath($file_name), "<?php\nreturn ".var_export($data, true).';'); // performance of serialize is not good
        $this->setTimeLimit($time);
    }

    protected function setTimeLimit($time = false) {
        if($time && is_int($time)) {
            $this->time_limit = (int)$time;
        }
    }

    public function getFilePath($file_name) {
        return $this->path.DIRECTORY_SEPARATOR.$this->prefix_file.$file_name;
    }

    public static function deleteAll() {
        $path = self::getInstance()->path;
        $dh = opendir($path);
        while(false !== ($filename = readdir($dh))) {
            if(stripos($filename, self::getInstance()->prefix_file) !== false) {
                unlink(self::getInstance()->path.DIRECTORY_SEPARATOR.$filename);
            }
        }
    }

    public static function delete($class, $method) {
        $path = self::getInstance($class, $method)->getFilePath($method);
        $is_file_isset = file_exists($path) && is_readable($path);
        if($is_file_isset) {
            unlink($path);
        }
    }
}