PluginProbe ʕ •ᴥ•ʔ
Jetpack – WP Security, Backup, Speed, & Growth / 14.9.2
Jetpack – WP Security, Backup, Speed, & Growth v14.9.2
12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 13.7.2 13.8.3 13.9.2 14.0.1 14.1.1 14.2.2 14.3.1 14.4.2 14.5.1 14.6.1 14.7.1 14.8.1 14.9.2 15.0.3 15.1.2 15.2.1 15.3.2 15.4.1 15.5.1 15.6.1 15.7.2 15.8.1 15.9.2 16.0.2 16.1.3 16.2-a.5 16.2-a.3 16.1.2 16.2-a.1 16.1.1 16.1 16.1-beta 16.1-beta.2 16.1-beta.3 16.1-a.5 16.1-a.3 16.0.1 16.1-a.1 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-jetpack-about-page.php 1 year ago class-jetpack-redux-state-helper.php 1 year ago class.jetpack-admin-page.php 1 year ago class.jetpack-landing-page.php 2 years ago class.jetpack-react-page.php 1 year ago class.jetpack-settings-page.php 3 years ago
class.jetpack-react-page.php
325 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\Publicize\Publicize_Script_Data;
8 use Automattic\Jetpack\Status;
9
10 require_once __DIR__ . '/class.jetpack-admin-page.php';
11 require_once __DIR__ . '/class-jetpack-redux-state-helper.php';
12
13 /**
14 * Builds the landing page and its menu.
15 */
16 class Jetpack_React_Page extends Jetpack_Admin_Page {
17 /**
18 * Show the landing page only when Jetpack is connected.
19 *
20 * @var bool
21 */
22 protected $dont_show_if_not_active = false;
23
24 /**
25 * Used for fallback when REST API is disabled.
26 *
27 * @var bool
28 */
29 protected $is_redirecting = false;
30
31 /**
32 * Add the main admin Jetpack menu.
33 *
34 * @return string|false Return value from WordPress's `add_menu_page()`.
35 */
36 public function get_page_hook() {
37 $icon = ( new Logo() )->get_base64_logo();
38 return add_menu_page( 'Jetpack', 'Jetpack', 'jetpack_admin_page', 'jetpack', array( $this, 'render' ), $icon, 3 );
39 }
40
41 /**
42 * Add page action.
43 *
44 * @param string $hook Hook of current page.
45 * @return void
46 */
47 public function add_page_actions( $hook ) {
48 /** This action is documented in class.jetpack-admin.php */
49 do_action( 'jetpack_admin_menu', $hook );
50
51 if ( ! isset( $_GET['page'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
52 return;
53 }
54 $page = sanitize_text_field( wp_unslash( $_GET['page'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
55 if ( 'jetpack' !== $page ) {
56 if ( strpos( $page, 'jetpack/' ) === 0 ) {
57 $section = substr( $page, 8 );
58 wp_safe_redirect( admin_url( 'admin.php?page=jetpack#/' . $section ) );
59 exit( 0 );
60 }
61 return; // No need to handle the fallback redirection if we are not on the Jetpack page.
62 }
63
64 // Adding a redirect meta tag if the REST API is disabled.
65 if ( ! $this->is_rest_api_enabled() ) {
66 $this->is_redirecting = true;
67 add_action( 'admin_head', array( $this, 'add_fallback_head_meta' ) );
68 }
69
70 // Adding a redirect meta tag wrapped in noscript tags for all browsers in case they have JavaScript disabled.
71 add_action( 'admin_head', array( $this, 'add_noscript_head_meta' ) );
72
73 // If this is the first time the user is viewing the admin, don't show JITMs.
74 // This filter is added just in time because this function is called on admin_menu
75 // and JITMs are initialized on admin_init.
76 if ( Jetpack::is_connection_ready() && ! Jetpack_Options::get_option( 'first_admin_view', false ) ) {
77 Jetpack_Options::update_option( 'first_admin_view', true );
78 add_filter( 'jetpack_just_in_time_msgs', '__return_false' );
79 }
80 }
81
82 /**
83 * Remove the main Jetpack submenu if a site is in offline mode or connected
84 * or if My Jetpack is available.
85 * At that point, admins can access the Jetpack Dashboard instead.
86 *
87 * @since 13.8
88 */
89 public function remove_jetpack_menu() {
90 $is_offline_mode = ( new Status() )->is_offline_mode();
91 $has_my_jetpack = (
92 class_exists( 'Automattic\Jetpack\My_Jetpack\Initializer' ) &&
93 method_exists( 'Automattic\Jetpack\My_Jetpack\Initializer', 'should_initialize' ) &&
94 \Automattic\Jetpack\My_Jetpack\Initializer::should_initialize()
95 );
96
97 if ( $is_offline_mode || $has_my_jetpack || Jetpack::is_connection_ready() ) {
98 remove_submenu_page( 'jetpack', 'jetpack' );
99 }
100 }
101
102 /**
103 * Determine whether a user can access the Jetpack Settings page.
104 *
105 * Rules are:
106 * - user is allowed to see the Jetpack Admin
107 * - site is connected or in offline mode
108 * - non-admins only need access to the settings when there are modules they can manage.
109 *
110 * @return bool $can_access_settings Can the user access settings.
111 */
112 private function can_access_settings() {
113 $connection = new Connection_Manager( 'jetpack' );
114 $status = new Status();
115
116 // User must have the necessary permissions to see the Jetpack settings pages.
117 if ( ! current_user_can( 'edit_posts' ) ) {
118 return false;
119 }
120
121 // In offline mode, allow access to admins.
122 if ( $status->is_offline_mode() && current_user_can( 'manage_options' ) ) {
123 return true;
124 }
125
126 // If not in offline mode but site is not connected, bail.
127 if ( ! Jetpack::is_connection_ready() ) {
128 return false;
129 }
130
131 /*
132 * Additional checks for non-admins.
133 */
134 if ( ! current_user_can( 'manage_options' ) ) {
135 // If the site isn't connected at all, bail.
136 if ( ! $connection->has_connected_owner() ) {
137 return false;
138 }
139
140 /*
141 * If they haven't connected their own account yet,
142 * they have no use for the settings page.
143 * They will not be able to manage any settings.
144 */
145 if ( ! $connection->is_user_connected() ) {
146 return false;
147 }
148
149 /*
150 * Non-admins only have access to settings
151 * for the following modules:
152 * - Publicize
153 * - Post By Email
154 * If those modules are not available, bail.
155 */
156 if (
157 ! Jetpack::is_module_active( 'post-by-email' )
158 && (
159 Publicize_Script_Data::has_feature_flag( 'admin-page' ) ||
160 ! Jetpack::is_module_active( 'publicize' ) ||
161 ! current_user_can( 'publish_posts' )
162 )
163 ) {
164 return false;
165 }
166 }
167
168 // fallback.
169 return true;
170 }
171
172 /**
173 * Jetpack Settings sub-link.
174 *
175 * @since 4.3.0
176 * @since 9.7.0 If Connection does not have an owner, restrict it to admins
177 */
178 public function jetpack_add_settings_sub_nav_item() {
179 if ( $this->can_access_settings() ) {
180 Admin_Menu::add_menu(
181 __( 'Settings', 'jetpack' ),
182 __( 'Settings', 'jetpack' ),
183 'jetpack_admin_page',
184 Jetpack::admin_url( array( 'page' => 'jetpack#/settings' ) ),
185 null,
186 13
187 );
188 }
189 }
190
191 /**
192 * Fallback redirect meta tag if the REST API is disabled.
193 *
194 * @return void
195 */
196 public function add_fallback_head_meta() {
197 echo '<meta http-equiv="refresh" content="0; url=?page=jetpack_modules">';
198 }
199
200 /**
201 * Fallback meta tag wrapped in noscript tags for all browsers in case they have JavaScript disabled.
202 *
203 * @return void
204 */
205 public function add_noscript_head_meta() {
206 echo '<noscript>';
207 $this->add_fallback_head_meta();
208 echo '</noscript>';
209 }
210
211 /**
212 * Add action to render page specific HTML.
213 *
214 * @return void
215 */
216 public function page_render() {
217 /** This action is already documented in class.jetpack-admin-page.php */
218 do_action( 'jetpack_notices' );
219
220 // Fetch static.html.
221 $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.
222
223 if ( false === $static_html ) {
224
225 // If we still have nothing, display an error.
226 echo '<p>';
227 esc_html_e( 'Error fetching static.html. Try running: ', 'jetpack' );
228 echo '<code>pnpm run distclean && pnpm jetpack build plugins/jetpack</code>';
229 echo '</p>';
230 } else {
231 // We got the static.html so let's display it.
232 echo $static_html; //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
233 }
234 }
235 /**
236 * Allow robust deep links to React.
237 *
238 * The Jetpack dashboard requires fragments/hash values to make
239 * a deep link to it but passing fragments as part of a return URL
240 * will most often be discarded throughout the process.
241 * This logic aims to bridge this gap and reduce the chance of React
242 * specific links being broken while passing them along.
243 */
244 public function react_redirects() {
245 global $pagenow;
246
247 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
248 if ( 'admin.php' !== $pagenow || ! isset( $_GET['jp-react-redirect'] ) ) {
249 return;
250 }
251
252 $allowed_paths = array(
253 'product-purchased' => admin_url( '/admin.php?page=jetpack#/recommendations/product-purchased' ),
254 );
255
256 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
257 $target = sanitize_text_field( wp_unslash( $_GET['jp-react-redirect'] ) );
258 if ( isset( $allowed_paths[ $target ] ) ) {
259 wp_safe_redirect( $allowed_paths[ $target ] );
260 exit( 0 );
261 }
262 }
263
264 /**
265 * Load styles for static page.
266 */
267 public function additional_styles() {
268 Jetpack_Admin_Page::load_wrapper_styles();
269 }
270
271 /**
272 * Load admin page scripts.
273 */
274 public function page_admin_scripts() {
275 if ( $this->is_redirecting ) {
276 return; // No need for scripts on a fallback page.
277 }
278
279 $status = new Status();
280 $is_offline_mode = $status->is_offline_mode();
281 $site_suffix = $status->get_site_suffix();
282 $script_deps_path = JETPACK__PLUGIN_DIR . '_inc/build/admin.asset.php';
283 $script_dependencies = array( 'jquery', 'wp-polyfill' );
284 $version = JETPACK__VERSION;
285 if ( file_exists( $script_deps_path ) ) {
286 $asset_manifest = include $script_deps_path;
287 $script_dependencies = $asset_manifest['dependencies'];
288 $version = $asset_manifest['version'];
289 }
290
291 $blog_id_prop = '';
292 if ( ! defined( 'IS_WPCOM' ) || ! IS_WPCOM ) {
293 $blog_id = Connection_Manager::get_site_id( true );
294 if ( $blog_id ) {
295 $blog_id_prop = ', currentBlogID: "' . (int) $blog_id . '"';
296 }
297 }
298
299 wp_enqueue_script(
300 'react-plugin',
301 plugins_url( '_inc/build/admin.js', JETPACK__PLUGIN_FILE ),
302 $script_dependencies,
303 $version,
304 true
305 );
306
307 if ( ! $is_offline_mode && Jetpack::is_connection_ready() ) {
308 // Required for Analytics.
309 wp_enqueue_script( 'jp-tracks', '//stats.wp.com/w.js', array(), gmdate( 'YW' ), true );
310 }
311
312 wp_set_script_translations( 'react-plugin', 'jetpack' );
313
314 // Add objects to be passed to the initial state of the app.
315 // Use wp_add_inline_script instead of wp_localize_script, see https://core.trac.wordpress.org/ticket/25280.
316 wp_add_inline_script( 'react-plugin', 'var Initial_State=JSON.parse(decodeURIComponent("' . rawurlencode( wp_json_encode( Jetpack_Redux_State_Helper::get_initial_state() ) ) . '"));', 'before' );
317
318 // This will set the default URL of the jp_redirects lib.
319 wp_add_inline_script( 'react-plugin', 'var jetpack_redirects = { currentSiteRawUrl: "' . $site_suffix . '"' . $blog_id_prop . ' };', 'before' );
320
321 // Adds Connection package initial state.
322 Connection_Initial_State::render_script( 'react-plugin' );
323 }
324 }
325