PluginProbe
ActivityPub / 8.0.2
ActivityPub v8.0.2
9.3.1 9.3.0 9.2.2 9.2.1 9.2.0 9.1.0 9.0.2 9.0.1 9.0.0 8.3.0 8.2.1 8.2.0 8.1.1 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.2.0 1.3.0 2.0.0 2.0.1 2.1.0 2.1.1 All 160 releases
← All changes | includes/wp-admin/class-app.php +40 -367 9.2.08.0.2 View file →
@@ -11,31 +11,9 @@
11 11 * ActivityPub App Admin Page Class.
12 12 */
13 13 class App {
14 14
15 - const MOUNT_ID = 'activitypub-app-root';
16 - const LOADER_MODULE = '@activitypub/app';
17 - const FEED_CONTENT_MODULE = '@activitypub/app/routes/feed/content';
18 - const FEED_ROUTE_MODULE = '@activitypub/app/routes/feed/route';
19 -
20 15 /**
21 - * Whether the WordPress admin app boot stack is available.
22 - *
23 - * This is the WordPress 7.0+ gate for the Social Web app. Instead of a
24 - * `version_compare()` against `7.0`, it detects the boot stack by capability:
25 - * the Script Modules API plus core's `@wordpress/boot` module asset, which
26 - * ships in 7.0. Capability detection is deliberate, because a `version_compare`
27 - * would lock out pre-release builds — `7.0-alpha`/`7.0-RC1` fail
28 - * `version_compare( …, '7.0', '>=' )` yet already ship the boot module — so
29 - * early-adopter installs would wrongly fall back to no app.
30 - *
31 - * @return bool True when the Social Web app can be booted (WordPress 7.0+).
32 - */
33 - public static function is_supported() {
34 - return \function_exists( 'wp_register_script_module' ) && \is_array( self::get_boot_asset() );
35 - }
36 -
37 - /**
38 16 * Initialize the App page.
39 17 *
40 18 * Must run early (on admin_init) before the admin bar is initialized.
41 19 */
@@ -69,137 +47,8 @@
69 47 \wp_dequeue_style( 'colors' );
70 48 \wp_dequeue_script( 'common' );
71 49 \wp_dequeue_script( 'svg-painter' );
72 50
73 - if ( ! self::is_supported() ) {
74 - return;
75 - }
76 -
77 - $boot_asset = self::get_boot_asset();
78 -
79 - if ( ! \is_array( $boot_asset ) ) {
80 - return;
81 - }
82 -
83 - self::preload_rest_data();
84 -
85 - $routes = self::get_routes();
86 - self::add_loader_data( $routes );
87 -
88 - \wp_register_script(
89 - 'activitypub-app-prerequisites',
90 - false,
91 - self::get_script_dependencies( $boot_asset ),
92 - $boot_asset['version'],
93 - true
94 - );
95 -
96 - $style_dependencies = \array_filter(
97 - $boot_asset['dependencies'],
98 - static function ( $handle ) {
99 - return \wp_style_is( $handle, 'registered' );
100 - }
101 - );
102 -
103 - \wp_register_style(
104 - 'activitypub-app-prerequisites',
105 - false,
106 - $style_dependencies,
107 - $boot_asset['version']
108 - );
109 -
110 - self::register_app_modules( $routes );
111 - self::enqueue_app_styles();
112 -
113 - \wp_enqueue_script( 'activitypub-app-prerequisites' );
114 - \wp_enqueue_script_module( self::LOADER_MODULE );
115 - \wp_enqueue_style( 'activitypub-app-prerequisites' );
116 - }
117 -
118 - /**
119 - * Get classic script dependencies required before app script modules run.
120 - *
121 - * @param array $boot_asset Core boot module asset metadata.
122 - * @return array Script handles.
123 - */
124 - private static function get_script_dependencies( $boot_asset ) {
125 - $dependencies = \array_merge(
126 - $boot_asset['dependencies'] ?? array(),
127 - array(
128 - 'lodash',
129 - 'moment',
130 - 'react',
131 - 'react-dom',
132 - 'react-jsx-runtime',
133 - 'wp-api-fetch',
134 - 'wp-commands',
135 - 'wp-components',
136 - 'wp-compose',
137 - 'wp-core-data',
138 - 'wp-data',
139 - 'wp-data-controls',
140 - 'wp-date',
141 - 'wp-dom',
142 - 'wp-element',
143 - 'wp-html-entities',
144 - 'wp-hooks',
145 - 'wp-i18n',
146 - 'wp-keyboard-shortcuts',
147 - 'wp-keycodes',
148 - 'wp-notices',
149 - 'wp-preferences',
150 - 'wp-primitives',
151 - 'wp-private-apis',
152 - 'wp-url',
153 - 'wp-viewport',
154 - )
155 - );
156 -
157 - /**
158 - * Filters the ActivityPub app prerequisite script dependencies.
159 - *
160 - * @param array $dependencies Script handles.
161 - * @param array $boot_asset Core boot module asset metadata.
162 - */
163 - $dependencies = (array) \apply_filters(
164 - 'activitypub_app_prerequisite_dependencies',
165 - \array_values( \array_unique( $dependencies ) ),
166 - $boot_asset
167 - );
168 -
169 - return \array_values(
170 - \array_filter(
171 - \array_unique( $dependencies ),
172 - static function ( $handle ) {
173 - return \wp_script_is( $handle, 'registered' );
174 - }
175 - )
176 - );
177 - }
178 -
179 - /**
180 - * Add boot configuration for the app loader module.
181 - *
182 - * @param array $routes Route definitions.
183 - */
184 - private static function add_loader_data( $routes ) {
185 - $mount_id = self::MOUNT_ID;
186 -
187 - \add_filter(
188 - 'script_module_data_' . self::LOADER_MODULE,
189 - static function ( $data ) use ( $mount_id, $routes ) {
190 - $data['mountId'] = $mount_id;
191 - $data['routes'] = $routes;
192 -
193 - return $data;
194 - }
195 - );
196 - }
197 -
198 - /**
199 - * Preload REST data used by the first app render.
200 - */
201 - private static function preload_rest_data() {
202 51 // Define paths to preload - must match exact fields from entities.js.
203 52 $preload_paths = array(
204 53 '/?_fields=description,gmt_offset,home,name,site_icon,site_icon_url,site_logo,timezone_string,url,page_for_posts,page_on_front,show_on_front',
205 54 array( '/wp/v2/settings', 'OPTIONS' ),
@@ -204,8 +53,9 @@
204 53 '/?_fields=description,gmt_offset,home,name,site_icon,site_icon_url,site_logo,timezone_string,url,page_for_posts,page_on_front,show_on_front',
205 54 array( '/wp/v2/settings', 'OPTIONS' ),
206 55 );
207 56
57 + // Use rest_preload_api_request to gather the preloaded data.
208 58 $preload_data = \array_reduce(
209 59 $preload_paths,
210 60 'rest_preload_api_request',
211 61 array()
@@ -210,246 +60,69 @@
210 60 'rest_preload_api_request',
211 61 array()
212 62 );
213 63
64 + // Register the preloading middleware with wp-api-fetch.
214 65 \wp_add_inline_script(
215 66 'wp-api-fetch',
216 - \sprintf( 'wp.apiFetch.use( wp.apiFetch.createPreloadingMiddleware( %s ) );', \wp_json_encode( $preload_data ) ),
217 - 'after'
67 + \sprintf( 'wp.apiFetch.use( wp.apiFetch.createPreloadingMiddleware( %s ) );', \wp_json_encode( $preload_data ) )
218 68 );
219 - }
220 69
221 - /**
222 - * Get the app route registry.
223 - *
224 - * @return array Route definitions.
225 - */
226 - private static function get_routes() {
227 - $routes = array(
228 - array(
229 - 'path' => '/',
230 - 'content_module' => self::FEED_CONTENT_MODULE,
231 - 'route_module' => self::FEED_ROUTE_MODULE,
232 - ),
70 + $router_asset = include \plugin_dir_path( ACTIVITYPUB_PLUGIN_FILE ) . 'build/app/tanstack-router.asset.php';
71 + \wp_enqueue_script(
72 + 'activitypub-app-tanstack-router',
73 + \plugins_url( 'build/app/tanstack-router.js', ACTIVITYPUB_PLUGIN_FILE ),
74 + $router_asset['dependencies'],
75 + $router_asset['version'],
76 + true
233 77 );
234 78
235 - /**
236 - * Filters the ActivityPub app route registry.
237 - *
238 - * @param array $routes Route definitions.
239 - */
240 - return \apply_filters( 'activitypub_app_routes', $routes );
241 - }
242 -
243 - /**
244 - * Register app script modules.
245 - *
246 - * @param array $routes Route definitions.
247 - */
248 - private static function register_app_modules( $routes ) {
249 - $module_assets = self::get_app_module_assets();
250 - $module_ids = array();
251 -
252 - foreach ( $routes as $route ) {
253 - foreach ( array( 'content_module', 'route_module' ) as $module_key ) {
254 - if ( ! empty( $route[ $module_key ] ) ) {
255 - $module_ids[] = $route[ $module_key ];
256 - }
257 - }
258 - }
259 -
260 - foreach ( \array_unique( $module_ids ) as $module_id ) {
261 - if ( ! isset( $module_assets[ $module_id ] ) ) {
262 - continue;
263 - }
264 -
265 - self::register_script_module(
266 - $module_id,
267 - $module_assets[ $module_id ]['script'],
268 - $module_assets[ $module_id ]['asset']
269 - );
270 - }
271 -
272 - $loader_asset = self::get_asset( 'build/app/loader.asset.php' );
273 -
274 - \wp_register_script_module(
275 - self::LOADER_MODULE,
276 - \plugins_url( 'build/app/loader.js', ACTIVITYPUB_PLUGIN_FILE ),
277 - self::get_boot_dependencies( $routes ),
278 - \is_array( $loader_asset ) && isset( $loader_asset['version'] ) ? $loader_asset['version'] : ACTIVITYPUB_PLUGIN_VERSION
79 + $vendors_asset = include \plugin_dir_path( ACTIVITYPUB_PLUGIN_FILE ) . 'build/app/vendors.asset.php';
80 + \wp_enqueue_script(
81 + 'activitypub-app-vendors',
82 + \plugins_url( 'build/app/vendors.js', ACTIVITYPUB_PLUGIN_FILE ),
83 + $vendors_asset['dependencies'],
84 + $vendors_asset['version'],
85 + true
279 86 );
280 - }
281 87
282 - /**
283 - * Get built app module asset paths keyed by script module ID.
284 - *
285 - * @return array Module asset definitions.
286 - */
287 - private static function get_app_module_assets() {
288 - return array(
289 - self::FEED_CONTENT_MODULE => array(
290 - 'script' => 'build/app/routes/feed/content.js',
291 - 'asset' => 'build/app/routes/feed/content.asset.php',
292 - ),
293 - self::FEED_ROUTE_MODULE => array(
294 - 'script' => 'build/app/routes/feed/route.js',
295 - 'asset' => 'build/app/routes/feed/route.asset.php',
296 - ),
297 - );
298 - }
88 + $asset_file = include \plugin_dir_path( ACTIVITYPUB_PLUGIN_FILE ) . 'build/app/index.asset.php';
299 89
300 - /**
301 - * Register a built script module.
302 - *
303 - * @param string $module_id Script module ID.
304 - * @param string $script Script path relative to the plugin root.
305 - * @param string $asset_file Asset metadata path relative to the plugin root.
306 - */
307 - private static function register_script_module( $module_id, $script, $asset_file ) {
308 - $asset = self::get_asset( $asset_file );
309 -
310 - if ( ! $asset ) {
311 - return;
312 - }
313 -
314 - \wp_register_script_module(
315 - $module_id,
316 - \plugins_url( $script, ACTIVITYPUB_PLUGIN_FILE ),
317 - isset( $asset['dependencies'] ) && \is_array( $asset['dependencies'] ) ? $asset['dependencies'] : array(),
318 - isset( $asset['version'] ) ? $asset['version'] : ACTIVITYPUB_PLUGIN_VERSION
90 + \wp_enqueue_script(
91 + 'activitypub-app',
92 + \plugins_url( 'build/app/index.js', ACTIVITYPUB_PLUGIN_FILE ),
93 + array_merge( $asset_file['dependencies'], array( 'activitypub-app-tanstack-router', 'activitypub-app-vendors' ) ),
94 + $asset_file['version'],
95 + true
319 96 );
320 - }
321 97
322 - /**
323 - * Build dependencies for the app loader module.
324 - *
325 - * @param array $routes Route definitions.
326 - * @return array Script module dependencies.
327 - */
328 - private static function get_boot_dependencies( $routes ) {
329 - $dependencies = array(
330 - array(
331 - 'id' => '@wordpress/boot',
332 - 'import' => 'static',
333 - ),
334 - );
335 -
336 - foreach ( $routes as $route ) {
337 - if ( ! empty( $route['route_module'] ) ) {
338 - $dependencies[] = array(
339 - 'id' => $route['route_module'],
340 - 'import' => 'static',
341 - );
342 - }
343 -
344 - if ( ! empty( $route['content_module'] ) ) {
345 - $dependencies[] = array(
346 - 'id' => $route['content_module'],
347 - 'import' => 'dynamic',
348 - );
349 - }
350 - }
351 -
352 - /**
353 - * Filters the ActivityPub app loader module dependencies.
354 - *
355 - * @param array $dependencies Script module dependencies.
356 - * @param array $routes Route definitions.
357 - */
358 - return \apply_filters( 'activitypub_app_boot_dependencies', $dependencies, $routes );
359 - }
360 -
361 - /**
362 - * Enqueue styles emitted by the module build.
363 - */
364 - private static function enqueue_app_styles() {
365 - $style_path = 'build/app/routes/feed/style-content.css';
366 - $asset = self::get_asset( 'build/app/routes/feed/content.asset.php' );
367 -
368 - if ( ! \file_exists( \plugin_dir_path( ACTIVITYPUB_PLUGIN_FILE ) . $style_path ) ) {
369 - return;
370 - }
371 -
372 - $style_dependencies = \array_filter(
98 + \wp_enqueue_style(
99 + 'activitypub-app',
100 + \plugins_url( 'build/app/style-index.css', ACTIVITYPUB_PLUGIN_FILE ),
373 101 array( 'wp-components', 'wp-edit-site' ),
374 - static function ( $handle ) {
375 - return \wp_style_is( $handle, 'registered' );
376 - }
102 + $asset_file['version']
377 103 );
378 104
379 - \wp_enqueue_style(
105 + \wp_add_inline_script(
380 106 'activitypub-app',
381 - \plugins_url( $style_path, ACTIVITYPUB_PLUGIN_FILE ),
382 - $style_dependencies,
383 - \is_array( $asset ) && isset( $asset['version'] ) ? $asset['version'] : ACTIVITYPUB_PLUGIN_VERSION
107 + sprintf(
108 + 'wp.domReady( function() {
109 + wp.activitypubApp.initialize( "activitypub-app-root", %s );
110 + } );',
111 + \wp_json_encode(
112 + array(
113 + 'namespace' => ACTIVITYPUB_REST_NAMESPACE,
114 + )
115 + )
116 + )
384 117 );
385 118 }
386 119
387 120 /**
388 - * Get the core boot asset file path.
389 - *
390 - * @return string Boot asset file path.
391 - */
392 - private static function get_boot_asset_file() {
393 - return ABSPATH . WPINC . '/js/dist/script-modules/boot/index.min.asset.php';
394 - }
395 -
396 - /**
397 - * Get the core boot asset metadata.
398 - *
399 - * @return array|null Boot asset metadata, or null when unavailable.
400 - */
401 - private static function get_boot_asset() {
402 - static $cached = false;
403 - static $asset = null;
404 -
405 - if ( $cached ) {
406 - return $asset;
407 - }
408 -
409 - $cached = true;
410 -
411 - $boot_asset_file = self::get_boot_asset_file();
412 -
413 - if ( ! \file_exists( $boot_asset_file ) ) {
414 - return $asset;
415 - }
416 -
417 - $boot_asset = include $boot_asset_file;
418 - $asset = \is_array( $boot_asset ) ? $boot_asset : null;
419 -
420 - return $asset;
421 - }
422 -
423 - /**
424 - * Get built asset metadata.
425 - *
426 - * @param string $asset_file Asset metadata path relative to the plugin root.
427 - * @return array|null Asset metadata, or null when unavailable.
428 - */
429 - private static function get_asset( $asset_file ) {
430 - $path = \plugin_dir_path( ACTIVITYPUB_PLUGIN_FILE ) . $asset_file;
431 -
432 - if ( ! \file_exists( $path ) ) {
433 - return null;
434 - }
435 -
436 - return include $path;
437 - }
438 -
439 - /**
440 121 * Render the App admin page.
441 122 */
442 123 public static function render_page() {
443 - if ( ! self::is_supported() ) {
444 - ?>
445 - <div class="notice notice-error">
446 - <p><?php \esc_html_e( 'The Social Web screen requires a newer WordPress admin app runtime. Please update WordPress to use this screen.', 'activitypub' ); ?></p>
447 - </div>
448 - <?php
449 - return;
450 - }
451 124 ?>
452 - <div id="<?php echo \esc_attr( self::MOUNT_ID ); ?>" class="boot-layout-container activitypub-app-layout"></div>
125 + <div id="activitypub-app-root" class="activitypub-app-layout"></div>
453 126 <?php
454 127 }
455 128 }