@wp-playground/wordpress 0.7.19 → 0.7.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.d.ts +30 -1
- package/index.js +205 -1
- package/package.json +2 -5
package/index.d.ts
CHANGED
|
@@ -1,2 +1,31 @@
|
|
|
1
|
+
import { BasePHP, UniversalPHP } from '../../../php-wasm/universal/src/index.ts';
|
|
1
2
|
export * from './rewrite-rules';
|
|
2
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Preloads the platform mu-plugins from /internal/shared/mu-plugins.
|
|
5
|
+
* This avoids polluting the WordPress installation with mu-plugins
|
|
6
|
+
* that are only needed in the Playground environment.
|
|
7
|
+
*
|
|
8
|
+
* @param php
|
|
9
|
+
*/
|
|
10
|
+
export declare function enablePlatformMuPlugins(php: UniversalPHP): Promise<void>;
|
|
11
|
+
export declare function preloadRequiredMuPlugin(php: UniversalPHP): Promise<void>;
|
|
12
|
+
/**
|
|
13
|
+
* Runs phpinfo() when the requested path is /phpinfo.php.
|
|
14
|
+
*/
|
|
15
|
+
export declare function preloadPhpInfoRoute(php: UniversalPHP, requestPath?: string): Promise<void>;
|
|
16
|
+
export declare function preloadSqliteIntegration(php: UniversalPHP, sqliteZip: File): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* Prepare the WordPress document root given a WordPress zip file and
|
|
19
|
+
* the sqlite-database-integration zip file.
|
|
20
|
+
*
|
|
21
|
+
* This is a TypeScript function for now, just to get something off the
|
|
22
|
+
* ground, but it may be superseded by the PHP Blueprints library developed
|
|
23
|
+
* at https://github.com/WordPress/blueprints-library/
|
|
24
|
+
*
|
|
25
|
+
* That PHP library will come with a set of functions and a CLI tool to
|
|
26
|
+
* turn a Blueprint into a WordPress directory structure or a zip Snapshot.
|
|
27
|
+
* Let's **not** invest in the TypeScript implementation of this function,
|
|
28
|
+
* accept the limitation, and switch to the PHP implementation as soon
|
|
29
|
+
* as that's viable.
|
|
30
|
+
*/
|
|
31
|
+
export declare function unzipWordPress(php: BasePHP, wpZip: File): Promise<void>;
|
package/index.js
CHANGED
|
@@ -1 +1,205 @@
|
|
|
1
|
-
|
|
1
|
+
function o(...e){let t=e.join("/");const i=t[0]==="/",n=t.substring(t.length-1)==="/";return t=c(t),!t&&!i&&(t="."),t&&n&&(t+="/"),t}function c(e){const t=e[0]==="/";return e=f(e.split("/").filter(i=>!!i),!t).join("/"),(t?"/":"")+e.replace(/\/$/,"")}function f(e,t){let i=0;for(let n=e.length-1;n>=0;n--){const r=e[n];r==="."?e.splice(n,1):r===".."?(e.splice(n,1),i++):i&&(e.splice(n,1),i--)}if(t)for(;i;i--)e.unshift("..");return e}function s(e){return`json_decode(base64_decode('${_(JSON.stringify(e))}'), true)`}function g(e){const t={};for(const i in e)t[i]=s(e[i]);return t}function _(e){return w(new TextEncoder().encode(e))}function w(e){const t=String.fromCodePoint(...e);return btoa(t)}const a="/tmp/file.zip",d=async(e,t,i)=>{if(t instanceof File){const r=t;t=a,await e.writeFile(t,new Uint8Array(await r.arrayBuffer()))}const n=g({zipPath:t,extractToPath:i});await e.run({code:`<?php
|
|
2
|
+
function unzip($zipPath, $extractTo, $overwrite = true)
|
|
3
|
+
{
|
|
4
|
+
if (!is_dir($extractTo)) {
|
|
5
|
+
mkdir($extractTo, 0777, true);
|
|
6
|
+
}
|
|
7
|
+
$zip = new ZipArchive;
|
|
8
|
+
$res = $zip->open($zipPath);
|
|
9
|
+
if ($res === TRUE) {
|
|
10
|
+
$zip->extractTo($extractTo);
|
|
11
|
+
$zip->close();
|
|
12
|
+
chmod($extractTo, 0777);
|
|
13
|
+
} else {
|
|
14
|
+
throw new Exception("Could not unzip file");
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
unzip(${n.zipPath}, ${n.extractToPath});
|
|
18
|
+
`}),await e.fileExists(a)&&await e.unlink(a)},m=[{match:/^\/(.*?)(\/wp-(content|admin|includes)\/.*)/g,replacement:"$2"}];async function $(e){await e.mkdir("/internal/shared/mu-plugins"),await e.writeFile("/internal/shared/preload/env.php",`<?php
|
|
19
|
+
|
|
20
|
+
// Allow adding filters/actions prior to loading WordPress.
|
|
21
|
+
// $function_to_add MUST be a string.
|
|
22
|
+
function playground_add_filter( $tag, $function_to_add, $priority = 10, $accepted_args = 1 ) {
|
|
23
|
+
global $wp_filter;
|
|
24
|
+
$wp_filter[$tag][$priority][$function_to_add] = array('function' => $function_to_add, 'accepted_args' => $accepted_args);
|
|
25
|
+
}
|
|
26
|
+
function playground_add_action( $tag, $function_to_add, $priority = 10, $accepted_args = 1 ) {
|
|
27
|
+
playground_add_filter( $tag, $function_to_add, $priority, $accepted_args );
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Load our mu-plugins after customer mu-plugins
|
|
31
|
+
// NOTE: this means our mu-plugins can't use the muplugins_loaded action!
|
|
32
|
+
playground_add_action( 'muplugins_loaded', 'playground_load_mu_plugins', 0 );
|
|
33
|
+
function playground_load_mu_plugins() {
|
|
34
|
+
// Load all PHP files from /internal/shared/mu-plugins, sorted by filename
|
|
35
|
+
$mu_plugins_dir = '/internal/shared/mu-plugins';
|
|
36
|
+
if(!is_dir($mu_plugins_dir)){
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
$mu_plugins = glob( $mu_plugins_dir . '/*.php' );
|
|
40
|
+
sort( $mu_plugins );
|
|
41
|
+
foreach ( $mu_plugins as $mu_plugin ) {
|
|
42
|
+
require_once $mu_plugin;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
`)}async function h(e){const i=Object.values({addTrailingSlashToWpAdmin:`<?php
|
|
46
|
+
// Redirect /wp-admin to /wp-admin/
|
|
47
|
+
add_filter( 'redirect_canonical', function( $redirect_url ) {
|
|
48
|
+
if ( '/wp-admin' === $redirect_url ) {
|
|
49
|
+
return $redirect_url . '/';
|
|
50
|
+
}
|
|
51
|
+
return $redirect_url;
|
|
52
|
+
} );
|
|
53
|
+
?>`,allowRedirectHosts:`<?php
|
|
54
|
+
// Needed because gethostbyname( 'wordpress.org' ) returns
|
|
55
|
+
// a private network IP address for some reason.
|
|
56
|
+
add_filter( 'allowed_redirect_hosts', function( $deprecated = '' ) {
|
|
57
|
+
return array(
|
|
58
|
+
'wordpress.org',
|
|
59
|
+
'api.wordpress.org',
|
|
60
|
+
'downloads.wordpress.org',
|
|
61
|
+
);
|
|
62
|
+
} );
|
|
63
|
+
?>`,supportPermalinksWithoutIndexPhp:`<?php
|
|
64
|
+
add_filter( 'got_url_rewrite', '__return_true' );
|
|
65
|
+
?>`,createFontsDirectory:`<?php
|
|
66
|
+
// Create the fonts directory if missing
|
|
67
|
+
if(!file_exists(WP_CONTENT_DIR . '/fonts')) {
|
|
68
|
+
mkdir(WP_CONTENT_DIR . '/fonts');
|
|
69
|
+
}
|
|
70
|
+
?>`,configureErrorLogging:`<?php
|
|
71
|
+
$log_file = WP_CONTENT_DIR . '/debug.log';
|
|
72
|
+
define('ERROR_LOG_FILE', $log_file);
|
|
73
|
+
ini_set('error_log', $log_file);
|
|
74
|
+
?>`}).map(n=>n.trim()).join(`
|
|
75
|
+
`);await e.writeFile("/internal/shared/mu-plugins/0-playground.php",i),await e.writeFile("/internal/shared/preload/error-handler.php",`<?php
|
|
76
|
+
(function() {
|
|
77
|
+
$playground_consts = [];
|
|
78
|
+
if(file_exists('/internal/shared/consts.json')) {
|
|
79
|
+
$playground_consts = @json_decode(file_get_contents('/internal/shared/consts.json'), true) ?: [];
|
|
80
|
+
$playground_consts = array_keys($playground_consts);
|
|
81
|
+
}
|
|
82
|
+
set_error_handler(function($severity, $message, $file, $line) use($playground_consts) {
|
|
83
|
+
/**
|
|
84
|
+
* This is a temporary workaround to hide the 32bit integer warnings that
|
|
85
|
+
* appear when using various time related function, such as strtotime and mktime.
|
|
86
|
+
* Examples of the warnings that are displayed:
|
|
87
|
+
*
|
|
88
|
+
* Warning: mktime(): Epoch doesn't fit in a PHP integer in <file>
|
|
89
|
+
* Warning: strtotime(): Epoch doesn't fit in a PHP integer in <file>
|
|
90
|
+
*/
|
|
91
|
+
if (strpos($message, "fit in a PHP integer") !== false) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Playground defines some constants upfront, and some of them may be redefined
|
|
96
|
+
* in wp-config.php. For example, SITE_URL or WP_DEBUG. This is expected and
|
|
97
|
+
* we want Playground constants to take priority without showing warnings like:
|
|
98
|
+
*
|
|
99
|
+
* Warning: Constant SITE_URL already defined in
|
|
100
|
+
*/
|
|
101
|
+
if (strpos($message, "already defined") !== false) {
|
|
102
|
+
foreach($playground_consts as $const) {
|
|
103
|
+
if(strpos($message, "Constant $const already defined") !== false) {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Don't complain about network errors when not connected to the network.
|
|
110
|
+
*/
|
|
111
|
+
if (
|
|
112
|
+
(
|
|
113
|
+
! defined('USE_FETCH_FOR_REQUESTS') ||
|
|
114
|
+
! USE_FETCH_FOR_REQUESTS
|
|
115
|
+
) &&
|
|
116
|
+
strpos($message, "WordPress could not establish a secure connection to WordPress.org") !== false)
|
|
117
|
+
{
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
return false;
|
|
121
|
+
});
|
|
122
|
+
})();`)}async function b(e,t="/phpinfo.php"){await e.writeFile("/internal/shared/preload/phpinfo.php",`<?php
|
|
123
|
+
// Render PHPInfo if the requested page is /phpinfo.php
|
|
124
|
+
if ( ${s(t)} === $_SERVER['REQUEST_URI'] ) {
|
|
125
|
+
phpinfo();
|
|
126
|
+
exit;
|
|
127
|
+
}
|
|
128
|
+
`)}async function y(e,t){await e.isDir("/tmp/sqlite-database-integration")&&await e.rmdir("/tmp/sqlite-database-integration",{recursive:!0}),await e.mkdir("/tmp/sqlite-database-integration"),await d(e,t,"/tmp/sqlite-database-integration");const i="/internal/shared/sqlite-database-integration";await e.mv("/tmp/sqlite-database-integration/sqlite-database-integration-main",i);const r=(await e.readFileAsText(o(i,"db.copy"))).replace("'{SQLITE_IMPLEMENTATION_FOLDER_PATH}'",s(i)).replace("'{SQLITE_PLUGIN}'",s(o(i,"load.php"))),u=o(await e.documentRoot,"wp-content/db.php"),l=`<?php
|
|
129
|
+
// Do not preload this if WordPress comes with a custom db.php file.
|
|
130
|
+
if(file_exists(${s(u)})) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
?>`,p="/internal/shared/mu-plugins/sqlite-database-integration.php";await e.writeFile(p,l+r),await e.writeFile("/internal/shared/preload/0-sqlite.php",l+`<?php
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Loads the SQLite integration plugin before WordPress is loaded
|
|
137
|
+
* and without creating a drop-in "db.php" file.
|
|
138
|
+
*
|
|
139
|
+
* Technically, it creates a global $wpdb object whose only two
|
|
140
|
+
* purposes are to:
|
|
141
|
+
*
|
|
142
|
+
* * Exist – because the require_wp_db() WordPress function won't
|
|
143
|
+
* connect to MySQL if $wpdb is already set.
|
|
144
|
+
* * Load the SQLite integration plugin the first time it's used
|
|
145
|
+
* and replace the global $wpdb reference with the SQLite one.
|
|
146
|
+
*
|
|
147
|
+
* This lets Playground keep the WordPress installation clean and
|
|
148
|
+
* solves dillemas like:
|
|
149
|
+
*
|
|
150
|
+
* * Should we include db.php in Playground exports?
|
|
151
|
+
* * Should we remove db.php from Playground imports?
|
|
152
|
+
* * How should we treat stale db.php from long-lived OPFS sites?
|
|
153
|
+
*
|
|
154
|
+
* @see https://github.com/WordPress/wordpress-playground/discussions/1379 for
|
|
155
|
+
* more context.
|
|
156
|
+
*/
|
|
157
|
+
class Playground_SQLite_Integration_Loader {
|
|
158
|
+
public function __call($name, $arguments) {
|
|
159
|
+
$this->load_sqlite_integration();
|
|
160
|
+
if($GLOBALS['wpdb'] === $this) {
|
|
161
|
+
throw new Exception('Infinite loop detected in $wpdb – SQLite integration plugin could not be loaded');
|
|
162
|
+
}
|
|
163
|
+
return call_user_func_array(
|
|
164
|
+
array($GLOBALS['wpdb'], $name),
|
|
165
|
+
$arguments
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
public function __get($name) {
|
|
169
|
+
$this->load_sqlite_integration();
|
|
170
|
+
if($GLOBALS['wpdb'] === $this) {
|
|
171
|
+
throw new Exception('Infinite loop detected in $wpdb – SQLite integration plugin could not be loaded');
|
|
172
|
+
}
|
|
173
|
+
return $GLOBALS['wpdb']->$name;
|
|
174
|
+
}
|
|
175
|
+
public function __set($name, $value) {
|
|
176
|
+
$this->load_sqlite_integration();
|
|
177
|
+
if($GLOBALS['wpdb'] === $this) {
|
|
178
|
+
throw new Exception('Infinite loop detected in $wpdb – SQLite integration plugin could not be loaded');
|
|
179
|
+
}
|
|
180
|
+
$GLOBALS['wpdb']->$name = $value;
|
|
181
|
+
}
|
|
182
|
+
protected function load_sqlite_integration() {
|
|
183
|
+
require_once ${s(p)};
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
$wpdb = $GLOBALS['wpdb'] = new Playground_SQLite_Integration_Loader();
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* WordPress is capable of using a preloaded global $wpdb. However, if
|
|
190
|
+
* it cannot find the drop-in db.php plugin it still checks whether
|
|
191
|
+
* the mysqli_connect() function exists even though it's not used.
|
|
192
|
+
*
|
|
193
|
+
* What WordPress demands, Playground shall provide.
|
|
194
|
+
*/
|
|
195
|
+
if(!function_exists('mysqli_connect')) {
|
|
196
|
+
function mysqli_connect() {}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
`),await e.writeFile("/internal/shared/mu-plugins/sqlite-test.php",`<?php
|
|
200
|
+
global $wpdb;
|
|
201
|
+
if(!($wpdb instanceof WP_SQLite_DB)) {
|
|
202
|
+
var_dump(isset($wpdb));
|
|
203
|
+
die("SQLite integration not loaded " . get_class($wpdb));
|
|
204
|
+
}
|
|
205
|
+
`)}async function P(e,t){e.mkdir("/tmp/unzipped-wordpress"),await d(e,t,"/tmp/unzipped-wordpress"),e.fileExists("/tmp/unzipped-wordpress/wordpress.zip")&&await d(e,"/tmp/unzipped-wordpress/wordpress.zip","/tmp/unzipped-wordpress");const i=e.fileExists("/tmp/unzipped-wordpress/wordpress")?"/tmp/unzipped-wordpress/wordpress":e.fileExists("/tmp/unzipped-wordpress/build")?"/tmp/unzipped-wordpress/build":"/tmp/unzipped-wordpress";e.mv(i,e.documentRoot),!e.fileExists(o(e.documentRoot,"wp-config.php"))&&e.fileExists(o(e.documentRoot,"wp-config-sample.php"))&&e.writeFile(o(e.documentRoot,"wp-config.php"),e.readFileAsText(o(e.documentRoot,"/wp-config-sample.php")))}export{$ as enablePlatformMuPlugins,b as preloadPhpInfoRoute,h as preloadRequiredMuPlugin,y as preloadSqliteIntegration,P as unzipWordPress,m as wordPressRewriteRules};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wp-playground/wordpress",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.20",
|
|
4
4
|
"description": "WordPress-related plumbing for WordPress Playground",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -27,8 +27,5 @@
|
|
|
27
27
|
"access": "public",
|
|
28
28
|
"directory": "../../../dist/packages/playground/wordpress"
|
|
29
29
|
},
|
|
30
|
-
"
|
|
31
|
-
"@php-wasm/universal": "^0.6.6"
|
|
32
|
-
},
|
|
33
|
-
"gitHead": "687ec237085853ff5c808814c28be349146a5d1a"
|
|
30
|
+
"gitHead": "5915ef756c88da8dcb665f9f0e49ddc0c0b10d50"
|
|
34
31
|
}
|