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
thinkrank / includes / abilities / analysis / class-get-integrations-status.php

class-get-integrations-status.php in ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO 2.7.0, at includes/abilities/analysis/class-get-integrations-status.php

181 lines 6.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Get integrations status ability.
4 *
5 * @package ThinkRank\Abilities\Analysis
6 */
7
8 declare(strict_types=1);
9
10 namespace ThinkRank\Abilities\Analysis;
11
12 use ThinkRank\Abilities\Ability_Base;
13 use ThinkRank\Core\Settings;
14 use ThinkRank\Integrations\Google_PageSpeed_Client;
15
16 if ( ! defined( 'ABSPATH' ) ) {
17 exit; // Exit if accessed directly.
18 }
19
20 /**
21 * Reports the connection status of ThinkRank's Google integrations.
22 *
23 * Covers Google Analytics (GA4), Search Console, and PageSpeed. Returns only
24 * non-sensitive status — connected/configured booleans, the public GA4
25 * measurement ID, and the selected Search Console site. It deliberately never
26 * returns API keys, OAuth access/refresh tokens, or any secret material.
27 */
28 class Get_Integrations_Status extends Ability_Base {
29 /**
30 * Constructor.
31 */
32 public function __construct() {
33 $this->id = 'thinkrank/get-integrations-status';
34 $this->label = __( 'Get Integrations Status', 'thinkrank' );
35 $this->description = __( 'Report the connection status of the Google Analytics, Search Console, and PageSpeed integrations (connected/configured flags, selected GA4 property, selected Search Console site). Never returns API keys or OAuth tokens.', 'thinkrank' );
36 }
37
38 /**
39 * {@inheritDoc}
40 *
41 * @return array<string, bool|float|string>
42 */
43 public function get_annotations() {
44 return [
45 'readonly' => true,
46 'destructive' => false,
47 'idempotent' => true,
48 'priority' => 1.0,
49 'openWorldHint' => false,
50 ];
51 }
52
53 /**
54 * {@inheritDoc}
55 *
56 * @return array<string, mixed>
57 */
58 public function get_input_schema() {
59 return [
60 'type' => 'object',
61 'additionalProperties' => false,
62 'properties' => self::empty_properties(),
63 ];
64 }
65
66 /**
67 * {@inheritDoc}
68 *
69 * @return array<string, mixed>
70 */
71 public function get_output_schema() {
72 return [
73 'type' => 'object',
74 'properties' => [
75 'google_account_connected' => [ 'type' => 'boolean' ],
76 'google_analytics' => [
77 'type' => 'object',
78 'additionalProperties' => true,
79 ],
80 'search_console' => [
81 'type' => 'object',
82 'additionalProperties' => true,
83 ],
84 'pagespeed' => [
85 'type' => 'object',
86 'additionalProperties' => true,
87 ],
88 ],
89 ];
90 }
91
92 /**
93 * Execute ability.
94 *
95 * @param array<string, mixed> $input Ability input payload.
96 * @return array<string, mixed>
97 */
98 public function execute( $input ) {
99 $settings = Settings::instance();
100
101 // "Configured" must mean "this integration can actually make a call",
102 // derived from the SAME conditions the client-initialization code uses.
103 //
104 // It previously keyed off three manual `*_api_key` options that no
105 // current code path writes — the OAuth connect flow stores tokens only
106 // (Google_OAuth_Proxy) and the property pickers store property ids — so
107 // an OAuth-connected site actively serving GA4/GSC/PSI data reported
108 // `configured: false` for all three while the same payload reported
109 // `google_account_connected: true`. The report contradicted itself on
110 // the one thing it exists to answer, which is worse than useless to an
111 // agent deciding whether an integration is available.
112 //
113 // The keys are retained as OR-branches: they are optional for data
114 // retrieval but still honored when present (see
115 // Google_PageSpeed_Client::for_site()).
116 $oauth_present = '' !== (string) $settings->get( 'google_access_token', '' );
117
118 // GA4: Analytics_Manager builds the Data API client only when a token
119 // AND a selected property both exist — mirror that exactly.
120 $ga_property = (string) $settings->get( 'seo_analytics_google_analytics_property_id', '' );
121 $ga_configured = ( $oauth_present && '' !== $ga_property )
122 || '' !== (string) $settings->get( 'google_analytics_api_key', '' );
123
124 // Search Console: the client authenticates with the token; the API key
125 // is passed as '' on an OAuth site. A property is not required to
126 // construct it (Analytics_Manager falls back to the site URL).
127 $sc_property = (string) $settings->get( 'search_console_property', '' );
128 $sc_configured = $oauth_present
129 || '' !== (string) $settings->get( 'google_search_console_api_key', '' );
130
131 // PageSpeed: for_site() prefers a dedicated key, else the OAuth token,
132 // else runs keyless on the per-IP quota. Report credentialed state, and
133 // read it from the same predicate the Performance tab gates on, so the
134 // two screens cannot disagree about the same site again (#519).
135 $ps_key = (string) $settings->get( 'google_pagespeed_api_key', '' );
136 $ps_configured = Google_PageSpeed_Client::site_has_credentials();
137
138 $google_analytics = [
139 'configured' => $ga_configured,
140 // The selected GA4 property, in the Admin API's
141 // "properties/XXXXXXXX" form. Empty means no property picked,
142 // which is the usual reason GA is connected but unusable.
143 'property_id' => $ga_property,
144 ];
145
146 /**
147 * Filters the google_analytics block of the integrations status.
148 *
149 * ThinkRank Pro, which installs the GA4 tag, adds its state here as
150 * `tag_injection`. That describes the tag Pro prints, not whether the
151 * site has a working GA4 tag (#250); `configured` answers whether
152 * ThinkRank can read Analytics data.
153 *
154 * @since 2.6.0
155 *
156 * @param array<string, mixed> $google_analytics Status block.
157 */
158 $filtered = apply_filters( 'thinkrank_integrations_status_google_analytics', $google_analytics );
159
160 return [
161 'google_account_connected' => (bool) $settings->get( 'google_account_connected', false ),
162 'google_analytics' => is_array( $filtered ) ? $filtered : $google_analytics,
163 'search_console' => [
164 'configured' => $sc_configured,
165 // Was reading `google_search_console_site` — a key with no
166 // writer anywhere in the plugin (only two disconnect paths
167 // clear it), so this was unconditionally ''. The property
168 // picker writes `search_console_property`.
169 'site' => $sc_property,
170 ],
171 'pagespeed' => [
172 'configured' => $ps_configured,
173 'oauth_connected' => $oauth_present,
174 // Distinguishes "own key, own quota" from "shared OAuth quota"
175 // — the difference between reliable and 429-prone PSI runs.
176 'has_api_key' => '' !== $ps_key,
177 ],
178 ];
179 }
180 }
181