Skip to content

Commit

Permalink
Blueprints: Detect silent failures when activating plugins and theme (#…
Browse files Browse the repository at this point in the history
…1436)

The `activatePlugin` and `activateTheme` steps may fail silently and
without any feedback for the developer. This PR adds safeguards in place
to throw an error if the specified plugin or theme is not active once
the step is finished.

 ## Testing instructions

Confirm the CI checks passed
  • Loading branch information
adamziel authored May 20, 2024
1 parent 350a374 commit 8fb2623
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ describe('Blueprint step activatePlugin()', () => {
`<?php /**\n * Plugin Name: Test Plugin */`
);
await activatePlugin(php, {
pluginPath: docroot + '/wp-content/plugins/test-plugin.php',
pluginPath: 'test-plugin.php',
});

const response = await php.run({
Expand All @@ -41,6 +41,24 @@ describe('Blueprint step activatePlugin()', () => {
expect(response.text).toBe('true');
});

it('should detect a silent failure in activating the plugin', async () => {
const docroot = php.documentRoot;
php.writeFile(
`/${docroot}/wp-content/plugins/test-plugin.php`,
`<?php /**\n * Plugin Name: Test Plugin */`
);
php.writeFile(
`/${docroot}/wp-content/mu-plugins/0-exit.php`,
`<?php exit(0); `
);
expect(
async () =>
await activatePlugin(php, {
pluginPath: 'test-plugin.php',
})
).rejects.toThrow(/Plugin test-plugin.php could not be activated/);
});

it('should run the activation hooks as a priviliged user', async () => {
const docroot = php.documentRoot;
const createdFilePath =
Expand All @@ -56,7 +74,7 @@ describe('Blueprint step activatePlugin()', () => {
`
);
await activatePlugin(php, {
pluginPath: docroot + '/wp-content/plugins/test-plugin.php',
pluginPath: 'test-plugin.php',
});

expect(php.fileExists(createdFilePath)).toBe(true);
Expand Down
12 changes: 11 additions & 1 deletion packages/playground/blueprints/src/lib/steps/activate-plugin.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { phpVar } from '@php-wasm/util';
import { StepHandler } from '.';
import { logger } from '@php-wasm/logger';

/**
* @inheritDoc activatePlugin
Expand Down Expand Up @@ -34,7 +35,7 @@ export const activatePlugin: StepHandler<ActivatePluginStep> = async (
progress?.tracker.setCaption(`Activating ${pluginName || pluginPath}`);

const docroot = await playground.documentRoot;
await playground.run({
const result = await playground.run({
code: `<?php
define( 'WP_ADMIN', true );
require_once( ${phpVar(docroot)}. "/wp-load.php" );
Expand Down Expand Up @@ -69,4 +70,13 @@ export const activatePlugin: StepHandler<ActivatePluginStep> = async (
throw new Exception( 'Unable to activate plugin' );
`,
});
if (result.text !== 'Plugin activated successfully') {
logger.debug(result);
throw new Error(
`Plugin ${pluginPath} could not be activated – WordPress exited with no error. ` +
`Sometimes, when $_SERVER or site options are not configured correctly, ` +
`WordPress exits early with a 301 redirect. ` +
`Inspect the "debug" logs in the console for more details`
);
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,28 @@ describe('Blueprint step activateTheme()', () => {

expect(php.fileExists(createdFilePath)).toBe(true);
});

it('should detect a silent failure in activating the theme', async () => {
const docroot = php.documentRoot;
php.mkdir(`${docroot}/wp-content/themes/test-theme`);
php.writeFile(
`${docroot}/wp-content/themes/test-theme/style.css`,
`/**
* Theme Name: Test Theme
* Theme URI: https://example.com/test-theme
* Author: Test Author
*/
`
);
php.writeFile(
`/${docroot}/wp-content/mu-plugins/0-exit.php`,
`<?php exit(0); `
);
expect(
async () =>
await activateTheme(php, {
themeFolderName: 'test-theme',
})
).rejects.toThrow(/Theme test-theme could not be activated/);
});
});
26 changes: 22 additions & 4 deletions packages/playground/blueprints/src/lib/steps/activate-theme.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { phpVar } from '@php-wasm/util';
import { StepHandler } from '.';
import { logger } from '@php-wasm/logger';

/**
* @inheritDoc activateTheme
Expand Down Expand Up @@ -44,15 +44,33 @@ export const activateTheme: StepHandler<ActivateThemeStep> = async (
More info can be found in the Blueprint documentation: https://wordpress.github.io/wordpress-playground/blueprints-api/steps/#ActivateThemeStep
`);
}
await playground.run({
const result = await playground.run({
code: `<?php
define( 'WP_ADMIN', true );
require_once( ${phpVar(docroot)}. "/wp-load.php" );
require_once( getenv('docroot') . "/wp-load.php" );
// Set current user to admin
wp_set_current_user( get_users(array('role' => 'Administrator') )[0]->ID );
switch_theme( ${phpVar(themeFolderName)} );
switch_theme( getenv('themeFolderName') );
if( wp_get_theme()->get_stylesheet() !== getenv('themeFolderName') ) {
throw new Exception( 'Theme ' . getenv('themeFolderName') . ' could not be activated.' );
}
die('Theme activated successfully');
`,
env: {
docroot,
themeFolderName,
},
});
if (result.text !== 'Theme activated successfully') {
logger.debug(result);
throw new Error(
`Theme ${themeFolderName} could not be activated – WordPress exited with no error. ` +
`Sometimes, when $_SERVER or site options are not configured correctly, ` +
`WordPress exits early with a 301 redirect. ` +
`Inspect the "debug" logs in the console for more details`
);
}
};

0 comments on commit 8fb2623

Please sign in to comment.