<?php

class MyCache {
    static $instance = null;
    static $ary = array();
    protected $status = 0;

    private function __construct(){}

    static function getInstance() {
        if (is_null(self::$instance)) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    function get($key) {
        if (isset(self::$ary[$key]) && self::$ary[$key]['time'] > microtime(true)) {
            $this->status = 0;
            return self::$ary[$key]['value'];
        } else {
            $this->status = 1;
            return false;
        }
    }

    function set($key, $value, $time) {
        self::$ary[$key] = array(
            'value' => $value,
            'time'  => $time + microtime(true),
        );
    }

    function getOrUpdate($key, $time) {
        $value = $this->get($key);
        if (($value === false) && ($this->status != 0)) {
            $bt = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT, 2)[1];
            $params = $bt['args'];
            $params[count($params)-1] = false;
            $value = call_user_func_array(
                isset($bt['type'])
                    ? array(
                        ($bt['type'] == '->') ? $bt['object'] : $bt['class'],
                        $bt['function']
                    )
                    : $bt['function'],
                $params
            );
            $this->set($key, $value, $time);
        }
        return $value;
    }
}


function globalLol($cache = false) {
    if ($cache) {
        return MyCache::getInstance()->getOrUpdate('lol', 0.5);
    }
    echo "# new lol\n";
    return microtime();
}

class Pysch {
    function instanceLol($cache = false) {
        if ($cache) {
            return MyCache::getInstance()->getOrUpdate('instance_lol', 0.5);
        }
        echo "# new instance lol\n";
        return microtime();
    }
    static function staticLol($cache = false) {
        if ($cache) {
            return MyCache::getInstance()->getOrUpdate('static_lol', 0.5);
        }
        echo "# new static lol\n";
        return microtime();
    }
}

var_dump(globalLol(true));
var_dump(globalLol(true));
sleep(1);
var_dump(globalLol(true));
var_dump(globalLol(true));

var_dump(Pysch::staticLol(true));
var_dump(Pysch::staticLol(true));
sleep(1);
var_dump(Pysch::staticLol(true));
var_dump(Pysch::staticLol(true));

$pysch = new Pysch();
var_dump($pysch->instanceLol(true));
var_dump($pysch->instanceLol(true));
sleep(1);
var_dump($pysch->instanceLol(true));
var_dump($pysch->instanceLol(true));
