PluginProbe ʕ •ᴥ•ʔ
Jetpack – WP Security, Backup, Speed, & Growth / 13.3.3
Jetpack – WP Security, Backup, Speed, & Growth v13.3.3
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 / modules / masterbar / admin-menu / class-wpcom-admin-menu.php
jetpack / modules / masterbar / admin-menu Last commit date
admin-menu-nav-unification-rtl.css 2 years ago admin-menu-nav-unification-rtl.min.css 2 years ago admin-menu-nav-unification.css 2 years ago admin-menu-nav-unification.min.css 2 years ago admin-menu-rtl.css 2 years ago admin-menu-rtl.min.css 2 years ago admin-menu.css 2 years ago admin-menu.js 2 years ago admin-menu.min.css 2 years ago class-admin-menu.php 2 years ago class-atomic-admin-menu.php 2 years ago class-base-admin-menu.php 2 years ago class-dashboard-switcher-tracking.php 3 years ago class-domain-only-admin-menu.php 2 years ago class-jetpack-admin-menu.php 2 years ago class-p2-admin-menu.php 4 years ago class-wpcom-admin-menu.php 2 years ago class-wpcom-email-subscription-checker.php 3 years ago dashicon-set.php 4 years ago globe-icon.svg 3 years ago load.php 2 years ago menu-mappings.php 3 years ago
class-wpcom-admin-menu.php
509 lines
1 <?php
2 /**
3 * WP.com Admin Menu file.
4 *
5 * @package automattic/jetpack
6 */
7
8 namespace Automattic\Jetpack\Dashboard_Customizations;
9
10 use Automattic\Jetpack\Status;
11 use Jetpack_Custom_CSS;
12 use JITM;
13
14 require_once __DIR__ . '/class-admin-menu.php';
15
16 /**
17 * Class WPcom_Admin_Menu.
18 */
19 class WPcom_Admin_Menu extends Admin_Menu {
20 /**
21 * Holds the current plan, set by get_current_plan().
22 *
23 * @var array
24 */
25 private $current_plan = array();
26
27 /**
28 * WPcom_Admin_Menu constructor.
29 */
30 protected function __construct() {
31 parent::__construct();
32
33 add_action( 'wp_ajax_sidebar_state', array( $this, 'ajax_sidebar_state' ) );
34 add_action( 'wp_ajax_jitm_dismiss', array( $this, 'wp_ajax_jitm_dismiss' ) );
35 add_action( 'wp_ajax_upsell_nudge_jitm', array( $this, 'wp_ajax_upsell_nudge_jitm' ) );
36 add_action( 'admin_init', array( $this, 'sync_sidebar_collapsed_state' ) );
37 add_action( 'admin_menu', array( $this, 'remove_submenus' ), 140 ); // After hookpress hook at 130.
38 }
39
40 /**
41 * Create the desired menu output.
42 */
43 public function reregister_menu_items() {
44 parent::reregister_menu_items();
45
46 $this->add_my_home_menu();
47 $this->add_my_mailboxes_menu();
48 $this->remove_gutenberg_menu();
49
50 // Not needed outside of wp-admin.
51 if ( ! $this->is_api_request ) {
52 $this->add_browse_sites_link();
53 $this->add_site_card_menu();
54 $this->add_new_site_link();
55 }
56
57 $this->add_woocommerce_installation_menu( $this->get_current_plan() );
58
59 ksort( $GLOBALS['menu'] );
60 }
61
62 /**
63 * Get the preferred view for the given screen.
64 *
65 * @param string $screen Screen identifier.
66 * @param bool $fallback_global_preference (Optional) Whether the global preference for all screens should be used
67 * as fallback if there is no specific preference for the given screen.
68 * Default: true.
69 * @return string
70 */
71 public function get_preferred_view( $screen, $fallback_global_preference = true ) {
72 // When no preferred view has been set for Themes, keep the previous behavior that forced the default view
73 // regardless of the global preference.
74 if ( $fallback_global_preference && 'themes.php' === $screen ) {
75 $preferred_view = parent::get_preferred_view( $screen, false );
76 if ( self::UNKNOWN_VIEW === $preferred_view ) {
77 return self::DEFAULT_VIEW;
78 }
79 return $preferred_view;
80 }
81
82 // Plugins on Simple sites are always managed on Calypso.
83 if ( 'plugins.php' === $screen ) {
84 return self::DEFAULT_VIEW;
85 }
86
87 return parent::get_preferred_view( $screen, $fallback_global_preference );
88 }
89
90 /**
91 * Retrieve the number of blogs that the current user has.
92 *
93 * @return int
94 */
95 public function get_current_user_blog_count() {
96 if ( function_exists( '\get_blog_count_for_user' ) ) {
97 return \get_blog_count_for_user( get_current_user_id() );
98 }
99
100 $blogs = get_blogs_of_user( get_current_user_id() );
101 return is_countable( $blogs ) ? count( $blogs ) : 0;
102 }
103
104 /**
105 * Adds the site switcher link if user has more than one site.
106 */
107 public function add_browse_sites_link() {
108 if ( $this->get_current_user_blog_count() < 2 ) {
109 return;
110 }
111
112 // Add the menu item.
113 add_menu_page( __( 'site-switcher', 'jetpack' ), __( 'Browse sites', 'jetpack' ), 'read', 'https://wordpress.com/sites', null, 'dashicons-arrow-left-alt2', 0 );
114 add_filter( 'add_menu_classes', array( $this, 'set_browse_sites_link_class' ) );
115 }
116
117 /**
118 * Adds a custom element class for Site Switcher menu item.
119 *
120 * @param array $menu Associative array of administration menu items.
121 * @return array
122 */
123 public function set_browse_sites_link_class( array $menu ) {
124 foreach ( $menu as $key => $menu_item ) {
125 if ( 'site-switcher' !== $menu_item[3] ) {
126 continue;
127 }
128
129 $menu[ $key ][4] = add_cssclass( 'site-switcher', $menu_item[4] );
130 break;
131 }
132
133 return $menu;
134 }
135
136 /**
137 * Adds a link to the menu to create a new site.
138 */
139 public function add_new_site_link() {
140 if ( $this->get_current_user_blog_count() > 1 ) {
141 return;
142 }
143
144 $this->add_admin_menu_separator();
145 add_menu_page( __( 'Add New Site', 'jetpack' ), __( 'Add New Site', 'jetpack' ), 'read', 'https://wordpress.com/start?ref=calypso-sidebar', null, 'dashicons-plus-alt' );
146 }
147
148 /**
149 * Adds site card component.
150 */
151 public function add_site_card_menu() {
152 $default = plugins_url( 'globe-icon.svg', __FILE__ );
153 $icon = get_site_icon_url( 32, $default );
154 $blog_name = get_option( 'blogname' ) !== '' ? get_option( 'blogname' ) : $this->domain;
155 $status = new Status();
156 $is_private_site = $status->is_private_site();
157 $is_coming_soon = $status->is_coming_soon();
158
159 if ( $default === $icon && blavatar_exists( $this->domain ) ) {
160 $icon = blavatar_url( $this->domain, 'img', 32 );
161 }
162
163 $badge = '';
164 if ( $is_private_site || $is_coming_soon ) {
165 $badge .= sprintf(
166 '<span class="site__badge site__badge-private">%s</span>',
167 $is_coming_soon ? esc_html__( 'Coming Soon', 'jetpack' ) : esc_html__( 'Private', 'jetpack' )
168 );
169 }
170
171 if ( function_exists( 'is_simple_site_redirect' ) && is_simple_site_redirect( $this->domain ) ) {
172 $badge .= '<span class="site__badge site__badge-redirect">' . esc_html__( 'Redirect', 'jetpack' ) . '</span>';
173 }
174
175 if ( ! empty( get_option( 'options' )['is_domain_only'] ) ) {
176 $badge .= '<span class="site__badge site__badge-domain-only">' . esc_html__( 'Domain', 'jetpack' ) . '</span>';
177 }
178
179 $site_card = '
180 <div class="site__info">
181 <div class="site__title">%1$s</div>
182 <div class="site__domain">%2$s</div>
183 %3$s
184 </div>';
185
186 $site_card = sprintf(
187 $site_card,
188 $blog_name,
189 $this->domain,
190 $badge
191 );
192
193 add_menu_page( 'site-card', $site_card, 'read', get_home_url(), null, $icon, 1 );
194 add_filter( 'add_menu_classes', array( $this, 'set_site_card_menu_class' ) );
195 }
196
197 /**
198 * Adds a custom element class and id for Site Card's menu item.
199 *
200 * @param array $menu Associative array of administration menu items.
201 * @return array
202 */
203 public function set_site_card_menu_class( array $menu ) {
204 foreach ( $menu as $key => $menu_item ) {
205 if ( 'site-card' !== $menu_item[3] ) {
206 continue;
207 }
208
209 $classes = ' toplevel_page_site-card';
210 if ( blavatar_exists( $this->domain ) ) {
211 $classes .= ' has-site-icon';
212 }
213
214 $menu[ $key ][4] = $menu_item[4] . $classes;
215 $menu[ $key ][5] = 'toplevel_page_site_card';
216 break;
217 }
218
219 return $menu;
220 }
221
222 /**
223 * Returns the first available upsell nudge.
224 *
225 * @return array
226 */
227 public function get_upsell_nudge() {
228 require_lib( 'jetpack-jitm/jitm-engine' );
229 $jitm_engine = new JITM\Engine();
230
231 $message_path = 'calypso:sites:sidebar_notice';
232 $current_user = wp_get_current_user();
233 $user_id = $current_user->ID;
234 $user_roles = implode( ',', $current_user->roles );
235 $query_string = array(
236 'message_path' => $message_path,
237 );
238
239 // Get the top message only.
240 $message = $jitm_engine->get_top_messages( $message_path, $user_id, $user_roles, $query_string );
241
242 if ( isset( $message[0] ) ) {
243 $message = $message[0];
244 return array(
245 'content' => $message->content['message'],
246 'cta' => $message->CTA['message'], // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
247 'link' => $message->CTA['link'], // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
248 'tracks_impression_event_name' => $message->tracks['display']['name'] ?? null,
249 'tracks_impression_cta_name' => $message->tracks['display']['props']['cta_name'] ?? null,
250 'tracks_click_event_name' => $message->tracks['click']['name'] ?? null,
251 'tracks_click_cta_name' => $message->tracks['click']['props']['cta_name'] ?? null,
252 'dismissible' => $message->is_dismissible,
253 'feature_class' => $message->feature_class,
254 'id' => $message->id,
255 );
256 }
257 }
258
259 /**
260 * Adds Stats menu.
261 */
262 public function add_stats_menu() {
263 $menu_title = __( 'Stats', 'jetpack' );
264
265 if ( ! $this->is_api_request ) {
266 $menu_title .= sprintf(
267 '<img class="sidebar-unified__sparkline" width="80" height="20" src="%1$s" alt="%2$s">',
268 esc_url( site_url( 'wp-includes/charts/admin-bar-hours-scale-2x.php?masterbar=1&s=' . get_current_blog_id() ) ),
269 esc_attr__( 'Hourly views', 'jetpack' )
270 );
271 }
272
273 add_menu_page( __( 'Stats', 'jetpack' ), $menu_title, 'read', 'https://wordpress.com/stats/day/' . $this->domain, null, 'dashicons-chart-bar', 3 );
274 }
275
276 /**
277 * Gets the current plan and stores it in $this->current_plan so the database is only called once per request.
278 *
279 * @return array
280 */
281 private function get_current_plan() {
282 if ( empty( $this->current_plan ) && class_exists( 'WPCOM_Store_API' ) ) {
283 $this->current_plan = \WPCOM_Store_API::get_current_plan( get_current_blog_id() );
284 }
285 return $this->current_plan;
286 }
287
288 /**
289 * Adds Upgrades menu.
290 *
291 * @param string $plan The current WPCOM plan of the blog.
292 */
293 public function add_upgrades_menu( $plan = null ) {
294 $current_plan = $this->get_current_plan();
295 if ( ! empty( $current_plan['product_name_short'] ) ) {
296 $plan = $current_plan['product_name_short'];
297 }
298
299 parent::add_upgrades_menu( $plan );
300
301 $last_upgrade_submenu_position = $this->get_submenu_item_count( 'paid-upgrades.php' );
302
303 add_submenu_page( 'paid-upgrades.php', __( 'Domains', 'jetpack' ), __( 'Domains', 'jetpack' ), 'manage_options', 'https://wordpress.com/domains/manage/' . $this->domain, null, $last_upgrade_submenu_position - 1 );
304
305 /** This filter is already documented in modules/masterbar/admin-menu/class-atomic-admin-menu.php */
306 if ( apply_filters( 'jetpack_show_wpcom_upgrades_email_menu', false ) ) {
307 add_submenu_page( 'paid-upgrades.php', __( 'Emails', 'jetpack' ), __( 'Emails', 'jetpack' ), 'manage_options', 'https://wordpress.com/email/' . $this->domain, null, $last_upgrade_submenu_position );
308 }
309
310 if ( defined( 'WPCOM_ENABLE_ADD_ONS_MENU_ITEM' ) && WPCOM_ENABLE_ADD_ONS_MENU_ITEM ) {
311 add_submenu_page( 'paid-upgrades.php', __( 'Add-Ons', 'jetpack' ), __( 'Add-Ons', 'jetpack' ), 'manage_options', 'https://wordpress.com/add-ons/' . $this->domain, null, 1 );
312 }
313 }
314
315 /**
316 * Adds Appearance menu.
317 */
318 public function add_appearance_menu() {
319 $customize_url = parent::add_appearance_menu();
320
321 $this->hide_submenu_page( 'themes.php', 'theme-editor.php' );
322
323 $user_can_customize = current_user_can( 'customize' );
324
325 if ( wp_is_block_theme() ) {
326 add_filter( 'safecss_is_freetrial', '__return_false', PHP_INT_MAX );
327 if ( class_exists( 'Jetpack_Custom_CSS' ) && empty( Jetpack_Custom_CSS::get_css() ) ) {
328 $user_can_customize = false;
329 }
330 remove_filter( 'safecss_is_freetrial', '__return_false', PHP_INT_MAX );
331 }
332
333 if ( $user_can_customize ) {
334 $customize_custom_css_url = add_query_arg( array( 'autofocus' => array( 'section' => 'jetpack_custom_css' ) ), $customize_url );
335 add_submenu_page( 'themes.php', esc_attr__( 'Additional CSS', 'jetpack' ), __( 'Additional CSS', 'jetpack' ), 'customize', esc_url( $customize_custom_css_url ), null, 20 );
336 }
337 }
338
339 /**
340 * Adds Users menu.
341 */
342 public function add_users_menu() {
343 $submenus_to_update = array(
344 'grofiles-editor' => 'https://wordpress.com/me',
345 'grofiles-user-settings' => 'https://wordpress.com/me/account',
346 );
347
348 if ( self::DEFAULT_VIEW === $this->get_preferred_view( 'users.php' ) ) {
349 $submenus_to_update['users.php'] = 'https://wordpress.com/people/team/' . $this->domain;
350 }
351
352 $slug = current_user_can( 'list_users' ) ? 'users.php' : 'profile.php';
353 $this->update_submenus( $slug, $submenus_to_update );
354 add_submenu_page( 'users.php', esc_attr__( 'Add New User', 'jetpack' ), __( 'Add New User', 'jetpack' ), 'promote_users', 'https://wordpress.com/people/new/' . $this->domain, null, 1 );
355 add_submenu_page( 'users.php', esc_attr__( 'Subscribers', 'jetpack' ), __( 'Subscribers', 'jetpack' ), 'list_users', 'https://wordpress.com/subscribers/' . $this->domain, null, 3 );
356 }
357
358 /**
359 * Adds Settings menu.
360 */
361 public function add_options_menu() {
362 parent::add_options_menu();
363
364 add_submenu_page( 'options-general.php', esc_attr__( 'Hosting Configuration', 'jetpack' ), __( 'Hosting Configuration', 'jetpack' ), 'manage_options', 'https://wordpress.com/hosting-config/' . $this->domain, null, 10 );
365 }
366
367 /**
368 * Adds My Home menu.
369 */
370 public function add_my_home_menu() {
371 $this->update_menu( 'index.php', 'https://wordpress.com/home/' . $this->domain, __( 'My Home', 'jetpack' ), 'read', 'dashicons-admin-home' );
372 }
373
374 /**
375 * Also remove the Gutenberg plugin menu.
376 */
377 public function remove_gutenberg_menu() {
378 // Always remove the Gutenberg menu.
379 remove_menu_page( 'gutenberg' );
380 }
381
382 /**
383 * Whether to use wp-admin pages rather than Calypso.
384 *
385 * @return bool
386 */
387 public function should_link_to_wp_admin() {
388 $result = false; // Calypso.
389
390 $user_attribute = get_user_attribute( get_current_user_id(), 'calypso_preferences' );
391 if ( ! empty( $user_attribute['linkDestination'] ) ) {
392 $result = $user_attribute['linkDestination'];
393 }
394
395 return $result;
396 }
397
398 /**
399 * Adds Plugins menu.
400 */
401 public function add_plugins_menu() {
402 // TODO: Remove wpcom_menu (/wp-content/admin-plugins/wpcom-misc.php).
403 $count = '';
404 if ( ! is_multisite() && current_user_can( 'update_plugins' ) ) {
405 $update_data = wp_get_update_data();
406 $count = sprintf(
407 '<span class="update-plugins count-%s"><span class="plugin-count">%s</span></span>',
408 $update_data['counts']['plugins'],
409 number_format_i18n( $update_data['counts']['plugins'] )
410 );
411 }
412 /* translators: %s: Number of pending plugin updates. */
413 add_menu_page( esc_attr__( 'Plugins', 'jetpack' ), sprintf( __( 'Plugins %s', 'jetpack' ), $count ), 'activate_plugins', 'plugins.php', null, 'dashicons-admin-plugins', 65 );
414
415 parent::add_plugins_menu();
416 }
417
418 /**
419 * Saves the sidebar state ( expanded / collapsed ) via an ajax request.
420 *
421 * @return never
422 */
423 public function ajax_sidebar_state() {
424 $expanded = isset( $_REQUEST['expanded'] ) ? filter_var( wp_unslash( $_REQUEST['expanded'] ), FILTER_VALIDATE_BOOLEAN ) : false; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
425 $user_id = get_current_user_id();
426 $preferences = get_user_attribute( $user_id, 'calypso_preferences' );
427 if ( empty( $preferences ) ) {
428 $preferences = array();
429 }
430
431 $value = array_merge( (array) $preferences, array( 'sidebarCollapsed' => ! $expanded ) );
432 $value = array_filter(
433 $value,
434 function ( $preference ) {
435 return null !== $preference;
436 }
437 );
438
439 update_user_attribute( $user_id, 'calypso_preferences', $value );
440
441 die();
442 }
443
444 /**
445 * Handle ajax requests to dismiss a just-in-time-message
446 */
447 public function wp_ajax_jitm_dismiss() {
448 check_ajax_referer( 'jitm_dismiss' );
449 require_lib( 'jetpack-jitm/jitm-engine' );
450 if ( isset( $_REQUEST['id'] ) && isset( $_REQUEST['feature_class'] ) ) {
451 JITM\Engine::dismiss( sanitize_text_field( wp_unslash( $_REQUEST['id'] ) ), sanitize_text_field( wp_unslash( $_REQUEST['feature_class'] ) ) );
452 }
453 wp_die();
454 }
455
456 /**
457 * Syncs the sidebar collapsed state from Calypso Preferences.
458 */
459 public function sync_sidebar_collapsed_state() {
460 $calypso_preferences = get_user_attribute( get_current_user_id(), 'calypso_preferences' );
461
462 $sidebar_collapsed = isset( $calypso_preferences['sidebarCollapsed'] ) ? $calypso_preferences['sidebarCollapsed'] : false;
463
464 // Read the current stored setting and convert it to boolean in order to be able to compare the values later.
465 $current_sidebar_collapsed_setting = ( 'f' === get_user_setting( 'mfold' ) ) ? true : false;
466
467 // Only set the setting if the value differs, as `set_user_setting` always updates at least the timestamp
468 // which leads to unnecessary user meta cache purging on all wp-admin screen requests.
469 if ( $current_sidebar_collapsed_setting !== $sidebar_collapsed ) {
470 set_user_setting( 'mfold', $sidebar_collapsed ? 'f' : 'o' );
471 }
472 }
473
474 /**
475 * Removes unwanted submenu items.
476 *
477 * These submenus are added across wp-content and should be removed together with these function calls.
478 */
479 public function remove_submenus() {
480 global $_registered_pages;
481
482 remove_submenu_page( 'index.php', 'akismet-stats' );
483 remove_submenu_page( 'index.php', 'my-comments' );
484 remove_submenu_page( 'index.php', 'stats' );
485 remove_submenu_page( 'index.php', 'subscriptions' );
486
487 /* @see https://github.com/Automattic/wp-calypso/issues/49210 */
488 remove_submenu_page( 'index.php', 'my-blogs' );
489 $_registered_pages['admin_page_my-blogs'] = true; // phpcs:ignore
490
491 remove_submenu_page( 'paid-upgrades.php', 'premium-themes' );
492 remove_submenu_page( 'paid-upgrades.php', 'domains' );
493 remove_submenu_page( 'paid-upgrades.php', 'my-upgrades' );
494 remove_submenu_page( 'paid-upgrades.php', 'billing-history' );
495
496 remove_submenu_page( 'themes.php', 'customize.php?autofocus[panel]=amp_panel&return=' . rawurlencode( admin_url() ) );
497
498 remove_submenu_page( 'users.php', 'wpcom-invite-users' ); // Wpcom_Invite_Users::action_admin_menu.
499
500 remove_submenu_page( 'options-general.php', 'adcontrol' );
501
502 // Remove menu item but continue allowing access.
503 foreach ( array( 'openidserver', 'webhooks' ) as $page_slug ) {
504 remove_submenu_page( 'options-general.php', $page_slug );
505 $_registered_pages[ 'admin_page_' . $page_slug ] = true; // phpcs:ignore
506 }
507 }
508 }
509