PluginProbe ʕ •ᴥ•ʔ
Jetpack – WP Security, Backup, Speed, & Growth / 16.0-beta
Jetpack – WP Security, Backup, Speed, & Growth v16.0-beta
16.0 16.0-beta 16.0-a.7 16.0-a.5 15.9.1 16.0-a.3 16.0-a.1 15.9 15.9-beta 15.9-a.7 15.9-a.5 15.9-a.3 15.9-a.1 15.8 15.8-beta 15.8-a.7 15.8-a.5 5.2.5 5.3.4 5.4.4 5.5.5 5.6.5 5.7.5 5.8.4 5.9.4 6.0.4 6.1 6.1.1 6.1.2 6.1.3 6.1.4 6.1.5 6.2 6.2.1 6.2.2 6.2.3 6.2.4 6.2.5 6.3 6.3.1 6.3.2 6.3.3 6.3.4 6.3.5 6.3.6 6.3.7 6.4 6.4.1 6.4.2 6.4.3 6.4.4 6.4.5 6.4.6 6.5 6.5.1 6.5.2 6.5.3 6.5.4 6.6 6.6.1 6.6.2 6.6.3 6.6.4 6.6.5 6.7 6.7.1 6.7.2 6.7.3 6.7.4 6.8 6.8.1 6.8.2 6.8.3 6.8.4 6.8.5 6.9 6.9.1 6.9.2 6.9.3 6.9.4 7.0 7.0.1 7.0.2 7.0.3 7.0.4 7.0.5 7.1 7.1.1 7.1.2 7.1.3 7.1.4 7.1.5 7.2 7.2.1 7.2.1.1 7.2.2 7.2.3 7.2.4 7.2.5 7.3 7.3.0.1 7.3.1 7.3.1.1 7.3.2 7.3.3 7.3.4 7.3.5 7.4 7.4.1 7.4.2 7.4.3 7.4.4 7.4.5 7.5 7.5.0.1 7.5.1 7.5.2 7.5.3 7.5.4 7.5.5 7.5.6 7.5.7 7.6 7.6.1 7.6.2 7.6.3 7.6.4 7.7 7.7.1 7.7.2 7.7.3 7.7.4 7.7.5 7.7.6 7.8 7.8.1 7.8.2 7.8.3 7.8.4 7.9 7.9.1 7.9.2 7.9.3 7.9.4 8.0 8.0.1 8.0.2 8.0.3 8.1 8.1.1 8.1.2 8.1.3 8.1.4 8.2 8.2.0.1 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.2.6 8.3 8.3.1 8.3.2 8.3.3 8.4 8.4.1 8.4.2 8.4.3 8.4.4 8.4.5 8.5 8.5.1 8.5.2 8.5.3 8.6 8.6.1 8.6.2 8.6.3 8.6.4 8.7 8.7.0.1 8.7.1 8.7.2 8.7.3 8.7.4 8.8 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.9 8.9.1 8.9.2 8.9.3 8.9.4 9.0 9.0.1 9.0.2 9.0.3 9.0.4 9.0.5 9.1 9.1.1 9.1.2 9.1.3 9.2 9.2.1 9.2.2 9.2.3 9.2.4 9.3 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.4 9.4.1 9.4.2 9.4.3 9.4.4 9.5 9.5.1 9.5.2 9.5.3 9.5.4 9.5.5 9.6 9.6.1 9.6.2 9.6.3 9.6.4 9.7 9.7.1 9.7.2 15.7-beta.2 9.7.3 15.7.1 9.8 15.8-a.1 9.8.1 15.8-a.3 9.8.2 2.0.9 9.8.3 2.1.7 9.9 2.2.10 9.9.1 2.3.10 9.9.2 2.4.7 9.9.3 2.5.5 2.6.6 2.7.5 2.8.5 2.9.6 3.0.6 3.1.5 3.2.5 3.3.6 3.4.6 3.5.6 3.6.4 3.7.5 3.8.5 3.9.10 4.0.7 4.1.4 4.2.5 4.3.5 4.4.5 4.5.3 4.6.3 4.7.4 4.8.5 4.9.3 5.0.3 5.1.4 trunk 10.0 10.0.1 10.0.2 10.1 10.1.1 10.1.2 10.2 10.2.1 10.2.2 10.2.3 10.3 10.3.1 10.3.2 10.4 10.4.1 10.4.2 10.5 10.5.1 10.5.2 10.5.3 10.6 10.6.1 10.6.2 10.7 10.7.1 10.7.2 10.8 10.8.1 10.8.2 10.9 10.9.1 10.9.2 10.9.3 11.0 11.0.1 11.0.2 11.1 11.1.1 11.1.2 11.1.3 11.1.4 11.2 11.2.1 11.2.2 11.3 11.3.1 11.3.2 11.3.3 11.3.4 11.4 11.4.1 11.4.2 11.5 11.5.1 11.5.2 11.5.3 11.6 11.6.1 11.6.2 11.7 11.7.1 11.7.2 11.7.3 11.8 11.8.3 11.8.4 11.8.5 11.8.6 11.9 11.9.1 11.9.2 11.9.3 12.0 12.0.1 12.0.2 12.1 12.1.1 12.1.2 12.2 12.2.1 12.2.2 12.3 12.3.1 12.4 12.4.1 12.5 12.5.1 12.6 12.6.1 12.6.2 12.6.3 12.7 12.7.1 12.7.2 12.8 12.8.1 12.8.2 12.9 12.9.1 12.9.2 12.9.3 12.9.4 13.0 13.0.1 13.1 13.1.1 13.1.2 13.1.3 13.1.4 13.2 13.2.1 13.2.2 13.2.3 13.3 13.3.1 13.3.2 13.4 13.4.1 13.4.2 13.4.3 13.4.4 13.5 13.5.1 13.6 13.6.1 13.7 13.7.1 13.8 13.8.1 13.8.2 13.9 13.9.1 14.0 14.1 14.2 14.2.1 14.3 14.4 14.4.1 14.5 14.6 14.7 14.8 14.9 14.9.1 15.0 15.0.1 15.0.2 15.1 15.1.1 15.2 15.3 15.3.1 15.4 15.5 15.6 15.7 15.7-a.1 15.7-a.3 15.7-a.5 15.7-a.7 15.7-beta
jetpack / _inc / lib / admin-pages / class.jetpack-react-page.php
jetpack / _inc / lib / admin-pages Last commit date
class-akismet-admin-chrome.php 2 weeks ago class-jetpack-about-page.php 1 month ago class-jetpack-ai-page.php 1 month ago class-jetpack-redux-state-helper.php 2 weeks ago class.jetpack-admin-page.php 1 month ago class.jetpack-landing-page.php 2 years ago class.jetpack-react-page.php 6 months ago class.jetpack-settings-page.php 7 months ago
class.jetpack-react-page.php
323 lines
1 <?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
2
3 use Automattic\Jetpack\Admin_UI\Admin_Menu;
4 use Automattic\Jetpack\Assets\Logo;
5 use Automattic\Jetpack\Connection\Initial_State as Connection_Initial_State;
6 use Automattic\Jetpack\Connection\Manager as Connection_Manager;
7 use Automattic\Jetpack\Status;
8
9 require_once __DIR__ . '/class.jetpack-admin-page.php';
10 require_once __DIR__ . '/class-jetpack-redux-state-helper.php';
11
12 /**
13 * Builds the landing page and its menu.
14 */
15 class Jetpack_React_Page extends Jetpack_Admin_Page {
16 /**
17 * Show the landing page only when Jetpack is connected.
18 *
19 * @var bool
20 */
21 protected $dont_show_if_not_active = false;
22
23 /**
24 * Used for fallback when REST API is disabled.
25 *
26 * @var bool
27 */
28 protected $is_redirecting = false;
29
30 /**
31 * Add the main admin Jetpack menu.
32 *
33 * @return string|false Return value from WordPress's `add_menu_page()`.
34 */
35 public function get_page_hook() {
36 $icon = ( new Logo() )->get_base64_logo();
37 return add_menu_page( 'Jetpack', 'Jetpack', 'jetpack_admin_page', 'jetpack', array( $this, 'render' ), $icon, 3 );
38 }
39
40 /**
41 * Add page action.
42 *
43 * @param string $hook Hook of current page.
44 * @return void
45 */
46 public function add_page_actions( $hook ) {
47 /** This action is documented in class.jetpack-admin.php */
48 do_action( 'jetpack_admin_menu', $hook );
49
50 if ( ! isset( $_GET['page'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
51 return;
52 }
53 $page = sanitize_text_field( wp_unslash( $_GET['page'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
54 if ( 'jetpack' !== $page ) {
55 if ( strpos( $page, 'jetpack/' ) === 0 ) {
56 $section = substr( $page, 8 );
57 wp_safe_redirect( admin_url( 'admin.php?page=jetpack#/' . $section ) );
58 exit( 0 );
59 }
60 return; // No need to handle the fallback redirection if we are not on the Jetpack page.
61 }
62
63 // Adding a redirect meta tag if the REST API is disabled.
64 if ( ! $this->is_rest_api_enabled() ) {
65 $this->is_redirecting = true;
66 add_action( 'admin_head', array( $this, 'add_fallback_head_meta' ) );
67 }
68
69 // Adding a redirect meta tag wrapped in noscript tags for all browsers in case they have JavaScript disabled.
70 add_action( 'admin_head', array( $this, 'add_noscript_head_meta' ) );
71
72 // If this is the first time the user is viewing the admin, don't show JITMs.
73 // This filter is added just in time because this function is called on admin_menu
74 // and JITMs are initialized on admin_init.
75 if ( Jetpack::is_connection_ready() && ! Jetpack_Options::get_option( 'first_admin_view', false ) ) {
76 Jetpack_Options::update_option( 'first_admin_view', true );
77 add_filter( 'jetpack_just_in_time_msgs', '__return_false' );
78 }
79 }
80
81 /**
82 * Remove the main Jetpack submenu if a site is in offline mode or connected
83 * or if My Jetpack is available.
84 * At that point, admins can access the Jetpack Dashboard instead.
85 *
86 * @since 13.8
87 */
88 public function remove_jetpack_menu() {
89 $is_offline_mode = ( new Status() )->is_offline_mode();
90 $has_my_jetpack = (
91 class_exists( 'Automattic\Jetpack\My_Jetpack\Initializer' ) &&
92 method_exists( 'Automattic\Jetpack\My_Jetpack\Initializer', 'should_initialize' ) &&
93 \Automattic\Jetpack\My_Jetpack\Initializer::should_initialize()
94 );
95
96 if ( $is_offline_mode || $has_my_jetpack || Jetpack::is_connection_ready() ) {
97 remove_submenu_page( 'jetpack', 'jetpack' );
98 }
99 }
100
101 /**
102 * Determine whether a user can access the Jetpack Settings page.
103 *
104 * Rules are:
105 * - user is allowed to see the Jetpack Admin
106 * - site is connected or in offline mode
107 * - non-admins only need access to the settings when there are modules they can manage.
108 *
109 * @return bool $can_access_settings Can the user access settings.
110 */
111 private function can_access_settings() {
112 $connection = new Connection_Manager( 'jetpack' );
113 $status = new Status();
114
115 // User must have the necessary permissions to see the Jetpack settings pages.
116 if ( ! current_user_can( 'edit_posts' ) ) {
117 return false;
118 }
119
120 // In offline mode, allow access to admins.
121 if ( $status->is_offline_mode() && current_user_can( 'manage_options' ) ) {
122 return true;
123 }
124
125 // If not in offline mode but site is not connected, bail.
126 if ( ! Jetpack::is_connection_ready() ) {
127 return false;
128 }
129
130 /*
131 * Additional checks for non-admins.
132 */
133 if ( ! current_user_can( 'manage_options' ) ) {
134 // If the site isn't connected at all, bail.
135 if ( ! $connection->has_connected_owner() ) {
136 return false;
137 }
138
139 /*
140 * If they haven't connected their own account yet,
141 * they have no use for the settings page.
142 * They will not be able to manage any settings.
143 */
144 if ( ! $connection->is_user_connected() ) {
145 return false;
146 }
147
148 /*
149 * Non-admins only have access to settings
150 * for the following modules:
151 * - Publicize
152 * - Post By Email
153 * If those modules are not available, bail.
154 */
155 if (
156 ! Jetpack::is_module_active( 'post-by-email' )
157 && (
158 ! Jetpack::is_module_active( 'publicize' ) ||
159 ! current_user_can( 'publish_posts' )
160 )
161 ) {
162 return false;
163 }
164 }
165
166 // fallback.
167 return true;
168 }
169
170 /**
171 * Jetpack Settings sub-link.
172 *
173 * @since 4.3.0
174 * @since 9.7.0 If Connection does not have an owner, restrict it to admins
175 */
176 public function jetpack_add_settings_sub_nav_item() {
177 if ( $this->can_access_settings() ) {
178 Admin_Menu::add_menu(
179 __( 'Settings', 'jetpack' ),
180 __( 'Settings', 'jetpack' ),
181 'jetpack_admin_page',
182 Jetpack::admin_url( array( 'page' => 'jetpack#/settings' ) ),
183 null,
184 13
185 );
186 }
187 }
188
189 /**
190 * Fallback redirect meta tag if the REST API is disabled.
191 *
192 * @return void
193 */
194 public function add_fallback_head_meta() {
195 echo '<meta http-equiv="refresh" content="0; url=?page=jetpack_modules">';
196 }
197
198 /**
199 * Fallback meta tag wrapped in noscript tags for all browsers in case they have JavaScript disabled.
200 *
201 * @return void
202 */
203 public function add_noscript_head_meta() {
204 echo '<noscript>';
205 $this->add_fallback_head_meta();
206 echo '</noscript>';
207 }
208
209 /**
210 * Add action to render page specific HTML.
211 *
212 * @return void
213 */
214 public function page_render() {
215 /** This action is already documented in class.jetpack-admin-page.php */
216 do_action( 'jetpack_notices' );
217
218 // Fetch static.html.
219 $static_html = @file_get_contents( JETPACK__PLUGIN_DIR . '_inc/build/static.html' ); //phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged, WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents, Not fetching a remote file.
220
221 if ( false === $static_html ) {
222
223 // If we still have nothing, display an error.
224 echo '<p>';
225 esc_html_e( 'Error fetching static.html. Try running: ', 'jetpack' );
226 echo '<code>pnpm run distclean && pnpm jetpack build plugins/jetpack</code>';
227 echo '</p>';
228 } else {
229 // We got the static.html so let's display it.
230 echo $static_html; //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
231 }
232 }
233 /**
234 * Allow robust deep links to React.
235 *
236 * The Jetpack dashboard requires fragments/hash values to make
237 * a deep link to it but passing fragments as part of a return URL
238 * will most often be discarded throughout the process.
239 * This logic aims to bridge this gap and reduce the chance of React
240 * specific links being broken while passing them along.
241 */
242 public function react_redirects() {
243 global $pagenow;
244
245 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
246 if ( 'admin.php' !== $pagenow || ! isset( $_GET['jp-react-redirect'] ) ) {
247 return;
248 }
249
250 $allowed_paths = array(
251 'product-purchased' => admin_url( '/admin.php?page=jetpack#/recommendations/product-purchased' ),
252 );
253
254 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
255 $target = sanitize_text_field( wp_unslash( $_GET['jp-react-redirect'] ) );
256 if ( isset( $allowed_paths[ $target ] ) ) {
257 wp_safe_redirect( $allowed_paths[ $target ] );
258 exit( 0 );
259 }
260 }
261
262 /**
263 * Load styles for static page.
264 */
265 public function additional_styles() {
266 Jetpack_Admin_Page::load_wrapper_styles();
267 }
268
269 /**
270 * Load admin page scripts.
271 */
272 public function page_admin_scripts() {
273 if ( $this->is_redirecting ) {
274 return; // No need for scripts on a fallback page.
275 }
276
277 $status = new Status();
278 $is_offline_mode = $status->is_offline_mode();
279 $site_suffix = $status->get_site_suffix();
280 $script_deps_path = JETPACK__PLUGIN_DIR . '_inc/build/admin.asset.php';
281 $script_dependencies = array( 'jquery', 'wp-polyfill' );
282 $version = JETPACK__VERSION;
283 if ( file_exists( $script_deps_path ) ) {
284 $asset_manifest = include $script_deps_path;
285 $script_dependencies = $asset_manifest['dependencies'];
286 $version = $asset_manifest['version'];
287 }
288
289 $blog_id_prop = '';
290 if ( ! defined( 'IS_WPCOM' ) || ! IS_WPCOM ) {
291 $blog_id = Connection_Manager::get_site_id( true );
292 if ( $blog_id ) {
293 $blog_id_prop = ', currentBlogID: "' . (int) $blog_id . '"';
294 }
295 }
296
297 wp_enqueue_script(
298 'react-plugin',
299 plugins_url( '_inc/build/admin.js', JETPACK__PLUGIN_FILE ),
300 $script_dependencies,
301 $version,
302 true
303 );
304
305 if ( ! $is_offline_mode && Jetpack::is_connection_ready() ) {
306 // Required for Analytics.
307 wp_enqueue_script( 'jp-tracks', '//stats.wp.com/w.js', array(), gmdate( 'YW' ), true );
308 }
309
310 wp_set_script_translations( 'react-plugin', 'jetpack' );
311
312 // Add objects to be passed to the initial state of the app.
313 // Use wp_add_inline_script instead of wp_localize_script, see https://core.trac.wordpress.org/ticket/25280.
314 wp_add_inline_script( 'react-plugin', 'var Initial_State=' . wp_json_encode( Jetpack_Redux_State_Helper::get_initial_state(), JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_HEX_AMP ) . ';', 'before' );
315
316 // This will set the default URL of the jp_redirects lib.
317 wp_add_inline_script( 'react-plugin', 'var jetpack_redirects = { currentSiteRawUrl: "' . $site_suffix . '"' . $blog_id_prop . ' };', 'before' );
318
319 // Adds Connection package initial state.
320 Connection_Initial_State::render_script( 'react-plugin' );
321 }
322 }
323