Skip to content

Commit 9dd2ebf

Browse files
committed
fix: expose CLI streams in Playground PHP runtimes
1 parent 7b1e774 commit 9dd2ebf

5 files changed

Lines changed: 19 additions & 11 deletions

File tree

packages/runtime-playground/src/php-bootstrap.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { readFile } from "node:fs/promises"
22
import { argValue, normalizePhpCode, phpBody } from "./commands.js"
3-
import { phpEnvAssignments, phpRuntimeRecipePluginPreloadFunction, phpWpConfigDefineAssignments } from "./php-snippets.js"
3+
import { phpCliStreamConstants, phpEnvAssignments, phpRuntimeRecipePluginPreloadFunction, phpWpConfigDefineAssignments } from "./php-snippets.js"
44
import { normalizeRuntimeEnvRecord, resolveCommandPath, type RuntimeCreateSpec } from "@automattic/wp-codebox-core"
55

66
interface PhpBootstrapBridge {
@@ -29,6 +29,7 @@ export function bootstrapPhpCode(spec: RuntimeCreateSpec, code: string, args: st
2929

3030
return `<?php
3131
${command.strictTypesDeclare ? `${command.strictTypesDeclare}\n` : ""}${phpFatalDiagnosticPhp()}
32+
${phpCliStreamConstants()}
3233
${pluginRuntimeBootstrapPhp(spec)}
3334
${saveQueriesBootstrapPhp(args)}
3435
${runtimeEnvPhp(spec)}

packages/runtime-playground/src/php-snippets.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,18 @@ export { phpRuntimeComponentLifecycleReplayFunction, phpRuntimeRecipePluginPrelo
44

55
export type PhpScalar = string | number | boolean | null
66

7+
export function phpCliStreamConstants(): string {
8+
return `if (!defined('STDIN')) {
9+
define('STDIN', fopen('php://stdin', 'rb'));
10+
}
11+
if (!defined('STDOUT')) {
12+
define('STDOUT', fopen('php://stdout', 'wb'));
13+
}
14+
if (!defined('STDERR')) {
15+
define('STDERR', fopen('php://stderr', 'wb'));
16+
}`
17+
}
18+
719
export function phpEnvAssignments(env: Record<string, unknown>): string {
820
const lines = Object.entries(env)
921
.filter(([name]) => isSafeEnvName(name))

packages/runtime-playground/src/wp-cli-command-handlers.ts

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { argValue } from "./command-args.js"
2+
import { phpCliStreamConstants } from "./php-snippets.js"
23

34
export function wpCliCommandFromArgs(args: string[]): string {
45
const explicit = argValue(args, "command")
@@ -52,15 +53,7 @@ export function wpCliPhpScript(argv: string[]): string {
5253
return `<?php
5354
putenv('SHELL_PIPE=0');
5455
$GLOBALS['argv'] = array_merge(array('/tmp/wp-cli.phar', '--path=/wordpress', '--no-color'), json_decode(${JSON.stringify(JSON.stringify(argv))}, true));
55-
if (!defined('STDIN')) {
56-
define('STDIN', fopen('php://stdin', 'rb'));
57-
}
58-
if (!defined('STDOUT')) {
59-
define('STDOUT', fopen('php://stdout', 'wb'));
60-
}
61-
if (!defined('STDERR')) {
62-
define('STDERR', fopen('php://stderr', 'wb'));
63-
}
56+
${phpCliStreamConstants()}
6457
require '/tmp/wp-cli.phar';
6558
`
6659
}

tests/playground-phpunit-readonly-cache.integration.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ async function writeFixture(): Promise<void> {
6363
await mkdir(dependency, { recursive: true })
6464
await writeFile(join(plugin, "readonly-phpunit-fixture.php"), "<?php\n/**\n * Plugin Name: Readonly PHPUnit Fixture\n */\n")
6565
await writeFile(join(plugin, "source-sentinel.bin"), sentinel)
66-
await writeFile(join(plugin, "tests", "ReadonlyCacheTest.php"), "<?php\nclass ReadonlyCacheTest extends WP_UnitTestCase { public function test_multisite_runtime_is_active(): void { $this->assertTrue(is_multisite()); } public function test_sentinel_is_available(): void { $this->assertGreaterThan(0, filesize(dirname(__DIR__) . \'/source-sentinel.bin\')); } public function test_dependency_activation_runs_after_install(): void { $this->assertGreaterThanOrEqual(1, get_option(\'wp_codebox_dependency_activation_users\')); } public function test_dependency_plugins_loaded_runs_once(): void { $this->assertSame(1, (int) get_option(\'wp_codebox_dependency_plugins_loaded_count\')); } }\n")
66+
await writeFile(join(plugin, "tests", "ReadonlyCacheTest.php"), "<?php\nclass ReadonlyCacheTest extends WP_UnitTestCase { public function test_multisite_runtime_is_active(): void { $this->assertTrue(is_multisite()); } public function test_sentinel_is_available(): void { $this->assertGreaterThan(0, filesize(dirname(__DIR__) . \'/source-sentinel.bin\')); } public function test_dependency_activation_runs_after_install(): void { $this->assertGreaterThanOrEqual(1, get_option(\'wp_codebox_dependency_activation_users\')); } public function test_dependency_plugins_loaded_runs_once(): void { $this->assertSame(1, (int) get_option(\'wp_codebox_dependency_plugins_loaded_count\')); } public function test_wp_cli_namespaced_stdout_is_available(): void { $this->assertTrue(eval(\'namespace cli; return is_resource(STDOUT);\')); } }\n")
6767
await writeFile(join(dependency, "activation-dependency.php"), "<?php\n/**\n * Plugin Name: Activation Dependency\n */\nadd_action('plugins_loaded', static function (): void { update_option('wp_codebox_dependency_plugins_loaded_count', (int) get_option('wp_codebox_dependency_plugins_loaded_count', 0) + 1); });\nregister_activation_hook(__FILE__, static function (): void { update_option('wp_codebox_dependency_activation_users', count(get_users(array('number' => 1)))); });\n")
6868
}
6969

tests/runtime-php-snippets.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ const bootstrappedRunPhp = bootstrapPhpCode({
9292
} as never, "<?php echo 'ok';", [])
9393
assert.match(bootstrappedRunPhp, /contained_runtime_run_php_component_lifecycle_replay_prepare/)
9494
assert.match(bootstrappedRunPhp, /CONTAINED_RUNTIME_COMPONENT_MANIFEST_JSON/)
95+
assert.match(bootstrappedRunPhp, /define\('STDOUT', fopen\('php:\/\/stdout', 'wb'\)\)/)
96+
assert.ok(bootstrappedRunPhp.indexOf("define('STDOUT'") < bootstrappedRunPhp.indexOf("require_once '/wordpress/wp-load.php';"), "CLI streams must exist before WordPress and test dependencies load")
9597
assert.doesNotMatch(bootstrappedRunPhp, /wp_codebox_run_php|wp_codebox_component_manifest|WP_CODEBOX_COMPONENT_MANIFEST_JSON/)
9698

9799
const strictTypesCodeFileRoot = mkdtempSync(join(tmpdir(), "wp-codebox-run-php-strict-types-"))

0 commit comments

Comments
 (0)