Completed
Push — try/wpcom-nav-package ( c38648 )
by
unknown
12:50 queued 02:43
created

Simple_Admin_Menu::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 7
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * WP.com Admin Menu file.
4
 *
5
 * @package automattic/jetpack
6
 */
7
8
namespace Automattic\Jetpack;
9
10
/**
11
 * Class Simple_Admin_Menu.
12
 */
13
class Simple_Admin_Menu extends Admin_Menu {
14
	/**
15
	 * Simple_Admin_Menu constructor.
16
	 */
17
	protected function __construct() {
18
		parent::__construct();
19
20
		add_action( 'wp_ajax_sidebar_state', array( $this, 'ajax_sidebar_state' ) );
21
		add_action( 'admin_init', array( $this, 'sync_sidebar_collapsed_state' ) );
22
		add_action( 'admin_menu', array( $this, 'remove_submenus' ), 140 ); // After hookpress hook at 130.
23
	}
24
25
	/**
26
	 * Sets up class properties for REST API requests.
27
	 *
28
	 * @param WP_REST_Response $response Response from the endpoint.
29
	 */
30
	public function rest_api_init( $response ) {
31
		parent::rest_api_init( $response );
32
33
		// Get domain for requested site.
34
		$this->domain = ( new Status() )->get_site_suffix();
35
36
		return $response;
37
	}
38
39
	/**
40
	 * Create the desired menu output.
41
	 */
42 View Code Duplication
	public function reregister_menu_items() {
43
		parent::reregister_menu_items();
44
45
		$this->add_my_home_menu();
46
47
		// Not needed outside of wp-admin.
48
		if ( ! $this->is_api_request ) {
49
			$this->add_browse_sites_link();
50
			$this->add_site_card_menu();
51
			$this->add_new_site_link();
52
		}
53
54
		ksort( $GLOBALS['menu'] );
55
	}
56
57
	/**
58
	 * Adds the site switcher link if user has more than one site.
59
	 */
60
	public function add_browse_sites_link() {
61
		if ( count( get_blogs_of_user( get_current_user_id() ) ) < 2 ) {
62
			return;
63
		}
64
65
		// Add the menu item.
66
		add_menu_page( __( 'site-switcher', 'jetpack' ), __( 'Browse sites', 'jetpack' ), 'read', 'https://wordpress.com/home', null, 'dashicons-arrow-left-alt2', 0 );
67
		add_filter( 'add_menu_classes', array( $this, 'set_browse_sites_link_class' ) );
68
	}
69
70
	/**
71
	 * Adds a custom element class for Site Switcher menu item.
72
	 *
73
	 * @param array $menu Associative array of administration menu items.
74
	 * @return array
75
	 */
76 View Code Duplication
	public function set_browse_sites_link_class( array $menu ) {
77
		foreach ( $menu as $key => $menu_item ) {
78
			if ( 'site-switcher' !== $menu_item[3] ) {
79
				continue;
80
			}
81
82
			$menu[ $key ][4] = add_cssclass( 'site-switcher', $menu_item[4] );
83
			break;
84
		}
85
86
		return $menu;
87
	}
88
89
	/**
90
	 * Adds a link to the menu to create a new site.
91
	 */
92
	public function add_new_site_link() {
93
		if ( count( get_blogs_of_user( get_current_user_id() ) ) > 1 ) {
94
			return;
95
		}
96
97
		$this->add_admin_menu_separator();
98
		add_menu_page( __( 'Add New Site', 'jetpack' ), __( 'Add New Site', 'jetpack' ), 'read', 'https://wordpress.com/start?ref=calypso-sidebar', null, 'dashicons-plus-alt' );
99
	}
100
101
	/**
102
	 * Adds site card component.
103
	 */
104
	public function add_site_card_menu() {
105
		$default   = 'data:image/svg+xml,' . rawurlencode( '<svg class="gridicon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><title>Globe</title><rect fill-opacity="0" x="0" width="24" height="24"/><g><path fill="#fff" d="M12 2C6.477 2 2 6.477 2 12s4.477 10 10 10 10-4.477 10-10S17.523 2 12 2zm0 18l2-2 1-1v-2h-2v-1l-1-1H9v3l2 2v1.93c-3.94-.494-7-3.858-7-7.93l1 1h2v-2h2l3-3V6h-2L9 5v-.41C9.927 4.21 10.94 4 12 4s2.073.212 3 .59V6l-1 1v2l1 1 3.13-3.13c.752.897 1.304 1.964 1.606 3.13H18l-2 2v2l1 1h2l.286.286C18.03 18.06 15.24 20 12 20z"/></g></svg>' );
106
		$icon      = get_site_icon_url( 32, $default );
107
		$blog_name = get_option( 'blogname' ) !== '' ? get_option( 'blogname' ) : $this->domain;
108
109
		if ( $default === $icon && blavatar_exists( $this->domain ) ) {
110
			$icon = blavatar_url( $this->domain, 'img', 32 );
111
		}
112
113
		$badge = '';
114
		if ( is_private_blog() ) {
115
			$badge .= sprintf(
116
				'<span class="site__badge site__badge-private">%s</span>',
117
				wpcom_is_coming_soon() ? esc_html__( 'Coming Soon', 'jetpack' ) : esc_html__( 'Private', 'jetpack' )
118
			);
119
		}
120
121
		if ( is_redirected_domain( $this->domain ) ) {
122
			$badge .= '<span class="site__badge site__badge-redirect">' . esc_html__( 'Redirect', 'jetpack' ) . '</span>';
123
		}
124
125
		if ( ! empty( get_option( 'options' )['is_domain_only'] ) ) {
126
			$badge .= '<span class="site__badge site__badge-domain-only">' . esc_html__( 'Domain', 'jetpack' ) . '</span>';
127
		}
128
129
		$site_card = '
130
<div class="site__info">
131
	<div class="site__title">%1$s</div>
132
	<div class="site__domain">%2$s</div>
133
	%3$s
134
</div>';
135
136
		$site_card = sprintf(
137
			$site_card,
138
			$blog_name,
139
			$this->domain,
140
			$badge
141
		);
142
143
		add_menu_page( 'site-card', $site_card, 'read', get_home_url(), null, $icon, 1 );
144
		add_filter( 'add_menu_classes', array( $this, 'set_site_card_menu_class' ) );
145
	}
146
147
	/**
148
	 * Adds a custom element class and id for Site Card's menu item.
149
	 *
150
	 * @param array $menu Associative array of administration menu items.
151
	 * @return array
152
	 */
153
	public function set_site_card_menu_class( array $menu ) {
154
		foreach ( $menu as $key => $menu_item ) {
155
			if ( 'site-card' !== $menu_item[3] ) {
156
				continue;
157
			}
158
159
			$classes = ' toplevel_page_site-card';
160
			if ( blavatar_exists( $this->domain ) ) {
161
				$classes .= ' has-site-icon';
162
			}
163
164
			$menu[ $key ][4] = $menu_item[4] . $classes;
165
			$menu[ $key ][5] = 'toplevel_page_site_card';
166
			break;
167
		}
168
169
		return $menu;
170
	}
171
172
	/**
173
	 * Adds Stats menu.
174
	 */
175
	public function add_stats_menu() {
176
		$menu_title = __( 'Stats', 'jetpack' );
177
178
		if ( ! $this->is_api_request ) {
179
			$menu_title .= sprintf(
180
				'<img class="sidebar-unified__sparkline" width="80" height="20" src="%1$s" alt="%2$s">',
181
				esc_url( site_url( 'wp-includes/charts/admin-bar-hours-scale-2x.php?masterbar=1&s=' . get_current_blog_id() ) ),
182
				esc_attr__( 'Hourly views', 'jetpack' )
183
			);
184
		}
185
186
		add_menu_page( __( 'Stats', 'jetpack' ), $menu_title, 'edit_posts', 'https://wordpress.com/stats/day/' . $this->domain, null, 'dashicons-chart-bar', 3 );
187
	}
188
189
	/**
190
	 * Adds Upgrades menu.
191
	 *
192
	 * @param string $plan The current WPCOM plan of the blog.
0 ignored issues
show
Documentation introduced by
Should the type for parameter $plan not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
193
	 */
194
	public function add_upgrades_menu( $plan = null ) {
195
		if ( class_exists( 'WPCOM_Store_API' ) ) {
196
			$products = \WPCOM_Store_API::get_current_plan( get_current_blog_id() );
197
			if ( array_key_exists( 'product_name_short', $products ) ) {
198
				$plan = $products['product_name_short'];
199
			}
200
		}
201
		parent::add_upgrades_menu( $plan );
202
203
		$last_upgrade_submenu_position = $this->get_submenu_item_count( 'paid-upgrades.php' );
204
205
		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 );
206
207
		/** This filter is already documented in modules/masterbar/admin-menu/class-atomic-admin-menu.php */
208 View Code Duplication
		if ( apply_filters( 'jetpack_show_wpcom_upgrades_email_menu', false ) ) {
209
			add_submenu_page( 'paid-upgrades.php', __( 'Emails', 'jetpack' ), __( 'Emails', 'jetpack' ), 'manage_options', 'https://wordpress.com/email/' . $this->domain, null, $last_upgrade_submenu_position );
210
		}
211
	}
212
213
	/**
214
	 * Adds Appearance menu.
215
	 *
216
	 * @param bool $wp_admin_themes Optional. Whether Themes link should point to Calypso or wp-admin. Default false (Calypso).
217
	 * @param bool $wp_admin_customize Optional. Whether Customize link should point to Calypso or wp-admin. Default false (Calypso).
218
	 */
219
	public function add_appearance_menu( $wp_admin_themes = false, $wp_admin_customize = false ) {
220
		// $wp_admin_themes can have a `true` value here if the user has activated the "Show advanced dashboard pages" account setting.
221
		// We force $wp_admin_themes to `false` anyways, since Simple sites should always see the Calypso Theme showcase.
222
		$wp_admin_themes = false;
223
		$customize_url   = parent::add_appearance_menu( $wp_admin_themes, $wp_admin_customize );
224
225
		$this->hide_submenu_page( 'themes.php', 'theme-editor.php' );
226
227
		$user_can_customize = current_user_can( 'customize' );
228
229
		if ( $user_can_customize ) {
230
			// If the user does not have the custom CSS option then present them with the CSS nudge upsell section instead.
231
			$custom_css_section = '1' === get_option( 'custom-design-upgrade' ) ? 'jetpack_custom_css' : 'css_nudge'; //phpcs:ignore
232
			$customize_custom_css_url = add_query_arg( array( 'autofocus' => array( 'section' => $custom_css_section ) ), $customize_url );
233
			add_submenu_page( 'themes.php', esc_attr__( 'Additional CSS', 'jetpack' ), __( 'Additional CSS', 'jetpack' ), 'customize', esc_url( $customize_custom_css_url ), null, 20 );
234
		}
235
	}
236
237
	/**
238
	 * Adds Users menu.
239
	 *
240
	 * @param bool $wp_admin Optional. Whether links should point to Calypso or wp-admin. Default false (Calypso).
241
	 */
242
	public function add_users_menu( $wp_admin = false ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
243
		if ( current_user_can( 'list_users' ) ) {
244
			$submenus_to_update = array(
245
				'users.php'              => 'https://wordpress.com/people/team/' . $this->domain,
246
				'grofiles-editor'        => 'https://wordpress.com/me',
247
				'grofiles-user-settings' => 'https://wordpress.com/me/account',
248
			);
249
			$this->update_submenus( 'users.php', $submenus_to_update );
250
		} else {
251
			$submenus_to_update = array(
252
				'grofiles-editor'        => 'https://wordpress.com/me',
253
				'grofiles-user-settings' => 'https://wordpress.com/me/account',
254
			);
255
			$this->update_submenus( 'profile.php', $submenus_to_update );
256
		}
257
		add_submenu_page( 'users.php', esc_attr__( 'Add New', 'jetpack' ), __( 'Add New', 'jetpack' ), 'promote_users', 'https://wordpress.com/people/new/' . $this->domain, null, 1 );
258
	}
259
260
	/**
261
	 * Adds Settings menu.
262
	 *
263
	 * @param bool $wp_admin Optional. Whether links should point to Calypso or wp-admin. Default false (Calypso).
264
	 */
265
	public function add_options_menu( $wp_admin = false ) {
266
		parent::add_options_menu( $wp_admin );
267
268
		add_submenu_page( 'options-general.php', esc_attr__( 'Hosting Configuration', 'jetpack' ), __( 'Hosting Configuration', 'jetpack' ), 'manage_options', 'https://wordpress.com/hosting-config/' . $this->domain, null, 6 );
269
	}
270
271
	/**
272
	 * Also remove the Gutenberg plugin menu.
273
	 *
274
	 * @param bool $wp_admin Optional. Whether links should point to Calypso or wp-admin. Default false (Calypso).
275
	 */
276
	public function add_gutenberg_menus( $wp_admin = false ) {
277
		// Always remove the Gutenberg menu.
278
		remove_menu_page( 'gutenberg' );
279
		parent::add_gutenberg_menus( $wp_admin );
280
	}
281
282
	/**
283
	 * Whether to use wp-admin pages rather than Calypso.
284
	 *
285
	 * @return bool
286
	 */
287
	public function should_link_to_wp_admin() {
288
		$result = false; // Calypso.
289
290
		$user_attribute = get_user_attribute( get_current_user_id(), 'calypso_preferences' );
291
		if ( ! empty( $user_attribute['linkDestination'] ) ) {
292
			$result = $user_attribute['linkDestination'];
293
		}
294
295
		return $result;
296
	}
297
298
	/**
299
	 * Adds Plugins menu.
300
	 *
301
	 * @param bool $wp_admin Optional. Whether links should point to Calypso or wp-admin. Default false (Calypso).
302
	 */
303
	public function add_plugins_menu( $wp_admin = false ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
304
		// TODO: Remove wpcom_menu (/wp-content/admin-plugins/wpcom-misc.php).
305
		$count = '';
306
		if ( ! is_multisite() && current_user_can( 'update_plugins' ) ) {
307
			$update_data = wp_get_update_data();
308
			$count       = sprintf(
309
				'<span class="update-plugins count-%s"><span class="plugin-count">%s</span></span>',
310
				$update_data['counts']['plugins'],
311
				number_format_i18n( $update_data['counts']['plugins'] )
312
			);
313
		}
314
		/* translators: %s: Number of pending plugin updates. */
315
		add_menu_page( esc_attr__( 'Plugins', 'jetpack' ), sprintf( __( 'Plugins %s', 'jetpack' ), $count ), 'activate_plugins', 'plugins.php', null, 'dashicons-admin-plugins', 65 );
316
317
		// Plugins on Simple sites are always managed on Calypso.
318
		parent::add_plugins_menu( false );
319
	}
320
321
	/**
322
	 * Saves the sidebar state ( expanded / collapsed ) via an ajax request.
323
	 */
324
	public function ajax_sidebar_state() {
325
		$expanded    = filter_var( $_REQUEST['expanded'], FILTER_VALIDATE_BOOLEAN ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
326
		$user_id     = get_current_user_id();
327
		$preferences = get_user_attribute( $user_id, 'calypso_preferences' );
328
		if ( empty( $preferences ) ) {
329
			$preferences = array();
330
		}
331
332
		$value = array_merge( (array) $preferences, array( 'sidebarCollapsed' => ! $expanded ) );
333
		$value = array_filter(
334
			$value,
335
			function ( $preference ) {
336
				return null !== $preference;
337
			}
338
		);
339
340
		update_user_attribute( $user_id, 'calypso_preferences', $value );
341
342
		die();
343
	}
344
345
	/**
346
	 * Syncs the sidebar collapsed state from Calypso Preferences.
347
	 */
348
	public function sync_sidebar_collapsed_state() {
349
		$calypso_preferences = get_user_attribute( get_current_user_id(), 'calypso_preferences' );
350
351
		$sidebar_collapsed = isset( $calypso_preferences['sidebarCollapsed'] ) ? $calypso_preferences['sidebarCollapsed'] : false;
352
		set_user_setting( 'mfold', $sidebar_collapsed ? 'f' : 'o' );
353
	}
354
355
	/**
356
	 * Removes unwanted submenu items.
357
	 *
358
	 * These submenus are added across wp-content and should be removed together with these function calls.
359
	 */
360
	public function remove_submenus() {
361
		global $_registered_pages;
362
363
		remove_submenu_page( 'index.php', 'akismet-stats' );
364
		remove_submenu_page( 'index.php', 'my-comments' );
365
		remove_submenu_page( 'index.php', 'stats' );
366
		remove_submenu_page( 'index.php', 'subscriptions' );
367
368
		/* @see https://github.com/Automattic/wp-calypso/issues/49210 */
369
		remove_submenu_page( 'index.php', 'my-blogs' );
370
		$_registered_pages['admin_page_my-blogs'] = true; // phpcs:ignore
371
372
		remove_submenu_page( 'paid-upgrades.php', 'premium-themes' );
373
		remove_submenu_page( 'paid-upgrades.php', 'domains' );
374
		remove_submenu_page( 'paid-upgrades.php', 'my-upgrades' );
375
		remove_submenu_page( 'paid-upgrades.php', 'billing-history' );
376
377
		remove_submenu_page( 'themes.php', 'customize.php?autofocus[panel]=amp_panel&return=' . rawurlencode( admin_url() ) );
378
379
		remove_submenu_page( 'users.php', 'wpcom-invite-users' ); // Wpcom_Invite_Users::action_admin_menu.
380
381
		remove_submenu_page( 'options-general.php', 'adcontrol' );
382
383
		// Remove menu item but continue allowing access.
384
		foreach ( array( 'openidserver', 'webhooks' ) as $page_slug ) {
385
			remove_submenu_page( 'options-general.php', $page_slug );
386
			$_registered_pages[ 'admin_page_' . $page_slug ] = true; // phpcs:ignore
387
		}
388
	}
389
}
390