PluginProbe
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO / 2.9.0
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO v2.9.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 1.0.1 1.0.2 All 50 releases
← All changes | includes/core/class-seo-plugin-detector.php +74 -11 1.0.1 → 2.9.0 View file →
@@ -36,8 +36,10 @@
36 36 'name' => 'Yoast SEO',
37 37 'class' => 'WPSEO',
38 38 'function' => 'wpseo_init',
39 39 'file' => 'wordpress-seo/wp-seo.php',
40 + 'extra_files' => ['wordpress-seo-premium/wp-seo-premium.php'],
41 + 'importable' => true,
40 42 ],
41 43 'rankmath' => [
42 44 'name' => 'Rank Math',
43 45 'class' => 'RankMath',
@@ -42,8 +44,10 @@
42 44 'name' => 'Rank Math',
43 45 'class' => 'RankMath',
44 46 'function' => 'rank_math',
45 47 'file' => 'seo-by-rank-math/rank-math.php',
48 + 'extra_files' => ['seo-by-rank-math-pro/rank-math-pro.php'],
49 + 'importable' => true,
46 50 ],
47 51 'seopress' => [
48 52 'name' => 'SEOPress',
49 53 'class' => 'SEOPress',
@@ -48,8 +52,10 @@
48 52 'name' => 'SEOPress',
49 53 'class' => 'SEOPress',
50 54 'function' => 'seopress_init',
51 55 'file' => 'wp-seopress/seopress.php',
56 + 'extra_files' => ['wp-seopress-pro/seopress-pro.php'],
57 + 'importable' => true,
52 58 ],
53 59 'aioseo' => [
54 60 'name' => 'All in One SEO',
55 61 'class' => 'AIOSEO',
@@ -54,14 +60,26 @@
54 60 'name' => 'All in One SEO',
55 61 'class' => 'AIOSEO',
56 62 'function' => 'aioseo',
57 63 'file' => 'all-in-one-seo-pack/all_in_one_seo_pack.php',
64 + 'extra_files' => ['all-in-one-seo-pack-pro/all_in_one_seo_pack.php'],
65 + 'importable' => true,
58 66 ],
67 + 'squirrly' => [
68 + 'name' => 'Squirrly SEO',
69 + 'class' => 'SQ_Classes_ObjController',
70 + 'function' => 'sq_wpcall',
71 + 'file' => 'squirrly-seo/squirrly.php',
72 + 'extra_files' => ['squirrly-seo-pack/index.php'],
73 + 'importable' => true,
74 + ],
59 75 'theseoframework' => [
60 76 'name' => 'The SEO Framework',
61 77 'class' => 'The_SEO_Framework\\Load',
62 78 'function' => 'the_seo_framework',
63 79 'file' => 'autodescription/autodescription.php',
80 + 'extra_files' => [],
81 + 'importable' => false,
64 82 ],
65 83 ];
66 84
67 85 /**
@@ -148,25 +166,70 @@
148 166 }
149 167
150 168 /**
151 169 * Get admin notice message
152 - *
170 + *
153 171 * @return string Notice message
154 172 */
155 173 public static function get_notice_message(): string {
156 - $plugin_names = self::get_plugin_names();
157 -
158 - if (empty($plugin_names)) {
174 + if (!self::has_seo_plugins()) {
159 175 return '';
160 176 }
161 -
162 - $plugin_list = implode(', ', $plugin_names);
163 177
164 - return sprintf(
165 - /* translators: %s: comma-separated list of detected SEO plugin names */
166 - __('⚠️ SEO Plugin Detected: %s. ThinkRank will take priority for posts where you generate AI metadata. Consider disabling other SEO plugins for best results.', 'thinkrank'),
167 - $plugin_list
168 - );
178 + return __('Running more than one SEO plugin can create conflicts — duplicate meta tags, sitemaps, and schema markup that may hurt your search rankings. To avoid any SEO-related conflicts, we recommend deactivating third-party SEO plugins.', 'thinkrank');
179 + }
180 +
181 + /**
182 + * Whether any detected plugin's SEO data can be imported into ThinkRank.
183 + *
184 + * @return bool True if at least one detected plugin has an importer
185 + */
186 + public static function has_importable_plugin(): bool {
187 + foreach (self::detect_plugins() as $plugin) {
188 + if (!empty($plugin['importable'])) {
189 + return true;
190 + }
191 + }
192 +
193 + return false;
194 + }
195 +
196 + /**
197 + * Get the human-readable name for a known plugin slug.
198 + *
199 + * Falls back to the slug itself when unknown, so callers always have a
200 + * displayable label.
201 + *
202 + * @param string $slug Plugin slug from KNOWN_PLUGINS
203 + * @return string Plugin name (or the slug if unknown)
204 + */
205 + public static function get_plugin_name(string $slug): string {
206 + return self::KNOWN_PLUGINS[$slug]['name'] ?? $slug;
207 + }
208 +
209 + /**
210 + * Get the active plugin files to deactivate for a detected plugin.
211 + *
212 + * Resolves the plugin file(s) — including premium companions such as
213 + * Rank Math Pro — server-side from the known-plugins map, so callers
214 + * never pass arbitrary plugin paths to deactivate_plugins().
215 + *
216 + * @param string $slug Plugin slug from KNOWN_PLUGINS
217 + * @return array Active plugin file paths (may be empty)
218 + */
219 + public static function get_deactivatable_files(string $slug): array {
220 + if (!isset(self::KNOWN_PLUGINS[$slug]) || !self::is_plugin_detected($slug)) {
221 + return [];
222 + }
223 +
224 + if (!function_exists('is_plugin_active')) {
225 + require_once ABSPATH . 'wp-admin/includes/plugin.php';
226 + }
227 +
228 + $plugin = self::KNOWN_PLUGINS[$slug];
229 + $files = array_merge([$plugin['file']], $plugin['extra_files'] ?? []);
230 +
231 + return array_values(array_filter($files, 'is_plugin_active'));
169 232 }
170 233
171 234 /**
172 235 * Should show admin notice