| @@ -294,8 +294,24 @@ | ||
| 294 | 294 | $this->sitemap_generator->save_settings('site', null, $settings); |
| 295 | 295 | } |
| 296 | 296 | |
| 297 | 297 | /** |
| 298 | + * Stored sitemap settings with this request's options laid over them. | |
| 299 | + * | |
| 300 | + * The generate payload is partial — the admin screen posts the sitemap | |
| 301 | + * shape, not the whole settings record — so reading `delivery_mode` straight | |
| 302 | + * off it would resolve to `auto` on every ordinary request and defeat an | |
| 303 | + * explicit choice. Merging keeps a mode sent in the payload authoritative | |
| 304 | + * while falling back to what is saved. | |
| 305 | + * | |
| 306 | + * @param array $options Request options. | |
| 307 | + * @return array Effective settings for this generation. | |
| 308 | + */ | |
| 309 | + private function effective_settings(array $options): array { | |
| 310 | + return array_merge($this->sitemap_generator->get_settings('site'), $options); | |
| 311 | + } | |
| 312 | + | |
| 313 | + /** | |
| 298 | 314 | * Persist a manual-generation auto-promotion into the stored settings. |
| 299 | 315 | * |
| 300 | 316 | * maybe_promote_to_index() may flip use_sitemap_index on and synthesize the |
| 301 | 317 | * segmented sitemap_urls for the current generation. On the automatic path |
| @@ -367,8 +383,17 @@ | ||
| 367 | 383 | } |
| 368 | 384 | |
| 369 | 385 | $sitemap_url = $this->sitemap_generator->get_primary_sitemap_url($settings); |
| 370 | 386 | |
| 387 | + // Dynamic delivery publishes no file, so there is nothing to ensure and | |
| 388 | + // nothing to look for on disk. Dropping the rendered documents is what | |
| 389 | + // makes the saved settings take effect on the next request (#752). | |
| 390 | + if ('dynamic' === $this->sitemap_generator->resolve_delivery_mode($settings)) { | |
| 391 | + $this->sitemap_generator->flush_dynamic_cache(); | |
| 392 | + | |
| 393 | + return $sitemap_url; | |
| 394 | + } | |
| 395 | + | |
| 371 | 396 | if ($this->sitemap_generator->primary_sitemap_file_exists($settings)) { |
| 372 | 397 | return $sitemap_url; |
| 373 | 398 | } |
| 374 | 399 | |
| @@ -437,8 +462,59 @@ | ||
| 437 | 462 | // generate_and_save() already does this on the automatic path; the |
| 438 | 463 | // manual generate route must match it. |
| 439 | 464 | $this->persist_promoted_mode($options); |
| 440 | 465 | |
| 466 | + // Dynamic delivery answers the sitemap URLs from PHP, so there is | |
| 467 | + // nothing to write. Every other sitemap write path already returns | |
| 468 | + // early here (class-sitemap-generator.php:2189 and :2313); this one | |
| 469 | + // did not, which broke the feature from both directions: on a | |
| 470 | + // read-only root — the case dynamic delivery exists for — the button | |
| 471 | + // reported 500 "Failed to save sitemap: sitemap.xml" while the URL | |
| 472 | + // was serving correctly, and on a writable root with dynamic chosen | |
| 473 | + // explicitly it wrote files the web server then served in place of | |
| 474 | + // the dynamic route. | |
| 475 | + // | |
| 476 | + // Regenerating here means dropping the rendered documents so the | |
| 477 | + // next request rebuilds them, and clearing any file left behind by | |
| 478 | + // an earlier static generation for the same reason. | |
| 479 | + if ('dynamic' === $this->sitemap_generator->resolve_delivery_mode($this->effective_settings($options))) { | |
| 480 | + $this->sitemap_generator->flush_dynamic_cache(); | |
| 481 | + | |
| 482 | + $removal = $this->sitemap_generator->delete_published_sitemaps(); | |
| 483 | + $stuck = is_array($removal['failed'] ?? null) ? $removal['failed'] : []; | |
| 484 | + | |
| 485 | + // A stale file shadows the dynamic route, so this is a real | |
| 486 | + // failure rather than a tidy-up that did not matter. Worded by | |
| 487 | + // the generator so this and its own rebuild paths cannot | |
| 488 | + // describe the same stuck files differently (#764). | |
| 489 | + if (!empty($stuck)) { | |
| 490 | + return new WP_Error( | |
| 491 | + 'sitemap_stale_files', | |
| 492 | + $this->sitemap_generator->stuck_files_message($stuck), | |
| 493 | + ['status' => 500] | |
| 494 | + ); | |
| 495 | + } | |
| 496 | + | |
| 497 | + // last_generated deliberately stays untouched: it means "these | |
| 498 | + // files are on disk", and primary_sitemap_file_exists() callers | |
| 499 | + // rely on that. clear_generation_record() drops a value left | |
| 500 | + // over from a previous static generation, so the admin stops | |
| 501 | + // linking to files that no longer exist. | |
| 502 | + $this->clear_generation_record(); | |
| 503 | + $this->sitemap_generator->mark_regeneration_complete(); | |
| 504 | + | |
| 505 | + return new WP_REST_Response([ | |
| 506 | + 'success' => true, | |
| 507 | + 'data' => [ | |
| 508 | + 'delivery_mode' => 'dynamic', | |
| 509 | + 'sitemap_url' => $this->sitemap_generator->get_primary_sitemap_url(), | |
| 510 | + 'generated_at' => gmdate('c'), | |
| 511 | + 'last_generated' => '', | |
| 512 | + ], | |
| 513 | + 'message' => __('Sitemap refreshed. WordPress serves it directly, so no files were written.', 'thinkrank'), | |
| 514 | + ]); | |
| 515 | + } | |
| 516 | + | |
| 441 | 517 | // Check if an index (multiple sitemaps) is configured |
| 442 | 518 | if (!empty($options['use_sitemap_index']) || (!empty($options['sitemap_urls']) && count($options['sitemap_urls']) > 1)) { |
| 443 | 519 | // Generate multiple sitemaps |
| 444 | 520 | $results = $this->sitemap_generator->generate_multiple_sitemaps($options); |
| @@ -935,8 +1011,18 @@ | ||
| 935 | 1011 | // Kept out of `settings` on purpose: this is generator state, |
| 936 | 1012 | // not something the settings POST round-trips. |
| 937 | 1013 | 'health' => $context_type === 'site' |
| 938 | 1014 | ? $this->sitemap_generator->get_regeneration_health() |
| 1015 | + : null, | |
| 1016 | + // `delivery_mode` in `settings` may still be 'auto', which | |
| 1017 | + // only the server can resolve (it depends on whether the web | |
| 1018 | + // root is writable). The admin screen needs the answer, not | |
| 1019 | + // the question: a dynamic site publishes no file, so gating | |
| 1020 | + // its sitemap links on `last_generated` — which dynamic | |
| 1021 | + // delivery deliberately never sets — left every link | |
| 1022 | + // permanently disabled. | |
| 1023 | + 'resolved_delivery_mode' => $context_type === 'site' | |
| 1024 | + ? $this->sitemap_generator->resolve_delivery_mode($settings) | |
| 939 | 1025 | : null |
| 940 | 1026 | ], |
| 941 | 1027 | 'message' => 'Sitemap settings retrieved successfully' |
| 942 | 1028 | ], 200); |