Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
35.29% covered (danger)
35.29%
12 / 34
25.00% covered (danger)
25.00%
1 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
Jetpack_WP_Build_Page
37.50% covered (danger)
37.50%
12 / 32
25.00% covered (danger)
25.00%
1 / 4
54.26
0.00% covered (danger)
0.00%
0 / 1
 load
15.00% covered (danger)
15.00%
3 / 20
0.00% covered (danger)
0.00%
0 / 1
20.35
 alias_screen_id
80.00% covered (warning)
80.00%
4 / 5
0.00% covered (danger)
0.00%
0 / 1
3.07
 restore_screen_id
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 enqueue_i18n_loader
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2/**
3 * Loads the Jetpack plugin's wp-build output for one admin page.
4 *
5 * @package automattic/jetpack
6 */
7
8use Automattic\Jetpack\WP_Build_Polyfills\WP_Build_Polyfills;
9
10if ( ! defined( 'ABSPATH' ) ) {
11    exit( 0 );
12}
13
14/**
15 * Loads `build/build.php` for the admin page that renders a wp-build route.
16 *
17 * @since $$next-version$$
18 */
19class Jetpack_WP_Build_Page {
20
21    /**
22     * The route page id the screen ID is aliased to.
23     *
24     * @var string|null
25     */
26    private static $page_id = null;
27
28    /**
29     * The screen ID alias_screen_id() replaced, until it is restored.
30     *
31     * @var string|null
32     */
33    private static $original_screen_id = null;
34
35    /**
36     * Load wp-build for one page. Call it at `admin_menu` priority 1, and only on that page's request.
37     *
38     * Scoped to the page so WP_Build_Polyfills does not replace core scripts everywhere else.
39     *
40     * @param string $page_id The route's page id. It must not be the menu slug: the generated
41     *                        standalone page.php intercepts `admin_init` for its own id and exits.
42     * @return bool Whether the build output exists and can render the page.
43     */
44    public static function load( $page_id ) {
45        $build_index = JETPACK__PLUGIN_DIR . 'build/build.php';
46        if ( ! file_exists( $build_index ) ) {
47            return false;
48        }
49
50        self::$page_id = $page_id;
51
52        // Hooked on either side of the require, so the alias holds only for the generated
53        // enqueue check it registers at the same priority.
54        add_action( 'admin_enqueue_scripts', array( __CLASS__, 'alias_screen_id' ) );
55        require_once $build_index;
56
57        // A stale or partial build can't render the page, so don't swap core's scripts for it.
58        if ( ! function_exists( 'jetpack_plugin_' . str_replace( '-', '_', $page_id ) . '_wp_admin_render_page' ) ) {
59            remove_action( 'admin_enqueue_scripts', array( __CLASS__, 'alias_screen_id' ) );
60            self::$page_id = null;
61            return false;
62        }
63
64        add_action( 'admin_enqueue_scripts', array( __CLASS__, 'restore_screen_id' ) );
65        add_action( 'admin_enqueue_scripts', array( __CLASS__, 'enqueue_i18n_loader' ) );
66
67        // wp-build hooks module registration to wp_default_scripts, which has already fired by
68        // admin_menu — call it directly or the init module never reaches the import map.
69        if ( function_exists( 'jetpack_plugin_register_script_modules' ) ) {
70            jetpack_plugin_register_script_modules(); // @phan-suppress-current-line PhanUndeclaredFunction -- Checked with function_exists(); defined in the generated build/modules.php, which Phan excludes.
71        }
72
73        if ( class_exists( WP_Build_Polyfills::class ) ) {
74            WP_Build_Polyfills::register(
75                'jetpack',
76                array_merge( WP_Build_Polyfills::SCRIPT_HANDLES, WP_Build_Polyfills::MODULE_IDS )
77            );
78        }
79
80        return true;
81    }
82
83    /**
84     * Point the screen ID at the wp-build page while its generated enqueue check runs.
85     *
86     * @return void
87     */
88    public static function alias_screen_id() {
89        $screen = get_current_screen();
90        if ( ! $screen || null === self::$page_id ) {
91            return;
92        }
93
94        self::$original_screen_id = $screen->id;
95        $screen->id               = self::$page_id;
96    }
97
98    /**
99     * Undo alias_screen_id(), since JITM builds its message path from the screen ID.
100     *
101     * @return void
102     */
103    public static function restore_screen_id() {
104        $screen = get_current_screen();
105        if ( ! $screen || null === self::$original_screen_id ) {
106            return;
107        }
108
109        $screen->id               = self::$original_screen_id;
110        self::$original_screen_id = null;
111    }
112
113    /**
114     * Enqueue the JS translation loader the route bundles need.
115     *
116     * Registered on every admin page but only enqueued when depended on, and the esbuild
117     * bundles don't pull it in — without it every string renders untranslated.
118     *
119     * @return void
120     */
121    public static function enqueue_i18n_loader() {
122        if ( wp_script_is( 'wp-jp-i18n-loader', 'registered' ) ) {
123            wp_enqueue_script( 'wp-jp-i18n-loader' );
124        }
125    }
126}