PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3
Jetpack – WP Security, Backup, Speed, & Growth v16.3
16.3 16.3-beta 16.3-a.5 16.3-a.7 16.3-a.3 16.3-a.1 16.2 16.2-beta 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 All 508 releases
← All changes | jetpack_vendor/automattic/jetpack-activity-log/src/class-jetpack-activity-log.php +195 -14 16.2 → 16.3 View file →
@@ -14,14 +14,19 @@
14 14 use Automattic\Jetpack\Activity_Log\Initial_State as Activity_Log_Initial_State;
15 15 use Automattic\Jetpack\Admin_UI\Admin_Menu;
16 16 use Automattic\Jetpack\Connection\Initial_State as Connection_Initial_State;
17 17 use Automattic\Jetpack\Connection\Manager as Connection_Manager;
18 +use Automattic\Jetpack\Modules;
18 19 use Automattic\Jetpack\WP_Build_Polyfills\WP_Build_Polyfills;
20 +use Automattic\Jetpack\WP_Build_Polyfills\WP_Build_Screen_Id;
21 +use Jetpack_Options;
19 22 use function add_action;
20 23 use function add_filter;
24 +use function class_exists;
21 25 use function current_user_can;
22 26 use function did_action;
23 27 use function do_action;
28 +use function get_current_screen;
24 29 use function is_admin;
25 30 use function is_multisite;
26 31 use function sanitize_text_field;
27 32 use function wp_add_inline_script;
@@ -45,8 +50,23 @@
45 50 */
46 51 const PAGE_SLUG = 'jetpack-activity-log';
47 52
48 53 /**
54 + * Slug of the Jetpack module that turns the Activity Log on and off.
55 + *
56 + * @var string
57 + */
58 + const MODULE_SLUG = 'activity-log';
59 +
60 + /**
61 + * Jetpack_Options key recording that the module was switched on for a site
62 + * with no Jetpack plugin. See `activate_standalone_default()`.
63 + *
64 + * @var string
65 + */
66 + const DEFAULT_ACTIVATED_OPTION = 'activity_log_default_activated';
67 +
68 + /**
49 69 * Page slug for the wp-build dashboard. Distinct from the wp-admin menu
50 70 * slug (`PAGE_SLUG`) so the user-facing URL stays `admin.php?page=jetpack-activity-log`;
51 71 * we alias the current screen id to this value so wp-build's
52 72 * screen-match enqueue callback fires. Must match the `page` in
@@ -77,12 +97,32 @@
77 97 */
78 98 const REFRESH_ACCESS_NONCE_ACTION = 'jetpack_activity_log_refresh_access';
79 99
80 100 /**
101 + * The screen ID alias_screen_id_for_wp_build() replaced, until it is restored.
102 + *
103 + * @var string|null
104 + */
105 + private static $wp_build_original_screen_id = null;
106 +
107 + /**
108 + * The dashboard screen hide_jitms_on_wp_build_dashboard() opts out of JITMs.
109 + *
110 + * @var string|null
111 + */
112 + private static $jitm_opt_out_screen_id = null;
113 +
114 + /**
81 115 * Entry point. Idempotent: safe to call from multiple bootstraps.
116 + *
117 + * Bootstraps only while the `activity-log` module is on, so the toggle
118 + * means the same thing to the Jetpack plugin and to every standalone
119 + * plugin that carries this package.
82 120 */
83 121 public static function initialize() {
84 - if ( did_action( 'jetpack_activity_log_initialized' ) ) {
122 + self::register_module();
123 +
124 + if ( did_action( 'jetpack_activity_log_initialized' ) || ! self::is_module_active() ) {
85 125 return;
86 126 }
87 127
88 128 add_action( 'admin_menu', array( __CLASS__, 'add_wp_admin_submenu' ) );
@@ -97,8 +137,77 @@
97 137 do_action( 'jetpack_activity_log_initialized' );
98 138 }
99 139
100 140 /**
141 + * Whether the Activity Log module is switched on.
142 + *
143 + * @return bool
144 + */
145 + public static function is_module_active() {
146 + return ( new Modules() )->is_active( self::MODULE_SLUG );
147 + }
148 +
149 + /**
150 + * Make the module controllable, and give a site with no Jetpack plugin the
151 + * same default-on state the Jetpack plugin gets from `Auto Activate: Yes`.
152 + *
153 + * @return void
154 + */
155 + private static function register_module() {
156 + add_filter( 'jetpack_get_available_standalone_modules', array( __CLASS__, 'add_standalone_module' ) );
157 +
158 + // `class_exists( 'Jetpack' )` is only reliable once every plugin file has
159 + // loaded: `jetpack-backup/` sorts before `jetpack/` in active_plugins, so
160 + // Backup reaches initialize() while the Jetpack class is still undefined.
161 + if ( did_action( 'plugins_loaded' ) ) {
162 + self::activate_standalone_default();
163 + } else {
164 + add_action( 'plugins_loaded', array( __CLASS__, 'activate_standalone_default' ) );
165 + }
166 + }
167 +
168 + /**
169 + * Make the module available to the module controller when the Jetpack
170 + * plugin is not installed, so `jetpack_active_modules` is not inert there.
171 + *
172 + * @param array $modules Available standalone module slugs.
173 + * @return array
174 + */
175 + public static function add_standalone_module( $modules ) {
176 + $modules[] = self::MODULE_SLUG;
177 +
178 + return array_values( array_unique( $modules ) );
179 + }
180 +
181 + /**
182 + * Switch the module on once on a site with no Jetpack plugin.
183 + *
184 + * The Jetpack plugin activates the module for you via `Auto Activate: Yes`;
185 + * a standalone install has no equivalent, so without this the page would
186 + * disappear from every Backup/Boost/Protect/Search/VideoPress site on
187 + * upgrade. Recorded in an option rather than repeated, so a later opt-out
188 + * is not undone on the next request.
189 + *
190 + * @return void
191 + */
192 + public static function activate_standalone_default() {
193 + if ( class_exists( 'Jetpack' ) || Jetpack_Options::get_option( self::DEFAULT_ACTIVATED_OPTION ) ) {
194 + return;
195 + }
196 +
197 + if ( ! ( new Modules() )->activate( self::MODULE_SLUG, false, false ) ) {
198 + return;
199 + }
200 +
201 + // Record before re-entering initialize(), which calls back into here.
202 + Jetpack_Options::update_option( self::DEFAULT_ACTIVATED_OPTION, true );
203 +
204 + // initialize() ran before this and found the module off, so wire up now
205 + // rather than leaving the page missing for the rest of the request.
206 + self::initialize();
207 + }
208 +
209 + /**
101 210 * Register the Activity Log submenu under Jetpack.
102 211 *
103 212 * Mirrors the gating used by the legacy my-jetpack "Activity Log" menu
104 213 * item (connected user + non-multisite).
@@ -111,16 +220,11 @@
111 220 }
112 221
113 222 // Load wp-build only on the Activity Log request so its generated
114 223 // render function exists before the menu callback runs, and its
115 - // enqueue pipeline/polyfills stay off every other admin page. Alias
116 - // the screen id here too — `current_screen` fires before the
117 - // `load-{$page_suffix}` hook that runs admin_init(), so registering
118 - // the alias from admin_init() would be too late for wp-build's
119 - // screen-matched enqueue callback.
224 + // enqueue pipeline/polyfills stay off every other admin page.
120 225 if ( self::is_activity_log_admin_request() ) {
121 - self::load_wp_build();
122 - add_action( 'current_screen', array( __CLASS__, 'alias_screen_id_for_wp_build' ) );
226 + self::load_wp_build_with_screen_alias();
123 227 }
124 228
125 229 // The menu item must appear on every admin page, but the generated
126 230 // render function is only loaded on the Activity Log request (above).
@@ -140,8 +244,9 @@
140 244 );
141 245
142 246 if ( $page_suffix ) {
143 247 add_action( 'load-' . $page_suffix, array( __CLASS__, 'admin_init' ) );
248 + self::opt_out_of_jitms( $page_suffix );
144 249 }
145 250
146 251 return $page_suffix;
147 252 }
@@ -228,23 +333,99 @@
228 333 );
229 334 }
230 335
231 336 /**
337 + * Load wp-build with the screen ID aliased across its generated enqueue check.
338 + *
339 + * @see WP_Build_Screen_Id::load_with_alias()
340 + * @return void
341 + */
342 + private static function load_wp_build_with_screen_alias() {
343 + // Fallback: an older wp-build-polyfills under the jetpack-autoloader may predate load_with_alias().
344 + if ( method_exists( WP_Build_Screen_Id::class, 'load_with_alias' ) ) {
345 + WP_Build_Screen_Id::load_with_alias(
346 + array( __CLASS__, 'alias_screen_id_for_wp_build' ),
347 + array( __CLASS__, 'restore_screen_id_after_wp_build' ),
348 + function () {
349 + self::load_wp_build();
350 + }
351 + );
352 + return;
353 + }
354 +
355 + add_action( 'admin_enqueue_scripts', array( __CLASS__, 'alias_screen_id_for_wp_build' ) );
356 + self::load_wp_build();
357 + add_action( 'admin_enqueue_scripts', array( __CLASS__, 'restore_screen_id_after_wp_build' ) );
358 + }
359 +
360 + /**
232 361 * Alias the current screen id to the wp-build page slug.
233 362 *
234 363 * The wp-build-generated enqueue callback only fires when the screen id
235 364 * equals the wp-build page slug. Our menu slug stays `jetpack-activity-log`,
236 365 * so alias the screen id in place to make the check pass without changing
237 - * the user-facing URL. Hooked on `current_screen` only for the Activity Log
238 - * request, so this never affects any other screen.
366 + * the user-facing URL. Hooked only for the Activity Log request, so this
367 + * never affects any other screen.
239 368 *
240 - * @param \WP_Screen|null $screen The current screen object (passed by WP).
369 + * @since 0.4.1 Takes no argument; hooked on `admin_enqueue_scripts`.
370 + *
241 371 * @return void
242 372 */
243 - public static function alias_screen_id_for_wp_build( $screen ) {
244 - if ( is_object( $screen ) ) {
245 - $screen->id = self::WP_BUILD_PAGE_SLUG;
373 + public static function alias_screen_id_for_wp_build() {
374 + $screen = get_current_screen();
375 + if ( ! $screen ) {
376 + return;
246 377 }
378 +
379 + self::$wp_build_original_screen_id = $screen->id;
380 + $screen->id = self::WP_BUILD_PAGE_SLUG;
381 + }
382 +
383 + /**
384 + * Undo alias_screen_id_for_wp_build(), so code after the generated check sees the real screen ID.
385 + *
386 + * @since 0.4.1
387 + *
388 + * @return void
389 + */
390 + public static function restore_screen_id_after_wp_build() {
391 + $screen = get_current_screen();
392 + if ( ! $screen || null === self::$wp_build_original_screen_id ) {
393 + return;
394 + }
395 +
396 + $screen->id = self::$wp_build_original_screen_id;
397 + self::$wp_build_original_screen_id = null;
398 + }
399 +
400 + /**
401 + * Opt the dashboard's screen out of JITMs.
402 + *
403 + * @param string $screen_id The hook suffix the page was registered under, which is its screen ID.
404 + * @return void
405 + */
406 + private static function opt_out_of_jitms( $screen_id ) {
407 + self::$jitm_opt_out_screen_id = $screen_id;
408 + add_filter( 'jetpack_display_jitms_on_screen', array( __CLASS__, 'hide_jitms_on_wp_build_dashboard' ), 10, 2 );
409 + }
410 +
411 + /**
412 + * Keep JITMs off the wp-build dashboard, which has no `#jp-admin-notices` to show them in.
413 + *
414 + * Fetching a JITM records a view, so one the page hides would still be counted.
415 + *
416 + * @since 0.4.1
417 + *
418 + * @param bool $show Whether to show JITMs on the screen.
419 + * @param string $screen_id The screen ID.
420 + * @return bool
421 + */
422 + public static function hide_jitms_on_wp_build_dashboard( $show, $screen_id ) {
423 + if ( null !== self::$jitm_opt_out_screen_id && self::$jitm_opt_out_screen_id === $screen_id ) {
424 + return false;
425 + }
426 +
427 + return $show;
247 428 }
248 429
249 430 /**
250 431 * Print the React initial state and the Connection initial state, and load