PluginProbe
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO / 2.7.0
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO v2.7.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 1.0.1 1.0.2 1.1.0 1.10.0 All 48 releases
← All changes | includes/core/class-deactivator.php +66 -18 2.0.02.7.0 View file →
@@ -24,12 +24,23 @@
24 24 *
25 25 * @since 1.0.0
26 26 */
27 27 class Deactivator {
28 -
28 +
29 29 /**
30 + * Which web-root artifacts deactivation removed, for activation to restore.
31 + *
32 + * Holds a subset of ['sitemap', 'robots', 'llms']. Read and deleted by
33 + * {@see Activator::restore_webroot_artifacts()}. Keep in sync with
34 + * Activator::REPUBLISH_OPTION.
35 + *
36 + * @since 2.1.0
37 + */
38 + public const REPUBLISH_OPTION = 'thinkrank_webroot_republish';
39 +
40 + /**
30 41 * Plugin deactivation tasks
31 - *
42 + *
32 43 * @return void
33 44 */
34 45 public function deactivate(): void {
35 46 $this->clear_scheduled_hooks();
@@ -42,16 +53,58 @@
42 53 }
43 54
44 55 /**
45 56 * Remove physically published files so they stop serving once the plugin
46 - * is inactive (the published llms.txt would otherwise keep serving forever).
57 + * is inactive.
47 58 *
59 + * ThinkRank publishes its sitemap, robots.txt and llms.txt as real files in
60 + * the web root rather than serving them through rewrite rules. A leftover
61 + * file is served by the web server before WordPress boots, so it does not
62 + * merely go stale — it shadows the route of whatever the user switched to
63 + * (#510). Deactivating to trial another SEO plugin is the common way people
64 + * hit that, which is why removal belongs here and not only in uninstall.
65 + *
66 + * The stored settings and documents are deliberately untouched: only the
67 + * artifacts go. {@see Activator::restore_webroot_artifacts()} republishes
68 + * them from those settings when the plugin is switched back on.
69 + *
70 + * @since 2.1.0 Also removes the sitemap files and a generated robots.txt,
71 + * and keeps the llms.txt document instead of discarding it.
72 + *
48 73 * @return void
49 74 */
50 75 private function remove_published_files(): void {
76 + require_once THINKRANK_PLUGIN_DIR . 'includes/cleanup-webroot.php';
77 +
78 + // Record what was actually published so reactivation restores exactly
79 + // that, and nothing else. Republishing from settings alone would write
80 + // files a site never had — every artifact defaults to enabled, so a
81 + // fresh install would start emitting a robots.txt it had not asked for.
82 + $republish = [];
83 +
84 + if (thinkrank_webroot_delete_sitemaps(thinkrank_webroot_read_sitemap_settings())['deleted']) {
85 + $republish[] = 'sitemap';
86 + }
87 +
88 + if (thinkrank_webroot_delete_robots_txt()['deleted']) {
89 + $republish[] = 'robots';
90 + }
91 +
51 92 if (class_exists('ThinkRank\\SEO\\LLMs_Txt_Manager')) {
52 - (new \ThinkRank\SEO\LLMs_Txt_Manager())->delete_llms_txt_file();
93 + // Checked up front: unpublish_static_file() reports success for a
94 + // file that was never there, which would mark a site that never
95 + // published llms.txt for republishing.
96 + $was_published = file_exists(ABSPATH . 'llms.txt');
97 +
98 + // unpublish_static_file(), not delete_llms_txt_file(): the served
99 + // file goes, the user's document stays for reactivation.
100 + if ((new \ThinkRank\SEO\LLMs_Txt_Manager())->unpublish_static_file() && $was_published) {
101 + $republish[] = 'llms';
102 + }
53 103 }
104 +
105 + // Autoload off: this is read once, on the next activation.
106 + update_option(self::REPUBLISH_OPTION, $republish, false);
54 107 // Static /.well-known/ OAuth discovery files (published by the MCP
55 108 // self-test on hosts whose proxy intercepts that directory) — a
56 109 // static copy must not keep advertising a server that is now off.
57 110 if (class_exists('ThinkRank\\Mcp\\Mcp_Static_Discovery')) {
@@ -64,22 +117,17 @@
64 117 *
65 118 * @return void
66 119 */
67 120 private function clear_scheduled_hooks(): void {
68 - $scheduled_hooks = [
69 - 'thinkrank_cache_cleanup',
70 - 'thinkrank_usage_analytics',
71 - // Email report tick (see ThinkRank\SEO\Email_Report_Scheduler::CRON_HOOK)
72 - // — was previously left scheduled after deactivation.
73 - 'thinkrank_email_report_tick',
74 - // Brand Visibility drain + its recurring stall watchdog
75 - // (ThinkRank\AI\Brand_Visibility_Runner::TICK_HOOK / WATCHDOG_HOOK).
76 - 'thinkrank_bv_tick',
77 - 'thinkrank_bv_watchdog',
78 - ];
79 -
80 - // Clear all instances of our hooks
81 - foreach ($scheduled_hooks as $hook) {
121 + // Read from the shared manifest rather than a local copy. Deactivation
122 + // cleared 5 of the 15 hooks the plugin schedules and uninstall cleared
123 + // 2, so a removal left recurring events behind — including
124 + // thinkrank_google_token_refresh on the custom thinkrank_45min
125 + // recurrence, whose interval no longer resolves once the plugin's
126 + // cron_schedules filter is gone (#389).
127 + $manifest = require THINKRANK_PLUGIN_DIR . 'includes/cleanup-manifest.php';
128 +
129 + foreach ($manifest['cron_hooks'] as $hook) {
82 130 wp_clear_scheduled_hook($hook);
83 131 }
84 132 }
85 133