| @@ -547,8 +547,10 @@ | ||
| 547 | 547 | // Bail if not SureForms post type. |
| 548 | 548 | return $template; |
| 549 | 549 | } |
| 550 | 550 | |
| 551 | + self::reset_printed_assets(); | |
| 552 | + | |
| 551 | 553 | $file_name = 'single-form.php'; |
| 552 | 554 | $template = locate_template( $file_name ); |
| 553 | 555 | |
| 554 | 556 | /** |
| @@ -556,7 +558,45 @@ | ||
| 556 | 558 | * |
| 557 | 559 | * @since 0.0.1 |
| 558 | 560 | */ |
| 559 | 561 | return apply_filters( 'srfm_form_template', $template ? $template : SRFM_DIR . '/templates/' . $file_name ); |
| 562 | + } | |
| 563 | + | |
| 564 | + /** | |
| 565 | + * Let the Instant Form template print assets a discarded render already claimed. | |
| 566 | + * | |
| 567 | + * `page_template()` runs on `template_include` at PHP_INT_MAX and returns the | |
| 568 | + * Instant Form template regardless of what earlier filters returned. A page | |
| 569 | + * builder that renders the whole page inside its own `template_include` | |
| 570 | + * filter has therefore already run `wp_head()` and `wp_footer()` into an | |
| 571 | + * output buffer that is about to be thrown away. | |
| 572 | + * | |
| 573 | + * The buffer goes, but `WP_Styles::$done` and `WP_Scripts::$done` still hold | |
| 574 | + * every handle it claimed, so `do_items()` skips them when `single-form.php` | |
| 575 | + * calls `wp_head()` and `wp_footer()` for real. The form arrives with no | |
| 576 | + * stylesheets, and -- because `srfm-form-submit` is registered for the footer | |
| 577 | + * -- no submit handler either. | |
| 578 | + * | |
| 579 | + * Clearing both `done` lists wholesale is the right scope rather than an | |
| 580 | + * over-broad one: only the render that begins after this filter returns | |
| 581 | + * reaches the browser, so nothing recorded before it was ever delivered. The | |
| 582 | + * handles are re-enqueued by the second `wp_enqueue_scripts` pass, so they | |
| 583 | + * print normally once `done` stops shadowing them. | |
| 584 | + * | |
| 585 | + * Guarded on `wp_head` having already fired, so this is inert on the ordinary | |
| 586 | + * path where no builder rendered first and nothing has been printed yet. | |
| 587 | + * | |
| 588 | + * @since 2.12.7 | |
| 589 | + * @return void | |
| 590 | + */ | |
| 591 | + private static function reset_printed_assets() { | |
| 592 | + // No earlier wp_head() means no discarded render, so there is nothing to | |
| 593 | + // forget. Deny is the fallthrough: act only on the state this repairs. | |
| 594 | + if ( ! did_action( 'wp_head' ) ) { | |
| 595 | + return; | |
| 596 | + } | |
| 597 | + | |
| 598 | + wp_styles()->done = []; | |
| 599 | + wp_scripts()->done = []; | |
| 560 | 600 | } |
| 561 | 601 | |
| 562 | 602 | } |