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

Breaking: PHP: Remove NodePHP and WebPHP classes in favor of a single "PHP" class #1457

Merged
merged 19 commits into from
May 25, 2024

Conversation

adamziel
Copy link
Collaborator

@adamziel adamziel commented May 23, 2024

Warning

This is breaking change! Review the description below to assess the impact on your app.

Consolidates the BasePHP, NodePHP, and WebPHP classes into a single PHP class. This refactor reduces redundancy and clarifies the PHP handling process across different environments.

Examples

NodePHP

Before

import { NodePHP } from '@php-wasm/node';
const php = await NodePHP.load('8.0');

After

import { loadNodeRuntime } from '@php-wasm/node';
import { PHP } from '@php-wasm/universal';
const php = new PHP(await loadNodeRuntime('8.0'));

WebPHP

Before

import { WebPHP } from '@php-wasm/web';
const php = await WebPHP.loadRuntime('8.0');

After

import { loadWebRuntime } from '@php-wasm/web';
import { PHP } from '@php-wasm/universal';
const php = new PHP(await loadWebRuntime('8.0'));

Mounting

Before

php.useHostFilesystem();
// or 
php.mount( '/home/users/adam/my-dir', '/my-dir-in-vfs');

After

import { NodeFSMount, useHostFilesystem } from '@php-wasm/node';
useHostFilesystem( php );
php.mount( new NodeFSMount( '/home/users/adam/my-dir' ), '/my-dir-in-vfs' );

Closes #1399

Motivation

First, the public API surface of all the PHP classes and interfaces is overly complex. This PR is a step towards simplifying it.

Second, in the Boot Protocol, PR the bootWordPress() function requires separate createPHP and createPHPRuntime callbacks just because Playground uses different classes in node.js and in the browser. With this PR, createPHP callback will no longer be needed anymore as bootWordPress() will just always create a new PHP() instance.

Public API Changes

  • Removes BasePHP, NodePHP, and WebPHP classes in favor of a single PHP class exported from @php-wasm/universal
  • php.useHostFilesystem() was removed in favor of a decoupled function useHostFilesystem( php ) available in @php-wasm/node.
  • PHP.mount() signature changed from mount( hostPath: string, vfsPath: string ) to mount( mountable: Mountable, vfsPath: string )
  • Moves WebPHPEndpoint from @php-wasm/web to @php-wasm/universal and renames it to PHPWorker. That class isn't specific to the web and could be easily used by Node workers.
  • Removes the IsomorphicLocalPHP interface. The PHP class is now the source of truth for all derived worker, client, etc. implementations.
  • Removes the createPhpInstance() option from bootWordPress( options ) in favor of always using the PHP class.
  • Updates to Documentation: Adjusted examples and references in the documentation to reflect the new PHP class.
  • Refactoring of Test Suites: Updated tests to work with the new class structure.

Testing instructions

Confirm all the CI checks pass – this PR includes an extensive refactor of all the tests.

Heads up @wojtekn @fluiddot @sejas

@adamziel adamziel changed the title PHP: Remove NodePHP and WebPHP classes in favor of a single "PHP" class Breaking: PHP: Remove NodePHP and WebPHP classes in favor of a single "PHP" class May 23, 2024
@adamziel adamziel marked this pull request as ready for review May 23, 2024 16:09
@adamziel adamziel requested a review from a team as a code owner May 23, 2024 16:09
adamziel added a commit that referenced this pull request May 23, 2024
Implements a `bootWordPress()` function aiming to provide a reliable and
consistent boot pipeline for every Playground-based app, whether it's a
browser app, server app, a VS Code extension, or anything else.

As a nice side-effect, Playground can now boot not just from the custom
minified WordPress builds, but also from the official WordPress
releases!

Related issue:
#1398

## How does it work?

`bootWordPress()` ties together all the pieces from different
Playground-based apps. [Boot flow
diagram](#1379 (comment))
demonstrates the idea. A tl;dr pipeline is:

* Mount resources (stage=before WordPress files)
* Unzip WordPress, if that's requested
* Mount resources (stage=before database setup)
* Setup SQLite, MySQL (TODO), or rely on a mounted database
* Run WordPress installer, if the site isn't installed yet

Here's a usage example in a Node.js app:

```ts
const requestHandler = await bootWordPress({
	siteUrl: absoluteUrl,
	createPhpInstance() {
		return new NodePHP();
	},
	createPhpRuntime: async () =>
		await NodePHP.loadRuntime(compiledBlueprint.versions.php),
	wordPressZip,
	sqliteIntegrationPluginZip: fetchSqliteIntegration(monitor),
	sapiName: 'cli',
	createFiles: {
		'/internal/shared/ca-bundle.crt':
			rootCertificates.join('\n'),
	},
	phpIniEntries: {
		'openssl.cafile': '/internal/shared/ca-bundle.crt',
		allow_url_fopen: '1',
		disable_functions: '',
	},
	hooks: {
		async beforeWordPressFiles(php) {
			if (args.mountBeforeInstall) {
				mountResources(php, args.mountBeforeInstall);
			}
		},
	},
});
```

## Testing instructions

* Confirm all the CI checks work
* Load the latest nightly **official WordPress build** into Playground:

http://localhost:5400/website-server/?php=8.0&wp=http://localhost:5400/plugin-proxy.php?url=https://wordpress.org/nightly-builds/wordpress-latest.zip
* Load the official WordPress 6.5 release into Playground:
http://localhost:5400/website-server/?php=8.0&wp=http://localhost:5400/plugin-proxy.php?url=https://wordpress.org/latest.zip
* Confirm Playground CLI still works: Run bun
packages/playground/cli/src/cli.ts server --login and confirm it loads
an installed WordPress.

## Follow-up work

* Replace manual calls to `setupPlatformLevelMuPlugins()` in unit tests
with `bootWordPress()`
* Add unit tests to confirm boot works with minified WordPress build,
official WordPress release, SQLite, MySQL. Test all the `BootOptions`
and confirm PHP.ini directives are used, constants are created etc.
* Remove the `createPhpInstance()` argument in favor of using just the
`PHP` class – once
#1457 merges
* Figure out storing `debug.log` in the `configureErrorLogging`
mu-plugin – right now it's stored in `/wordpress/wp-content`
* Support more database modes: MySQL and `custom` where Playground
relies on `db.php` brought in from
* Replace hooks with a Mount data type that would have different
implementations, like OPFS, Native FS, and Node FS – explorations
started in #1457
* Once the API settles, document the usage for developers

cc @brandonpayton @bgrgicak
/* eslint-disable @typescript-eslint/no-namespace */
/** Other WebAssembly declarations, for compatibility with older versions of Typescript */

export namespace Emscripten {
Copy link
Collaborator Author

@adamziel adamziel May 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DefinitelyTyped types didn't play well the way we build rollup.d.ts – it's easier to ship a copy of these types. If that turns out to be a maintenance burden, let's reassess.

Copy link
Collaborator

@bgrgicak bgrgicak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! Having a single PHP class will make things much cleaner and should make it easier to understand the code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Remove NodePHP and WebPHP classes
2 participants