Files
EasySoft-ZenTaoPMS/module/cache/model.php
T

396 lines
11 KiB
PHP

<?php
declare(strict_types=1);
/**
* The model file of cache module of ZenTaoPMS.
*
* @copyright Copyright 2009-2024 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.cnezsoft.com)
* @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
* @author Gang Liu <liugang@chandao.com>
* @package cache
* @link https://www.zentao.net
*/
class cacheModel extends model
{
/**
* 缓存的模块。
* The module of cache.
*
* @access private
* @var string
*/
private $module = '';
/**
* 缓存的方法。
* The method of cache.
*
* @access private
* @var string
*/
private $method = ''
/**
* 缓存的键。
* The key of cache.
*
* @access private
* @var string
*/
private $key = '';
/**
* 缓存的值。
* The value of cache.
*
* @access private
* @var int|string|object|array
*/
private $value = '';
/**
* 缓存相关的键。
* The related keys of cache.
*
* @access private
* @var array
*/
private $relatedKeys = [];
/**
* 构造方法。
* Constructor.
*
* @access public
* @return void
*/
public function __construct(): void
{
parent::__construct();
$this->cache = $this->app->loadClass('cache');
}
/**
* 魔术方法,加载子类。
* Magic get method.
*
* @param string $module
* @access public
* @return cacheModel
*/
public function __get(string $module): cacheModel
{
$this->reset();
if(!isset($this->config->cache->keys[$module])) return $this->log("The cache configuration of the module {$module} is not exist.");
$this->setModule($module);
if(isset($this->$module)) return $this;
$file = dirname(__FILE__) . DS . 'handler' . DS . strtolower($module) . '.php';
if(!helper::import($file)) return $this->log("The handler file {$file} is not exist.");
$class = $module . 'Handler';
$this->$module = new $class();
return $this;
}
/**
* 魔术方法,调用子类方法。
* Magic call method.
*
* @param string $method
* @param array $args
* @access public
* @return cacheModel
*/
public function __call(string $method, array $args)
{
if(!isset($this->config->cache->keys[$this->module])) return $this->log('The module is not exist.');
$this->setMethod($method);
$key = "res:{$this->module}:{$method}";
$this->setKey($key);
if(empty($this->$module)) return $this;
if(!method_exists($this->$module, $method)) return $this->log("The method {$method} is not exist.");
$key = call_user_func_array([$this->$module, $method], $args);
$this->setKey($key);
return $this;
}
/**
* 设置缓存的模块。
* Set the module of cache.
*
* @param string $module
* @access private
* @return void
*/
private function setModule(string $module): void
{
$this->module = $module;
}
/**
* 设置缓存的方法。
* Set the method of cache.
*
* @param string $method
* @access private
* @return void
*/
private function setMethod(string $method): void
{
$this->method = $method;
}
/**
* 设置缓存的键。
* Set the key of cache.
*
* @param string $key
* @access private
* @return void
*/
private function setKey(string $key): void
{
$this->key = $key;
}
/**
* 设置缓存的值。
* Set the value of cache.
*
* @param int|string|object|array $value
* @access private
* @return void
*/
private function setValue(int|string|object|array $value): void
{
$this->value = $value;
}
/**
* 设置缓存相关的键。
* Set the related keys of cache.
*
* @param array $relatedKeys
* @access private
* @return void
*/
private function setRelatedKeys(array $relatedKeys): void
{
$this->relatedKeys = $relatedKeys;
}
/**
* 重置缓存相关设置。
* Reset the cache settings.
*
* @access private
* @return void
*/
private function reset(): void
{
$this->setModule('');
$this->setMethod('');
$this->setKey('');
$this->setValue('');
$this->setRelatedKeys([]);
}
/**
* 设置缓存的值。
* Set the value of cache.
*
* @param int|string|object|array $value
* @access public
* @return cacheModel
*/
public function value(int|string|object|array $value): cacheModel
{
if(empty($this->config->cache->keys[$this->module][$this->method]['type'])) return $this->log("The cache configuration of [{$this->module}][{$this->method}] is not exist.");
$config = $this->config->cache->keys[$this->module][$this->method];
$type = $config['type'];
$filter = isset($config['filter']) ? $config['filter'] : '';
if($type == 'int' && !is_int($value)) return $this->log('The value must be int.');
if($type == 'string' && !is_string($value)) return $this->log('The value must be string.');
if($type == 'object' && !is_object($value)) return $this->log('The value must be object.');
if($type == 'array')
{
if(!is_array($value)) return $this->log('The value must be array.');
if($filter != 'encode' && !$this->isIndexedArray($array)) return $this->log('The value must be indexed array.');
}
if($type == 'object' || ($type == 'array' && $filter == 'encode')) $value = json_encode($value);
$this->setValue($value);
return $this;
}
/**
* 设置缓存相关的键。
* Set the related keys of cache.
*
* @param array $relatedKeys
* @access public
* @return cacheModel
*/
public function relatedKeys(array $relatedKeys): cacheModel
{
if(!is_array($relatedKeys)) return $this->log('The relatedKeys must be array.');
if(!$this->isIndexedArray($relatedKeys)) return $this->log('The relatedKeys must be indexed array.');
$this->setRelatedKeys($relatedKeys);
return $this;
}
/**
* 获取缓存。
* Fetch the cache.
*
* @access public
* @return false|int|string|object|array
*/
public function fetch(): bool|int|string|object|array
{
if(empty($this->config->cache->keys[$this->module][$this->method]['type']))
{
$this->log("The cache configuration of [{$this->module}][{$this->method}] is not exist.");
return false;
}
$config = $this->config->cache->keys[$this->module][$this->method];
$type = $config['type'];
$filter = isset($config['filter']) ? $config['filter'] : '';
if($type == 'int') return (int)$this->app->redis->get($this->key);
if($type == 'string') return $this->app->redis->get($this->key);
if($type == 'object') return json_decode($this->app->redis->get($this->key));
if($type == 'array')
{
if($filter == 'encode') return json_decode($this->app->redis->get($this->key));
return $this->app->redis->smembers($this->key);
}
return false;
}
/**
* 保存缓存。
* Save the cache.
*
* @access public
* @return false|int|string|object|array
*/
public function save(): bool|int|string|object|array
{
if(empty($this->value))
{
$this->log('The value is empty.');
return $this->result(false);
}
if(empty($this->config->cache->keys[$this->module][$this->method]['type']))
{
$this->log("The cache configuration of [{$this->module}][{$this->method}] is not exist.");
return $this->result(false);
}
$config = $this->config->cache->keys[$this->module][$this->method];
$type = $config['type'];
$filter = isset($config['filter']) ? $config['filter'] : '';
if($type == 'int') return $this->result($this->app->redis->set($this->key, $this->value));
if($type == 'string') return $this->result($this->app->redis->set($this->key, $this->value));
if($type == 'object') return $this->result($this->app->redis->set($this->key, $this->value));
if($type == 'array')
{
if($filter == 'encode') return $this->result($this->app->redis->set($this->key, $this->value));
return return $this->result($this->app->redis->sadd($this->key, ...$this->value));
}
return $this->result(false);
}
/**
* 返回结果。
* Return the result.
*
* @param bool|int|string|object|array $result
* @access private
* @return bool|int|string|object|array
*/
private function result(bool|int|string|object|array $result): bool|int|string|object|array
{
if($result) $this->updateRelated();
$this->reset();
return $result;
}
/**
* 更新相关的缓存。
* Update the related cache.
*
* @access private
* @return bool
*/
private function updateRelatedKeys(): bool
{
if(empty($this->config->objectTables[$this->module])) return false;
$pairs = [];
$table = $this->config->objectTables[$this->module];
$code = str_replace(['`', $this->config->db->prefix], '', $table);
$object = $this->app->redis->fetchAll($table, $this->relatedKeys);
$key = $this->config->redis->caches[$table];
foreach($objects as $object)
{
$relatedKeys = isset($object->_relatedKeys) ? $object->_relatedKeys : [];
$relatedKeys[] = $this->key;
$object->_relatedKeys = array_unique($relatedKeys);
$pairs["raw:{$code}:{$object->$key}"] = json_encode($object, JSON_UNESCAPED_UNICODE);
}
$this->app->redis->mset($pairs);
return true;
}
/**
* 检查是否为索引数组。
* Check if it is an indexed array.
*
* @param array $array
* @access private
* @return bool
*/
private function isIndexedArray(array $array): bool
{
if(function_exists('array_is_list')) return array_is_list($value);
return $value === array_values($value);
}
/**
* 记录日志。
* Save log.
*
* @param string $message
* @access private
* @return object
*/
private function log(string $message)
{
if($this->config->debug) $this->app->triggerError($message, __FILE__, __LINE__, $this->config->debug >= 2);
return $this;
}
}