multisite = \function_exists('is_multisite') && is_multisite(); $this->blog_prefix = $this->switch_to_blog(get_current_blog_id()); $this->cache_path = $this->fs()->define_cache_path($this->cf()->dcvalue('PATH')); if (\function_exists('is_multisite') && is_multisite()) { $this->cache_path = nwdcx_network_dirpath($this->cache_path); } if ($this->cf()->is_dcint('MAXSIZE', $dcvalue)) { if (!empty($dcvalue)) { $this->cache_maxsize = $this->fs()->sanitize_maxsize($dcvalue); } } if ($this->cf()->is_dcint('MAXTTL', $dcvalue)) { if (!empty($dcvalue)) { $this->cache_maxttl = $this->fs()->sanitize_maxttl($dcvalue); } } $this->network_id = (int) nwdcx_network_id(); $this->max_execution_time = $this->fs()->get_max_execution_time(); } public static function export() { if (!isset(self::$inst)) { self::$inst = new self(); } self::$inst->export_transient(); self::$inst->export_alloptions(); } private function fs() { static $inst; if (!\is_object($inst)) { $inst = new Filesystem(); } return $inst; } private function cf() { static $inst; if (!\is_object($inst)) { $inst = new Constans(); } return $inst; } private function cache_key($key, $group) { if ($this->multisite && 'site-transient' === $group) { $key = $this->blog_prefix.$key; } return $key; } private function item_hash($str, $length = 12) { if (empty($length)) { return md5($str); } return substr(md5($str), 0, $length); } private function get_file_path($key, $group) { $hash_group = $this->item_hash($group); $hash_key = $this->item_hash($key); $index = $hash_group.'-'.$hash_key; if ($this->cf()->is_dcfalse('CHUNKCACHEDIR', true)) { return $this->cache_path.$index.'.php'; } $chunk_path = $this->fs()->get_chunk_path($hash_group, $hash_key); return $this->cache_path.$chunk_path.$index.'.php'; } private function dump_code($file, $arr) { $data = $this->fs()->export_var($arr, $error); if (false === $data) { return false; } $code = $this->fs()->code_stub($data); $stat = $this->fs()->dump($file, $code, false); if (false === $stat) { return false; } if (-1 === $stat) { return false; } $this->fs()->validate_fatal_error_file($file); return $stat; } private function store_cache($key, $data, $group, $expire = 0) { if (!$this->fs()->mkdir_p($this->cache_path)) { return false; } $cache_key = $this->cache_key($key, $group); $file = $this->get_file_path($cache_key, $group); // chunk dir if ($this->cf()->is_dctrue('CHUNKCACHEDIR', true) && !$this->fs()->mkdir_p(\dirname($file))) { return false; } if ($this->fs()->is_transient($group)) { // transient timeout already as timestamp in DB. $timeout = $expire > 0 ? $expire : time() + 3600; } elseif ('options' === $group) { // initial set to 1 hour. $timeout = time() + 3600; } $timeout = $timeout > $this->cache_maxttl ? time() + $this->cache_maxttl : $timeout; $type = \gettype($data); if ('NULL' === $type && null === $data) { $data = ''; } if (!empty($data)) { $len = 0; $nwdcx_suppresserrors = nwdcx_suppresserrors(true); if (\function_exists('maybe_serialize')) { $len = \strlen(@maybe_serialize($data)); } else { $len = \strlen(@serialize($data)); } nwdcx_suppresserrors($nwdcx_suppresserrors); if ($len >= $this->cache_maxsize) { $this->fs()->unlink($file, false); return false; } if ('string' === $type) { $data = nwdcx_unserialize($data); } elseif ('array' === $type) { $data_r = nwdcx_arraymap('nwdcx_unserialize', $data); if (!empty($data_r)) { $data = $data_r; } unset($data_r); } } $meta = []; $meta['timestamp'] = time(); if ($this->multisite) { $meta['network_id'] = $this->network_id; } $final_type = \gettype($data); if ('string' === $final_type && nwdcx_serialized($data)) { $final_type = 'string_serialize'; } elseif ('array' === $final_type) { $nwdcx_suppresserrors = nwdcx_suppresserrors(true); $export_data = @var_export($data, 1); if (!empty($export_data)) { if (false !== strpos($export_data, 'Requests_Utility_CaseInsensitiveDictionary::__set_state')) { $data = @serialize($data); if (nwdcx_serialized($data)) { $final_type = 'array_serialize'; } } if ('array' === $final_type && $this->fs()->is_transient($group) && false !== strpos($export_data, '::__set_state')) { $data = @serialize($data); if (nwdcx_serialized($data)) { $final_type = 'array_serialize'; } } } unset($export_data); nwdcx_suppresserrors($nwdcx_suppresserrors); } $meta['site_id'] = get_current_blog_id(); $meta['group'] = $group; $meta['key'] = $cache_key; $meta['type'] = $final_type; $meta['timeout'] = $timeout; $meta['data'] = $data; if (true === $this->dump_code($file, $meta)) { return true; } return false; } public function export_transient() { if ($this->cf()->is_dctrue('TRANSIENTDB')) { return false; } if (!nwdcx_wpdb($wpdb)) { return false; } $suppress = $wpdb->suppress_errors(true); $collect = []; // $results = $wpdb->get_results('SELECT `option_id`,`option_name`,`option_value` FROM `'.$wpdb->options.'` WHERE `option_name` LIKE "_transient_%" OR `option_name` LIKE "_site_transient_%" ORDER BY `option_id` ASC LIMIT '.$this->qlimit, ARRAY_A); $results = $wpdb->get_results('SELECT `option_id`,`option_name`,`option_value` FROM `'.$wpdb->options.'` WHERE `option_name` RLIKE "^(_site)?(_transient)(_timeout)?_.*?" ORDER BY `option_id` ASC LIMIT '.$this->qlimit, ARRAY_A); if (!empty($results) && \is_array($results)) { while ($row = @array_shift($results)) { if ($this->max_execution_time > 0 && \defined('WP_START_TIMESTAMP') && (microtime(true) - WP_START_TIMESTAMP) > $this->max_execution_time) { $collect = []; break; } // ignore empty value if ('' === $row['option_value']) { continue; } $key = @preg_replace('@^(_site)?(_transient)(_timeout)?_@', '', $row['option_name']); if (!isset($collect[$key])) { $collect[$key] = ['value' => '', 'group' => 'transient', 'timeout' => 0]; } $collect[$key]['value'] = $row['option_value']; if ('_site_' === substr($row['option_name'], 0, 6)) { $collect[$key]['group'] = 'site-transient'; } if (false !== strpos($row['option_name'], '_transient_timeout_')) { $collect[$key]['timeout'] = (int) $row['option_value']; if (time() > $collect[$key]['timeout']) { unset($collect[$key]); } } } if (!empty($collect)) { foreach ($collect as $key => $arr) { if ($this->max_execution_time > 0 && \defined('WP_START_TIMESTAMP') && (microtime(true) - WP_START_TIMESTAMP) > $this->max_execution_time) { break; } $timeout = isset($arr['timeout']) ? $arr['timeout'] : 0; $this->store_cache($key, $arr['value'], $arr['group'], $timeout); } } } $collect = []; if ($this->multisite && isset($wpdb->sitemeta)) { // $results = $wpdb->get_results('SELECT `meta_id`,`meta_key`,`meta_value` FROM `'.$wpdb->sitemeta.'` WHERE `meta_key` LIKE "_site_transient_%" ORDER BY `meta_id` ASC LIMIT '.$this->qlimit, ARRAY_A); $results = $wpdb->get_results('SELECT `meta_id`,`meta_key`,`meta_value` FROM `'.$wpdb->sitemeta.'` WHERE `meta_key` RLIKE "^(_site_transient)(_timeout)?_.*?" ORDER BY `meta_id` ASC LIMIT '.$this->qlimit, ARRAY_A); if (!empty($results) && \is_array($results)) { while ($row = @array_shift($results)) { if ($this->max_execution_time > 0 && \defined('WP_START_TIMESTAMP') && (microtime(true) - WP_START_TIMESTAMP) > $this->max_execution_time) { $collect = []; break; } // ignore empty value if ('' === $row['meta_value']) { continue; } $key = @preg_replace('@^(_site_transient)(_timeout)?_@', '', $row['meta_key']); if (!isset($collect[$key])) { $collect[$key] = ['value' => '', 'group' => 'site-transient', 'timeout' => 0]; } $collect[$key]['value'] = $row['meta_value']; if (false !== strpos($row['meta_key'], '_site_transient_timeout_')) { $collect[$key]['timeout'] = (int) $row['meta_value']; if (time() > $collect[$key]['timeout']) { unset($collect[$key]); } } } if (!empty($collect)) { foreach ($collect as $key => $arr) { $timeout = isset($arr['timeout']) ? $arr['timeout'] : 0; $this->store_cache($key, $arr['value'], $arr['group'], $timeout); } } } } unset($collect, $results); $wpdb->suppress_errors($suppress); return true; } public static function cleanup_transient() { if (nwdcx_construe('TRANSIENTDB')) { return false; } if (\function_exists('nwdcx_cleanuptransient')) { return nwdcx_cleanuptransient(); } return false; } public function export_alloptions() { if (!nwdcx_wpdb($wpdb) || $this->multisite) { return false; } // Only export if autoload=yes and not transient. $suppress = $wpdb->suppress_errors(true); $alloptions_db = $wpdb->get_results('SELECT `option_name`,`option_value` FROM `'.$wpdb->options.'` WHERE autoload = \'yes\' AND `option_name` NOT LIKE "_transient_%" AND `option_name` NOT LIKE "_site_transient_%"', ARRAY_A); if (empty($alloptions_db)) { return false; } $wpdb->suppress_errors($suppress); $alloptions = []; if (\is_array($alloptions_db)) { $is_filter = $this->cf()->is_dctrue('WPOPTALOAD', true); $wp_options = []; if ($is_filter) { $wp_options = $this->fs()->keys_alloptions(); } foreach ($alloptions_db as $num => $options) { if ($this->max_execution_time > 0 && \defined('WP_START_TIMESTAMP') && (microtime(true) - WP_START_TIMESTAMP) > $this->max_execution_time) { $alloptions = []; break; } $key = $options['option_name']; if ($is_filter && \array_key_exists($key, $wp_options)) { continue; } $alloptions[$key] = $options['option_value']; } if (!empty($alloptions)) { $this->store_cache('alloptions', $alloptions, 'options'); } } unset($alloptions, $alloptions_db); // always true return true; } private function switch_to_blog($blog_id) { $blog_id = (int) $blog_id; $this->blog_prefix = $this->multisite ? $blog_id.':' : ''; } }