| @@ -100,10 +100,10 @@ | ||
| 100 | 100 | return false; |
| 101 | 101 | } |
| 102 | 102 | |
| 103 | 103 | # Parse saved domain + incoming URL |
| 104 | - $saved_domain = parse_url($saved['domain'], PHP_URL_HOST); | |
| 105 | - $incoming_domain = parse_url($url, PHP_URL_HOST); | |
| 104 | + $saved_domain = wp_parse_url($saved['domain'], PHP_URL_HOST); | |
| 105 | + $incoming_domain = wp_parse_url($url, PHP_URL_HOST); | |
| 106 | 106 | |
| 107 | 107 | # Domain mismatch - not crawled |
| 108 | 108 | if (empty($saved_domain) || empty($incoming_domain) || strcasecmp($saved_domain, $incoming_domain) !== 0) { |
| 109 | 109 | return false; |
| @@ -109,9 +109,9 @@ | ||
| 109 | 109 | return false; |
| 110 | 110 | } |
| 111 | 111 | |
| 112 | 112 | # Parse incoming path (ignore query string) |
| 113 | - $parsed_url = parse_url($url); | |
| 113 | + $parsed_url = wp_parse_url($url); | |
| 114 | 114 | $url_path = $parsed_url['path'] ?? '/'; |
| 115 | 115 | |
| 116 | 116 | # Ensure path starts with / but don't modify trailing slashes |
| 117 | 117 | # Otto stores paths exactly as they appear in URLs |
| @@ -196,8 +196,21 @@ | ||
| 196 | 196 | |
| 197 | 197 | # render route html |
| 198 | 198 | function render_route_html(){ |
| 199 | 199 | |
| 200 | + # Headless frontends do not consume WordPress-rendered HTML, so avoid | |
| 201 | + # suggestion lookups, buffering and internal fetches altogether. | |
| 202 | + # Falls back to a guarded direct read rather than skipping the check: | |
| 203 | + # silently skipping would render OTTO markup on a headless site. | |
| 204 | + # @phpstan-ignore-next-line function.alreadyNarrowedType | |
| 205 | + $headless = function_exists('metasync_headless_is_active') | |
| 206 | + ? metasync_headless_is_active() | |
| 207 | + : (class_exists('Metasync_Headless_Config') && Metasync_Headless_Config::is_active()); | |
| 208 | + | |
| 209 | + if ($headless) { | |
| 210 | + return; | |
| 211 | + } | |
| 212 | + | |
| 200 | 213 | # Clear per-request statics before any path runs. Harmless under PHP-FPM |
| 201 | 214 | # (the process ends with the request) but required under persistent-worker |
| 202 | 215 | # SAPIs, where a latched flag would silently disable cache capping and |
| 203 | 216 | # failure reporting for every later request in that worker. |
| @@ -298,15 +311,13 @@ | ||
| 298 | 311 | |
| 299 | 312 | # comment out for fixing pagination issues |
| 300 | 313 | # $route = rtrim($route, '/'); |
| 301 | 314 | |
| 302 | - # Now that OTTO has confirmed suggestions to apply to this URL, | |
| 303 | - # disable SiteGround SG Optimizer page caching for THIS request only. | |
| 304 | - # Doing it here (instead of unconditionally on the `wp` hook) ensures | |
| 305 | - # pages without OTTO suggestions keep being served from SG's page cache. | |
| 306 | - if (function_exists('metasync_otto_disable_sg_page_cache')) { | |
| 307 | - metasync_otto_disable_sg_page_cache(); | |
| 308 | - } | |
| 315 | + # SiteGround's page cache is no longer disabled up-front for every OTTO page. | |
| 316 | + # The cacheability decision now happens on the HTTP path in render_via_http(), | |
| 317 | + # AFTER the internal fetch — only session/form pages and incomplete renders are | |
| 318 | + # blocked, so plain content pages are finally cacheable. (SiteGround always uses | |
| 319 | + # the HTTP path; the disable is a no-op off SiteGround, so nothing else loses it.) | |
| 309 | 320 | |
| 310 | 321 | # Analyze what OTTO is providing for SEO plugin blocking |
| 311 | 322 | $blocking_flags = $this->analyze_otto_blocking($suggestions); |
| 312 | 323 | |
| @@ -680,8 +691,16 @@ | ||
| 680 | 691 | $route_html = $this->get_route_html($route, $cache_track_key, $suggestions); |
| 681 | 692 | |
| 682 | 693 | # check that route html is valid |
| 683 | 694 | if(empty($route_html)){ |
| 695 | + # Fetch failed / empty (e.g. SG Optimizer truncated the internal response) — | |
| 696 | + # WordPress will serve the un-optimized page. Cap how long that copy may be | |
| 697 | + # cached, using the same mechanism as the deliberate skips above rather than a | |
| 698 | + # second, competing one: it reconciles existing directives, keeps logged-in | |
| 699 | + # responses fully no-store, and never grants caching nothing had granted. | |
| 700 | + if (function_exists('metasync_otto_limit_response_cache')) { | |
| 701 | + metasync_otto_limit_response_cache('HTTP_FETCH_FAILED'); | |
| 702 | + } | |
| 684 | 703 | return false; |
| 685 | 704 | } |
| 686 | 705 | |
| 687 | 706 | $route_html_string = is_string($route_html) ? $route_html : $route_html->__toString(); |
| @@ -796,10 +815,31 @@ | ||
| 796 | 815 | } |
| 797 | 816 | } |
| 798 | 817 | } |
| 799 | 818 | |
| 819 | + # Decide cacheability from the internal fetch + the final output, then serve. | |
| 820 | + # 1) Hand the visitor the session their page was built around (fixes forms that | |
| 821 | + # were silently failing on the HTTP path because the fetch cookie was dropped). | |
| 822 | + # 2) Block shared caching when the fetched page set a cookie, when its own render | |
| 823 | + # declared itself uncacheable (PHP's session cache-limiter — true for resumed | |
| 824 | + # sessions too), when the visitor carries cart/auth cookies that change the | |
| 825 | + # rendered content, or when the render came back incomplete. | |
| 826 | + # 3) A plain, complete page gets no cache header at all → the host finally caches | |
| 827 | + # it (the SiteGround/Oxygen relief this ticket is about). | |
| 828 | + Metasync_Otto_Render_Strategy::passthrough_http_fetch_cookies(); | |
| 829 | + | |
| 830 | + $must_not_cache = | |
| 831 | + Metasync_Otto_Render_Strategy::http_fetch_had_cookie() | |
| 832 | + || Metasync_Otto_Render_Strategy::http_fetch_no_cache() | |
| 833 | + || Metasync_Otto_Render_Strategy::request_has_visitor_specific_cookie() | |
| 834 | + || !Metasync_Otto_Render_Strategy::http_output_is_complete($route_html_string); | |
| 835 | + | |
| 800 | 836 | # Send response headers |
| 801 | 837 | Metasync_Otto_Render_Strategy::send_headers($cache_status); |
| 838 | + | |
| 839 | + if ($must_not_cache) { | |
| 840 | + Metasync_Otto_Render_Strategy::block_http_cache(); | |
| 841 | + } | |
| 802 | 842 | |
| 803 | 843 | # continue to render the html |
| 804 | 844 | echo $route_html_string; |
| 805 | 845 | |