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

Playground Boot: Align the boot process between remote.html and CLI #1389

Merged
merged 3 commits into from
May 15, 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
23 changes: 8 additions & 15 deletions packages/playground/cli/src/setup-php.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ import {
} from '@php-wasm/universal';
import { rootCertificates } from 'tls';
import { dirname } from '@php-wasm/util';
import { envPHP_to_loadMuPlugins } from '@wp-playground/wordpress';
import {
preloadPhpInfoRoute,
enablePlatformMuPlugins,
preloadRequiredMuPlugin,
} from '@wp-playground/wordpress';

export async function createPhp(
requestHandler: PHPRequestHandler<NodePHP>,
Expand Down Expand Up @@ -44,20 +48,9 @@ export async function createPhp(
'/internal/shared/ca-bundle.crt',
rootCertificates.join('\n')
);
php.writeFile(
'/internal/shared/preload/env.php',
envPHP_to_loadMuPlugins
);
php.writeFile(
'/internal/shared/preload/phpinfo.php',
`<?php
// Render PHPInfo if the requested page is /phpinfo.php
if ( '/phpinfo.php' === $_SERVER['REQUEST_URI'] ) {
phpinfo();
exit;
}`
);
php.mkdir('/internal/shared/mu-plugins');
await preloadPhpInfoRoute(php);
await enablePlatformMuPlugins(php);
await preloadRequiredMuPlugin(php);
} else {
/**
* @TODO: Consider an API similar to
Expand Down
20 changes: 6 additions & 14 deletions packages/playground/cli/src/setup-wp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,7 @@ import {
readAsFile,
} from './download';
import { withPHPIniValues } from './setup-php';
import {
playgroundMuPlugin,
preloadSqliteIntegration,
} from '@wp-playground/wordpress';
import { preloadSqliteIntegration } from '@wp-playground/wordpress';

/**
* Ensures a functional WordPress installation in php document root.
Expand Down Expand Up @@ -52,9 +49,11 @@ export async function setupWordPress(
monitor
),
]);

await prepareWordPress(php, wpZip);
await preloadSqliteIntegration(php, sqliteZip);
// Setup the SQLite integration if no custom database drop-in is present
if (!php.fileExists('/wordpress/wp-content/db.php')) {
await preloadSqliteIntegration(php, sqliteZip);
}

const preinstalledWpContentPath = path.join(
CACHE_FOLDER,
Expand Down Expand Up @@ -101,7 +100,7 @@ export async function setupWordPress(
* the sqlite-database-integration zip file.
*
* This is a TypeScript function for now, just to get something off the
* ground, but it will be superseded by the PHP Blueprints library developed
* ground, but it may be superseded by the PHP Blueprints library developed
* at https://github.com/WordPress/blueprints-library/
*
* That PHP library will come with a set of functions and a CLI tool to
Expand All @@ -111,13 +110,6 @@ export async function setupWordPress(
* as that's viable.
*/
async function prepareWordPress(php: NodePHP, wpZip: File) {
php.mkdir('/internal/shared/mu-plugins');
php.writeFile(
'/internal/shared/mu-plugins/0-playground.php',
playgroundMuPlugin
);

// Extract WordPress {{{
php.mkdir('/tmp/unzipped-wordpress');
await unzip(php, {
zipFile: wpZip,
Expand Down
63 changes: 6 additions & 57 deletions packages/playground/remote/src/lib/worker-thread.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,8 @@ import {
LatestSupportedWordPressVersion,
SupportedWordPressVersions,
} from '@wp-playground/wordpress-builds';
import {
envPHP_to_loadMuPlugins,
playgroundMuPlugin,
wordPressRewriteRules,
} from '@wp-playground/wordpress';
import {
PHPRequestHandler,
proxyFileSystem,
writeFiles,
} from '@php-wasm/universal';
import { wordPressRewriteRules } from '@wp-playground/wordpress';
import { PHPRequestHandler } from '@php-wasm/universal';
import {
SyncProgressCallback,
bindOpfs,
Expand All @@ -28,13 +20,7 @@ import {
unzip,
} from '@wp-playground/blueprints';

/** @ts-ignore */
import transportFetch from './playground-mu-plugin/playground-includes/wp_http_fetch.php?raw';
/** @ts-ignore */
import transportDummy from './playground-mu-plugin/playground-includes/wp_http_dummy.php?raw';
/** @ts-ignore */
import playgroundWebMuPlugin from './playground-mu-plugin/0-playground.php?raw';
import { joinPaths, randomString } from '@php-wasm/util';
import { randomString } from '@php-wasm/util';
import {
requestedWPVersion,
createPhp,
Expand Down Expand Up @@ -169,37 +155,12 @@ export class PlaygroundWorkerEndpoint extends WebPHPEndpoint {

const scopedSiteUrl = setURLScope(wordPressSiteUrl, scope).toString();
const requestHandler = new PHPRequestHandler({
phpFactory: async ({ isPrimary }) => {
const php = await createPhp(requestHandler);
php.defineConstant('SCOPED_SITE_PATH', new URL(scopedSiteUrl).pathname);
if (isPrimary) {
php.writeFile(
'/internal/shared/preload/env.php',
envPHP_to_loadMuPlugins
);
php.writeFile(
'/internal/shared/preload/phpinfo.php',
`<?php
// Render PHPInfo if the requested page is /phpinfo.php
if ( SCOPED_SITE_PATH . '/phpinfo.php' === $_SERVER['REQUEST_URI'] ) {
phpinfo();
exit;
}
`
);
} else {
proxyFileSystem(await requestHandler.getPrimaryPhp(), php, [
'/tmp',
requestHandler.documentRoot,
'/internal/shared',
]);
}
return php;
},
phpFactory: async ({ isPrimary }) =>
await createPhp(requestHandler, scopedSiteUrl, isPrimary),
documentRoot: DOCROOT,
absoluteUrl: scopedSiteUrl,
rewriteRules: wordPressRewriteRules,
});
}) as PHPRequestHandler<WebPHP>;
const apiEndpoint = new PlaygroundWorkerEndpoint(
requestHandler,
downloadMonitor,
Expand Down Expand Up @@ -241,18 +202,6 @@ try {
});
}

// Always install the playground mu-plugin, even if WordPress is loaded
// from the OPFS. This ensures:
// * The mu-plugin is always there, even when a custom WordPress directory
// is mounted.
// * The mu-plugin is always up to date.
await writeFiles(primaryPhp, joinPaths('/internal/shared/mu-plugins'), {
'0-playground.php': playgroundMuPlugin,
'1-playground-web.php': playgroundWebMuPlugin,
'playground-includes/wp_http_dummy.php': transportDummy,
'playground-includes/wp_http_fetch.php': transportFetch,
});

if (virtualOpfsDir) {
await bindOpfs({
php: primaryPhp,
Expand Down
46 changes: 43 additions & 3 deletions packages/playground/remote/src/lib/worker-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,24 @@ import {
SupportedPHPVersionsList,
rotatePHPRuntime,
PHPRequestHandler,
proxyFileSystem,
writeFiles,
} from '@php-wasm/universal';
import { EmscriptenDownloadMonitor } from '@php-wasm/progress';
import { createSpawnHandler, phpVar } from '@php-wasm/util';
import { createSpawnHandler, joinPaths, phpVar } from '@php-wasm/util';
import { createMemoizedFetch } from './create-memoized-fetch';
import { logger } from '@php-wasm/logger';
/** @ts-ignore */
import transportFetch from './playground-mu-plugin/playground-includes/wp_http_fetch.php?raw';
/** @ts-ignore */
import transportDummy from './playground-mu-plugin/playground-includes/wp_http_dummy.php?raw';
/** @ts-ignore */
import playgroundWebMuPlugin from './playground-mu-plugin/0-playground.php?raw';
import {
enablePlatformMuPlugins,
preloadPhpInfoRoute,
preloadRequiredMuPlugin,
} from '@wp-playground/wordpress';

export type ReceivedStartupOptions = {
wpVersion?: string;
Expand Down Expand Up @@ -59,15 +72,42 @@ export const startupOptions = {
phpExtensions: receivedParams.phpExtensions || [],
} as ParsedStartupOptions;

export async function createPhp(requestHandler: PHPRequestHandler<WebPHP>) {
export async function createPhp(
requestHandler: PHPRequestHandler<WebPHP>,
siteUrl: string,
isPrimary: boolean
) {
const php = new WebPHP();
php.requestHandler = requestHandler as any;

php.initializeRuntime(await createPhpRuntime());
php.setPhpIniEntry('memory_limit', '256M');
if (startupOptions.sapiName) {
await php.setSapiName(startupOptions.sapiName);
}
php.setPhpIniEntry('memory_limit', '256M');
php.setSpawnHandler(spawnHandlerFactory(requestHandler.processManager));

if (isPrimary) {
const scopedSitePath = new URL(siteUrl).pathname;
await preloadPhpInfoRoute(
php,
joinPaths(scopedSitePath, 'phpinfo.php')
);
await enablePlatformMuPlugins(php);
await preloadRequiredMuPlugin(php);
await writeFiles(php, joinPaths('/internal/shared/mu-plugins'), {
'1-playground-web.php': playgroundWebMuPlugin,
'playground-includes/wp_http_dummy.php': transportDummy,
'playground-includes/wp_http_fetch.php': transportFetch,
});
} else {
proxyFileSystem(await requestHandler.getPrimaryPhp(), php, [
'/tmp',
requestHandler.documentRoot,
'/internal/shared',
]);
}

// Rotate the PHP runtime periodically to avoid memory leak-related crashes.
// @see https://github.com/WordPress/wordpress-playground/pull/990 for more context
rotatePHPRuntime({
Expand Down
Loading
Loading