class SQL_JSON_Cache { private string $cache_dir; private int $cache_ttl; public function __construct() { $this->cache_dir = WP_CONTENT_DIR . '/sql-json-cache/'; $this->cache_ttl = (int)get_option('sql_json_cache_ttl', 3600); if (!file_exists($this->cache_dir)) { wp_mkdir_p($this->cache_dir); } add_filter('posts_request', [$this, 'cache_sql_request'], 10, 2); add_filter('the_posts', [$this, 'retrieve_from_cache'], 10, 2); } private function get_cache_key(string $sql): string { return md5($sql) . '.json'; } private function is_cache_valid(string $cache_file): bool { if (!file_exists($cache_file)) { return false; } $file_time = filemtime($cache_file); return (time() - $file_time) < $this->cache_ttl; } public function cache_sql_request(string $request, WP_Query $query): string { if (!$query->is_main_query() || (!is_single() && !is_page())) { return $request; } return $request; } private function get_post_taxonomies(int $post_id): array { $taxonomies = get_post_taxonomies($post_id); $terms_data = []; foreach ($taxonomies as $taxonomy) { if ($taxonomy !== 'post_format') { $terms = wp_get_post_terms($post_id, $taxonomy); if (!is_wp_error($terms)) { $terms_data[$taxonomy] = array_map(function($term) { return [ 'term_id' => $term->term_id, 'name' => $term->name, 'slug' => $term->slug ]; }, $terms); } } } return $terms_data; } private function get_post_meta_data(int $post_id): array { $meta_data = get_post_meta($post_id); $cleaned_meta = []; $exclude_keys = ['_edit_lock', '_edit_last', '_wp_page_template']; foreach ($meta_data as $key => $value) { if (!in_array($key, $exclude_keys, true)) { $cleaned_meta[$key] = maybe_unserialize($value[0]); if ($key === 'poster' && is_numeric($value[0])) { $cleaned_meta['poster_url'] = wp_get_attachment_url((int)$value[0]); } } } if (has_post_thumbnail($post_id)) { $thumbnail_id = get_post_thumbnail_id($post_id); $cleaned_meta['thumbnail_id'] = $thumbnail_id; $cleaned_meta['thumbnail_url'] = wp_get_attachment_url($thumbnail_id); } return $cleaned_meta; } public function retrieve_from_cache(array $posts, WP_Query $query): array { if (!$query->is_main_query() || (!is_single() && !is_page())) { return $posts; } $sql = $query->request; $cache_key = $this->get_cache_key($sql); $cache_file = $this->cache_dir . $cache_key; if ($this->is_cache_valid($cache_file)) { $cached_data = file_get_contents($cache_file); $cached_content = json_decode($cached_data, true); if ($cached_content && isset($cached_content['posts'])) { $post_objects = []; foreach ($cached_content['posts'] as $post_data) { $post = new WP_Post((object)$post_data['post']); $GLOBALS['posts'][$post->ID] = $post; if (isset($post_data['meta'])) { foreach ($post_data['meta'] as $meta_key => $meta_value) { update_post_meta($post->ID, $meta_key, $meta_value); } } $post_objects[] = $post; } $query->posts = $post_objects; $query->post_count = count($post_objects); $query->post = $post_objects[0]; $query->found_posts = count($post_objects); return $post_objects; } } if (!empty($posts)) { $posts_array = array_map(function($post) { return [ 'post' => $post->to_array(), 'taxonomies' => $this->get_post_taxonomies($post->ID), 'meta' => $this->get_post_meta_data($post->ID) ]; }, $posts); $cache_data = ['posts' => $posts_array]; file_put_contents($cache_file, json_encode($cache_data)); } return $posts; } public function clear_cache(): void { $files = glob($this->cache_dir . '*.json'); if ($files !== false) { foreach ($files as $file) { unlink($file); } } } } function init_sql_json_cache(): void { new SQL_JSON_Cache(); } add_action('init', 'init_sql_json_cache'); function sql_json_cache_admin_menu(): void { add_options_page( 'SQL JSON Cache Settings', 'SQL JSON Cache', 'manage_options', 'sql-json-cache', 'sql_json_cache_admin_page' ); } add_action('admin_menu', 'sql_json_cache_admin_menu'); function sql_json_cache_admin_page(): void { if (isset($_POST['sql_json_cache_settings']) && check_admin_referer('sql_json_cache_settings')) { $ttl = (int)$_POST['cache_ttl']; update_option('sql_json_cache_ttl', $ttl); echo '
Settings saved successfully!
Cache cleared successfully!