diff --git a/plugin/Cache/Objects/CacheDB.php b/plugin/Cache/Objects/CacheDB.php
new file mode 100644
index 000000000000..f877ba23c68a
--- /dev/null
+++ b/plugin/Cache/Objects/CacheDB.php
@@ -0,0 +1,84 @@
+id = intval($id);
+ }
+
+ function setName($name) {
+ $this->name = $name;
+ }
+
+
+ function getId() {
+ return intval($this->id);
+ }
+
+ function getName() {
+ return $this->name;
+ }
+
+ public static function insert($name) {
+ $sql = "INSERT IGNORE INTO cache_schedule_delete (name) VALUES (?)";
+ $res = sqlDAL::writeSql($sql, "s", [$name]);
+ if ($res) {
+ return true;
+ } else {
+ error_log("ObjectYPT::insert::Error on save: " . $sql . " Error : " . json_encode($res));
+ return false;
+ }
+ }
+
+}
diff --git a/plugin/Cache/Objects/CachesInDB.php b/plugin/Cache/Objects/CachesInDB.php
new file mode 100644
index 000000000000..17b3d6943097
--- /dev/null
+++ b/plugin/Cache/Objects/CachesInDB.php
@@ -0,0 +1,434 @@
+id = intval($id);
+ }
+
+ public function setContent($content)
+ {
+ $content = self::encodeContent($content);
+ $this->content = $content;
+ }
+
+ public function setDomain($domain)
+ {
+ $this->domain = $domain;
+ }
+
+ public function setIshttps($ishttps)
+ {
+ $this->ishttps = $ishttps;
+ }
+
+ public function setLoggedType($loggedType)
+ {
+ $this->loggedType = $loggedType;
+ }
+
+ public function setUser_location($user_location)
+ {
+ $this->user_location = $user_location;
+ }
+
+ public function setExpires($expires)
+ {
+ $this->expires = $expires;
+ }
+
+ public function setTimezone($timezone)
+ {
+ $this->timezone = $timezone;
+ }
+
+ public function setName($name)
+ {
+ $this->name = $name;
+ }
+
+ public function getId()
+ {
+ return intval($this->id);
+ }
+
+ public function getContent()
+ {
+ $this->content = self::decodeContent($this->content);
+ return $this->content;
+ }
+
+ public function getDomain()
+ {
+ return $this->domain;
+ }
+
+ public function getIshttps()
+ {
+ return $this->ishttps;
+ }
+
+ public function getLoggedType()
+ {
+ return $this->loggedType;
+ }
+
+ public function getUser_location()
+ {
+ return $this->user_location;
+ }
+
+ public function getExpires()
+ {
+ return $this->expires;
+ }
+
+ public function getTimezone()
+ {
+ return $this->timezone;
+ }
+
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ static function hashName($name){
+ if(preg_match('/^hashName_/', $name)){
+ return $name;
+ }
+ return 'hashName_'.preg_replace('/[^0-9a-z]/i', '_', $name);
+ }
+
+ public static function _getCache($name, $domain, $ishttps, $user_location, $loggedType, $ignoreMetadata=false)
+ {
+ global $global;
+ $name = self::hashName($name);
+ $sql = "SELECT * FROM " . static::getTableName() . " WHERE name = ? ";
+ $formats = 's';
+ $values = [$name];
+ $sql .= " AND ishttps = ? AND domain = ? AND user_location = ? ";
+ $formats = 'siss';
+ $values = [$name, $ishttps, $domain, $user_location];
+ if(empty($ignoreMetadata)){
+ $sql .= " AND loggedType = ? ";
+ $formats .= 's';
+ $values[] = $loggedType;
+ }
+ $sql .= " ORDER BY id DESC LIMIT 1";
+
+ //var_dump($sql, $formats, $values );
+ //_error_log(json_encode(array($sql, $values )));
+ // I had to add this because the about from customize plugin was not loading on the about page http://127.0.0.1/AVideo/about
+ $res = sqlDAL::readSql($sql, $formats, $values);
+ $data = sqlDAL::fetchAssoc($res);
+ //var_dump( $data);
+ sqlDAL::close($res);
+ if ($res) {
+ if (!empty($data) && !empty($data['content'])) {
+ $originalContent = $data['content'];
+ $data['content'] = self::decodeContent($data['content']);
+ //var_dump($originalContent );
+ //var_dump($data['content']);
+ if($data['content'] === null){
+ _error_log("Fail decode content [{$name}]".$originalContent);
+ //_error_log(json_encode(debug_backtrace()));exit;
+ //var_dump(debug_backtrace());exit;
+ //var_dump("Fail decode content [{$name}]", $originalContent);exit;
+ }
+ }
+ $row = $data;
+ } else {
+ if (empty($global['mysqli'])) {
+ $global['mysqli'] = new stdClass();
+ }
+ if($global['mysqli']->errno == 1146){
+ $error = array($global['mysqli']->error);
+ $file = $global['systemRootPath'] . 'plugin/Cache/install/install.sql';
+ sqlDal::executeFile($file);
+ if (!static::isTableInstalled()) {
+ $error[] = $global['mysqli']->error;
+ die("We could not create table ".static::getTableName().'
'.implode('
', $error));
+ }
+ }
+ $row = false;
+ }
+ //var_dump($row);
+ return $row;
+ }
+
+ public static function _setCache($name, $value, $domain, $ishttps, $user_location, $loggedType)
+ {
+ if (!is_string($value)) {
+ $value = _json_encode($value);
+ }
+ if (empty($value)) {
+ return false;
+ }
+
+ $row = self::_getCache($name, $domain, $ishttps, $user_location, $loggedType);
+ if (!empty($row)) {
+ $c = new CachesInDB($row['id']);
+ } else {
+ $c = new CachesInDB(0);
+ }
+
+ $name = self::hashName($name);
+ $c->setContent($value);
+ $c->setName($name);
+ $c->setDomain($domain);
+ $c->setIshttps($ishttps);
+ $c->setUser_location($user_location);
+ $c->setLoggedType($loggedType);
+ $c->setExpires(date('Y-m-d H:i:s', strtotime('+ 1 month')));
+ return $c->save();
+ }
+ private static function prepareCacheItem($name, $cache, $metadata, $tz, $time) {
+ $formattedCacheItem = [];
+
+ $name = self::hashName($name);
+ $content = !is_string($cache) ? json_encode($cache) : $cache;
+ if (empty($content)) {
+ return null;
+ }
+
+ $expires = date('Y-m-d H:i:s', strtotime('+1 month'));
+
+ // Format for the prepared statement
+ $formattedCacheItem['format'] = "ssssssssi";
+ $formattedCacheItem['values'] = [
+ $name,
+ $content,
+ $metadata['domain'],
+ $metadata['ishttps'],
+ $metadata['user_location'],
+ $metadata['loggedType'],
+ $expires,
+ $tz,
+ $time
+ ];
+
+ return $formattedCacheItem;
+ }
+
+ public static function setBulkCache($cacheArray, $metadata, $batchSize = 50) {
+ if(isBot()){
+ return false;
+ }
+ if (empty($cacheArray)) {
+ return false;
+ }
+
+ global $global;
+ $cacheBatches = array_chunk($cacheArray, $batchSize, true);
+ $tz = date_default_timezone_get();
+ $time = time();
+ $result = true;
+
+ foreach ($cacheBatches as $batch) {$placeholders = [];
+ $formats = [];
+ $values = [];
+
+ foreach ($batch as $name => $cache) {
+ $cacheItem = self::prepareCacheItem($name, $cache, $metadata, $tz, $time);
+ if ($cacheItem === null) continue;
+
+ $placeholders[] = "(?, ?, ?, ?, ?, ?, ?, ?, ?, NOW(), NOW())";
+ $formats[] = $cacheItem['format'];
+ $values = array_merge($values, $cacheItem['values']);
+ }
+
+ $sql = "INSERT INTO " . static::getTableName() . " (name, content, domain, ishttps, user_location, loggedType, expires, timezone, created_php_time, created, modified)
+ VALUES " . implode(", ", $placeholders) . "
+ ON DUPLICATE KEY UPDATE
+ content = VALUES(content),
+ expires = VALUES(expires),
+ created_php_time = VALUES(created_php_time),
+ modified = NOW()";
+
+ // Start transaction
+ mysqlBeginTransaction();
+
+ try {
+ $res = sqlDAL::writeSql($sql, implode('', $formats), $values);
+ $result &= $res;
+ mysqlCommit();
+ } catch (\Throwable $th) {
+ mysqlRollback();
+ _error_log($th->getMessage() . " name={$name} ".$sql, AVideoLog::$ERROR);
+ //return false;
+ }
+ }
+
+ return $result;
+ }
+
+ public static function readUncomited($uncomited=true)
+ {
+ if($uncomited){
+ $sql = "SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;";
+ }else{
+ $sql = "SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;";
+ }
+ return sqlDAL::writeSql($sql);
+ }
+
+ public static function _deleteCache($name)
+ {
+ if(isBot()){
+ return false;
+ }
+ global $global;
+ if (empty($name)) {
+ return false;
+ }
+
+ if (!static::isTableInstalled()) {
+ return false;
+ }
+ $name = self::hashName($name);
+ self::set_innodb_lock_wait_timeout();
+ $sql = "DELETE FROM " . static::getTableName() . " ";
+ $sql .= " WHERE name = ?";
+ $global['lastQuery'] = $sql;
+ //_error_log("Delete Query: ".$sql);
+ self::readUncomited();
+ $return = sqlDAL::writeSql($sql, "s", [$name]);
+ self::readUncomited(false);
+ return $return;
+ }
+ public static function set_innodb_lock_wait_timeout($timeout = 10)
+ {
+ global $global;
+ $sql = "SET SESSION innodb_lock_wait_timeout = {$timeout};";
+ /**
+ *
+ * @var array $global
+ * @var object $global['mysqli']
+ */
+ return $global['mysqli']->query($sql);
+ }
+
+ public static function _deleteCacheStartingWith($name)
+ {
+ if(isBot() && !preg_match('/plugin\/Live\/on_/', $_SERVER['SCRIPT_NAME'])){
+ _error_log("CachesInDB::_deleteCacheStartingWith($name) error line=".__LINE__);
+ return false;
+ }
+ global $global;
+ if (empty($name)) {
+ _error_log("CachesInDB::_deleteCacheStartingWith($name) error line=".__LINE__);
+ return false;
+ }
+ if (!static::isTableInstalled()) {
+ _error_log("CachesInDB::_deleteCacheStartingWith($name) error line=".__LINE__);
+ return false;
+ }
+ $name = self::hashName($name);
+ self::set_innodb_lock_wait_timeout();
+ //$sql = "DELETE FROM " . static::getTableName() . " WHERE name LIKE '{$name}%'";
+ $sql = "DELETE FROM " . static::getTableName() . " WHERE MATCH(name) AGAINST('{$name}*' IN BOOLEAN MODE) OR name like '{$name}%';";
+
+ _error_log("CachesInDB::_deleteCacheStartingWith($name) $sql");
+ $global['lastQuery'] = $sql;
+ //_error_log("Delete Query: ".$sql);
+ self::readUncomited();
+ $return = sqlDAL::writeSql($sql);
+ self::readUncomited(false);
+ return $return;
+ }
+
+
+ public static function _deleteCacheWith($name)
+ {
+ if(isBot()){
+ return false;
+ }
+ global $global;
+ if (empty($name)) {
+ return false;
+ }
+ if (!static::isTableInstalled()) {
+ return false;
+ }
+ $name = self::hashName($name);
+ $name = str_replace('hashName_', '', $name);
+ self::set_innodb_lock_wait_timeout();
+ $sql = "DELETE FROM " . static::getTableName() . " ";
+ $sql .= " WHERE name LIKE '%{$name}%'";
+ $global['lastQuery'] = $sql;
+ //_error_log("Delete Query: ".$sql);
+ self::readUncomited();
+ $return = sqlDAL::writeSql($sql);
+ self::readUncomited(false);
+ return $return;
+ }
+
+ public static function _deleteAllCache()
+ {
+ if(isBot()){
+ return false;
+ }
+ global $global;
+ if (!static::isTableInstalled()) {
+ return false;
+ }
+ /*
+ $sql = "TRUNCATE TABLE " . static::getTableName() . " ";
+ $global['lastQuery'] = $sql;
+ //_error_log("Delete Query: ".$sql);
+ return sqlDAL::writeSql($sql);
+ */
+ $sql = 'DROP TABLE IF EXISTS `CachesInDB`';
+ sqlDal::writeSql($sql);
+ $file = $global['systemRootPath'] . 'plugin/Cache/install/install.sql';
+ return sqlDal::executeFile($file);
+ }
+
+ public static function encodeContent($content)
+ {
+ $original = $content;
+ if (!is_string($content)) {
+ $content = _json_encode($content);
+ }
+ $prefix = substr($content, 0, 10);
+ if ($prefix!== CacheDB::$prefix) {
+ //$content = base64_encode($content);
+ $content = CacheDB::$prefix.$content;
+ }
+ return $content;
+ }
+
+ public static function decodeContent($content)
+ {
+ $prefix = substr($content, 0, strlen(CacheDB::$prefix));
+ if ($prefix === CacheDB::$prefix) {
+ $content = str_replace(CacheDB::$prefix, '', $content);
+ //$content = base64_decode($content);
+ }
+ return $content;
+ }
+}
diff --git a/plugin/Cache/Objects/CachesInDBMem.php b/plugin/Cache/Objects/CachesInDBMem.php
new file mode 100644
index 000000000000..92064a968fda
--- /dev/null
+++ b/plugin/Cache/Objects/CachesInDBMem.php
@@ -0,0 +1,223 @@
+errno == 1146) {
+ self::tryToCreateTables();
+ }
+ }
+ return false;
+ }
+ public static function setBulkCache($cacheArray, $metadata, $batchSize = 50)
+ {
+ if (empty($cacheArray)) {
+ return false;
+ }
+ $start = microtime(true);
+ foreach ($cacheArray as $name => $cache) {
+ self::_setCache($name, $cache, $metadata['domain'], $metadata['ishttps'], $metadata['user_location'], $metadata['loggedType']);
+ }
+
+ $end = number_format(microtime(true) - $start, 5);
+ //_error_log("Memory setBulkCache took {$end} seconds");
+ return true;
+ }
+
+
+ public static function _setCache($name, $content, $domain, $ishttps, $user_location, $loggedType)
+ {
+ if (!is_string($content)) {
+ $content = _json_encode($content);
+ }
+
+ if (empty($content)){
+ return false;
+ }
+
+ global $global;
+ $time = time();
+ $timezone = date_default_timezone_get();;
+
+ // Preparing SQL for Metadata Insertion
+ $metadataSql = "INSERT INTO " . self::$metadataTable . " (name, domain, ishttps, user_location, loggedType, created, modified, expires, timezone, created_php_time)
+ VALUES (?, ?, ?, ?, ?, NOW(), NOW(), ?, ?, ?)
+ ON DUPLICATE KEY UPDATE
+ expires = VALUES(expires),
+ created_php_time = VALUES(created_php_time),
+ modified = NOW()";
+
+ $contentSqlBase = "INSERT INTO " . self::$contentTable . " (id, content)
+ VALUES (?, ?)
+ ON DUPLICATE KEY UPDATE
+ content = VALUES(content)";
+
+ $name = self::hashName($name);
+
+ $expires = date('Y-m-d H:i:s', strtotime('+1 month'));
+
+ $metadataSqlValues = [$name, $domain, $ishttps, $user_location, $loggedType, $expires, $timezone, $time];
+ /**
+ *
+ * @var array $global
+ * @var object $global['mysqli']
+ */
+
+ // Insert metadata
+ $metadataResult = sqlDAL::writeSql($metadataSql, 'sssssssi', $metadataSqlValues);
+ if ($metadataResult) {
+ $insertedId = @$global['mysqli']->insert_id; // Get the last inserted ID
+ // Insert content
+ if ($insertedId > 0) {
+ return sqlDAL::writeSql($contentSqlBase, 'is', [$insertedId, $content]);
+ } else {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+
+
+ public static function _deleteCache($name)
+ {
+ global $global;
+ if (empty($name)) {
+ return false;
+ }
+
+ if (!static::isTableInstalled(self::$metadataTable)) {
+ return false;
+ }
+ $name = self::hashName($name);
+
+ // Delete from content table
+ $sqlContent = "DELETE FROM " . self::$contentTable . " WHERE id IN (SELECT id FROM " . self::$metadataTable . " WHERE name = ?)";
+ sqlDAL::writeSql($sqlContent, "s", [$name]);
+
+ // Delete from metadata table
+ $sqlMetadata = "DELETE FROM " . self::$metadataTable . " WHERE name = ?";
+ return sqlDAL::writeSql($sqlMetadata, "s", [$name]);
+ }
+ public static function _deleteCacheStartingWith($name)
+ {
+ global $global;
+ if (empty($name)) {
+ return false;
+ }
+
+ if (!static::isTableInstalled(self::$metadataTable)) {
+ return false;
+ }
+ $name = self::hashName($name);
+
+ // Delete from content table
+ $sqlContent = "DELETE FROM " . self::$contentTable . " WHERE id IN (SELECT id FROM " . self::$metadataTable . " WHERE name LIKE '{$name}%')";
+ sqlDAL::writeSql($sqlContent);
+
+ // Delete from metadata table
+ $sqlMetadata = "DELETE FROM " . self::$metadataTable . " WHERE name LIKE '{$name}%'";
+ return sqlDAL::writeSql($sqlMetadata);
+ }
+ public static function _deleteCacheWith($name)
+ {
+ global $global;
+ if (empty($name)) {
+ return false;
+ }
+
+ if (!static::isTableInstalled(self::$metadataTable)) {
+ return false;
+ }
+ $name = self::hashName($name);
+
+ // Delete from content table
+ $sqlContent = "DELETE FROM " . self::$contentTable . " WHERE id IN (SELECT id FROM " . self::$metadataTable . " WHERE name LIKE '%{$name}%')";
+ sqlDAL::writeSql($sqlContent);
+
+ // Delete from metadata table
+ $sqlMetadata = "DELETE FROM " . self::$metadataTable . " WHERE name LIKE '%{$name}%'";
+ return sqlDAL::writeSql($sqlMetadata);
+ }
+ public static function _deleteAllCache()
+ {
+ global $global;
+
+ if (!static::isTableInstalled(self::$metadataTable)) {
+ return false;
+ }
+
+ // Truncate content table
+ $sqlContent = "TRUNCATE TABLE " . self::$contentTable . "";
+ sqlDAL::writeSql($sqlContent);
+
+ // Truncate metadata table
+ $sqlMetadata = "TRUNCATE TABLE " . self::$metadataTable . "";
+ return sqlDAL::writeSql($sqlMetadata);
+ }
+}