Skip to content

Release - #1137

Open
pirate-bot wants to merge 13 commits into
masterfrom
development
Open

Release#1137
pirate-bot wants to merge 13 commits into
masterfrom
development

Conversation

@pirate-bot

@pirate-bot pirate-bot commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Linked issues

This release will close the following issues once merged:

Public changelog

  • Fixed Jetpack conflict warnings when its image Site Accelerator is disabled.
  • Fixed unwanted cache headers on cart, checkout, and other non-cacheable pages.
  • Fixed viewport lazy loading crashes when saved page profiles use object data.
  • Fixed dashboard image polling when the image service returns an error.
  • Fixed replaced media files keeping restrictive permissions.
  • Fixed frontend fatal errors when Optimole rewrites image URLs.

pirate-bot and others added 6 commits August 26, 2026 12:57
Bumps [codeinwp/themeisle-sdk](https://github.com/Codeinwp/themeisle-sdk) from 3.3.58 to 3.3.61.
- [Release notes](https://github.com/Codeinwp/themeisle-sdk/releases)
- [Changelog](https://github.com/Codeinwp/themeisle-sdk/blob/v3.3.61/CHANGELOG.md)
- [Commits](Codeinwp/themeisle-sdk@v3.3.58...v3.3.61)

---
updated-dependencies:
- dependency-name: codeinwp/themeisle-sdk
  dependency-version: 3.3.61
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* fix: gate Jetpack conflict notice on Photon

* refactor: centralize Jetpack Photon status

* refactor: register Photon conflict as compatibility
@pirate-bot

pirate-bot commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator Author

Plugin build for d6cc7b5 is ready 🛎️!

selul and others added 7 commits September 2, 2026 13:18
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…overs this repo) [skip ci]

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
While page profiling is pending, replace_content() sent
'Cache-Control: max-age=300' for every not-logged-in request with
headers still unsent. Because PHP's header() replaces same-name
headers, it overwrote the no-cache header WooCommerce sets on cart,
checkout and account pages, letting proxies cache user-specific pages
for five minutes.

The header is now sent only when DONOTCACHEPAGE is not set and no
Cache-Control header exists yet, so a no-cache or longer-lived policy
set by WordPress, WooCommerce or a cache plugin is never overridden.
The new optml_send_temporary_cache_header filter lets developers
override the decision in both directions.

Fixes #1082

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* fix: coerce object-shaped page profiles before viewport lookup

Object-cache backends that JSON-decode without associative arrays store profiler payloads as stdClass, which fatals on ['af'] access during frontend lazyload. Normalize storage reads and guard device lookups.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: drop stale PHPStan baseline entries for typed storage get()

Co-authored-by: Cursor <cursoragent@cursor.com>

* refactor: keep object-shaped profile fix at the storage boundary

Drop per-lookup Profile/Lazyload guards now that storage get() normalizes stdClass. Keep the LCP imageId null coalesce. Seed tests through transients instead of reflection.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
get_optimized_images() can return WP_Error or false on transport and API failures. Guard poll_optimized_images() so dashboard polling degrades to an empty list instead of fatalling.

Co-authored-by: Cursor <cursoragent@cursor.com>
* fix: normalize file permissions during replacement

* fix: improve file permission handling

* fix: phpunit

* fix: improve error message

* fix: reuse existing generic error for permission failure

The permission failure isn't actionable by the user, so reuse the
already-translated "Error replacing file" string instead of adding a new
untranslated one.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: selul <marius.cristea@vertistudio.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
…1132)

* fix: process page HTML outside PHP's output-buffer display handler

Running replace_content() as the ob_start() display handler meant any
output-buffering call from third-party code hooked into our filters was
a fatal error, and any real fatal during processing (e.g. memory
exhaustion) was masked as "Cannot use output buffering in output
buffering display handlers" with a misleading crash location.

The buffer is now a plain capture: close_buffer() flushes third-party
buffers stacked above ours, captures our own by its recorded nesting
level (never popping someone else's buffer), processes the HTML in
normal execution context and re-arms the capture so late shutdown
output is still handled. The attached handler remains only as a
fallback that keeps the previous behavior when third-party code
flushes our buffer mid-request.

Also replaces the per-URL full-page preg_replace() loop with chunked
single-pass replacement to reduce peak memory on large pages, the
likely trigger of the masked production fatals.

Fixes #1126

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix: bound URL replacement chunks by pattern size, not only count

A chunk of 200 very long URLs (e.g. signed CDN URLs with kilobyte-sized
query strings) could exceed PCRE's ~64KB compiled-pattern limit, failing
the whole chunk and leaving those URLs unreplaced. Chunks now flush when
the accumulated quoted pattern reaches 24KB, so compilation always
succeeds regardless of URL length, and a failed chunk is logged via
optml_log instead of being silently skipped.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* perf: apply URL replacement chunks as they fill

Building every chunk's bookkeeping up front held all origin/replacement
maps in memory at once, which cost about 1MB extra on pages with
thousands of URLs. Each chunk is now applied as soon as it fills, so
only one chunk's bookkeeping exists at a time; peak memory is now at or
below the old per-URL loop at every scale.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix: address review — no in-handler processing, real buffer ownership

P1: the fallback handler no longer runs replace_content() when a third
party flushes our buffer early. The ob-in-handler fatal is an engine
E_ERROR that catch (Throwable) cannot intercept, so processing there
reintroduced the crash this rework removes; early-flushed content is
now passed through unprocessed and logged. Only the explicit legacy
mode (optml_capture_at_shutdown false) keeps in-handler processing.

P2: buffer ownership is now verified by handler identity, not nesting
level alone. The capture buffer uses a named method handler so
ob_get_status()['name'] reports Optml_Manager::handle_buffer_fallback,
and capture_and_process_buffer() refuses any buffer that does not
carry it — a foreign buffer at our recorded level is never consumed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment