Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Blueprints] Prevent WSOD when autologin is enabled and a plugin logs a notice #2079

Merged
merged 1 commit into from
Dec 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions packages/playground/website/playwright/e2e/blueprints.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: `<?php
echo 'This is a notice printed by an mu-plugin.';
`,
},
],
};

const encodedBlueprint = JSON.stringify(blueprint);
await website.goto(`./#${encodedBlueprint}`);

// Wait for the page to load and verify it contains both WordPress content and the notice
await expect(wordpress.locator('body')).toContainText(
'Welcome to WordPress. This is your first post.'
);

// Verify there's no admin bar
await expect(wordpress.locator('body')).not.toContainText('Dashboard');
});
30 changes: 30 additions & 0 deletions packages/playground/wordpress/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,15 +147,45 @@ export async function setupPlatformLevelMuPlugins(php: UniversalPHP) {
if (!$user) {
return;
}

/**
* We're about to set cookies and redirect. It will log the user in
* if the headers haven't been sent yet.
*
* However, if they have been sent already – e.g. there a PHP
* notice was printed, we'll exit the script with a bunch of errors
* on the screen and without the user being logged in. This
* will happen on every page load and will effectively make Playground
* unusable.
*
* Therefore, we just won't auto-login if headers have been sent. Maybe
* we'll be able to finish the operation in one of the future requests
* or maybe not, but at least we won't end up with a permanent white screen.
*/
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;
}

/**
* This approach is described in a comment on
* https://developer.wordpress.org/reference/functions/wp_set_current_user/
*/
wp_set_current_user( $user->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,
Expand Down
Loading