PluginProbe
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO / 2.11.0
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO v2.11.0
2.11.0 2.10.0 2.9.0 2.8.0 2.7.0 2.6.0 2.5.0 2.4.0 2.3.0 2.2.0 2.1.1 2.1.0 2.0.2 2.0.1 2.0.0 1.32.0 1.31.0 1.30.0 1.29.0 1.28.0 1.27.0 1.26.0 1.25.0 trunk 1.0.0 All 52 releases
← All changes | includes/abilities/maintenance/class-purge-caches.php +56 -27 2.9.0 → 2.11.0 View file →
@@ -44,8 +44,13 @@
44 44 'ai' => 'AI response cache',
45 45 'integrations' => 'Google integration responses',
46 46 'content_type' => 'Content Type Matrix resolution',
47 47 'transients' => 'ThinkRank transients',
48 + // Not a cache in the same sense — it rebuilds a published file rather
49 + // than dropping a stored value — but it is what a caller looking at a
50 + // stale sitemap reaches for, and the docblock above already named that
51 + // problem as a reason this ability exists (#764).
52 + 'sitemap' => 'Served XML sitemap (rebuilt, not just cleared)',
48 53 ];
49 54
50 55 /**
51 56 * Constructor.
@@ -52,9 +57,9 @@
52 57 */
53 58 public function __construct() {
54 59 $this->id = 'thinkrank/purge-caches';
55 60 $this->label = __( 'Purge ThinkRank Caches', 'thinkrank' );
56 - $this->description = __( 'Clear ThinkRank\'s cached data when it is showing something stale — the site audit, schema output, AI responses, Google integration responses, or all of them. Pass scopes to clear only what you need; omit it to clear everything. Nothing is deleted except caches: settings and content are untouched, and each cache rebuilds on the next request. After clearing the analyzer scope, use run-seo-analyzer to rebuild the audit immediately rather than waiting for the next request.', 'thinkrank' );
61 + $this->description = __( 'Clear ThinkRank\'s cached data when it is showing something stale — the site audit, schema output, AI responses, Google integration responses, or all of them. Pass scopes to clear only what you need; omit it to clear everything. Nothing is deleted except caches: settings and content are untouched, and each cache rebuilds on the next request. After clearing the analyzer scope, use run-seo-analyzer to rebuild the audit immediately rather than waiting for the next request. The "sitemap" scope is the exception to "rebuilds on the next request": the sitemap is a published file, so that scope rebuilds it there and then and reports whether it succeeded.', 'thinkrank' );
57 62 }
58 63
59 64 /**
60 65 * {@inheritDoc}
@@ -114,8 +119,13 @@
114 119 'type' => 'array',
115 120 'items' => [ 'type' => 'string' ],
116 121 'description' => __( 'Scopes whose subsystem is not present on this install, so there was nothing to clear.', 'thinkrank' ),
117 122 ],
123 + 'failed' => [
124 + 'type' => 'array',
125 + 'items' => [ 'type' => 'string' ],
126 + 'description' => __( 'Scopes that exist but could not be cleared or rebuilt. For "sitemap" this means the served sitemap did not change, because another rebuild held the lock or the files could not be written or removed. Try again shortly; the Sitemap settings screen shows any recorded reason.', 'thinkrank' ),
127 + ],
118 128 ],
119 129 ];
120 130 }
121 131
@@ -130,75 +140,94 @@
130 140 $requested = isset( $input['scopes'] ) && is_array( $input['scopes'] ) && ! empty( $input['scopes'] )
131 141 ? array_values( array_intersect( array_keys( self::SCOPES ), array_map( 'strval', $input['scopes'] ) ) )
132 142 : array_keys( self::SCOPES );
133 143
134 - $cleared = [];
135 - $skipped = [];
144 + $results = [
145 + 'cleared' => [],
146 + 'skipped' => [],
147 + 'failed' => [],
148 + ];
136 149
137 150 foreach ( $requested as $scope ) {
138 - if ( $this->purge( $scope ) ) {
139 - $cleared[] = $scope;
140 - } else {
141 - $skipped[] = $scope;
142 - }
151 + $results[ $this->purge( $scope ) ][] = $scope;
143 152 }
144 153
145 - return [
146 - 'success' => true,
147 - 'cleared' => $cleared,
148 - 'skipped' => $skipped,
149 - ];
154 + // `success` stays true when a scope failed: the call itself ran, and
155 + // every other requested scope was still cleared. The failure is
156 + // reported per scope in `failed`, which is where a caller has to look
157 + // to know which cache is still stale.
158 + return [ 'success' => true ] + $results;
150 159 }
151 160
152 161 /**
153 162 * Clear one scope.
154 163 *
164 + * Three outcomes rather than a bool. A bool had only "cleared" and
165 + * "skipped" to map onto, and skipped is documented as "the subsystem is
166 + * not present", so a sitemap rebuild that lost the lock or failed to write
167 + * was reported to the caller as a sitemap that does not exist.
168 + *
169 + * @since 2.10.0 Returns 'cleared', 'skipped' or 'failed' instead of a bool.
170 + *
155 171 * @param string $scope Scope key.
156 - * @return bool True when the subsystem existed and was cleared.
172 + * @return string 'cleared', 'skipped' (subsystem absent) or 'failed'.
157 173 */
158 - private function purge( string $scope ): bool {
174 + private function purge( string $scope ): string {
159 175 switch ( $scope ) {
160 176 case 'analyzer':
161 177 if ( ! class_exists( 'ThinkRank\\SEO\\SEO_Analyzer' ) ) {
162 - return false;
178 + return 'skipped';
163 179 }
164 180 ( new \ThinkRank\SEO\SEO_Analyzer() )->flush_cache();
165 - return true;
181 + return 'cleared';
166 182
167 183 case 'schema':
168 184 if ( ! class_exists( 'ThinkRank\\SEO\\Schema_Cache_Manager' ) ) {
169 - return false;
185 + return 'skipped';
170 186 }
171 187 ( new \ThinkRank\SEO\Schema_Cache_Manager() )->clear_all();
172 - return true;
188 + return 'cleared';
173 189
174 190 case 'ai':
175 191 if ( ! class_exists( 'ThinkRank\\AI\\Cache_Manager' ) ) {
176 - return false;
192 + return 'skipped';
177 193 }
178 194 ( new \ThinkRank\AI\Cache_Manager() )->clear_all();
179 - return true;
195 + return 'cleared';
180 196
181 197 case 'integrations':
182 198 if ( ! method_exists( 'ThinkRank\\API\\Integrations_Endpoint', 'purge_search_console_sites_cache' ) ) {
183 - return false;
199 + return 'skipped';
184 200 }
185 201 \ThinkRank\API\Integrations_Endpoint::purge_search_console_sites_cache();
186 - return true;
202 + return 'cleared';
187 203
188 204 case 'content_type':
189 205 if ( ! method_exists( 'ThinkRank\\SEO\\Content_Type_Settings', 'flush_cache' ) ) {
190 - return false;
206 + return 'skipped';
191 207 }
192 208 \ThinkRank\SEO\Content_Type_Settings::flush_cache();
193 - return true;
209 + return 'cleared';
194 210
195 211 case 'transients':
196 212 $this->purge_transients();
197 - return true;
213 + return 'cleared';
214 +
215 + case 'sitemap':
216 + if ( ! class_exists( 'ThinkRank\\SEO\\Sitemap_Generator' ) ) {
217 + return 'skipped';
218 + }
219 +
220 + // Rebuilds rather than invalidates: the sitemap is a static file
221 + // on most installs, so there is no next request that would
222 + // regenerate it. Lock-guarded, and reports false when another
223 + // process holds the lock or the write fails, so the caller is
224 + // told the served file did not change.
225 + return ( new \ThinkRank\SEO\Sitemap_Generator( false ) )
226 + ->regenerate_sitemap_from_settings() ? 'cleared' : 'failed';
198 227 }
199 228
200 - return false;
229 + return 'skipped';
201 230 }
202 231
203 232 /**
204 233 * Delete ThinkRank's prefixed transients.