From 1bed67210da09c5605ea49f553c89c7ae1fc4ca8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Zieli=C5=84ski?= Date: Tue, 17 Dec 2024 17:19:01 +0100 Subject: [PATCH] [Blueprints] Prevent WSOD when autologin is enabled and a plugin logs a notice (#2079) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR ensures the autologin step won't cause a perpetual white screen of death when one of the plugins displays a notice. The autologin flow consists of a bunch of checks, setcookie() call, a header('Location') call, and an `exit;`. However, when the headers are already sent, the cookies won't be set, the redirect won't work, but the script will still. This, effectively, prevents loading any WordPress page. This PR adds a `headers_sent()` check to stop the autologin step early in those scenarios when we can't finish the login. ## Testing instructions * CI has a new E2E test – confirm everything is green * Try this Blueprint (courtesy of @janw-me). It should open a white screen with errors. Now change the landing page to "/". It should open the homepage with a few errors at the top. Before this PR, you'd see a blank page instead of the homepage. ```json { "plugins": [ "pronamic-ideal" ], "preferredVersions": { "php": "8.2", "wp": "6.7" }, "features": { "networking": true }, "login": true, "landingPage": "/wp-admin/update-core.php", "steps": [ { "step": "defineWpConfigConsts", "consts": { "WP_DEBUG": true, "WP_DEBUG_DISPLAY": true } }, { "step": "setSiteLanguage", "language": "nl_NL" } ] } ``` --- .../website/playwright/e2e/blueprints.spec.ts | 42 +++++++++++++++++++ packages/playground/wordpress/src/index.ts | 30 +++++++++++++ 2 files changed, 72 insertions(+) diff --git a/packages/playground/website/playwright/e2e/blueprints.spec.ts b/packages/playground/website/playwright/e2e/blueprints.spec.ts index 45eadef70d..f944baac40 100644 --- a/packages/playground/website/playwright/e2e/blueprints.spec.ts +++ b/packages/playground/website/playwright/e2e/blueprints.spec.ts @@ -449,3 +449,45 @@ test('should correctly redirect to a multisite wp-admin url', async ({ await expect(wordpress.locator('body')).toContainText('Escritorio'); }); }); + +test('WordPress homepage loads when mu-plugin prints a notice', async ({ + wordpress, + website, + page, +}) => { + // Load a blueprint that enables debug mode and adds a mu-plugin that prints a notice + const blueprint = { + landingPage: '/', + preferredVersions: { + wp: '6.7', + php: '8.0', + }, + steps: [ + { + step: 'defineWpConfigConsts', + consts: { + WP_DEBUG: true, + WP_DEBUG_DISPLAY: true, + }, + }, + { + step: 'writeFile', + path: '/wordpress/wp-content/mu-plugins/000-print-notice.php', + data: `ID, $user->user_login ); wp_set_auth_cookie( $user->ID ); do_action( 'wp_login', $user->user_login, $user ); + setcookie('playground_auto_login_already_happened', '1'); + /** + * Confirm that nothing in WordPress, plugins, or filters have finalized + * the headers sending phase. See the comment above for more context. + */ + if (headers_sent()) { + _doing_it_wrong('playground_auto_login', 'Headers already sent, the Playground runtime will not auto-login the user', '1.0.0'); + return; + } + /** * Reload page to ensure the user is logged in correctly. * WordPress uses cookies to determine if the user is logged in,