Skip to content

Commit

Permalink
Add installPlugin support for single plugin files (#2033)
Browse files Browse the repository at this point in the history
## Motivation for the change, related issues

When testing #2029, I wanted to be able to install a plugin from a
single PHP file and have it activated as part of the same step. This
seemed reasonable, so I added support.

## Implementation details

Prior to this PR, if the `installPlugin` step received a file resource
it assumed it was a Zip file. This PR generally continues that practice
but makes an exception for file names ending with a `.php` extension.
File with names ending with `.php` are simply written to
`wp-content/plugins/<filename>`.

## Testing Instructions (or ideally a Blueprint)

CI - this PR adds a relevant unit test
  • Loading branch information
brandonpayton authored Nov 28, 2024
1 parent 986b0d9 commit 6c54e29
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -535,7 +535,7 @@ const schema11 = {
{ $ref: '#/definitions/DirectoryReference' },
],
description:
'The plugin files to install. It can be either a plugin zip file, or a directory containing all the plugin files at its root.',
'The plugin files to install. It can be a plugin zip file, a single PHP file, or a directory containing all the plugin files at its root.',
},
pluginZipFile: {
$ref: '#/definitions/FileReference',
Expand Down Expand Up @@ -3225,7 +3225,7 @@ const schema22 = {
{ $ref: '#/definitions/DirectoryReference' },
],
description:
'The plugin files to install. It can be either a plugin zip file, or a directory containing all the plugin files at its root.',
'The plugin files to install. It can be a plugin zip file, a single PHP file, or a directory containing all the plugin files at its root.',
},
pluginZipFile: {
$ref: '#/definitions/FileReference',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -647,7 +647,7 @@
"$ref": "#/definitions/DirectoryReference"
}
],
"description": "The plugin files to install. It can be either a plugin zip file, or a directory containing all the plugin files at its root."
"description": "The plugin files to install. It can be a plugin zip file, a single PHP file, or a directory containing all the plugin files at its root."
},
"pluginZipFile": {
"$ref": "#/definitions/FileReference",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ describe('Blueprint step installPlugin', () => {
let php: PHP;
// Create plugins folder
let rootPath = '';
let pluginsPath = '';
let installedPluginPath = '';
const pluginName = 'test-plugin';
const zipFileName = `${pluginName}-0.0.1.zip`;
Expand All @@ -80,8 +81,9 @@ describe('Blueprint step installPlugin', () => {
php = await handler.getPrimaryPhp();

rootPath = php.documentRoot;
php.mkdir(`${rootPath}/wp-content/plugins`);
installedPluginPath = `${rootPath}/wp-content/plugins/${pluginName}`;
pluginsPath = `${rootPath}/wp-content/plugins`;
php.mkdir(pluginsPath);
installedPluginPath = `${pluginsPath}/${pluginName}`;
});

it('should install a plugin', async () => {
Expand All @@ -97,6 +99,23 @@ describe('Blueprint step installPlugin', () => {
expect(php.fileExists(installedPluginPath)).toBe(true);
});

it('should install a single PHP file as a plugin', async () => {
const rawPluginContent = `<?php\n/**\n * Plugin Name: Test Plugin`;
await installPlugin(php, {
pluginData: new File(
[new TextEncoder().encode(rawPluginContent)],
'test-plugin.php'
),
ifAlreadyInstalled: 'overwrite',
options: {
activate: false,
},
});
const pluginFilePath = `${pluginsPath}/test-plugin.php`;
expect(php.fileExists(pluginFilePath)).toBe(true);
expect(php.readFileAsText(pluginFilePath)).toBe(rawPluginContent);
});

it('should install a plugin using the deprecated pluginZipFile option', async () => {
// @ts-ignore
await installPlugin(php, {
Expand Down
58 changes: 40 additions & 18 deletions packages/playground/blueprints/src/lib/steps/install-plugin.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { StepHandler } from '.';
import { InstallAssetOptions, installAsset } from './install-asset';
import { activatePlugin } from './activate-plugin';
import { writeFile } from './write-file';
import { zipNameToHumanName } from '../utils/zip-name-to-human-name';
import { Directory } from '../resources';
import { joinPaths } from '@php-wasm/util';
Expand Down Expand Up @@ -51,8 +52,8 @@ export interface InstallPluginStep<FileResource, DirectoryResource>
*/
step: 'installPlugin';
/**
* The plugin files to install. It can be either a plugin zip file, or a
* directory containing all the plugin files at its root.
* The plugin files to install. It can be a plugin zip file, a single PHP
* file, or a directory containing all the plugin files at its root.
*/
pluginData: FileResource | DirectoryResource;

Expand Down Expand Up @@ -99,31 +100,52 @@ export const installPlugin: StepHandler<
);
}

const targetFolderName = 'targetFolderName' in options ? options.targetFolderName : '';
const pluginsDirectoryPath = joinPaths(
await playground.documentRoot,
'wp-content',
'plugins'
);
const targetFolderName =
'targetFolderName' in options ? options.targetFolderName : '';
let assetFolderPath = '';
let assetNiceName = '';
if (pluginData instanceof File) {
// @TODO: Consider validating whether this is a zip file?
const zipFileName = pluginData.name.split('/').pop() || 'plugin.zip';
assetNiceName = zipNameToHumanName(zipFileName);
if (pluginData.name.endsWith('.php')) {
const destinationFilePath = joinPaths(
pluginsDirectoryPath,
pluginData.name
);
await writeFile(playground, {
path: destinationFilePath,
data: pluginData,
});
assetFolderPath = pluginsDirectoryPath;
assetNiceName = pluginData.name;
} else {
// Assume any other file is a zip file
// @TODO: Consider validating whether this is a zip file?
const zipFileName =
pluginData.name.split('/').pop() || 'plugin.zip';
assetNiceName = zipNameToHumanName(zipFileName);

progress?.tracker.setCaption(`Installing the ${assetNiceName} plugin`);
const assetResult = await installAsset(playground, {
ifAlreadyInstalled,
zipFile: pluginData,
targetPath: `${await playground.documentRoot}/wp-content/plugins`,
targetFolderName: targetFolderName
});
assetFolderPath = assetResult.assetFolderPath;
assetNiceName = assetResult.assetFolderName;
progress?.tracker.setCaption(
`Installing the ${assetNiceName} plugin`
);
const assetResult = await installAsset(playground, {
ifAlreadyInstalled,
zipFile: pluginData,
targetPath: `${await playground.documentRoot}/wp-content/plugins`,
targetFolderName: targetFolderName,
});
assetFolderPath = assetResult.assetFolderPath;
assetNiceName = assetResult.assetFolderName;
}
} else if (pluginData) {
assetNiceName = pluginData.name;
progress?.tracker.setCaption(`Installing the ${assetNiceName} plugin`);

const pluginDirectoryPath = joinPaths(
await playground.documentRoot,
'wp-content',
'plugins',
pluginsDirectoryPath,
targetFolderName || pluginData.name
);
await writeFiles(playground, pluginDirectoryPath, pluginData.files, {
Expand Down

0 comments on commit 6c54e29

Please sign in to comment.