is_api_request ) {
add_filter( 'submenu_file', array( $this, 'override_the_theme_installer' ), 10, 2 );
}
add_action(
'admin_menu',
function () {
remove_action( 'admin_menu', 'gutenberg_menu', 9 );
},
0
);
// Add notices to the settings pages when there is a Calypso page available.
if ( get_option( 'wpcom_admin_interface' ) === 'wp-admin' ) {
add_action( 'current_screen', array( $this, 'add_settings_page_notice' ) );
}
}
/**
* Dequeues unnecessary scripts.
*/
public function dequeue_scripts() {
wp_dequeue_script( 'a8c_wpcom_masterbar_overrides' ); // Initially loaded in modules/masterbar/masterbar/class-masterbar.php.
}
/**
* Determines whether the current locale is right-to-left (RTL).
*
* Performs the check against the current locale set on the WordPress.com's account settings.
* See `Masterbar::__construct` in `modules/masterbar/masterbar/class-masterbar.php`.
*/
public function is_rtl() {
return get_user_option( 'jetpack_wpcom_is_rtl' );
}
/**
* Create the desired menu output.
*/
public function reregister_menu_items() {
parent::reregister_menu_items();
$this->add_my_home_menu();
$this->remove_gutenberg_menu();
// We don't need the `My Mailboxes` when the interface is set to wp-admin or the site is a staging site,
if ( get_option( 'wpcom_admin_interface' ) !== 'wp-admin' && ! get_option( 'wpcom_is_staging_site' ) ) {
$this->add_my_mailboxes_menu();
}
// Not needed outside of wp-admin.
if ( ! $this->is_api_request ) {
$this->add_browse_sites_link();
$this->add_site_card_menu();
$this->add_new_site_link();
}
$this->add_woocommerce_installation_menu();
ksort( $GLOBALS['menu'] );
}
/**
* Get the preferred view for the given screen.
*
* @param string $screen Screen identifier.
* @param bool $fallback_global_preference (Optional) Whether the global preference for all screens should be used
* as fallback if there is no specific preference for the given screen.
* Default: true.
* @return string
*/
public function get_preferred_view( $screen, $fallback_global_preference = true ) {
// Export on Atomic sites are always managed on WP Admin.
if ( in_array( $screen, array( 'export.php' ), true ) ) {
return self::CLASSIC_VIEW;
}
/**
* When Jetpack SSO is disabled, we need to force Calypso because it might create confusion to be redirected to WP-Admin.
* Furthermore, because we don't display the quick switcher, users having an WP-Admin interface by default won't be able to go back to the Calyso version.
*/
if ( ! \Jetpack::is_module_active( 'sso' ) ) {
return self::DEFAULT_VIEW;
}
return parent::get_preferred_view( $screen, $fallback_global_preference );
}
/**
* Adds Users menu.
*/
public function add_users_menu() {
$slug = current_user_can( 'list_users' ) ? 'users.php' : 'profile.php';
if ( self::DEFAULT_VIEW === $this->get_preferred_view( 'users.php' ) ) {
$submenus_to_update = array(
'users.php' => 'https://wordpress.com/people/team/' . $this->domain,
);
$this->update_submenus( $slug, $submenus_to_update );
}
if ( ! $this->use_wp_admin_interface() ) {
// The 'Subscribers' menu exists in the Jetpack menu for Classic wp-admin interface, so only add it for non-wp-admin interfaces.
add_submenu_page( 'users.php', esc_attr__( 'Subscribers', 'jetpack' ), __( 'Subscribers', 'jetpack' ), 'list_users', 'https://wordpress.com/subscribers/' . $this->domain, null );
// When the interface is not set to wp-admin, we replace the Profile submenu.
remove_submenu_page( 'users.php', 'profile.php' );
add_submenu_page( 'users.php', esc_attr__( 'My Profile', 'jetpack' ), __( 'My Profile', 'jetpack' ), 'read', 'https://wordpress.com/me/', null );
}
// Users who can't 'list_users' will see "Profile" menu & "Profile > Account Settings" as submenu.
add_submenu_page( $slug, esc_attr__( 'Account Settings', 'jetpack' ), __( 'Account Settings', 'jetpack' ), 'read', 'https://wordpress.com/me/account' );
}
/**
* Adds Plugins menu.
*/
public function add_plugins_menu() {
global $submenu;
// Calypso plugins screens link.
$plugins_slug = 'https://wordpress.com/plugins/' . $this->domain;
// Link to the Marketplace from Plugins > Add New on Atomic sites where the wpcom_admin_interface option is set to wp-admin.
if ( self::CLASSIC_VIEW === $this->get_preferred_view( 'plugins.php' ) ) {
$submenus_to_update = array( 'plugin-install.php' => $plugins_slug );
$this->update_submenus( 'plugins.php', $submenus_to_update );
return;
}
// Link to the Marketplace on sites that can't manage plugins.
if (
function_exists( 'wpcom_site_has_feature' ) &&
! wpcom_site_has_feature( \WPCOM_Features::MANAGE_PLUGINS )
) {
add_menu_page( __( 'Plugins', 'jetpack' ), __( 'Plugins', 'jetpack' ), 'manage_options', $plugins_slug, null, 'dashicons-admin-plugins', '65' );
return;
}
if ( ! isset( $submenu['plugins.php'] ) ) {
return;
}
$plugins_submenu = $submenu['plugins.php'];
// Move "Add New" plugin submenu to the top position.
foreach ( $plugins_submenu as $submenu_key => $submenu_keys ) {
if ( 'plugin-install.php' === $submenu_keys[2] ) {
// phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
$submenu['plugins.php'] = array( $submenu_key => $plugins_submenu[ $submenu_key ] ) + $plugins_submenu;
}
}
$submenus_to_update = array( 'plugin-install.php' => $plugins_slug );
$this->update_submenus( 'plugins.php', $submenus_to_update );
}
/**
* Adds the site switcher link if user has more than one site.
*/
public function add_browse_sites_link() {
$site_count = get_user_option( 'wpcom_site_count' );
if ( ! $site_count || $site_count < 2 ) {
return;
}
// Add the menu item.
add_menu_page( __( 'site-switcher', 'jetpack' ), __( 'Browse sites', 'jetpack' ), 'read', 'https://wordpress.com/sites', null, 'dashicons-arrow-left-alt2', 0 );
add_filter( 'add_menu_classes', array( $this, 'set_browse_sites_link_class' ) );
}
/**
* Adds a custom element class for Site Switcher menu item.
*
* @param array $menu Associative array of administration menu items.
*
* @return array
*/
public function set_browse_sites_link_class( array $menu ) {
foreach ( $menu as $key => $menu_item ) {
if ( 'site-switcher' !== $menu_item[3] ) {
continue;
}
$menu[ $key ][4] = add_cssclass( 'site-switcher', $menu_item[4] );
break;
}
return $menu;
}
/**
* Adds a link to the menu to create a new site.
*/
public function add_new_site_link() {
$site_count = get_user_option( 'wpcom_site_count' );
if ( $site_count && $site_count > 1 ) {
return;
}
add_menu_page( __( 'Add New Site', 'jetpack' ), __( 'Add New Site', 'jetpack' ), 'read', 'https://wordpress.com/start?ref=calypso-sidebar', null, 'dashicons-plus-alt' );
}
/**
* Adds site card component.
*/
public function add_site_card_menu() {
$default = plugins_url( 'globe-icon.svg', __FILE__ );
$icon = get_site_icon_url( 32, $default );
$blog_name = get_option( 'blogname' ) !== '' ? get_option( 'blogname' ) : $this->domain;
$is_coming_soon = ( new Status() )->is_coming_soon();
$badge = '';
if ( get_option( 'wpcom_is_staging_site' ) ) {
$badge .= '' . esc_html__( 'Staging', 'jetpack' ) . '';
}
if ( ( function_exists( 'site_is_private' ) && site_is_private() ) || $is_coming_soon ) {
$badge .= sprintf(
'%s',
$is_coming_soon ? esc_html__( 'Coming Soon', 'jetpack' ) : esc_html__( 'Private', 'jetpack' )
);
}
$site_card = '
';
$site_card = sprintf(
$site_card,
$blog_name,
$this->domain,
$badge
);
add_menu_page( 'site-card', $site_card, 'read', get_home_url(), null, $icon, 1 );
add_filter( 'add_menu_classes', array( $this, 'set_site_card_menu_class' ) );
}
/**
* Adds a custom element class and id for Site Card's menu item.
*
* @param array $menu Associative array of administration menu items.
*
* @return array
*/
public function set_site_card_menu_class( array $menu ) {
foreach ( $menu as $key => $menu_item ) {
if ( 'site-card' !== $menu_item[3] ) {
continue;
}
$classes = ' toplevel_page_site-card';
// webclip.png is the default on WoA sites. Anything other than that means we have a custom site icon.
if ( has_site_icon() && 'https://s0.wp.com/i/webclip.png' !== get_site_icon_url( 512 ) ) {
$classes .= ' has-site-icon';
}
$menu[ $key ][4] = $menu_item[4] . $classes;
$menu[ $key ][5] = 'toplevel_page_site_card';
break;
}
return $menu;
}
/**
* Returns the first available upsell nudge.
*
* @return array
*/
public function get_upsell_nudge() {
$jitm = \Automattic\Jetpack\JITMS\JITM::get_instance();
$message_path = 'calypso:sites:sidebar_notice';
$message = $jitm->get_messages( $message_path, wp_json_encode( array( 'message_path' => $message_path ) ), false );
if ( isset( $message[0] ) ) {
$message = $message[0];
return array(
'content' => $message->content->message,
'cta' => $message->CTA->message, // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
'link' => $message->CTA->link, // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
'tracks_impression_event_name' => $message->tracks->display->name,
'tracks_impression_cta_name' => $message->tracks->display->props->cta_name,
'tracks_click_event_name' => $message->tracks->click->name,
'tracks_click_cta_name' => $message->tracks->click->props->cta_name,
'dismissible' => $message->is_dismissible,
'feature_class' => $message->feature_class,
'id' => $message->id,
);
}
}
/**
* Adds Jetpack menu.
*/
public function add_jetpack_menu() {
// This is supposed to be the same as class-admin-menu but with a different position specified for the Jetpack menu.
if ( 'wp-admin' === get_option( 'wpcom_admin_interface' ) ) {
parent::create_jetpack_menu( 2, false );
} else {
parent::add_jetpack_menu();
}
global $submenu;
$backup_submenu_label = __( 'Backup', 'jetpack' );
$submenu_labels = array_column( $submenu['jetpack'], 3 );
$backup_position = array_search( $backup_submenu_label, $submenu_labels, true );
$scan_position = $backup_position !== false ? $backup_position + 1 : $this->get_submenu_item_count( 'jetpack' ) - 1;
add_submenu_page( 'jetpack', esc_attr__( 'Scan', 'jetpack' ), __( 'Scan', 'jetpack' ), 'manage_options', 'https://wordpress.com/scan/history/' . $this->domain, null, $scan_position );
/**
* Prevent duplicate menu items that link to Jetpack Backup.
* Hide the one that's shown when the standalone backup plugin is not installed, since Jetpack Backup is already included in Atomic sites.
*
* @see https://github.com/Automattic/jetpack/pull/33955
*/
$this->hide_submenu_page( 'jetpack', esc_url( Redirect::get_url( 'calypso-backups' ) ) );
// hide duplicate link to scan history that is shown in the untangling UI
$this->hide_submenu_page( 'jetpack', esc_url( Redirect::get_url( 'cloud-scan-history-wp-menu' ) ) );
}
/**
* Adds Stats menu.
*/
public function add_stats_menu() {
$menu_title = __( 'Stats', 'jetpack' );
if (
! $this->is_api_request &&
\Jetpack::is_module_active( 'stats' ) &&
function_exists( 'stats_get_image_chart_src' )
) {
$img_src = esc_attr(
stats_get_image_chart_src( 'admin-bar-hours-scale-2x', array( 'masterbar' => '' ) )
);
$alt = esc_attr__( 'Hourly views', 'jetpack' );
$menu_title .= "";
}
add_menu_page( __( 'Stats', 'jetpack' ), $menu_title, 'view_stats', 'https://wordpress.com/stats/day/' . $this->domain, null, 'dashicons-chart-bar', 3 );
}
/**
* Adds Upgrades menu.
*
* @param string $plan The current WPCOM plan of the blog.
*/
public function add_upgrades_menu( $plan = null ) {
if ( get_option( 'wpcom_is_staging_site' ) ) {
return;
}
$products = Jetpack_Plan::get();
if ( array_key_exists( 'product_name_short', $products ) ) {
$plan = $products['product_name_short'];
}
parent::add_upgrades_menu( $plan );
$last_upgrade_submenu_position = $this->get_submenu_item_count( 'paid-upgrades.php' );
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 );
/**
* Whether to show the WordPress.com Emails submenu under the main Upgrades menu.
*
* @use add_filter( 'jetpack_show_wpcom_upgrades_email_menu', '__return_true' );
* @module masterbar
*
* @since 9.7.0
*
* @param bool $show_wpcom_upgrades_email_menu Load the WordPress.com Emails submenu item. Default to false.
*/
if ( apply_filters( 'jetpack_show_wpcom_upgrades_email_menu', false ) ) {
add_submenu_page( 'paid-upgrades.php', __( 'Emails', 'jetpack' ), __( 'Emails', 'jetpack' ), 'manage_options', 'https://wordpress.com/email/' . $this->domain, null, $last_upgrade_submenu_position );
}
}
/**
* Adds Settings menu.
*/
public function add_options_menu() {
parent::add_options_menu();
if ( Jetpack_Plan::supports( 'security-settings' ) ) {
add_submenu_page(
'options-general.php',
esc_attr__( 'Security', 'jetpack' ),
__( 'Security', 'jetpack' ),
'manage_options',
'https://wordpress.com/settings/security/' . $this->domain,
null,
2
);
}
add_submenu_page( 'options-general.php', esc_attr__( 'Hosting Configuration', 'jetpack' ), __( 'Hosting Configuration', 'jetpack' ), 'manage_options', 'https://wordpress.com/hosting-config/' . $this->domain, null, 11 );
// Page Optimize is active by default on all Atomic sites and registers a Settings > Performance submenu which
// would conflict with our own Settings > Performance that links to Calypso, so we hide it it since the Calypso
// performance settings already have a link to Page Optimize settings page.
$this->hide_submenu_page( 'options-general.php', 'page-optimize' );
// Hide Settings > Performance when the interface is set to wp-admin.
// This is due to these settings are mostly also available in Jetpack > Settings, in the Performance tab.
if ( get_option( 'wpcom_admin_interface' ) === 'wp-admin' ) {
$this->hide_submenu_page( 'options-general.php', 'https://wordpress.com/settings/performance/' . $this->domain );
}
}
/**
* Adds Tools menu entries.
*/
public function add_tools_menu() {
parent::add_tools_menu();
// Link the Tools menu to Available Tools when the interface is set to wp-admin.
if ( get_option( 'wpcom_admin_interface' ) === 'wp-admin' ) {
add_submenu_page( 'tools.php', esc_attr__( 'Available Tools', 'jetpack' ), __( 'Available Tools', 'jetpack' ), 'edit_posts', 'tools.php', null, 0 );
}
/**
* Adds the WordPress.com Site Monitoring submenu under the main Tools menu.
*/
add_submenu_page( 'tools.php', esc_attr__( 'Site Monitoring', 'jetpack' ), __( 'Site Monitoring', 'jetpack' ), 'manage_options', 'https://wordpress.com/site-monitoring/' . $this->domain, null, 7 );
/**
* Adds the WordPress.com GitHub Deployments submenu under the main Tools menu.
*/
add_submenu_page( 'tools.php', esc_attr__( 'GitHub Deployments', 'jetpack' ), __( 'GitHub Deployments', 'jetpack' ), 'manage_options', 'https://wordpress.com/github-deployments/' . $this->domain, null, 8 );
}
/**
* Override the global submenu_file for theme-install.php page so the WP Admin menu item gets highlighted correctly.
*
* @param string $submenu_file The current pages $submenu_file global variable value.
* @return string | null
*/
public function override_the_theme_installer( $submenu_file ) {
global $pagenow;
if ( 'themes.php' === $submenu_file && 'theme-install.php' === $pagenow ) {
return null;
}
return $submenu_file;
}
/**
* Also remove the Gutenberg plugin menu.
*/
public function remove_gutenberg_menu() {
// Always remove the Gutenberg menu.
remove_menu_page( 'gutenberg' );
}
/**
* Saves the sidebar state ( expanded / collapsed ) via an ajax request.
*/
public function ajax_sidebar_state() {
$expanded = isset( $_REQUEST['expanded'] ) ? filter_var( wp_unslash( $_REQUEST['expanded'] ), FILTER_VALIDATE_BOOLEAN ) : false; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
Client::wpcom_json_api_request_as_user(
'/me/preferences',
'2',
array(
'method' => 'POST',
),
(object) array( 'calypso_preferences' => (object) array( 'sidebarCollapsed' => ! $expanded ) ),
'wpcom'
);
wp_die();
}
/**
* Handle ajax requests to dismiss a just-in-time-message
*/
public function wp_ajax_jitm_dismiss() {
check_ajax_referer( 'jitm_dismiss' );
$jitm = \Automattic\Jetpack\JITMS\JITM::get_instance();
if ( isset( $_REQUEST['id'] ) && isset( $_REQUEST['feature_class'] ) ) {
$jitm->dismiss( sanitize_text_field( wp_unslash( $_REQUEST['id'] ) ), sanitize_text_field( wp_unslash( $_REQUEST['feature_class'] ) ) );
}
wp_die();
}
/**
* Adds a notice above each settings page while using the Classic view to indicate
* that the Default view offers more features. Links to the default view.
*
* @return void
*/
public function add_settings_page_notice() {
if ( ! is_admin() ) {
return;
}
$current_screen = get_current_screen();
if ( ! $current_screen instanceof \WP_Screen ) {
return;
}
// Show the notice for the following screens and map them to the Calypso page.
$screen_map = array(
'options-general' => 'general',
'options-reading' => 'reading',
);
$mapped_screen = isset( $screen_map[ $current_screen->id ] )
? $screen_map[ $current_screen->id ]
: false;
if ( ! $mapped_screen ) {
return;
}
$switch_url = sprintf( 'https://wordpress.com/settings/%s/%s', $mapped_screen, $this->domain );
// Close over the $switch_url variable.
$admin_notices = function () use ( $switch_url ) {
wp_admin_notice(
wp_kses(
sprintf(
// translators: %s is a link to the Calypso settings page.
__( 'You are currently using the Classic view, which doesn’t offer the same set of features as the Default view. To access additional settings and features, switch to the Default view. ', 'jetpack' ),
esc_url( $switch_url )
),
array( 'a' => array( 'href' => array() ) )
),
array(
'type' => 'warning',
)
);
};
add_action( 'admin_notices', $admin_notices );
}
}