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/api/class-seo-analytics-endpoint.php +13 -205 1.32.02.7.0 View file →
@@ -145,21 +145,8 @@
145 145 ]
146 146 ]
147 147 );
148 148
149 - // Get indexing status
150 - register_rest_route(
151 - $this->namespace,
152 - '/' . $this->rest_base . '/indexing-status',
153 - [
154 - [
155 - 'methods' => 'GET',
156 - 'callback' => [$this, 'get_indexing_status'],
157 - 'permission_callback' => [$this, 'check_permissions'],
158 - ]
159 - ]
160 - );
161 -
162 149 // Refresh cached data
163 150 register_rest_route(
164 151 $this->namespace,
165 152 '/' . $this->rest_base . '/refresh',
@@ -184,54 +171,8 @@
184 171 ]
185 172 ]
186 173 );
187 174
188 - // ========================================
189 - // SEO Intelligence Enhancement Endpoints
190 - // ========================================
191 -
192 - // Get intelligent dashboard data with trends and insights
193 - register_rest_route(
194 - $this->namespace,
195 - '/' . $this->rest_base . '/intelligent-dashboard',
196 - [
197 - [
198 - 'methods' => 'GET',
199 - 'callback' => [$this, 'get_intelligent_dashboard'],
200 - 'permission_callback' => [$this, 'check_data_permissions'],
201 - 'args' => $this->get_dashboard_args()
202 - ]
203 - ]
204 - );
205 -
206 - // Get intelligent SEO opportunities with prioritization
207 - register_rest_route(
208 - $this->namespace,
209 - '/' . $this->rest_base . '/intelligent-opportunities',
210 - [
211 - [
212 - 'methods' => 'GET',
213 - 'callback' => [$this, 'get_intelligent_opportunities'],
214 - 'permission_callback' => [$this, 'check_data_permissions'],
215 - 'args' => $this->get_opportunities_args()
216 - ]
217 - ]
218 - );
219 -
220 - // Get SEO insights
221 - register_rest_route(
222 - $this->namespace,
223 - '/' . $this->rest_base . '/insights',
224 - [
225 - [
226 - 'methods' => 'GET',
227 - 'callback' => [$this, 'get_seo_insights'],
228 - 'permission_callback' => [$this, 'check_data_permissions'],
229 - 'args' => $this->get_dashboard_args()
230 - ]
231 - ]
232 - );
233 -
234 175 // Get Search Console totals for custom date range
235 176 register_rest_route(
236 177 $this->namespace,
237 178 '/' . $this->rest_base . '/search-totals',
@@ -430,32 +371,8 @@
430 371 }
431 372 }
432 373
433 374 /**
434 - * Get indexing status
435 - *
436 - * @param WP_REST_Request $request Request object
437 - * @return WP_REST_Response|WP_Error Response object
438 - */
439 - public function get_indexing_status(WP_REST_Request $request) {
440 - try {
441 - $indexing_status = $this->analytics_manager->get_indexing_status();
442 -
443 - return new WP_REST_Response([
444 - 'success' => true,
445 - 'data' => $indexing_status,
446 - 'message' => 'Indexing status retrieved successfully'
447 - ], 200);
448 - } catch (\Exception $e) {
449 - return new WP_Error(
450 - 'indexing_status_failed',
451 - 'Failed to retrieve indexing status: ' . $e->getMessage(),
452 - ['status' => 500]
453 - );
454 - }
455 - }
456 -
457 - /**
458 375 * Refresh cached analytics data
459 376 *
460 377 * @param WP_REST_Request $request Request object
461 378 * @return WP_REST_Response|WP_Error Response object
@@ -564,9 +481,21 @@
564 481 *
565 482 * @param string $site_url Site URL to validate
566 483 * @return bool|WP_Error Validation result
567 484 */
568 - public function validate_site_url(string $site_url) {
485 + public function validate_site_url($site_url) {
486 + // Not a `string` type hint: this is a validate_callback, so it runs on
487 + // the raw pre-sanitize parameter. `?site_url[]=x` handed it an array
488 + // and PHP raised an uncaught TypeError — a 500 where the API owes the
489 + // caller a 400 (#394).
490 + if (!is_string($site_url)) {
491 + return new WP_Error(
492 + 'invalid_site_url',
493 + 'Site URL must be a string',
494 + ['status' => 400]
495 + );
496 + }
497 +
569 498 if (empty($site_url)) {
570 499 return new WP_Error(
571 500 'invalid_site_url',
572 501 'Site URL is required',
@@ -939,127 +868,6 @@
939 868 );
940 869 }
941 870
942 871 return true;
943 - }
944 -
945 - // ========================================
946 - // SEO Intelligence Enhancement Endpoints
947 - // ========================================
948 -
949 - /**
950 - * Get intelligent dashboard data with trends and insights
951 - *
952 - * @param WP_REST_Request $request Request object
953 - * @return WP_REST_Response|WP_Error Response object
954 - */
955 - public function get_intelligent_dashboard(WP_REST_Request $request) {
956 - try {
957 - $date_range = $request->get_param('date_range');
958 -
959 - // Cache the intelligence computation (trend analysis + generators are
960 - // expensive) so the AI-insights panel doesn't recompute every load.
961 - $response = $this->cached_response(
962 - 'intelligent_dashboard',
963 - function () use ($date_range) {
964 - $intelligent_data = $this->analytics_manager->get_intelligent_dashboard_data($date_range);
965 -
966 - return [
967 - 'success' => isset($intelligent_data['success']) ? $intelligent_data['success'] : false,
968 - 'data' => $intelligent_data['data'] ?? null,
969 - 'message' => $intelligent_data['message'] ?? 'Intelligent dashboard data retrieved',
970 - 'timestamp' => current_time('mysql'),
971 - ];
972 - },
973 - ['date_range' => $date_range]
974 - );
975 -
976 - // Always return 200 for successful API calls, even when no data available.
977 - return new WP_REST_Response($response, 200);
978 -
979 - } catch (\Exception $e) {
980 - return new WP_Error(
981 - 'intelligent_dashboard_error',
982 - 'Failed to retrieve intelligent dashboard data: ' . $e->getMessage(),
983 - ['status' => 500]
984 - );
985 - }
986 - }
987 -
988 - /**
989 - * Get intelligent SEO opportunities with prioritization
990 - *
991 - * @param WP_REST_Request $request Request object
992 - * @return WP_REST_Response|WP_Error Response object
993 - */
994 - public function get_intelligent_opportunities(WP_REST_Request $request) {
995 - try {
996 - $date_range = $request->get_param('date_range');
997 -
998 - // Cache the opportunity detection so it doesn't recompute every load.
999 - $response = $this->cached_response(
1000 - 'intelligent_opportunities',
1001 - function () use ($date_range) {
1002 - $intelligent_opportunities = $this->analytics_manager->get_intelligent_seo_opportunities($date_range);
1003 -
1004 - return [
1005 - 'success' => isset($intelligent_opportunities['success']) ? $intelligent_opportunities['success'] : false,
1006 - 'data' => $intelligent_opportunities['data'] ?? null,
1007 - 'message' => $intelligent_opportunities['message'] ?? 'Intelligent opportunities retrieved',
1008 - 'timestamp' => current_time('mysql'),
1009 - ];
1010 - },
1011 - ['date_range' => $date_range]
1012 - );
1013 -
1014 - // Always return 200 for successful API calls, even when no data available.
1015 - return new WP_REST_Response($response, 200);
1016 -
1017 - } catch (\Exception $e) {
1018 - return new WP_Error(
1019 - 'intelligent_opportunities_error',
1020 - 'Failed to retrieve intelligent opportunities: ' . $e->getMessage(),
1021 - ['status' => 500]
1022 - );
1023 - }
1024 - }
1025 -
1026 - /**
1027 - * Get SEO insights
1028 - *
1029 - * @param WP_REST_Request $request Request object
1030 - * @return WP_REST_Response|WP_Error Response object
1031 - */
1032 - public function get_seo_insights(WP_REST_Request $request) {
1033 - try {
1034 - $date_range = $request->get_param('date_range');
1035 -
1036 - // Endpoint-level cache for consistency with the other two intelligence
1037 - // calls (the manager also caches insights internally).
1038 - $response = $this->cached_response(
1039 - 'seo_insights',
1040 - function () use ($date_range) {
1041 - $insights = $this->analytics_manager->get_seo_insights($date_range);
1042 -
1043 - return [
1044 - 'success' => isset($insights['success']) ? $insights['success'] : false,
1045 - 'data' => $insights['data'] ?? null,
1046 - 'cached' => $insights['cached'] ?? false,
1047 - 'message' => $insights['message'] ?? 'SEO insights retrieved',
1048 - 'timestamp' => current_time('mysql'),
1049 - ];
1050 - },
1051 - ['date_range' => $date_range]
1052 - );
1053 -
1054 - // Always return 200 for successful API calls, even when no data available.
1055 - return new WP_REST_Response($response, 200);
1056 -
1057 - } catch (\Exception $e) {
1058 - return new WP_Error(
1059 - 'seo_insights_error',
1060 - 'Failed to retrieve SEO insights: ' . $e->getMessage(),
1061 - ['status' => 500]
1062 - );
1063 - }
1064 872 }
1065 873 }