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/seo/class-email-report-generator.php +61 -1 2.3.0 → 2.9.0 View file →
@@ -99,8 +99,16 @@
99 99 private function run(array $config, bool $is_test): array {
100 100 $frequency = (int) ($config['frequency_days'] ?? 30);
101 101
102 102 try {
103 + // Is there a report to build? Asked before anything is fetched
104 + // (#742). A site without Search Console used to be fetched,
105 + // rendered and — before #611 — sent as a column of blanks.
106 + $readiness = $this->data_provider->readiness();
107 + if (empty($readiness['ready'])) {
108 + return $this->handle_not_ready($config, $readiness, $is_test);
109 + }
110 +
103 111 $shared = $this->data_provider->fetch($frequency);
104 112
105 113 $context = [
106 114 'period_start' => $shared['period_start'] ?? '',
@@ -175,13 +183,14 @@
175 183 $this->config->update_schedule(
176 184 $config['last_sent_at'] ?? null,
177 185 $this->compute_next_run($frequency)
178 186 );
187 + $this->config->record_skip('no_data');
179 188
180 189 return ['success' => false, 'skipped' => 'no_data'];
181 190 }
182 191
183 - $tokens = ['%period%' => $context['period_label']];
192 + $tokens = Email_Report_Data_Provider::subject_tokens($shared, $frequency);
184 193 $result = $this->mailer->send($config, $html, $tokens);
185 194
186 195 if (!$is_test) {
187 196 $this->finalize_log($config, $context, $result);
@@ -190,8 +199,9 @@
190 199 $this->config->update_schedule(
191 200 current_time('mysql'),
192 201 $this->compute_next_run($frequency)
193 202 );
203 + $this->config->clear_skip();
194 204 } else {
195 205 // A transient mail failure must not cost the user a whole
196 206 // period, and it must not stamp last_sent_at with a send
197 207 // that never happened. Retry soon; give up after
@@ -222,8 +232,58 @@
222 232 return ['success' => (bool) ($result['success'] ?? false), 'result' => $result];
223 233 } catch (Throwable $e) {
224 234 return ['success' => false, 'error' => $e->getMessage()];
225 235 }
236 + }
237 +
238 + /**
239 + * The report cannot be built — Search Console is not connected.
240 + *
241 + * A scheduled run records the reason for the panel and leaves the
242 + * schedule exactly where it is: `next_scheduled_at` stays in the past,
243 + * so the hourly tick keeps asking and the first tick after the
244 + * connection is made sends the report. No log row is written — there
245 + * was no attempt.
246 + *
247 + * A test send still goes out, as the one-card "connect Search Console"
248 + * email, so "Send Test Email" proves delivery and shows the recipient
249 + * what to do next instead of a report full of blanks.
250 + *
251 + * @return array{success:bool,skipped?:string,reason?:string,result?:array,not_connected?:bool}
252 + */
253 + private function handle_not_ready(array $config, array $readiness, bool $is_test): array {
254 + $reason = (string) ($readiness['reason'] ?? 'not_ready');
255 +
256 + if (!$is_test) {
257 + $this->config->record_skip($reason);
258 + return ['success' => false, 'skipped' => 'not_ready', 'reason' => $reason];
259 + }
260 +
261 + $context = [
262 + 'period_start' => '',
263 + 'period_end' => '',
264 + 'period_label' => '',
265 + 'is_test' => true,
266 + 'not_connected' => true,
267 + 'readiness' => $readiness,
268 + 'shared' => [],
269 + ];
270 +
271 + $html = $this->renderer->render($config, $context);
272 + $tokens = [
273 + '%period%' => '',
274 + '%headline%' => __('Connect Google Search Console to start your SEO reports', 'thinkrank'),
275 + ];
276 + $result = $this->mailer->send($config, $html, $tokens);
277 +
278 + do_action('thinkrank_email_report_after_send', $config, $result, true);
279 +
280 + return [
281 + 'success' => (bool) ($result['success'] ?? false),
282 + 'result' => $result,
283 + 'not_connected' => true,
284 + 'reason' => $reason,
285 + ];
226 286 }
227 287
228 288 /**
229 289 * Claim this period's send by inserting a `pending` row in