PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3-a.7
Jetpack – WP Security, Backup, Speed, & Growth v16.3-a.7
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 13.7.2 13.8.3 All 506 releases
jetpack / jetpack_vendor / automattic / jetpack-masterbar / src / admin-menu / class-wpcom-admin-menu.php

class-wpcom-admin-menu.php in Jetpack – WP Security, Backup, Speed, & Growth 16.3-a.7, at jetpack_vendor/automattic/jetpack-masterbar/src/admin-menu/class-wpcom-admin-menu.php

317 lines 10.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * WP.com Admin Menu file.
4 *
5 * @package automattic/jetpack-masterbar
6 */
7
8 namespace Automattic\Jetpack\Masterbar;
9
10 use Jetpack_Custom_CSS;
11 use JITM;
12
13 require_once __DIR__ . '/class-admin-menu.php';
14
15 /**
16 * Class WPcom_Admin_Menu.
17 */
18 class WPcom_Admin_Menu extends Admin_Menu {
19 /**
20 * WPcom_Admin_Menu constructor.
21 */
22 protected function __construct() {
23 parent::__construct();
24
25 add_action( 'wp_ajax_sidebar_state', array( $this, 'ajax_sidebar_state' ) );
26 add_action( 'wp_ajax_jitm_dismiss', array( $this, 'wp_ajax_jitm_dismiss' ) );
27 add_action( 'adminmenu', array( $this, 'render_upsell_nudge' ), 100 );
28 add_action( 'admin_init', array( $this, 'sync_sidebar_collapsed_state' ) );
29 add_action( 'admin_menu', array( $this, 'remove_submenus' ), 140 ); // After hookpress hook at 130.
30 }
31
32 /**
33 * Create the desired menu output.
34 */
35 public function reregister_menu_items() {
36 parent::reregister_menu_items();
37
38 $this->remove_gutenberg_menu();
39
40 // Not needed outside of wp-admin.
41 if ( ! $this->is_api_request ) {
42 $this->add_new_site_link();
43 }
44
45 ksort( $GLOBALS['menu'] );
46 }
47
48 /**
49 * Get the preferred view for the given screen.
50 *
51 * @param string $screen Screen identifier.
52 * @param bool $fallback_global_preference (Optional) Whether the global preference for all screens should be used
53 * as fallback if there is no specific preference for the given screen.
54 * Default: true.
55 * @return string
56 */
57 public function get_preferred_view( $screen, $fallback_global_preference = true ) {
58 // When no preferred view has been set for Themes, keep the previous behavior that forced the default view
59 // regardless of the global preference.
60 if ( $fallback_global_preference && 'themes.php' === $screen ) {
61 $preferred_view = parent::get_preferred_view( $screen, false );
62 if ( self::UNKNOWN_VIEW === $preferred_view ) {
63 return self::DEFAULT_VIEW;
64 }
65 return $preferred_view;
66 }
67
68 // Plugins on Simple sites are always managed on Calypso.
69 if ( 'plugins.php' === $screen ) {
70 return self::DEFAULT_VIEW;
71 }
72
73 return parent::get_preferred_view( $screen, $fallback_global_preference );
74 }
75
76 /**
77 * Retrieve the number of blogs that the current user has.
78 *
79 * @return int
80 */
81 public function get_current_user_blog_count() {
82 if ( function_exists( '\get_blog_count_for_user' ) ) {
83 return \get_blog_count_for_user( get_current_user_id() );
84 }
85
86 $blogs = get_blogs_of_user( get_current_user_id() );
87 return is_countable( $blogs ) ? count( $blogs ) : 0;
88 }
89
90 /**
91 * Adds a custom element class for Site Switcher menu item.
92 *
93 * @param array $menu Associative array of administration menu items.
94 * @return array
95 */
96 public function set_browse_sites_link_class( array $menu ) {
97 foreach ( $menu as $key => $menu_item ) {
98 if ( 'site-switcher' !== $menu_item[3] ) {
99 continue;
100 }
101
102 $menu[ $key ][4] = add_cssclass( 'site-switcher', $menu_item[4] );
103 break;
104 }
105
106 return $menu;
107 }
108
109 /**
110 * Adds a link to the menu to create a new site.
111 */
112 public function add_new_site_link() {
113 if ( $this->get_current_user_blog_count() > 1 ) {
114 return;
115 }
116
117 $this->add_admin_menu_separator();
118 // @phan-suppress-next-line PhanTypeMismatchArgumentProbablyReal -- Core should ideally document null for no-callback arg. https://core.trac.wordpress.org/ticket/52539.
119 add_menu_page( __( 'Add New Site', 'jetpack-masterbar' ), __( 'Add New Site', 'jetpack-masterbar' ), 'read', 'https://wordpress.com/start?ref=calypso-sidebar', null, 'dashicons-plus-alt' );
120 }
121
122 /**
123 * Returns the first available upsell nudge.
124 *
125 * @return array
126 */
127 public function get_upsell_nudge() {
128 require_lib( 'jetpack-jitm/jitm-engine' );
129 $jitm_engine = new JITM\Engine();
130
131 $message_path = 'calypso:sites:sidebar_notice';
132 $current_user = wp_get_current_user();
133 $user_id = $current_user->ID;
134 $user_roles = implode( ',', $current_user->roles );
135 $query_string = array(
136 'message_path' => $message_path,
137 );
138
139 // Get the top message only.
140 $message = $jitm_engine->get_top_messages( $message_path, $user_id, $user_roles, $query_string );
141
142 if ( isset( $message[0] ) ) {
143 $message = $message[0];
144 return array(
145 'content' => $message->content['message'],
146 'cta' => $message->CTA['message'], // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
147 'link' => $message->CTA['link'], // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
148 'tracks_impression_event_name' => $message->tracks['display']['name'] ?? null,
149 'tracks_impression_cta_name' => $message->tracks['display']['props']['cta_name'] ?? null,
150 'tracks_click_event_name' => $message->tracks['click']['name'] ?? null,
151 'tracks_click_cta_name' => $message->tracks['click']['props']['cta_name'] ?? null,
152 'dismissible' => $message->is_dismissible,
153 'feature_class' => $message->feature_class,
154 'id' => $message->id,
155 );
156 }
157 }
158
159 /**
160 * Adds Appearance menu.
161 *
162 * @return string The Customizer URL.
163 */
164 public function add_appearance_menu() {
165 $customize_url = parent::add_appearance_menu();
166
167 $this->hide_submenu_page( 'themes.php', 'theme-editor.php' );
168
169 $user_can_customize = current_user_can( 'customize' );
170
171 if ( wp_is_block_theme() ) {
172 add_filter( 'safecss_is_freetrial', '__return_false', PHP_INT_MAX );
173 if ( class_exists( 'Jetpack_Custom_CSS' ) && empty( Jetpack_Custom_CSS::get_css() ) ) {
174 $user_can_customize = false;
175 }
176 remove_filter( 'safecss_is_freetrial', '__return_false', PHP_INT_MAX );
177 }
178
179 if ( $user_can_customize ) {
180 $customize_custom_css_url = add_query_arg( array( 'autofocus' => array( 'section' => 'jetpack_custom_css' ) ), $customize_url );
181 // @phan-suppress-next-line PhanTypeMismatchArgumentProbablyReal -- Core should ideally document null for no-callback arg. https://core.trac.wordpress.org/ticket/52539.
182 add_submenu_page( 'themes.php', esc_attr__( 'Additional CSS', 'jetpack-masterbar' ), __( 'Additional CSS', 'jetpack-masterbar' ), 'customize', esc_url( $customize_custom_css_url ), null, 20 );
183 }
184
185 return $customize_url;
186 }
187
188 /**
189 * Adds Users menu.
190 */
191 public function add_users_menu() {
192 $submenus_to_update = array(
193 'grofiles-editor' => 'https://wordpress.com/me',
194 'grofiles-user-settings' => 'https://wordpress.com/me/account',
195 );
196
197 if ( self::DEFAULT_VIEW === $this->get_preferred_view( 'users.php' ) ) {
198 $submenus_to_update['users.php'] = 'https://wordpress.com/people/team/' . $this->domain;
199 }
200
201 $slug = current_user_can( 'list_users' ) ? 'users.php' : 'profile.php';
202 $this->update_submenus( $slug, $submenus_to_update );
203 // @phan-suppress-next-line PhanTypeMismatchArgumentProbablyReal -- Core should ideally document null for no-callback arg. https://core.trac.wordpress.org/ticket/52539.
204 add_submenu_page( 'users.php', esc_attr__( 'Add New User', 'jetpack-masterbar' ), __( 'Add New User', 'jetpack-masterbar' ), 'promote_users', 'https://wordpress.com/people/new/' . $this->domain, null, 1 );
205 }
206
207 /**
208 * Also remove the Gutenberg plugin menu.
209 */
210 public function remove_gutenberg_menu() {
211 // Always remove the Gutenberg menu.
212 remove_menu_page( 'gutenberg' );
213 }
214
215 /**
216 * Whether to use wp-admin pages rather than Calypso.
217 *
218 * @return bool
219 */
220 public function should_link_to_wp_admin() {
221 $result = false; // Calypso.
222
223 $user_attribute = get_user_attribute( get_current_user_id(), 'calypso_preferences' );
224 if ( ! empty( $user_attribute['linkDestination'] ) ) {
225 $result = $user_attribute['linkDestination'];
226 }
227
228 return $result;
229 }
230
231 /**
232 * Saves the sidebar state ( expanded / collapsed ) via an ajax request.
233 *
234 * @return never
235 */
236 public function ajax_sidebar_state() {
237 $expanded = isset( $_REQUEST['expanded'] ) ? filter_var( wp_unslash( $_REQUEST['expanded'] ), FILTER_VALIDATE_BOOLEAN ) : false; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
238 $user_id = get_current_user_id();
239 $preferences = get_user_attribute( $user_id, 'calypso_preferences' );
240 if ( empty( $preferences ) ) {
241 $preferences = array();
242 }
243
244 $value = array_merge( (array) $preferences, array( 'sidebarCollapsed' => ! $expanded ) );
245 $value = array_filter(
246 $value,
247 function ( $preference ) {
248 return null !== $preference;
249 }
250 );
251
252 update_user_attribute( $user_id, 'calypso_preferences', $value );
253
254 die( 0 );
255 }
256
257 /**
258 * Handle ajax requests to dismiss a just-in-time-message
259 */
260 public function wp_ajax_jitm_dismiss() {
261 check_ajax_referer( 'jitm_dismiss' );
262 require_lib( 'jetpack-jitm/jitm-engine' );
263 if ( isset( $_REQUEST['id'] ) && isset( $_REQUEST['feature_class'] ) ) {
264 JITM\Engine::dismiss( sanitize_text_field( wp_unslash( $_REQUEST['id'] ) ), sanitize_text_field( wp_unslash( $_REQUEST['feature_class'] ) ) );
265 }
266 wp_die();
267 }
268
269 /**
270 * Syncs the sidebar collapsed state from Calypso Preferences.
271 */
272 public function sync_sidebar_collapsed_state() {
273 $calypso_preferences = get_user_attribute( get_current_user_id(), 'calypso_preferences' );
274
275 $sidebar_collapsed = $calypso_preferences['sidebarCollapsed'] ?? false;
276
277 // Read the current stored setting and convert it to boolean in order to be able to compare the values later.
278 $current_sidebar_collapsed_setting = 'f' === get_user_setting( 'mfold' );
279
280 // Only set the setting if the value differs, as `set_user_setting` always updates at least the timestamp
281 // which leads to unnecessary user meta cache purging on all wp-admin screen requests.
282 if ( $current_sidebar_collapsed_setting !== $sidebar_collapsed ) {
283 set_user_setting( 'mfold', $sidebar_collapsed ? 'f' : 'o' );
284 }
285 }
286
287 /**
288 * Removes unwanted submenu items.
289 *
290 * These submenus are added across wp-content and should be removed together with these function calls.
291 */
292 public function remove_submenus() {
293 global $_registered_pages;
294
295 remove_submenu_page( 'index.php', 'akismet-stats' );
296 remove_submenu_page( 'index.php', 'my-comments' );
297 remove_submenu_page( 'index.php', 'stats' );
298 remove_submenu_page( 'index.php', 'subscriptions' );
299
300 /* @see https://github.com/Automattic/wp-calypso/issues/49210 */
301 remove_submenu_page( 'index.php', 'my-blogs' );
302 $_registered_pages['admin_page_my-blogs'] = true; // phpcs:ignore
303
304 remove_submenu_page( 'themes.php', 'customize.php?autofocus[panel]=amp_panel&return=' . rawurlencode( admin_url() ) );
305
306 remove_submenu_page( 'users.php', 'wpcom-invite-users' ); // Wpcom_Invite_Users::action_admin_menu.
307
308 remove_submenu_page( 'options-general.php', 'adcontrol' );
309
310 // Remove menu item but continue allowing access.
311 foreach ( array( 'openidserver', 'webhooks' ) as $page_slug ) {
312 remove_submenu_page( 'options-general.php', $page_slug );
313 $_registered_pages[ 'admin_page_' . $page_slug ] = true; // phpcs:ignore
314 }
315 }
316 }
317