Skip to content

Commit

Permalink
wp-now: accept arguments for wp-now php command (#451)
Browse files Browse the repository at this point in the history
Accept multiple arguments for `wp-now php` command. Solves WordPress/wordpress-playground#437

To test, run `wp-now php --php=8.2 -- example.php --foo=bar --php=7.4`. Observe the output `This is "example.php" file and the php version is: 8.2.0-dev`
  • Loading branch information
sejas authored May 30, 2023
1 parent 6170984 commit 56f55a6
Show file tree
Hide file tree
Showing 11 changed files with 193 additions and 106 deletions.
44 changes: 0 additions & 44 deletions packages/wp-now/src/execute-php-file.ts

This file was deleted.

40 changes: 40 additions & 0 deletions packages/wp-now/src/execute-php.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import startWPNow from './wp-now';
import { WPNowOptions } from './config';
import { disableOutput } from './output';

/**
* Execute a PHP cli given its parameters.
*
* @param phpArgs - Arguments to pass to the PHP cli. The first argument should be the string 'php'.
* @param options - Optional configuration object for WPNow. Defaults to an empty object.
* @returns - Returns a Promise that resolves to an object containing
* the exit name and status (0 for success).
* @throws - Throws an error if the first element in phpArgs is not the string 'php'.
*/
export async function executePHP(
phpArgs: string[],
options: WPNowOptions = {}
) {
if (phpArgs[0] !== 'php') {
throw new Error(
'The first argument to executePHP must be the string "php".'
);
}
disableOutput();
const { phpInstances } = await startWPNow({
...options,
numberOfPhpInstances: 2,
});
const [, php] = phpInstances;

try {
php.useHostFilesystem();
await php.cli(phpArgs);
} catch (resultOrError) {
const success =
resultOrError.name === 'ExitStatus' && resultOrError.status === 0;
if (!success) {
throw resultOrError;
}
}
}
36 changes: 21 additions & 15 deletions packages/wp-now/src/run-cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import { hideBin } from 'yargs/helpers';
import { startServer } from './start-server';
import { portFinder } from './port-finder';
import { SupportedPHPVersion } from '@php-wasm/universal';
import getWpNowConfig from './config';
import getWpNowConfig, { CliOptions } from './config';
import { spawn, SpawnOptionsWithoutStdio } from 'child_process';
import { executePHPFile } from './execute-php-file';
import { executePHP } from './execute-php';
import { output } from './output';

function startSpinner(message: string) {
Expand Down Expand Up @@ -38,13 +38,16 @@ export async function runCli() {
.scriptName('wp-now')
.usage('$0 <cmd> [args]')
.check(async (argv) => {
const config: CliOptions = {
php: argv.php as SupportedPHPVersion,
path: argv.path as string,
};
if (argv._[0] !== 'php') {
config.wp = argv.wp as string;
config.port = argv.port as number;
}
try {
await getWpNowConfig({
path: argv.path as string,
php: argv.php as SupportedPHPVersion,
wp: argv.wp as string,
port: argv.port as number,
});
await getWpNowConfig(config);
} catch (error) {
return error.message;
}
Expand Down Expand Up @@ -87,22 +90,25 @@ export async function runCli() {
}
)
.command(
'php <file>',
'Run the php command passing the arguments for php cli',
'php [..args]',
'Run the php command passing the arguments to php cli',
(yargs) => {
commonParameters(yargs);
yargs.positional('file', {
describe: 'Path to the PHP file to run',
type: 'string',
});
yargs.strict(false);
},
async (argv) => {
try {
// 0: node, 1: wp-now, 2: php, ...args
const args = process.argv.slice(2);
const options = await getWpNowConfig({
path: argv.path as string,
php: argv.php as SupportedPHPVersion,
});
await executePHPFile(argv.file as string, options);
const phpArgs = args.includes('--')
? (argv._ as string[])
: args;
// 0: php, ...args
await executePHP(phpArgs, options);
process.exit(0);
} catch (error) {
console.error(error);
Expand Down
47 changes: 0 additions & 47 deletions packages/wp-now/src/tests/execute-php-file.spec.ts

This file was deleted.

131 changes: 131 additions & 0 deletions packages/wp-now/src/tests/execute-php.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import fs from 'fs-extra';
import path from 'path';
import { executePHP } from '../execute-php';
import getWpNowConfig from '../config';
import { runCli } from '../run-cli';

const exampleDir = path.join(__dirname, 'execute-php');

test('php file execution in index mode', async () => {
const resultFilePath = path.join(exampleDir, 'hello-world-result.txt');
// reset result file
fs.writeFileSync(resultFilePath, '');
const options = await getWpNowConfig({
path: exampleDir,
});
await executePHP(
['php', path.join(exampleDir, 'hello-world.php')],
options
);
const output = fs.readFileSync(resultFilePath, 'utf8');
expect(output).toBe('Hello World!');
});

test('php file execution for each PHP Version', async () => {
const resultFilePath = path.join(exampleDir, 'php-version-result.txt');
const options = await getWpNowConfig({
path: exampleDir,
});
await executePHP(['php', path.join(exampleDir, 'php-version.php')], {
...options,
phpVersion: '7.4',
});
let output = fs.readFileSync(resultFilePath, 'utf8');
expect(output.substring(0, 16)).toBe('PHP Version: 7.4');

await executePHP(['php', path.join(exampleDir, 'php-version.php')], {
...options,
phpVersion: '8.0',
});
output = fs.readFileSync(resultFilePath, 'utf8');
expect(output.substring(0, 16)).toBe('PHP Version: 8.0');

await executePHP(['php', path.join(exampleDir, 'php-version.php')], {
...options,
phpVersion: '8.2',
});
output = fs.readFileSync(resultFilePath, 'utf8');
expect(output.substring(0, 16)).toBe('PHP Version: 8.2');

fs.writeFileSync(resultFilePath, 'PHP Version: X.Y');
});

test('php throws an error if the first element is not the string "php"', async () => {
const options = await getWpNowConfig({
path: exampleDir,
});
try {
await executePHP(
['word-different-to-php', path.join(exampleDir, 'php-version.php')],
{
...options,
phpVersion: '7.4',
}
);
} catch (error) {
expect(error.message).toBe(
'The first argument to executePHP must be the string "php".'
);
}
});

describe('validate php arguments passed through yargs', () => {
let output = '';
let consoleLogMock;
let processExitMock;
const argv = process.argv;
beforeEach(() => {
consoleLogMock = vi
.spyOn(console, 'log')
.mockImplementation((newLine: string) => {
output += `${newLine}\n`;
});
processExitMock = vi
.spyOn(process, 'exit')
.mockImplementation(() => null);
});

afterEach(() => {
output = '';
process.argv = argv;
consoleLogMock.mockRestore();
processExitMock.mockRestore();
});

test('php should receive the correct yargs arguments', async () => {
process.argv = ['node', 'wp-now', 'php', '--', '--version'];
await runCli();
expect(output).toMatch(/PHP 8\.0(.*)\(cli\)/i);
expect(processExitMock).toHaveBeenCalledWith(0);
});

test('wp-now should change the php version', async () => {
process.argv = [
'node',
'wp-now',
'php',
'--php=7.4',
'--',
'--version',
];
await runCli();
expect(output).toMatch(/PHP 7\.4(.*)\(cli\)/i);
expect(processExitMock).toHaveBeenCalledWith(0);
});

test('php should execute a file', async () => {
const filePath = path.join(exampleDir, 'print-php-version.php');
process.argv = ['node', 'wp-now', 'php', filePath];
await runCli();
expect(output).toMatch(/8\.0/i);
expect(processExitMock).toHaveBeenCalledWith(0);
});

test('php should execute a file and change php version', async () => {
const filePath = path.join(exampleDir, 'print-php-version.php');
process.argv = ['node', 'wp-now', 'php', '--php=7.4', '--', filePath];
await runCli();
expect(output).toMatch(/7\.4/i);
expect(processExitMock).toHaveBeenCalledWith(0);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<?php echo phpversion();

0 comments on commit 56f55a6

Please sign in to comment.