| @@ -264,8 +264,14 @@ | ||
| 264 | 264 | $timestamp = gmdate('c'); |
| 265 | 265 | $settings = $this->sitemap_generator->get_settings('site'); |
| 266 | 266 | $settings['last_generated'] = $timestamp; |
| 267 | 267 | $this->sitemap_generator->save_settings('site', null, $settings); |
| 268 | + | |
| 269 | + // This generation wrote the same files the outstanding automatic rebuild | |
| 270 | + // was queued to write, so clear its marker (and any recorded failure) | |
| 271 | + // instead of leaving a request-time takeover to repeat the work. | |
| 272 | + $this->sitemap_generator->mark_regeneration_complete(); | |
| 273 | + | |
| 268 | 274 | return $timestamp; |
| 269 | 275 | } |
| 270 | 276 | |
| 271 | 277 | /** |
| @@ -466,9 +472,21 @@ | ||
| 466 | 472 | $filename = 'sitemap.xml'; |
| 467 | 473 | if (!empty($options['sitemap_urls'][0]['url'])) { |
| 468 | 474 | $filename = basename(wp_parse_url($options['sitemap_urls'][0]['url'], PHP_URL_PATH)); |
| 469 | 475 | } |
| 470 | - $this->save_sitemap_file($sitemap_xml, $filename); | |
| 476 | + // A failed write has to surface here the way the index | |
| 477 | + // branch surfaces one. Discarding it let record_generation() | |
| 478 | + // advance last_generated and clear the pending marker and | |
| 479 | + // the recorded failure, so an unwritable site root — the | |
| 480 | + // exact case this endpoint reports health for — came back | |
| 481 | + // as a healthy "Generated successfully". | |
| 482 | + if (!$this->save_sitemap_file($sitemap_xml, $filename)) { | |
| 483 | + return new WP_Error( | |
| 484 | + 'sitemap_generation_failed', | |
| 485 | + 'Failed to save sitemap: ' . $filename, | |
| 486 | + ['status' => 500] | |
| 487 | + ); | |
| 488 | + } | |
| 471 | 489 | |
| 472 | 490 | // Regenerate the standalone local business sitemap on the |
| 473 | 491 | // single-sitemap path too (parity with Rank Math). |
| 474 | 492 | $this->sitemap_generator->regenerate_local_sitemap($options); |
| @@ -912,9 +930,14 @@ | ||
| 912 | 930 | 'success' => true, |
| 913 | 931 | 'data' => [ |
| 914 | 932 | 'settings' => $settings, |
| 915 | 933 | 'context_type' => $context_type, |
| 916 | - 'context_id' => $context_id | |
| 934 | + 'context_id' => $context_id, | |
| 935 | + // Kept out of `settings` on purpose: this is generator state, | |
| 936 | + // not something the settings POST round-trips. | |
| 937 | + 'health' => $context_type === 'site' | |
| 938 | + ? $this->sitemap_generator->get_regeneration_health() | |
| 939 | + : null | |
| 917 | 940 | ], |
| 918 | 941 | 'message' => 'Sitemap settings retrieved successfully' |
| 919 | 942 | ], 200); |
| 920 | 943 | |
| @@ -1304,9 +1327,9 @@ | ||
| 1304 | 1327 | * @since 1.0.0 |
| 1305 | 1328 | * @return bool True if lock acquired |
| 1306 | 1329 | */ |
| 1307 | 1330 | private function acquire_generation_lock(): bool { |
| 1308 | - $lock_key = 'thinkrank_sitemap_generation_lock'; | |
| 1331 | + $lock_key = Sitemap_Generator::GENERATION_LOCK_TRANSIENT; | |
| 1309 | 1332 | |
| 1310 | 1333 | if (get_transient($lock_key)) { |
| 1311 | 1334 | return false; // Generation already in progress |
| 1312 | 1335 | } |
| @@ -1321,7 +1344,7 @@ | ||
| 1321 | 1344 | * @since 1.0.0 |
| 1322 | 1345 | * @return void |
| 1323 | 1346 | */ |
| 1324 | 1347 | private function release_generation_lock(): void { |
| 1325 | - delete_transient('thinkrank_sitemap_generation_lock'); | |
| 1348 | + delete_transient(Sitemap_Generator::GENERATION_LOCK_TRANSIENT); | |
| 1326 | 1349 | } |
| 1327 | 1350 | } |