From a5ca5964c7eaa9a2039d96f655852580c7d1fa6b Mon Sep 17 00:00:00 2001 From: Imants Date: Mon, 25 May 2026 12:34:05 +0300 Subject: [PATCH 01/11] fix: replace raw SQL transient sweep with version-counter cache invalidation --- src/php/Client/Cloud_API.php | 131 +++++++++++++---------------------- src/php/Core/Uninstaller.php | 1 + 2 files changed, 48 insertions(+), 84 deletions(-) diff --git a/src/php/Client/Cloud_API.php b/src/php/Client/Cloud_API.php index 3ca6d078e..39447d1c8 100644 --- a/src/php/Client/Cloud_API.php +++ b/src/php/Client/Cloud_API.php @@ -359,17 +359,15 @@ public function update_snippet_from_cloud( Cloud_Snippet $snippet_to_store ): ar } /** - * Transient key for cached cloud types (languages). - */ - private const TYPES_TRANSIENT_KEY = 'cs_cloud_types'; - - /** - * Transient key for cached cloud categories. + * Option key holding the current featured-snippets cache version. + * + * Bumped on flush so old transient keys become unreachable and expire naturally, + * which avoids needing a raw SQL sweep across the options table. */ - private const CATEGORIES_TRANSIENT_KEY = 'cs_cloud_categories'; + private const FEATURED_VERSION_OPTION = 'cs_featured_cache_version'; /** - * Transient key for cached featured snippets. + * Base transient key for cached featured snippets. */ private const FEATURED_TRANSIENT_KEY = 'cs_featured_snippets'; @@ -378,6 +376,40 @@ public function update_snippet_from_cloud( Cloud_Snippet $snippet_to_store ): ar */ private const FEATURED_MIN_TTL = 3600; + /** + * Get the current featured-snippets cache version, initialising it if absent. + * + * @return int + */ + private static function get_featured_cache_version(): int { + $version = (int) get_option( self::FEATURED_VERSION_OPTION, 0 ); + + if ( $version <= 0 ) { + $version = 1; + update_option( self::FEATURED_VERSION_OPTION, $version, false ); + } + + return $version; + } + + /** + * Build the transient key for a specific (version, page, per_page, filters) slot. + * + * @param int $page Page number (1-indexed). + * @param int $per_page Results per page. + * @param array $filters Filter values. + * + * @return string + */ + private static function build_featured_cache_key( int $page, int $per_page, array $filters ): string { + $active_filters = array_filter( $filters ); + $encoded = wp_json_encode( $active_filters ); + $filter_hash = md5( false === $encoded ? '' : $encoded ); + $version = self::get_featured_cache_version(); + + return self::FEATURED_TRANSIENT_KEY . "_v{$version}_p{$page}_pp{$per_page}_{$filter_hash}"; + } + /** * Retrieve featured snippets from the cloud API, with transient caching. * @@ -389,9 +421,7 @@ public function update_snippet_from_cloud( Cloud_Snippet $snippet_to_store ): ar */ public static function get_featured_snippets( int $page = 1, int $per_page = 10, array $filters = [] ): Cloud_Snippets { $per_page = min( self::MAX_RESULTS_PER_PAGE, max( 1, $per_page ) ); - $encoded = wp_json_encode( $filters ); - $filter_hash = md5( false === $encoded ? '' : $encoded ); - $cache_key = self::FEATURED_TRANSIENT_KEY . "_p{$page}_pp{$per_page}_{$filter_hash}"; + $cache_key = self::build_featured_cache_key( $page, $per_page, $filters ); $cached = get_transient( $cache_key ); @@ -445,89 +475,22 @@ public static function get_featured_snippets( int $page = 1, int $per_page = 10, return $result; } - /** - * Retrieve available snippet types (languages) from the cloud API, with transient caching. - * - * @return array List of types. - */ - public static function get_cloud_types(): array { - $cached = get_transient( self::TYPES_TRANSIENT_KEY ); - - if ( is_array( $cached ) ) { - return $cached; - } - - $url = self::get_cloud_api_url() . 'public/types'; - $response = wp_remote_get( $url ); - - if ( is_wp_error( $response ) ) { - return []; - } - - $json = self::unpack_request_json( $response ); - - if ( ! is_array( $json ) || ! isset( $json['data'] ) ) { - return []; - } - - $types = $json['data']; - set_transient( self::TYPES_TRANSIENT_KEY, $types, DAY_IN_SECONDS ); - - return $types; - } - - /** - * Retrieve available snippet categories from the cloud API, with transient caching. - * - * @return array List of categories. - */ - public static function get_cloud_categories(): array { - $cached = get_transient( self::CATEGORIES_TRANSIENT_KEY ); - - if ( is_array( $cached ) ) { - return $cached; - } - - $url = self::get_cloud_api_url() . 'public/categories'; - $response = wp_remote_get( $url ); - - if ( is_wp_error( $response ) ) { - return []; - } - - $json = self::unpack_request_json( $response ); - - if ( ! is_array( $json ) || ! isset( $json['data'] ) ) { - return []; - } - - $categories = $json['data']; - set_transient( self::CATEGORIES_TRANSIENT_KEY, $categories, DAY_IN_SECONDS ); - - return $categories; - } - /** * Refresh the cached synced data. * + * Bumps the featured-cache version counter instead of issuing a raw SQL sweep + * across the options table: previously cached keys become unreachable and are + * cleaned up by WordPress's normal transient-expiry path. + * * @return void */ public function clear_caches() { - global $wpdb; - $this->cached_cloud_links = null; delete_transient( self::CLOUD_MAP_TRANSIENT_KEY ); - delete_transient( self::TYPES_TRANSIENT_KEY ); - delete_transient( self::CATEGORIES_TRANSIENT_KEY ); delete_transient( 'cs_codevault_snippets' ); - $wpdb->query( - $wpdb->prepare( - "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s OR option_name LIKE %s", - $wpdb->esc_like( '_transient_' . self::FEATURED_TRANSIENT_KEY ) . '%', - $wpdb->esc_like( '_transient_timeout_' . self::FEATURED_TRANSIENT_KEY ) . '%' - ) - ); + $version = self::get_featured_cache_version(); + update_option( self::FEATURED_VERSION_OPTION, $version + 1, false ); } } diff --git a/src/php/Core/Uninstaller.php b/src/php/Core/Uninstaller.php index be32773f5..782c1efcd 100644 --- a/src/php/Core/Uninstaller.php +++ b/src/php/Core/Uninstaller.php @@ -72,6 +72,7 @@ private function uninstall_current_site() { delete_option( 'code_snippets_settings' ); delete_option( 'code_snippets_cloud_settings' ); + delete_option( 'cs_featured_cache_version' ); delete_transient( 'cs_codevault_snippets' ); delete_transient( 'cs_local_to_cloud_map' ); } From 64bd8066dae6fa3c8ce531054ea59f2710deb551 Mon Sep 17 00:00:00 2001 From: Imants Date: Tue, 26 May 2026 18:00:20 +0300 Subject: [PATCH 02/11] fix: drop unused cloud types and categories endpoints, fix filter arg docstrings --- .../Cloud/Cloud_Snippets_REST_Controller.php | 51 +++---------------- 1 file changed, 6 insertions(+), 45 deletions(-) diff --git a/src/php/REST_API/Cloud/Cloud_Snippets_REST_Controller.php b/src/php/REST_API/Cloud/Cloud_Snippets_REST_Controller.php index 79f699d96..b1d5afce0 100644 --- a/src/php/REST_API/Cloud/Cloud_Snippets_REST_Controller.php +++ b/src/php/REST_API/Cloud/Cloud_Snippets_REST_Controller.php @@ -32,22 +32,25 @@ final class Cloud_Snippets_REST_Controller extends Cloud_Collection_REST_Control /** * Common filter args shared across search and featured endpoints. * + * Each filter accepts a single numeric ID (e.g. category=12). The cloud API + * resolves IDs to the underlying name/slug. + * * @return array> */ private function get_filter_args(): array { return [ 'category' => [ - 'description' => esc_html__( 'Filter by category name (comma-separated).', 'code-snippets' ), + 'description' => esc_html__( 'Filter by category ID.', 'code-snippets' ), 'type' => 'string', 'default' => '', ], 'type' => [ - 'description' => esc_html__( 'Filter by language/type name (comma-separated).', 'code-snippets' ), + 'description' => esc_html__( 'Filter by language/type ID.', 'code-snippets' ), 'type' => 'string', 'default' => '', ], 'status' => [ - 'description' => esc_html__( 'Filter by status ID (comma-separated).', 'code-snippets' ), + 'description' => esc_html__( 'Filter by status ID.', 'code-snippets' ), 'type' => 'string', 'default' => '', ], @@ -155,30 +158,6 @@ public function register_routes() { ] ); - register_rest_route( - $this->namespace, - $this->rest_base . '/types', - [ - [ - 'methods' => WP_REST_Server::READABLE, - 'callback' => [ $this, 'get_types' ], - 'permission_callback' => [ $this, 'get_items_permissions_check' ], - ], - ] - ); - - register_rest_route( - $this->namespace, - $this->rest_base . '/categories', - [ - [ - 'methods' => WP_REST_Server::READABLE, - 'callback' => [ $this, 'get_categories' ], - 'permission_callback' => [ $this, 'get_items_permissions_check' ], - ], - ] - ); - register_rest_route( $this->namespace, $this->rest_base . '/(?P\d+)/download', @@ -239,24 +218,6 @@ public function get_featured_items( WP_REST_Request $request ): WP_REST_Response return $cloud_snippets->to_rest_response(); } - /** - * Retrieve available snippet types (languages) from the cloud API. - * - * @return WP_REST_Response - */ - public function get_types(): WP_REST_Response { - return rest_ensure_response( Cloud_API::get_cloud_types() ); - } - - /** - * Retrieve available snippet categories from the cloud API. - * - * @return WP_REST_Response - */ - public function get_categories(): WP_REST_Response { - return rest_ensure_response( Cloud_API::get_cloud_categories() ); - } - /** * Get the user's snippets per-page preference for Screen Options pagination. * From 95a9c465e31d9a2f1c19fccedf0a4fa231b4c7bb Mon Sep 17 00:00:00 2001 From: Imants Date: Mon, 25 May 2026 12:34:44 +0300 Subject: [PATCH 03/11] fix: align community featured e2e selectors with rendered cloud-snippets-heading class --- tests/e2e/code-snippets-community-featured.spec.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/e2e/code-snippets-community-featured.spec.ts b/tests/e2e/code-snippets-community-featured.spec.ts index a0d3ade5e..53b4663aa 100644 --- a/tests/e2e/code-snippets-community-featured.spec.ts +++ b/tests/e2e/code-snippets-community-featured.spec.ts @@ -31,14 +31,13 @@ test.describe('Community Cloud Featured Snippets', () => { .waitFor({ state: 'hidden', timeout: TIMEOUTS.DEFAULT }) .catch(() => undefined) - const featuredHeading = page.locator('.cloud-featured-heading') + const featuredHeading = page.locator('.cloud-snippets-heading', { hasText: 'Featured Snippets' }) const headingVisible = await featuredHeading .waitFor({ state: 'visible', timeout: TIMEOUTS.SHORT }) .then(() => true) .catch(() => false) if (headingVisible) { - // Featured snippets loaded — verify the heading text. await expect(featuredHeading).toContainText('Featured Snippets') } else { // Cloud API unreachable — verify no crash: the search form is still functional. @@ -64,7 +63,7 @@ test.describe('Community Cloud Featured Snippets', () => { .waitFor({ state: 'hidden', timeout: TIMEOUTS.DEFAULT }) .catch(() => undefined) - // The "Featured Snippets" heading should no longer be visible. - await expect(page.locator('.cloud-featured-heading')).not.toBeVisible() + // The "Featured Snippets" heading should no longer be visible (search-mode heading replaces it). + await expect(page.locator('.cloud-snippets-heading', { hasText: 'Featured Snippets' })).not.toBeVisible() }) }) From 5ea205f5e3d17021b7265699ef2ea0c46054a69c Mon Sep 17 00:00:00 2001 From: Imants Date: Mon, 25 May 2026 12:34:53 +0300 Subject: [PATCH 04/11] fix: update featured cache tests to align with versioned transient key --- tests/phpunit/test-cloud-api-featured.php | 44 +++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/tests/phpunit/test-cloud-api-featured.php b/tests/phpunit/test-cloud-api-featured.php index bf6531033..e54405461 100644 --- a/tests/phpunit/test-cloud-api-featured.php +++ b/tests/phpunit/test-cloud-api-featured.php @@ -63,9 +63,12 @@ public function tear_down() { * @return string */ private function transient_key( int $page = 1, int $per_page = 10, array $filters = [] ): string { - $encoded = wp_json_encode( $filters ); + $active_filters = array_filter( $filters ); + $encoded = wp_json_encode( $active_filters ); $hash = md5( false === $encoded ? '' : $encoded ); - return "cs_featured_snippets_p{$page}_pp{$per_page}_{$hash}"; + $version = (int) get_option( 'cs_featured_cache_version', 1 ); + $version = $version > 0 ? $version : 1; + return "cs_featured_snippets_v{$version}_p{$page}_pp{$per_page}_{$hash}"; } /** @@ -75,6 +78,7 @@ private function transient_key( int $page = 1, int $per_page = 10, array $filter */ private function clear_featured_transients(): void { delete_transient( $this->transient_key() ); + delete_option( 'cs_featured_cache_version' ); } /** @@ -340,4 +344,40 @@ public function test_available_filters_preserved(): void { $this->assertArrayHasKey( 'types', $result->available_filters ); $this->assertArrayHasKey( 'statuses', $result->available_filters ); } + + /** + * Calling clear_caches() causes the next get_featured_snippets() to miss cache and re-fetch. + * + * @return void + */ + public function test_clear_caches_invalidates_featured_cache(): void { + Cloud_API::get_featured_snippets(); + $this->assertSame( 1, $this->http_request_count ); + + $api = new Cloud_API(); + $api->clear_caches(); + + Cloud_API::get_featured_snippets(); + $this->assertSame( 2, $this->http_request_count, 'Expected a fresh HTTP request after cache invalidation.' ); + } + + /** + * Empty filter values produce the same cache key as omitted filters. + * + * @return void + */ + public function test_empty_filters_produce_same_cache_key(): void { + $key_empty = $this->transient_key( + 1, + 10, + [ + 'category' => '', + 'type' => '', + 'status' => '', + ] + ); + $key_none = $this->transient_key( 1, 10, [] ); + + $this->assertSame( $key_none, $key_empty, 'Empty filter values should hash identically to no filters.' ); + } } From 2f6748e30912556ccd32f9dc06922da34ff40295 Mon Sep 17 00:00:00 2001 From: Imants Date: Mon, 25 May 2026 12:35:21 +0300 Subject: [PATCH 05/11] fix: correct Cloud_Snippets docblock types and remove dead success property --- src/php/Model/Cloud_Snippets.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/php/Model/Cloud_Snippets.php b/src/php/Model/Cloud_Snippets.php index 97d660377..301e383f3 100644 --- a/src/php/Model/Cloud_Snippets.php +++ b/src/php/Model/Cloud_Snippets.php @@ -15,7 +15,6 @@ * @property int $total_pages Total number of available pages of items. * @property int $total_snippets Total number of available snippet items. * @property array $cloud_id_rev An array of all cloud snippet IDs and their revision numbers. - * @property bool $success If the request has any results. * @property array $available_filters An array of available filters that can be applied to the collection. */ class Cloud_Snippets extends Model { @@ -50,7 +49,7 @@ class Cloud_Snippets extends Model { /** * Class constructor. * - * @param Cloud_Snippet $initial_data Initial data. + * @param array|null $initial_data Initial data from the cloud API response. */ public function __construct( $initial_data = null ) { parent::__construct( $this->normalize_cloud_api( $initial_data ) ); @@ -103,7 +102,6 @@ protected function prepare_snippets( $snippets ): array { * @return mixed Normalized data array or original value when no normalization is required. */ private function normalize_cloud_api( $initial_data ) { - // pagination metadata is nested under a 'meta' key. if ( is_array( $initial_data ) && isset( $initial_data['meta'] ) ) { $meta = $initial_data['meta']; $normalized = []; From b7de35369e8f90cae4e5e79dc7b35e9936fd0333 Mon Sep 17 00:00:00 2001 From: Imants Date: Mon, 25 May 2026 12:35:39 +0300 Subject: [PATCH 06/11] fix: remove dead connectCloud type from Window interface --- src/js/types/Window.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/js/types/Window.ts b/src/js/types/Window.ts index ad58b119a..001293444 100644 --- a/src/js/types/Window.ts +++ b/src/js/types/Window.ts @@ -43,7 +43,6 @@ declare global { welcome: string settings: string cloud: string - connectCloud: string } banner: { key: string From 2773607b49b0d9ef52bf6286c6de8e0482ff1302 Mon Sep 17 00:00:00 2001 From: Imants Date: Mon, 25 May 2026 14:21:19 +0300 Subject: [PATCH 07/11] fix: clean up agent-context docblocks and add missing available_filters property --- src/php/Client/Cloud_API.php | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/php/Client/Cloud_API.php b/src/php/Client/Cloud_API.php index 39447d1c8..34c8addc9 100644 --- a/src/php/Client/Cloud_API.php +++ b/src/php/Client/Cloud_API.php @@ -361,8 +361,7 @@ public function update_snippet_from_cloud( Cloud_Snippet $snippet_to_store ): ar /** * Option key holding the current featured-snippets cache version. * - * Bumped on flush so old transient keys become unreachable and expire naturally, - * which avoids needing a raw SQL sweep across the options table. + * Bumped on flush so old transient keys become unreachable and expire naturally. */ private const FEATURED_VERSION_OPTION = 'cs_featured_cache_version'; @@ -478,9 +477,8 @@ public static function get_featured_snippets( int $page = 1, int $per_page = 10, /** * Refresh the cached synced data. * - * Bumps the featured-cache version counter instead of issuing a raw SQL sweep - * across the options table: previously cached keys become unreachable and are - * cleaned up by WordPress's normal transient-expiry path. + * Bumps the featured-cache version counter so previously cached keys + * become unreachable and expire via WordPress's normal transient path. * * @return void */ From 7e2cb9b827e105ab4e8e3202ad537c7c03794962 Mon Sep 17 00:00:00 2001 From: Imants Date: Mon, 25 May 2026 14:26:01 +0300 Subject: [PATCH 08/11] fix: reference FEATURED_VERSION_OPTION constant from Uninstaller instead of string literal --- src/php/Client/Cloud_API.php | 2 +- src/php/Core/Uninstaller.php | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/php/Client/Cloud_API.php b/src/php/Client/Cloud_API.php index 34c8addc9..7d8b2d683 100644 --- a/src/php/Client/Cloud_API.php +++ b/src/php/Client/Cloud_API.php @@ -363,7 +363,7 @@ public function update_snippet_from_cloud( Cloud_Snippet $snippet_to_store ): ar * * Bumped on flush so old transient keys become unreachable and expire naturally. */ - private const FEATURED_VERSION_OPTION = 'cs_featured_cache_version'; + public const FEATURED_VERSION_OPTION = 'cs_featured_cache_version'; /** * Base transient key for cached featured snippets. diff --git a/src/php/Core/Uninstaller.php b/src/php/Core/Uninstaller.php index 782c1efcd..6182a00d1 100644 --- a/src/php/Core/Uninstaller.php +++ b/src/php/Core/Uninstaller.php @@ -9,6 +9,8 @@ namespace Code_Snippets\Core; +use Code_Snippets\Client\Cloud_API; + /** * Uninstaller class. * @@ -72,7 +74,7 @@ private function uninstall_current_site() { delete_option( 'code_snippets_settings' ); delete_option( 'code_snippets_cloud_settings' ); - delete_option( 'cs_featured_cache_version' ); + delete_option( Cloud_API::FEATURED_VERSION_OPTION ); delete_transient( 'cs_codevault_snippets' ); delete_transient( 'cs_local_to_cloud_map' ); } From 3e33cbc18f7d48c485aa84f99120780a4590322e Mon Sep 17 00:00:00 2001 From: Imants Date: Tue, 26 May 2026 18:03:17 +0300 Subject: [PATCH 09/11] fix: add missing i18n text domain and noopener to community cloud components --- src/js/components/ManageMenu/CommunityCloud/CloudSearch.tsx | 2 +- src/js/components/ManageMenu/CommunityCloud/SearchResult.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/js/components/ManageMenu/CommunityCloud/CloudSearch.tsx b/src/js/components/ManageMenu/CommunityCloud/CloudSearch.tsx index 9e33ef62b..a9038bbf2 100644 --- a/src/js/components/ManageMenu/CommunityCloud/CloudSearch.tsx +++ b/src/js/components/ManageMenu/CommunityCloud/CloudSearch.tsx @@ -100,7 +100,7 @@ const SearchResults = () => { if (isErrored) { return (
-

{__('An error occurred while fetching search results. Please try again.')}

+

{__('An error occurred while fetching search results. Please try again.', 'code-snippets')}

) } diff --git a/src/js/components/ManageMenu/CommunityCloud/SearchResult.tsx b/src/js/components/ManageMenu/CommunityCloud/SearchResult.tsx index d895f8e3a..e337aa409 100644 --- a/src/js/components/ManageMenu/CommunityCloud/SearchResult.tsx +++ b/src/js/components/ManageMenu/CommunityCloud/SearchResult.tsx @@ -114,7 +114,7 @@ const DownloadOrViewButton: React.FC = ({ if (localSnippetId) { return ( - + {__('View', 'code-snippets')} ) From 2861317bcde3ff453870b50f771c21c13e348809 Mon Sep 17 00:00:00 2001 From: Imants Date: Tue, 26 May 2026 18:13:50 +0300 Subject: [PATCH 10/11] fix: use string literal for cache version option in Uninstaller to match file convention --- src/php/Client/Cloud_API.php | 2 +- src/php/Core/Uninstaller.php | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/php/Client/Cloud_API.php b/src/php/Client/Cloud_API.php index 7d8b2d683..34c8addc9 100644 --- a/src/php/Client/Cloud_API.php +++ b/src/php/Client/Cloud_API.php @@ -363,7 +363,7 @@ public function update_snippet_from_cloud( Cloud_Snippet $snippet_to_store ): ar * * Bumped on flush so old transient keys become unreachable and expire naturally. */ - public const FEATURED_VERSION_OPTION = 'cs_featured_cache_version'; + private const FEATURED_VERSION_OPTION = 'cs_featured_cache_version'; /** * Base transient key for cached featured snippets. diff --git a/src/php/Core/Uninstaller.php b/src/php/Core/Uninstaller.php index 6182a00d1..782c1efcd 100644 --- a/src/php/Core/Uninstaller.php +++ b/src/php/Core/Uninstaller.php @@ -9,8 +9,6 @@ namespace Code_Snippets\Core; -use Code_Snippets\Client\Cloud_API; - /** * Uninstaller class. * @@ -74,7 +72,7 @@ private function uninstall_current_site() { delete_option( 'code_snippets_settings' ); delete_option( 'code_snippets_cloud_settings' ); - delete_option( Cloud_API::FEATURED_VERSION_OPTION ); + delete_option( 'cs_featured_cache_version' ); delete_transient( 'cs_codevault_snippets' ); delete_transient( 'cs_local_to_cloud_map' ); } From b633e06df1e1bffddb1e68819d1fab76661e97ca Mon Sep 17 00:00:00 2001 From: Imants Date: Tue, 26 May 2026 18:25:40 +0300 Subject: [PATCH 11/11] fix: use transient instead of option for featured cache version counter --- src/php/Client/Cloud_API.php | 13 ++++++------- src/php/Core/Uninstaller.php | 1 - tests/phpunit/test-cloud-api-featured.php | 8 +++++--- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/php/Client/Cloud_API.php b/src/php/Client/Cloud_API.php index 34c8addc9..abf973cdb 100644 --- a/src/php/Client/Cloud_API.php +++ b/src/php/Client/Cloud_API.php @@ -380,12 +380,12 @@ public function update_snippet_from_cloud( Cloud_Snippet $snippet_to_store ): ar * * @return int */ - private static function get_featured_cache_version(): int { - $version = (int) get_option( self::FEATURED_VERSION_OPTION, 0 ); + private static function get_featured_cache_version(): string { + $version = get_transient( self::FEATURED_VERSION_OPTION ); - if ( $version <= 0 ) { - $version = 1; - update_option( self::FEATURED_VERSION_OPTION, $version, false ); + if ( ! $version ) { + $version = (string) ( microtime( true ) * 1000 ); + set_transient( self::FEATURED_VERSION_OPTION, $version, MONTH_IN_SECONDS ); } return $version; @@ -488,7 +488,6 @@ public function clear_caches() { delete_transient( self::CLOUD_MAP_TRANSIENT_KEY ); delete_transient( 'cs_codevault_snippets' ); - $version = self::get_featured_cache_version(); - update_option( self::FEATURED_VERSION_OPTION, $version + 1, false ); + delete_transient( self::FEATURED_VERSION_OPTION ); } } diff --git a/src/php/Core/Uninstaller.php b/src/php/Core/Uninstaller.php index 782c1efcd..be32773f5 100644 --- a/src/php/Core/Uninstaller.php +++ b/src/php/Core/Uninstaller.php @@ -72,7 +72,6 @@ private function uninstall_current_site() { delete_option( 'code_snippets_settings' ); delete_option( 'code_snippets_cloud_settings' ); - delete_option( 'cs_featured_cache_version' ); delete_transient( 'cs_codevault_snippets' ); delete_transient( 'cs_local_to_cloud_map' ); } diff --git a/tests/phpunit/test-cloud-api-featured.php b/tests/phpunit/test-cloud-api-featured.php index e54405461..1bde6ed81 100644 --- a/tests/phpunit/test-cloud-api-featured.php +++ b/tests/phpunit/test-cloud-api-featured.php @@ -66,8 +66,10 @@ private function transient_key( int $page = 1, int $per_page = 10, array $filter $active_filters = array_filter( $filters ); $encoded = wp_json_encode( $active_filters ); $hash = md5( false === $encoded ? '' : $encoded ); - $version = (int) get_option( 'cs_featured_cache_version', 1 ); - $version = $version > 0 ? $version : 1; + $version = get_transient( 'cs_featured_cache_version' ); + if ( ! $version ) { + $version = (string) ( microtime( true ) * 1000 ); + } return "cs_featured_snippets_v{$version}_p{$page}_pp{$per_page}_{$hash}"; } @@ -78,7 +80,7 @@ private function transient_key( int $page = 1, int $per_page = 10, array $filter */ private function clear_featured_transients(): void { delete_transient( $this->transient_key() ); - delete_option( 'cs_featured_cache_version' ); + delete_transient( 'cs_featured_cache_version' ); } /**