PluginProbe
Yoast SEO – Advanced SEO with real-time guidance and built-in AI / 28.6
Yoast SEO – Advanced SEO with real-time guidance and built-in AI v28.6
28.6 28.5 28.4 28.3 28.2 28.1 28.0 27.9 27.8 27.7 27.6 27.5 trunk 18.0 18.1 18.2 18.3 18.4 18.4.1 18.5 18.5.1 18.6 18.7 18.8 18.9 All 130 releases
wordpress-seo / src / dashboard / infrastructure / search-console / site-kit-search-console-adapter.php

site-kit-search-console-adapter.php in Yoast SEO – Advanced SEO with real-time guidance and built-in AI 28.6, at src/dashboard/infrastructure/search-console/site-kit-search-console-adapter.php

193 lines 6.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 // phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong
4 // phpcs:disable Yoast.NamingConventions.NamespaceName.MaxExceeded
5 namespace Yoast\WP\SEO\Dashboard\Infrastructure\Search_Console;
6
7 use Google\Site_Kit_Dependencies\Google\Service\SearchConsole\ApiDataRow;
8 use WP_REST_Response;
9 use Yoast\WP\SEO\Dashboard\Domain\Data_Provider\Data_Container;
10 use Yoast\WP\SEO\Dashboard\Domain\Search_Console\Failed_Request_Exception;
11 use Yoast\WP\SEO\Dashboard\Domain\Search_Console\Unexpected_Response_Exception;
12 use Yoast\WP\SEO\Dashboard\Domain\Search_Rankings\Comparison_Search_Ranking_Data;
13 use Yoast\WP\SEO\Dashboard\Domain\Search_Rankings\Search_Ranking_Data;
14
15 /**
16 * The site API adapter to make calls to the Search Console API, via the Site_Kit plugin.
17 */
18 class Site_Kit_Search_Console_Adapter {
19
20 /**
21 * Holds the api call class.
22 *
23 * @var Site_Kit_Search_Console_Api_Call $site_kit_search_console_api_call
24 */
25 private $site_kit_search_console_api_call;
26
27 /**
28 * The constructor.
29 *
30 * @param Site_Kit_Search_Console_Api_Call $site_kit_search_console_api_call The api call class.
31 */
32 public function __construct( Site_Kit_Search_Console_Api_Call $site_kit_search_console_api_call ) {
33 $this->site_kit_search_console_api_call = $site_kit_search_console_api_call;
34 }
35
36 /**
37 * The wrapper method to do a Site Kit API request for Search Console.
38 *
39 * @param Search_Console_Parameters $parameters The parameters.
40 *
41 * @throws Failed_Request_Exception When the request responds with an error from Site Kit.
42 * @throws Unexpected_Response_Exception When the request responds with an unexpected format.
43 * @return Data_Container The Site Kit API response.
44 */
45 public function get_data( Search_Console_Parameters $parameters ): Data_Container {
46 $api_parameters = $this->build_parameters( $parameters );
47
48 $response = $this->site_kit_search_console_api_call->do_request( $api_parameters );
49
50 $this->validate_response( $response );
51
52 return $this->parse_response( $response->get_data() );
53 }
54
55 /**
56 * The wrapper method to do a comparison Site Kit API request for Search Console.
57 *
58 * @param Search_Console_Parameters $parameters The parameters.
59 *
60 * @throws Failed_Request_Exception When the request responds with an error from Site Kit.
61 * @throws Unexpected_Response_Exception When the request responds with an unexpected format.
62 * @return Data_Container The Site Kit API response.
63 */
64 public function get_comparison_data( Search_Console_Parameters $parameters ): Data_Container {
65 $api_parameters = $this->build_parameters( $parameters );
66
67 // Since we're doing a comparison request, we need to increase the date range to the start of the previous period. We'll later split the data into two periods.
68 $api_parameters['startDate'] = $parameters->get_compare_start_date();
69
70 $response = $this->site_kit_search_console_api_call->do_request( $api_parameters );
71
72 $this->validate_response( $response );
73
74 return $this->parse_comparison_response( $response->get_data(), $parameters->get_compare_end_date() );
75 }
76
77 /**
78 * Builds the parameters to be used in the Site Kit API request.
79 *
80 * @param Search_Console_Parameters $parameters The parameters.
81 *
82 * @return array<string, array<string, string>> The Site Kit API parameters.
83 */
84 private function build_parameters( Search_Console_Parameters $parameters ): array {
85 $api_parameters = [
86 'startDate' => $parameters->get_start_date(),
87 'endDate' => $parameters->get_end_date(),
88 'dimensions' => $parameters->get_dimensions(),
89 ];
90
91 if ( $parameters->get_limit() !== 0 ) {
92 $api_parameters['limit'] = $parameters->get_limit();
93 }
94
95 return $api_parameters;
96 }
97
98 /**
99 * Parses a response for a comparison Site Kit API request for Search Analytics.
100 *
101 * @param ApiDataRow[] $response The response to parse.
102 * @param string $compare_end_date The compare end date.
103 *
104 * @throws Unexpected_Response_Exception When the comparison request responds with an unexpected format.
105 * @return Data_Container The parsed comparison Site Kit API response.
106 */
107 private function parse_comparison_response( array $response, ?string $compare_end_date ): Data_Container {
108 $data_container = new Data_Container();
109 $comparison_search_ranking_data = new Comparison_Search_Ranking_Data();
110
111 foreach ( $response as $ranking_date ) {
112
113 if ( ! \is_a( $ranking_date, ApiDataRow::class ) ) {
114 throw new Unexpected_Response_Exception();
115 }
116
117 $ranking_data = new Search_Ranking_Data( $ranking_date->getClicks(), $ranking_date->getCtr(), $ranking_date->getImpressions(), $ranking_date->getPosition(), $ranking_date->getKeys()[0] );
118
119 // Now split the data into two periods.
120 if ( $ranking_date->getKeys()[0] <= $compare_end_date ) {
121 $comparison_search_ranking_data->add_previous_traffic_data( $ranking_data );
122 }
123 else {
124 $comparison_search_ranking_data->add_current_traffic_data( $ranking_data );
125 }
126 }
127
128 $data_container->add_data( $comparison_search_ranking_data );
129
130 return $data_container;
131 }
132
133 /**
134 * Parses a response for a Site Kit API request for Search Analytics.
135 *
136 * @param ApiDataRow[] $response The response to parse.
137 *
138 * @throws Unexpected_Response_Exception When the request responds with an unexpected format.
139 * @return Data_Container The parsed Site Kit API response.
140 */
141 private function parse_response( array $response ): Data_Container {
142 $search_ranking_data_container = new Data_Container();
143
144 foreach ( $response as $ranking ) {
145
146 if ( ! \is_a( $ranking, ApiDataRow::class ) ) {
147 throw new Unexpected_Response_Exception();
148 }
149
150 /**
151 * Filter: 'wpseo_transform_dashboard_subject_for_testing' - Allows overriding subjects like URLs for the dashboard, to facilitate testing in local environments.
152 *
153 * @param string $url The subject to be transformed.
154 *
155 * @internal
156 */
157 $subject = \apply_filters( 'wpseo_transform_dashboard_subject_for_testing', $ranking->getKeys()[0] );
158
159 $search_ranking_data_container->add_data( new Search_Ranking_Data( $ranking->getClicks(), $ranking->getCtr(), $ranking->getImpressions(), $ranking->getPosition(), $subject ) );
160 }
161
162 return $search_ranking_data_container;
163 }
164
165 /**
166 * Validates the response coming from Search Console.
167 *
168 * @param WP_REST_Response $response The response we want to validate.
169 *
170 * @return void.
171 *
172 * @throws Failed_Request_Exception When the request responds with an error from Site Kit.
173 * @throws Unexpected_Response_Exception When the request responds with an unexpected format.
174 */
175 private function validate_response( WP_REST_Response $response ): void {
176 if ( $response->is_error() ) {
177 $error_data = $response->as_error()->get_error_data();
178 $error_status_code = ( $error_data['status'] ?? 500 );
179 throw new Failed_Request_Exception(
180 \wp_kses_post(
181 $response->as_error()
182 ->get_error_message(),
183 ),
184 (int) $error_status_code,
185 );
186 }
187
188 if ( ! \is_array( $response->get_data() ) ) {
189 throw new Unexpected_Response_Exception();
190 }
191 }
192 }
193