Codeinwp / Codeinwp/optimole-wp
4.2.12 regression: close_buffer() at shutdown PHP_INT_MIN flushes other plugins' buffers, breaks Groovy Menu
@selul is already working on this.
Since Sep 15, 2026.
- Dominant language
- PHP
- Stars
- 72
- Forks
- 14
- Avg merge
- 2d 9h
- Merged PRs (30d)
- 15
Description
Description
Since 4.2.12 (PR #1132, "process page HTML outside PHP's output-buffer display handler"), Groovy Menu's header menu no longer appears on the front end. Rolling back to 4.2.11 fixes it. So does adding add_filter( 'optml_capture_at_shutdown', '__return_false' ); on 4.2.12.
Cause: Groovy Menu's Divi auto-integration starts its own output buffer on init (priority 0). On shutdown (priority 0) it runs ob_get_clean() and inserts the menu HTML after <body>. In 4.2.12, Optml_Manager::close_buffer() is hooked to shutdown at PHP_INT_MIN (inc/manager.php:428) and flushes every buffer above Optimole's own:
while ( ob_get_level() > self::$ob_level ) { if ( ! @ob_end_flush() ) { break; } }
That flushes Groovy Menu's buffer before Groovy's shutdown callback runs. Groovy then gets Optimole's empty buffer, finds no <body>, and the fully generated menu HTML (~40 KB) is thrown away.
Expected: the Groovy Menu is inserted into the page, as it was on 4.2.11.
Actual: the menu markup is missing on every page. Only Groovy Menu's inline JS settings are printed.
Step-by-step reproduction instructions
- Install the Divi theme and Groovy Menu (premium) and enable Groovy Menu's auto-integration for Divi. Assign a menu to the "Groovy menu Primary" location.
- Install Optimole 4.2.12 (or 4.2.13), connect it, and leave image replacement enabled.
- Load any front-end page with page caching bypassed.
- The Groovy Menu markup (
.gm-navbar,.gm-preset-id-*wrapper) is missing from the HTML. - Roll back to Optimole 4.2.11, or add
add_filter( 'optml_capture_at_shutdown', '__return_false' );, and reload: the menu appears.
Screenshots, screen recording, code snippet or Help Scout ticket
Buffer stack traced on an uncached render (PHP CLI, same page):
- After the template finishes, ob_level=5:
Optml_Manager::handle_buffer_fallback → default output handler (Groovy Menu) → SiteGround_Optimizer\Parser\Parser::run → hefo_callback → wp_finalize_template_enhancement_output_buffer - At
shutdownpriority -1, ob_level=1: only Optml_Manager::handle_buffer_fallback remains - Groovy's
groovy_menu_final_outputfilter receives a string of length 0
Same render with optml_capture_at_shutdown → false: Groovy receives the full page (~188 KB) and the menu is inserted.
On a live site the menu disappeared the morning after the auto-update to 4.2.12. It came back after rolling back to 4.2.11.
Possible directions:
- Run the flush/capture later in
shutdown(after default-priority callbacks) instead of at PHP_INT_MIN. - If other buffers are still open above Optimole's, fall back to the pre-4.2.12 behaviour instead of force-flushing them.
- At minimum, document
optml_capture_at_shutdownas a supported compatibility switch.
Environment info
WordPress 7.1, PHP 8.2.33, Optimole 4.2.12/4.2.13 (last working: 4.2.11), Divi 4.27.7, Groovy Menu 2.6.5, WP Rocket 3.23.x, SiteGround Optimizer 7.8.x, Header and Footer 3.3.6
Is the issue you are reporting a regression
Yes, this is a regression.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.