Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions vendor/wp-now/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export interface CliOptions {
reset?: boolean;
adminPassword?: string;
siteTitle?: string;
mode?: WPNowMode;
}

export const enum WPNowMode {
Expand All @@ -30,6 +31,7 @@ export const enum WPNowMode {
WP_CONTENT = 'wp-content',
PLAYGROUND = 'playground',
AUTO = 'auto',
CLI = 'cli',
}

export interface WPNowOptions {
Expand Down Expand Up @@ -111,6 +113,7 @@ export default async function getWpNowConfig( args: CliOptions ): Promise< WPNow
wordPressVersion: args.wp as string,
port,
reset: args.reset as boolean,
mode: args.mode as WPNowMode,
};

const options: WPNowOptions = {} as WPNowOptions;
Expand Down
20 changes: 20 additions & 0 deletions vendor/wp-now/src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
/**
* Playground internal shared folder.
*/
export const PLAYGROUND_INTERNAL_SHARED_FOLDER = '/internal/shared';

/**
* Playground internal mu-plugins folder.
*/
export const PLAYGROUND_INTERNAL_MU_PLUGINS_FOLDER = '/internal/shared/mu-plugins';

/**
* Playground internal preload path.
*/
export const PLAYGROUND_INTERNAL_PRELOAD_PATH = '/internal/shared/preload';

/**
* The file name for the SQLite plugin name.
*/
Expand All @@ -8,6 +23,11 @@ export const SQLITE_FILENAME = 'sqlite-database-integration';
*/
export const SQLITE_URL = 'https://downloads.wordpress.org/plugin/sqlite-database-integration.zip';

/**
* The folder for the SQLite plugin.
*/
export const SQLITE_PLUGIN_FOLDER = '/internal/shared/mu-plugins/sqlite-database-integration';

/**
* The default starting port for running the WP Now server.
*/
Expand Down
173 changes: 25 additions & 148 deletions vendor/wp-now/src/download.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import followRedirects, { FollowResponse } from 'follow-redirects';
import fs from 'fs-extra';
import { HttpProxyAgent, HttpsProxyAgent } from 'hpagent';
import { IncomingMessage } from 'http';
import os from 'os';
import path from 'path';
import followRedirects, { FollowResponse } from 'follow-redirects';
import fs from 'fs-extra';
import { HttpProxyAgent, HttpsProxyAgent } from 'hpagent';
import unzipper from 'unzipper';
import { DEFAULT_WORDPRESS_VERSION, SQLITE_FILENAME, SQLITE_URL, WP_CLI_URL } from './constants';
import getSqlitePath from './get-sqlite-path';
import getWordpressVersionsPath from './get-wordpress-versions-path';
import getWpCliPath from './get-wp-cli-path';
import getWpNowPath from './get-wp-now-path';
import { output } from './output';
import { isValidWordPressVersion } from './wp-playground-wordpress';

Expand Down Expand Up @@ -231,151 +230,29 @@ export async function downloadSQLiteCommand( downloadUrl: string, targetPath: st
overwrite: true,
} );
}
export function getWordPressVersionPath( wpVersion: string ) {
return path.join( getWordpressVersionsPath(), wpVersion );
}

export async function downloadMuPlugins( customMuPluginsPath = '' ) {
const muPluginsPath = customMuPluginsPath || path.join( getWpNowPath(), 'mu-plugins' );
fs.ensureDirSync( muPluginsPath );

fs.removeSync( path.join( muPluginsPath, '0-allow-wp-org.php' ) );

fs.writeFile(
path.join( muPluginsPath, '0-allowed-redirect-hosts.php' ),
`<?php
// Needed because gethostbyname( <host> ) returns
// a private network IP address for some reason.
add_filter( 'allowed_redirect_hosts', function( $hosts ) {
$redirect_hosts = array(
'wordpress.org',
'api.wordpress.org',
'downloads.wordpress.org',
'themes.svn.wordpress.org',
'fonts.gstatic.com',
);
return array_merge( $hosts, $redirect_hosts );
} );
add_filter('http_request_host_is_external', '__return_true', 20, 3 );
`
);

fs.writeFile(
path.join( muPluginsPath, '0-dns-functions.php' ),
`<?php
// Polyfill for DNS functions/features which are not currently supported by @php-wasm/node.
// See https://github.com/WordPress/wordpress-playground/issues/1042
// These specific features are polyfilled so the Jetpack plugin loads correctly, but others should be added as needed.
if ( ! function_exists( 'dns_get_record' ) ) {
function dns_get_record() {
return array();
}
}
if ( ! defined( 'DNS_NS' ) ) {
define( 'DNS_NS', 2 );
}`
);

fs.writeFile(
path.join( muPluginsPath, '0-thumbnails.php' ),
`<?php
// Facilitates the taking of screenshots to be used as thumbnails.
if ( isset( $_GET['studio-hide-adminbar'] ) ) {
add_filter( 'show_admin_bar', '__return_false' );
}
`
);

fs.writeFile(
path.join( muPluginsPath, '0-sqlite.php' ),
`<?php
if ( file_exists( WP_CONTENT_DIR . "/db.php" ) && file_exists( __DIR__ . "/${ SQLITE_FILENAME }/load.php" ) ) {
require_once __DIR__ . "/${ SQLITE_FILENAME }/load.php";
}`
);

fs.writeFile(
path.join( muPluginsPath, '0-32bit-integer-warnings.php' ),
`<?php
/**
* This is a temporary workaround to hide the 32bit integer warnings that
* appear when using various time related function, such as strtotime and mktime.
* Examples of the warnings that are displayed:
* Warning: mktime(): Epoch doesn't fit in a PHP integer in <file>
* Warning: strtotime(): Epoch doesn't fit in a PHP integer in <file>
* This function removes the internal mu-plugins that WP-now used to store.
*
* WP-now used to store some internal mu-plugins in the site's mu-plugins directory.
* This prevented users from using the mu-plugins directory for their own plugins,
* so Studio now mounts the mu-plugins directory to the shared mu-plugins directory.
*
* @param projectPath The path to the project directory.
*/
set_error_handler(function($severity, $message, $file, $line) {
if (strpos($message, "fit in a PHP integer") !== false) {
return;
}
return false;
});
`
);

fs.writeFile(
path.join( muPluginsPath, '0-check-theme-availability.php' ),
`<?php
function check_current_theme_availability() {
// Get the current theme's directory
$current_theme = wp_get_theme();
$theme_dir = get_theme_root() . '/' . $current_theme->stylesheet;

if (!is_dir($theme_dir)) {
$all_themes = wp_get_themes();
$available_themes = [];

foreach ($all_themes as $theme_slug => $theme_obj) {
if ($theme_slug != $current_theme->get_stylesheet()) {
$available_themes[$theme_slug] = $theme_obj;
}
}

if (!empty($available_themes)) {
$new_theme_slug = array_keys($available_themes)[0];
switch_theme($new_theme_slug);
}
}
}
add_action('after_setup_theme', 'check_current_theme_availability');
`
);

fs.writeFile(
path.join( muPluginsPath, '0-permalinks.php' ),
`<?php
// Support permalinks without "index.php"
add_filter( 'got_url_rewrite', '__return_true' );
`
);

fs.writeFile(
path.join( muPluginsPath, '0-deactivate-jetpack-modules.php' ),
`<?php
// Disable Jetpack Protect 2FA for local auto-login purpose
add_action( 'jetpack_active_modules', 'jetpack_deactivate_modules' );
function jetpack_deactivate_modules( $active ) {
if ( ( $index = array_search('protect', $active, true) ) !== false ) {
unset( $active[ $index ] );
}
return $active;
}
`
);

fs.writeFile(
path.join( muPluginsPath, '0-wp-config-constants-polyfill.php' ),
`<?php
// Define database constants if not already defined. It fixes the error
// for imported sites that don't have those defined e.g. WP Cloud and
// include plugins which try to access those directly e.g. Mailpoet
if (!defined('DB_NAME')) define('DB_NAME', 'database_name_here');
if (!defined('DB_USER')) define('DB_USER', 'username_here');
if (!defined('DB_PASSWORD')) define('DB_PASSWORD', 'password_here');
if (!defined('DB_HOST')) define('DB_HOST', 'localhost');
if (!defined('DB_CHARSET')) define('DB_CHARSET', 'utf8');
if (!defined('DB_COLLATE')) define('DB_COLLATE', '');
`
);
}

export function getWordPressVersionPath( wpVersion: string ) {
return path.join( getWordpressVersionsPath(), wpVersion );
export async function removeDownloadedMuPlugins( projectPath: string ) {
const wpContentPath = path.join( projectPath, 'wp-content' );
const muPluginsPath = path.join( wpContentPath, 'mu-plugins' );
fs.removeSync( path.join( muPluginsPath, '0-32bit-integer-warnings.php' ) );
fs.removeSync( path.join( muPluginsPath, '0-allowed-redirect-hosts.php' ) );
fs.removeSync( path.join( muPluginsPath, '0-check-theme-availability.php' ) );
fs.removeSync( path.join( muPluginsPath, '0-deactivate-jetpack-modules.php' ) );
fs.removeSync( path.join( muPluginsPath, '0-dns-functions.php' ) );
fs.removeSync( path.join( muPluginsPath, '0-permalinks.php' ) );
fs.removeSync( path.join( muPluginsPath, '0-wp-config-constants-polyfill.php' ) );
fs.removeSync( path.join( muPluginsPath, '0-sqlite.php' ) );
fs.removeSync( path.join( muPluginsPath, '0-thumbnails.php' ) );
}
32 changes: 20 additions & 12 deletions vendor/wp-now/src/execute-wp-cli.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
import { downloadWpCli } from './download';
import { readFileSync } from 'fs';
import path from 'path';
import { rootCertificates } from 'tls';
import getWpCliPath from './get-wp-cli-path';
import getWpNowConfig from './config';
import { DEFAULT_PHP_VERSION, DEFAULT_WORDPRESS_VERSION } from './constants';
import { phpVar } from '@php-wasm/util';
import { createNodeFsMountHandler, loadNodeRuntime } from '@php-wasm/node';
import { getSqliteCommandPath } from '../../../src/lib/sqlite-command-versions';
import { PHP, MountHandler, writeFiles, setPhpIniEntries } from '@php-wasm/universal';
import { readFileSync } from 'fs';
import { startSymlinkManager } from './wp-now';
import { phpVar } from '@php-wasm/util';
import { getSqliteCommandPath } from '../../../src/lib/sqlite-command-versions';
import getWpNowConfig, { WPNowMode } from './config';
import {
DEFAULT_PHP_VERSION,
DEFAULT_WORDPRESS_VERSION,
PLAYGROUND_INTERNAL_SHARED_FOLDER,
} from './constants';
import { downloadWpCli } from './download';
import getWpCliPath from './get-wp-cli-path';
import { prepareWordPress } from './wp-now';

const isWindows = process.platform === 'win32';

Expand All @@ -26,10 +31,11 @@ export async function executeWPCli(
{ phpVersion }: { phpVersion?: string } = {}
): Promise< { stdout: string; stderr: string; exitCode: number } > {
await downloadWpCli();
let options = await getWpNowConfig( {
const options = await getWpNowConfig( {
php: phpVersion || DEFAULT_PHP_VERSION,
wp: DEFAULT_WORDPRESS_VERSION,
path: projectPath,
mode: WPNowMode.CLI,
} );

const id = await loadNodeRuntime( options.phpVersion );
Expand All @@ -39,11 +45,12 @@ export async function executeWPCli(
options.documentRoot,
createNodeFsMountHandler( projectPath ) as unknown as MountHandler
);
await startSymlinkManager( php, projectPath, options.documentRoot );

//Set the SAPI name to cli before running the script
await php.setSapiName( 'cli' );

await prepareWordPress( php, options );

php.mkdir( '/tmp' );

const wpCliPath = '/tmp/wp-cli.phar';
Expand Down Expand Up @@ -90,13 +97,14 @@ export async function executeWPCli(
$_SERVER['argv'][0] = '${ wpCliPath }';

require( '${ wpCliPath }' );`,
[ '/internal/shared/ca-bundle.crt' ]: rootCertificates.join( '\n' ),
[ path.join( PLAYGROUND_INTERNAL_SHARED_FOLDER, 'ca-bundle.crt' ) ]:
rootCertificates.join( '\n' ),
};

await writeFiles( php, '/', createFiles );

await setPhpIniEntries( php, {
'openssl.cafile': '/internal/shared/ca-bundle.crt',
'openssl.cafile': path.join( PLAYGROUND_INTERNAL_SHARED_FOLDER, 'ca-bundle.crt' ),
} );
try {
php.mkdir( sqliteCommandPath );
Expand Down
Loading