PluginProbe
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO / 2.13.0
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO v2.13.0
2.13.0 2.12.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 All 54 releases
← All changes | includes/admin/importers/class-import-detector.php +75 -1 2.9.0 → 2.13.0 View file →
@@ -76,8 +76,16 @@
76 76 'meta_prefix' => '_sq_',
77 77 'option_keys' => ['sq_options'],
78 78 'plugin_files' => ['squirrly-seo/squirrly.php'],
79 79 ],
80 + 'slimseo' => [
81 + 'name' => 'Slim SEO',
82 + // One `slim_seo` meta array per post/term, plus primary-term keys
83 + // and option-stored redirects (#886) — counted by the exporter.
84 + 'meta_prefix' => 'slim_seo',
85 + 'option_keys' => ['slim_seo', 'ss_redirects', 'slim_seo_pro', 'slim_seo_schemas'],
86 + 'plugin_files' => ['slim-seo/slim-seo.php', 'slim-seo-pro/slim-seo-pro.php'],
87 + ],
80 88 ];
81 89
82 90 /**
83 91 * Detect all source plugins present in the database
@@ -166,10 +174,18 @@
166 174 // Only surface source plugins that are currently installed AND active.
167 175 // Migrating from a plugin the user no longer runs isn't actionable, so
168 176 // leftover data from a deactivated/uninstalled plugin is intentionally
169 177 // excluded from the migration screen.
178 + //
179 + // The one exception is Rank Math's FAQ / HowTo blocks. Those live in
180 + // post_content, and deactivating Rank Math is precisely what breaks
181 + // them: the blocks turn into "unsupported block" in the editor and lose
182 + // their schema on the front end. Hiding the only screen that can repair
183 + // them, at the exact moment they need repairing, left users with no way
184 + // out at all (#777) — so an inactive Rank Math stays listed whenever
185 + // convertible blocks remain, carrying that type and nothing else.
170 186 if (!$this->is_source_active($config['plugin_files'] ?? [])) {
171 - return null;
187 + return $this->detect_orphaned_blocks($slug, $config);
172 188 }
173 189
174 190 $counts = [];
175 191 $total = 0;
@@ -179,8 +195,12 @@
179 195 $counts = $this->detect_aioseo();
180 196 } elseif ($slug === 'squirrly') {
181 197 // Squirrly uses a custom table too; the exporter classifies rows.
182 198 $counts = $this->detect_squirrly();
199 + } elseif ($slug === 'slimseo') {
200 + // Slim SEO's redirects and 404 log live outside postmeta, and its
201 + // primary terms under a second key; the exporter counts all of it.
202 + $counts = $this->detect_slimseo();
183 203 } else {
184 204 // Standard postmeta-based plugins
185 205 $prefix = $config['meta_prefix'];
186 206
@@ -214,8 +234,18 @@
214 234 // when the exporter supports it (Rank Math Pro's redirects + 404
215 235 // Monitor and Yoast Premium's redirects were never offered).
216 236 $counts = array_merge($counts, $this->detect_redirect_data($slug));
217 237
238 + // FAQ / HowTo blocks, offered while Rank Math is still active too, so
239 + // the wizard converts them on the way out rather than leaving the user
240 + // to discover the breakage after deactivation.
241 + if ('rankmath' === $slug) {
242 + $block_count = Block_Converter::count_posts();
243 + if ($block_count > 0) {
244 + $counts[Block_Converter::TYPE] = $block_count;
245 + }
246 + }
247 +
218 248 // Check for settings
219 249 $has_settings = false;
220 250 foreach ($config['option_keys'] as $option_key) {
221 251 if (get_option($option_key, null) !== null) {
@@ -245,8 +275,39 @@
245 275 ];
246 276 }
247 277
248 278 /**
279 + * Detection result for a deactivated source that has left convertible
280 + * content blocks behind, or null when there is nothing to repair.
281 + *
282 + * Only the block type is reported. The plugin's postmeta and settings are
283 + * deliberately still withheld: migrating those from a plugin the site no
284 + * longer runs is the case the active-only rule exists to prevent, and it is
285 + * not what broke.
286 + *
287 + * @param string $slug Plugin slug.
288 + * @param array $config Plugin configuration.
289 + * @return array|null
290 + */
291 + private function detect_orphaned_blocks(string $slug, array $config): ?array {
292 + if ('rankmath' !== $slug) {
293 + return null;
294 + }
295 +
296 + $count = Block_Converter::count_posts();
297 + if ($count < 1) {
298 + return null;
299 + }
300 +
301 + return [
302 + 'plugin' => $slug,
303 + 'plugin_name' => $config['name'],
304 + 'counts' => [Block_Converter::TYPE => $count],
305 + 'total' => $count,
306 + ];
307 + }
308 +
309 + /**
249 310 * Whether any of a source plugin's known main files is active.
250 311 *
251 312 * Checks both single-site and network activation. A plugin that is merely
252 313 * installed but not active returns false.
@@ -332,8 +393,21 @@
332 393 */
333 394 private function detect_squirrly(): array {
334 395 $exporter = new Squirrly_Exporter();
335 396 $counts = $exporter->get_available_types();
397 + // Settings are added by the caller from option_keys.
398 + unset($counts['settings']);
399 +
400 + return $counts;
401 + }
402 +
403 + /**
404 + * Detect Slim SEO data: per-object meta, redirects and the 404 log.
405 + *
406 + * @return array Counts array
407 + */
408 + private function detect_slimseo(): array {
409 + $counts = (new Slim_SEO_Exporter())->get_available_types();
336 410 // Settings are added by the caller from option_keys.
337 411 unset($counts['settings']);
338 412
339 413 return $counts;