zira/zira/cache.php

209 lines
6.1 KiB
PHP
Raw Normal View History

2016-06-02 14:42:43 +02:00
<?php
/**
* Zira project
* cache.php
2019-10-09 15:27:31 +02:00
* (c)2015 https://github.com/ziracms/zira
2016-06-02 14:42:43 +02:00
*/
namespace Zira;
class Cache {
2017-12-03 19:46:24 +01:00
const LOCK_FILE = 'lock';
protected static $_lock_handler;
2017-12-05 16:47:37 +01:00
protected static $_on_clear_callbacks = array();
protected static $_on_force_clear_callbacks = array();
2017-12-03 19:46:24 +01:00
2017-12-04 01:29:19 +01:00
public static function isLockFile($file) {
return $file == '.' . self::LOCK_FILE . '.cache';
}
2016-06-02 14:42:43 +02:00
public static function set($key, $data, $serialize=false) {
if (!Config::get('caching')) return false;
2017-12-03 19:46:24 +01:00
if (!self::lock(true)) return false;
2016-06-02 14:42:43 +02:00
if ($serialize) {
$data = serialize($data);
}
$cache_file = ROOT_DIR . DIRECTORY_SEPARATOR .
CACHE_DIR . DIRECTORY_SEPARATOR .
'.' . $key . '.cache';
2017-12-03 19:46:24 +01:00
if (file_exists($cache_file)) @chmod($cache_file, 0660);
2016-06-02 14:42:43 +02:00
2017-12-03 14:10:43 +01:00
$f=@fopen($cache_file,'wb');
2017-12-04 12:01:55 +01:00
if (!$f) {
self::unlock();
return false;
}
2016-06-02 14:42:43 +02:00
fwrite($f, $data);
fclose($f);
2017-12-03 19:46:24 +01:00
//@chmod($cache_file, 0000);
self::unlock();
2016-06-02 14:42:43 +02:00
return true;
}
public static function setArray($key, $data) {
return self::set($key, $data, true);
}
public static function setObject($key, $data) {
return self::set($key, $data, true);
}
protected static function isExpired($cache_file) {
2017-12-04 15:22:11 +01:00
$mtime = @filemtime($cache_file);
2017-12-04 01:29:19 +01:00
if (!$mtime) return true;
2016-06-02 14:42:43 +02:00
return (time()-$mtime>Config::get('cache_lifetime'));
}
public static function get($key, $unserialize = false) {
if (!Config::get('caching')) return false;
2017-12-03 19:46:24 +01:00
if (!self::lock()) return false;
2016-06-02 14:42:43 +02:00
$cache_file = ROOT_DIR . DIRECTORY_SEPARATOR .
CACHE_DIR . DIRECTORY_SEPARATOR .
'.' . $key . '.cache';
2017-12-04 12:01:55 +01:00
if (!file_exists($cache_file) ||
self::isExpired($cache_file)
) {
self::unlock();
return false;
}
2016-06-02 14:42:43 +02:00
2017-12-04 12:01:55 +01:00
@chmod($cache_file, 0440);
2017-12-03 14:10:43 +01:00
$data = @file_get_contents($cache_file);
2017-12-03 19:46:24 +01:00
//@chmod($cache_file, 0000);
2017-12-03 14:10:43 +01:00
2017-12-04 12:01:55 +01:00
if (empty($data)) {
self::unlock();
return false;
}
2016-06-02 14:42:43 +02:00
if ($unserialize) {
$data = unserialize($data);
}
2017-12-03 19:46:24 +01:00
self::unlock();
2016-06-02 14:42:43 +02:00
return $data;
}
2017-12-03 23:48:16 +01:00
public static function lock($write=false,$block=false) {
2017-12-03 19:46:24 +01:00
$cache_file = ROOT_DIR . DIRECTORY_SEPARATOR .
CACHE_DIR . DIRECTORY_SEPARATOR .
'.' . self::LOCK_FILE . '.cache';
self::$_lock_handler=@fopen($cache_file,'wb');
2017-12-04 12:01:55 +01:00
if (!self::$_lock_handler) return false;
2017-12-03 19:46:24 +01:00
2017-12-03 23:48:16 +01:00
if (!$block) {
$lock = $write ? (LOCK_EX | LOCK_NB) : (LOCK_SH | LOCK_NB);
} else {
$lock = $write ? LOCK_EX : LOCK_SH;
}
2017-12-03 19:46:24 +01:00
return flock(self::$_lock_handler, $lock);
}
public static function unlock() {
$cache_file = ROOT_DIR . DIRECTORY_SEPARATOR .
CACHE_DIR . DIRECTORY_SEPARATOR .
'.' . self::LOCK_FILE . '.cache';
if (!file_exists($cache_file)) return false;
if (!self::$_lock_handler) return false;
$result = flock(self::$_lock_handler, LOCK_UN);
fclose(self::$_lock_handler);
return $result;
}
2016-06-02 14:42:43 +02:00
public static function getArray($key) {
return self::get($key, true);
}
public static function getObject($key) {
return self::get($key, true);
}
public static function clear($force=false) {
2017-12-04 12:01:55 +01:00
if (!Config::get('caching') && !$force) return false;
if (!self::lock(true, true)) return false;
if ($force && !Assets::lock(true, true)) {
self::unlock();
return false;
}
2017-12-03 14:10:43 +01:00
$d = @opendir(ROOT_DIR . DIRECTORY_SEPARATOR . CACHE_DIR);
2017-12-04 12:01:55 +01:00
if (!$d) {
self::unlock();
if ($force) Assets::unlock();
return false;
}
2016-06-02 14:42:43 +02:00
while(($f=readdir($d))!==false) {
if ($f=='.' || $f=='..' || !is_file(ROOT_DIR . DIRECTORY_SEPARATOR . CACHE_DIR . DIRECTORY_SEPARATOR . $f)) continue;
if (substr($f,-6)!='.cache') continue;
2017-12-04 01:29:19 +01:00
if (self::isLockFile($f) || Assets::isAssetsLockFile($f)) continue;
if (!$force && Assets::isAssetsCacheFile($f)) continue;
2016-06-02 14:42:43 +02:00
@chmod(ROOT_DIR . DIRECTORY_SEPARATOR . CACHE_DIR . DIRECTORY_SEPARATOR . $f, 0660);
@unlink(ROOT_DIR . DIRECTORY_SEPARATOR . CACHE_DIR . DIRECTORY_SEPARATOR . $f);
}
closedir($d);
2017-12-04 01:29:19 +01:00
if (Config::get('caching') && $force) {
2017-12-05 16:47:37 +01:00
self::_execOnForceClearCallbacks();
2017-12-03 23:48:16 +01:00
Assets::merge(false);
Assets::mergeCSSContent(false);
Assets::mergeJSContent(false);
}
2017-12-05 22:51:37 +01:00
if (Config::get('caching')) {
self::_execOnClearCallbacks();
}
2017-12-03 23:48:16 +01:00
self::unlock();
2017-12-04 01:29:19 +01:00
if ($force) Assets::unlock();
2017-12-04 12:01:55 +01:00
return true;
2016-06-02 14:42:43 +02:00
}
2017-12-05 16:47:37 +01:00
public static function addOnClearCallback($object, $method, $module='zira') {
self::$_on_clear_callbacks[$module] = array($object, $method);
2017-12-05 16:47:37 +01:00
}
public static function addOnForceClearCallback($object, $method, $module='zira') {
self::$_on_force_clear_callbacks[$module] = array($object, $method);
}
public static function removeOnClearCallback($module) {
self::$_on_clear_callbacks[$module] = null;
}
public static function removeOnForceClearCallback($module) {
self::$_on_force_clear_callbacks[$module] = null;
2017-12-05 16:47:37 +01:00
}
protected static function _execOnClearCallbacks() {
foreach(self::$_on_clear_callbacks as $module=>$callable) {
if (!$callable || !is_callable($callable)) continue;
2017-12-05 16:47:37 +01:00
try {
call_user_func($callable);
} catch(\Exception $e) {
// ignore
}
}
}
protected static function _execOnForceClearCallbacks() {
foreach(self::$_on_force_clear_callbacks as $module=>$callable) {
if (!$callable || !is_callable($callable)) continue;
2017-12-05 16:47:37 +01:00
try {
call_user_func($callable);
} catch(\Exception $e) {
// ignore
}
}
}
2016-06-02 14:42:43 +02:00
}