$runcache_value) { // Skip internal headers. Cast to string to prevent type errors. $runcache_nameStr = (string)$runcache_name; $runcache_valueStr = (string)$runcache_value; if (stripos($runcache_nameStr, 'X-RunCache-') !== 0) { header("$runcache_nameStr: $runcache_valueStr"); } } } header('X-RunCache-Status: HIT'); if ($runcache_body_gzip) { header('Content-Encoding: gzip'); header('Vary: Accept-Encoding', false); } echo $runcache_body; exit; } // Read failure: fall through to the MISS path. } // The scheduled cleanup task removes expired entries. } // ===== CACHE MISS: BUFFER AND STORE ===== $runcache_expiry = $runcache_config['cache_expiry'] ?? 28800; $runcache_gzip = $runcache_config['gzip_enabled'] ?? false; header('X-RunCache-Status: MISS'); // Record the buffer level before our buffer opens. The shutdown // function closes only the buffers this handler owns. $runcache_ob_level = ob_get_level(); ob_start(static function (string $content) use ($runcache_config, $runcache_file_html, $runcache_file_meta, $runcache_expiry, $runcache_gzip): string { // Skip empty bodies and non-200 responses. if ($content === '' || http_response_code() !== 200) { return $content; } $cache_dir = dirname($runcache_file_html); if (!is_dir($cache_dir)) { // This drop-in runs before WP_Filesystem is available. // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_mkdir -- Early cache writes cannot initialize WP_Filesystem during request handling. if (!@mkdir($cache_dir, 0755, true)) { return $content; } } // Capture the response headers before the cache decision. $headers = []; foreach (headers_list() as $header) { if (str_contains($header, ':')) { $parts = explode(':', $header, 2); $key = trim($parts[0]); // Skip the X-RunCache headers to avoid duplicates. if (stripos($key, 'X-RunCache-') !== 0) { $headers[$key] = trim($parts[1] ?? ''); } } } $cache_control = ''; foreach ($headers as $header_name => $header_value) { if (strcasecmp((string) $header_name, 'Cache-Control') === 0) { $cache_control = strtolower((string) $header_value); break; } } if (preg_match('/(?:^|,)\s*(?:no-store|no-cache|private)(?:\s*=|\s*(?:,|$))/i', $cache_control)) { return $content; } $headers['Cache-Control'] = 's-maxage=' . (int) $runcache_expiry . ', max-age=60'; $meta = [ 'time' => time(), 'expires' => time() + (int) $runcache_expiry, 'headers' => $headers, ]; // Write the gzip file first. Store its size in the meta. if (!empty($runcache_config['gzip_enabled']) && function_exists('gzencode')) { $gzipped = gzencode($content, 6); if ($gzipped && file_put_contents($runcache_file_html . '.gz', $gzipped) !== false) { $meta['gzip_size'] = strlen($gzipped); } } // Write the meta file and the page. $meta_written = file_put_contents($runcache_file_meta, json_encode($meta)) !== false; $body_written = file_put_contents($runcache_file_html, $content) !== false; // Send STORE only when both writes succeed. if ($meta_written && $body_written && !headers_sent()) { header('X-RunCache-Status: STORE'); } return $content; }); // Close the buffers this handler opened. The shutdown function runs // before PHP flushes. The cache callback always completes. register_shutdown_function(static function () use ($runcache_ob_level) { while (ob_get_level() > $runcache_ob_level) { if (!@ob_end_flush()) { break; } } });