PluginProbe ʕ •ᴥ•ʔ
Jetpack – WP Security, Backup, Speed, & Growth / 12.3.2
Jetpack – WP Security, Backup, Speed, & Growth v12.3.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 / modules / masterbar / admin-menu / class-wpcom-admin-menu.php
jetpack / modules / masterbar / admin-menu Last commit date
admin-menu-rtl.css 3 years ago admin-menu-rtl.min.css 3 years ago admin-menu.css 3 years ago admin-menu.js 3 years ago admin-menu.min.css 3 years ago class-admin-menu.php 3 years ago class-atomic-admin-menu.php 3 years ago class-base-admin-menu.php 3 years ago class-dashboard-switcher-tracking.php 3 years ago class-domain-only-admin-menu.php 3 years ago class-jetpack-admin-menu.php 3 years ago class-p2-admin-menu.php 4 years ago class-wpcom-admin-menu.php 3 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 3 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\Blaze;
11 use Automattic\Jetpack\Status;
12 use Jetpack_Custom_CSS;
13 use JITM;
14
15 require_once __DIR__ . '/class-admin-menu.php';
16
17 /**
18 * Class WPcom_Admin_Menu.
19 */
20 class WPcom_Admin_Menu extends Admin_Menu {
21 /**
22 * Holds the current plan, set by get_current_plan().
23 *
24 * @var array
25 */
26 private $current_plan = array();
27
28 /**
29 * WPcom_Admin_Menu constructor.
30 */
31 protected function __construct() {
32 parent::__construct();
33
34 add_action( 'wp_ajax_sidebar_state', array( $this, 'ajax_sidebar_state' ) );
35 add_action( 'wp_ajax_jitm_dismiss', array( $this, 'wp_ajax_jitm_dismiss' ) );
36 add_action( 'wp_ajax_upsell_nudge_jitm', array( $this, 'wp_ajax_upsell_nudge_jitm' ) );
37 add_action( 'admin_init', array( $this, 'sync_sidebar_collapsed_state' ) );
38 add_action( 'admin_menu', array( $this, 'remove_submenus' ), 140 ); // After hookpress hook at 130.
39 add_filter( 'block_editor_settings_all', array( $this, 'site_editor_dashboard_link' ) );
40 }
41
42 /**
43 * Create the desired menu output.
44 */
45 public function reregister_menu_items() {
46 parent::reregister_menu_items();
47
48 $this->add_my_home_menu();
49 $this->add_inbox_menu();
50 $this->remove_gutenberg_menu();
51
52 // Not needed outside of wp-admin.
53 if ( ! $this->is_api_request ) {
54 $this->add_browse_sites_link();
55 $this->add_site_card_menu();
56 $this->add_new_site_link();
57 }
58
59 $this->add_woocommerce_installation_menu( $this->get_current_plan() );
60
61 ksort( $GLOBALS['menu'] );
62 }
63
64 /**
65 * Get the preferred view for the given screen.
66 *
67 * @param string $screen Screen identifier.
68 * @param bool $fallback_global_preference (Optional) Whether the global preference for all screens should be used
69 * as fallback if there is no specific preference for the given screen.
70 * Default: true.
71 * @return string
72 */
73 public function get_preferred_view( $screen, $fallback_global_preference = true ) {
74 // When no preferred view has been set for Themes, keep the previous behavior that forced the default view
75 // regardless of the global preference.
76 if ( $fallback_global_preference && 'themes.php' === $screen ) {
77 $preferred_view = parent::get_preferred_view( $screen, false );
78 if ( self::UNKNOWN_VIEW === $preferred_view ) {
79 return self::DEFAULT_VIEW;
80 }
81 return $preferred_view;
82 }
83
84 // Plugins on Simple sites are always managed on Calypso.
85 if ( 'plugins.php' === $screen ) {
86 return self::DEFAULT_VIEW;
87 }
88
89 return parent::get_preferred_view( $screen, $fallback_global_preference );
90 }
91
92 /**
93 * Retrieve the number of blogs that the current user has.
94 *
95 * @return int
96 */
97 public function get_current_user_blog_count() {
98 if ( function_exists( '\get_blog_count_for_user' ) ) {
99 return \get_blog_count_for_user( get_current_user_id() );
100 }
101
102 $blogs = get_blogs_of_user( get_current_user_id() );
103 return is_countable( $blogs ) ? count( $blogs ) : 0;
104 }
105
106 /**
107 * Adds the site switcher link if user has more than one site.
108 */
109 public function add_browse_sites_link() {
110 if ( $this->get_current_user_blog_count() < 2 ) {
111 return;
112 }
113
114 // Add the menu item.
115 add_menu_page( __( 'site-switcher', 'jetpack' ), __( 'Browse sites', 'jetpack' ), 'read', 'https://wordpress.com/sites', null, 'dashicons-arrow-left-alt2', 0 );
116 add_filter( 'add_menu_classes', array( $this, 'set_browse_sites_link_class' ) );
117 }
118
119 /**
120 * Adds a custom element class for Site Switcher menu item.
121 *
122 * @param array $menu Associative array of administration menu items.
123 * @return array
124 */
125 public function set_browse_sites_link_class( array $menu ) {
126 foreach ( $menu as $key => $menu_item ) {
127 if ( 'site-switcher' !== $menu_item[3] ) {
128 continue;
129 }
130
131 $menu[ $key ][4] = add_cssclass( 'site-switcher', $menu_item[4] );
132 break;
133 }
134
135 return $menu;
136 }
137
138 /**
139 * Adds a link to the menu to create a new site.
140 */
141 public function add_new_site_link() {
142 if ( $this->get_current_user_blog_count() > 1 ) {
143 return;
144 }
145
146 $this->add_admin_menu_separator();
147 add_menu_page( __( 'Add New Site', 'jetpack' ), __( 'Add New Site', 'jetpack' ), 'read', 'https://wordpress.com/start?ref=calypso-sidebar', null, 'dashicons-plus-alt' );
148 }
149
150 /**
151 * Adds site card component.
152 */
153 public function add_site_card_menu() {
154 $default = plugins_url( 'globe-icon.svg', __FILE__ );
155 $icon = get_site_icon_url( 32, $default );
156 $blog_name = get_option( 'blogname' ) !== '' ? get_option( 'blogname' ) : $this->domain;
157 $status = new Status();
158 $is_private_site = $status->is_private_site();
159 $is_coming_soon = $status->is_coming_soon();
160
161 if ( $default === $icon && blavatar_exists( $this->domain ) ) {
162 $icon = blavatar_url( $this->domain, 'img', 32 );
163 }
164
165 $badge = '';
166 if ( $is_private_site || $is_coming_soon ) {
167 $badge .= sprintf(
168 '<span class="site__badge site__badge-private">%s</span>',
169 $is_coming_soon ? esc_html__( 'Coming Soon', 'jetpack' ) : esc_html__( 'Private', 'jetpack' )
170 );
171 }
172
173 if ( function_exists( 'is_simple_site_redirect' ) && is_simple_site_redirect( $this->domain ) ) {
174 $badge .= '<span class="site__badge site__badge-redirect">' . esc_html__( 'Redirect', 'jetpack' ) . '</span>';
175 }
176
177 if ( ! empty( get_option( 'options' )['is_domain_only'] ) ) {
178 $badge .= '<span class="site__badge site__badge-domain-only">' . esc_html__( 'Domain', 'jetpack' ) . '</span>';
179 }
180
181 $site_card = '
182 <div class="site__info">
183 <div class="site__title">%1$s</div>
184 <div class="site__domain">%2$s</div>
185 %3$s
186 </div>';
187
188 $site_card = sprintf(
189 $site_card,
190 $blog_name,
191 $this->domain,
192 $badge
193 );
194
195 add_menu_page( 'site-card', $site_card, 'read', get_home_url(), null, $icon, 1 );
196 add_filter( 'add_menu_classes', array( $this, 'set_site_card_menu_class' ) );
197 }
198
199 /**
200 * Adds a custom element class and id for Site Card's menu item.
201 *
202 * @param array $menu Associative array of administration menu items.
203 * @return array
204 */
205 public function set_site_card_menu_class( array $menu ) {
206 foreach ( $menu as $key => $menu_item ) {
207 if ( 'site-card' !== $menu_item[3] ) {
208 continue;
209 }
210
211 $classes = ' toplevel_page_site-card';
212 if ( blavatar_exists( $this->domain ) ) {
213 $classes .= ' has-site-icon';
214 }
215
216 $menu[ $key ][4] = $menu_item[4] . $classes;
217 $menu[ $key ][5] = 'toplevel_page_site_card';
218 break;
219 }
220
221 return $menu;
222 }
223
224 /**
225 * Returns the first available upsell nudge.
226 *
227 * @return array
228 */
229 public function get_upsell_nudge() {
230 require_lib( 'jetpack-jitm/jitm-engine' );
231 $jitm_engine = new JITM\Engine();
232
233 $message_path = 'calypso:sites:sidebar_notice';
234 $current_user = wp_get_current_user();
235 $user_id = $current_user->ID;
236 $user_roles = implode( ',', $current_user->roles );
237 $query_string = array(
238 'message_path' => $message_path,
239 );
240
241 // Get the top message only.
242 $message = $jitm_engine->get_top_messages( $message_path, $user_id, $user_roles, $query_string );
243
244 if ( isset( $message[0] ) ) {
245 $message = $message[0];
246 return array(
247 'content' => $message->content['message'],
248 'cta' => $message->CTA['message'], // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
249 'link' => $message->CTA['link'], // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
250 'tracks_impression_event_name' => $message->tracks['display']['name'],
251 'tracks_impression_cta_name' => $message->tracks['display']['props']['cta_name'],
252 'tracks_click_event_name' => $message->tracks['click']['name'],
253 'tracks_click_cta_name' => $message->tracks['click']['props']['cta_name'],
254 'dismissible' => $message->is_dismissible,
255 'feature_class' => $message->feature_class,
256 'id' => $message->id,
257 );
258 }
259 }
260
261 /**
262 * Adds Stats menu.
263 */
264 public function add_stats_menu() {
265 $menu_title = __( 'Stats', 'jetpack' );
266
267 if ( ! $this->is_api_request ) {
268 $menu_title .= sprintf(
269 '<img class="sidebar-unified__sparkline" width="80" height="20" src="%1$s" alt="%2$s">',
270 esc_url( site_url( 'wp-includes/charts/admin-bar-hours-scale-2x.php?masterbar=1&s=' . get_current_blog_id() ) ),
271 esc_attr__( 'Hourly views', 'jetpack' )
272 );
273 }
274
275 add_menu_page( __( 'Stats', 'jetpack' ), $menu_title, 'edit_posts', 'https://wordpress.com/stats/day/' . $this->domain, null, 'dashicons-chart-bar', 3 );
276 }
277
278 /**
279 * Gets the current plan and stores it in $this->current_plan so the database is only called once per request.
280 *
281 * @return array
282 */
283 private function get_current_plan() {
284 if ( empty( $this->current_plan ) && class_exists( 'WPCOM_Store_API' ) ) {
285 $this->current_plan = \WPCOM_Store_API::get_current_plan( get_current_blog_id() );
286 }
287 return $this->current_plan;
288 }
289
290 /**
291 * Adds Upgrades menu.
292 *
293 * @param string $plan The current WPCOM plan of the blog.
294 */
295 public function add_upgrades_menu( $plan = null ) {
296 $current_plan = $this->get_current_plan();
297 if ( ! empty( $current_plan['product_name_short'] ) ) {
298 $plan = $current_plan['product_name_short'];
299 }
300
301 parent::add_upgrades_menu( $plan );
302
303 $last_upgrade_submenu_position = $this->get_submenu_item_count( 'paid-upgrades.php' );
304
305 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 );
306
307 /** This filter is already documented in modules/masterbar/admin-menu/class-atomic-admin-menu.php */
308 if ( apply_filters( 'jetpack_show_wpcom_upgrades_email_menu', false ) ) {
309 add_submenu_page( 'paid-upgrades.php', __( 'Emails', 'jetpack' ), __( 'Emails', 'jetpack' ), 'manage_options', 'https://wordpress.com/email/' . $this->domain, null, $last_upgrade_submenu_position );
310 }
311
312 if ( defined( 'WPCOM_ENABLE_ADD_ONS_MENU_ITEM' ) && WPCOM_ENABLE_ADD_ONS_MENU_ITEM ) {
313 add_submenu_page( 'paid-upgrades.php', __( 'Add-Ons', 'jetpack' ), __( 'Add-Ons', 'jetpack' ), 'manage_options', 'https://wordpress.com/add-ons/' . $this->domain, null, 1 );
314 }
315 }
316
317 /**
318 * Adds Appearance menu.
319 */
320 public function add_appearance_menu() {
321 $customize_url = parent::add_appearance_menu();
322
323 $this->hide_submenu_page( 'themes.php', 'theme-editor.php' );
324
325 $user_can_customize = current_user_can( 'customize' );
326
327 if ( function_exists( 'wp_is_block_theme' ) && wp_is_block_theme() ) {
328 add_filter( 'safecss_is_freetrial', '__return_false', PHP_INT_MAX );
329 if ( class_exists( 'Jetpack_Custom_CSS' ) && empty( Jetpack_Custom_CSS::get_css() ) ) {
330 $user_can_customize = false;
331 }
332 remove_filter( 'safecss_is_freetrial', '__return_false', PHP_INT_MAX );
333 }
334
335 if ( $user_can_customize ) {
336 $customize_custom_css_url = add_query_arg( array( 'autofocus' => array( 'section' => 'jetpack_custom_css' ) ), $customize_url );
337 add_submenu_page( 'themes.php', esc_attr__( 'Additional CSS', 'jetpack' ), __( 'Additional CSS', 'jetpack' ), 'customize', esc_url( $customize_custom_css_url ), null, 20 );
338 }
339 }
340
341 /**
342 * Adds Users menu.
343 */
344 public function add_users_menu() {
345 $current_locale = get_user_locale();
346
347 $submenus_to_update = array(
348 'grofiles-editor' => 'https://wordpress.com/me',
349 'grofiles-user-settings' => 'https://wordpress.com/me/account',
350 );
351
352 if ( self::DEFAULT_VIEW === $this->get_preferred_view( 'users.php' ) ) {
353 $submenus_to_update['users.php'] = 'https://wordpress.com/people/team/' . $this->domain;
354 }
355
356 $slug = current_user_can( 'list_users' ) ? 'users.php' : 'profile.php';
357 $this->update_submenus( $slug, $submenus_to_update );
358 add_submenu_page( 'users.php', esc_attr__( 'Add New', 'jetpack' ), __( 'Add New', 'jetpack' ), 'promote_users', 'https://wordpress.com/people/new/' . $this->domain, null, 1 );
359 if ( substr( $current_locale, 0, 2 ) === 'en' ) {
360 add_submenu_page( 'users.php', esc_attr__( 'Subscribers', 'jetpack' ), __( 'Subscribers', 'jetpack' ), 'list_users', 'https://wordpress.com/subscribers/' . $this->domain, null, 3 );
361 }
362 }
363
364 /**
365 * Adds Settings menu.
366 */
367 public function add_options_menu() {
368 parent::add_options_menu();
369
370 if ( Blaze::should_initialize() ) {
371 add_submenu_page( 'tools.php', esc_attr__( 'Advertising', 'jetpack' ), __( 'Advertising', 'jetpack' ), 'manage_options', 'https://wordpress.com/advertising/' . $this->domain, null, 1 );
372 }
373 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 );
374 }
375
376 /**
377 * Also remove the Gutenberg plugin menu.
378 */
379 public function remove_gutenberg_menu() {
380 // Always remove the Gutenberg menu.
381 remove_menu_page( 'gutenberg' );
382 }
383
384 /**
385 * Whether to use wp-admin pages rather than Calypso.
386 *
387 * @return bool
388 */
389 public function should_link_to_wp_admin() {
390 $result = false; // Calypso.
391
392 $user_attribute = get_user_attribute( get_current_user_id(), 'calypso_preferences' );
393 if ( ! empty( $user_attribute['linkDestination'] ) ) {
394 $result = $user_attribute['linkDestination'];
395 }
396
397 return $result;
398 }
399
400 /**
401 * Adds Plugins menu.
402 */
403 public function add_plugins_menu() {
404 // TODO: Remove wpcom_menu (/wp-content/admin-plugins/wpcom-misc.php).
405 $count = '';
406 if ( ! is_multisite() && current_user_can( 'update_plugins' ) ) {
407 $update_data = wp_get_update_data();
408 $count = sprintf(
409 '<span class="update-plugins count-%s"><span class="plugin-count">%s</span></span>',
410 $update_data['counts']['plugins'],
411 number_format_i18n( $update_data['counts']['plugins'] )
412 );
413 }
414 /* translators: %s: Number of pending plugin updates. */
415 add_menu_page( esc_attr__( 'Plugins', 'jetpack' ), sprintf( __( 'Plugins %s', 'jetpack' ), $count ), 'activate_plugins', 'plugins.php', null, 'dashicons-admin-plugins', 65 );
416
417 parent::add_plugins_menu();
418 }
419
420 /**
421 * Saves the sidebar state ( expanded / collapsed ) via an ajax request.
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