2021-04-27 08:32:47 +02:00
< ? php
/**
* WP . com Admin Menu file .
*
* @ package automattic / jetpack
*/
namespace Automattic\Jetpack\Dashboard_Customizations ;
2023-04-26 17:39:43 +02:00
use Automattic\Jetpack\Status ;
2023-09-26 10:24:36 +02:00
use Jetpack_Custom_CSS ;
2021-07-23 11:58:50 +02:00
use JITM ;
2021-04-27 08:32:47 +02:00
require_once __DIR__ . '/class-admin-menu.php' ;
/**
* Class WPcom_Admin_Menu .
*/
class WPcom_Admin_Menu extends Admin_Menu {
2022-04-02 10:26:41 +02:00
/**
* Holds the current plan , set by get_current_plan () .
*
* @ var array
*/
private $current_plan = array ();
2021-04-27 08:32:47 +02:00
/**
2021-07-23 11:58:50 +02:00
* WPcom_Admin_Menu constructor .
2021-04-27 08:32:47 +02:00
*/
2021-07-23 11:58:50 +02:00
protected function __construct () {
parent :: __construct ();
2021-04-27 08:32:47 +02:00
2021-07-23 11:58:50 +02:00
add_action ( 'wp_ajax_sidebar_state' , array ( $this , 'ajax_sidebar_state' ) );
2022-04-02 10:26:41 +02:00
add_action ( 'wp_ajax_jitm_dismiss' , array ( $this , 'wp_ajax_jitm_dismiss' ) );
2022-06-16 14:01:47 +02:00
add_action ( 'wp_ajax_upsell_nudge_jitm' , array ( $this , 'wp_ajax_upsell_nudge_jitm' ) );
2021-07-23 11:58:50 +02:00
add_action ( 'admin_init' , array ( $this , 'sync_sidebar_collapsed_state' ) );
add_action ( 'admin_menu' , array ( $this , 'remove_submenus' ), 140 ); // After hookpress hook at 130.
2021-04-27 08:32:47 +02:00
}
/**
* Create the desired menu output .
*/
public function reregister_menu_items () {
parent :: reregister_menu_items ();
$this -> add_my_home_menu ();
2023-09-26 10:24:36 +02:00
$this -> add_my_mailboxes_menu ();
2023-05-23 23:18:12 +02:00
$this -> remove_gutenberg_menu ();
2021-04-27 08:32:47 +02:00
// 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 ();
}
2022-04-02 10:26:41 +02:00
$this -> add_woocommerce_installation_menu ( $this -> get_current_plan () );
2021-09-07 21:40:48 +02:00
2021-04-27 08:32:47 +02:00
ksort ( $GLOBALS [ 'menu' ] );
}
2021-07-23 11:58:50 +02:00
/**
* 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 ) {
// When no preferred view has been set for Themes, keep the previous behavior that forced the default view
// regardless of the global preference.
if ( $fallback_global_preference && 'themes.php' === $screen ) {
$preferred_view = parent :: get_preferred_view ( $screen , false );
if ( self :: UNKNOWN_VIEW === $preferred_view ) {
return self :: DEFAULT_VIEW ;
}
return $preferred_view ;
}
// Plugins on Simple sites are always managed on Calypso.
if ( 'plugins.php' === $screen ) {
return self :: DEFAULT_VIEW ;
}
return parent :: get_preferred_view ( $screen , $fallback_global_preference );
}
2022-06-16 14:01:47 +02:00
/**
* Retrieve the number of blogs that the current user has .
*
* @ return int
*/
public function get_current_user_blog_count () {
if ( function_exists ( '\get_blog_count_for_user' ) ) {
return \get_blog_count_for_user ( get_current_user_id () );
}
2023-09-26 10:24:36 +02:00
$blogs = get_blogs_of_user ( get_current_user_id () );
return is_countable ( $blogs ) ? count ( $blogs ) : 0 ;
2022-06-16 14:01:47 +02:00
}
2021-04-27 08:32:47 +02:00
/**
* Adds the site switcher link if user has more than one site .
*/
public function add_browse_sites_link () {
2022-06-16 14:01:47 +02:00
if ( $this -> get_current_user_blog_count () < 2 ) {
2021-04-27 08:32:47 +02:00
return ;
}
// Add the menu item.
2022-12-15 17:41:53 +01:00
add_menu_page ( __ ( 'site-switcher' , 'jetpack' ), __ ( 'Browse sites' , 'jetpack' ), 'read' , 'https://wordpress.com/sites' , null , 'dashicons-arrow-left-alt2' , 0 );
2021-04-27 08:32:47 +02:00
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 () {
2022-06-16 14:01:47 +02:00
if ( $this -> get_current_user_blog_count () > 1 ) {
2021-04-27 08:32:47 +02:00
return ;
}
$this -> add_admin_menu_separator ();
2021-07-23 11:58:50 +02:00
add_menu_page ( __ ( 'Add New Site' , 'jetpack' ), __ ( 'Add New Site' , 'jetpack' ), 'read' , 'https://wordpress.com/start?ref=calypso-sidebar' , null , 'dashicons-plus-alt' );
2021-04-27 08:32:47 +02:00
}
/**
* Adds site card component .
*/
public function add_site_card_menu () {
2023-04-26 17:39:43 +02:00
$default = plugins_url ( 'globe-icon.svg' , __FILE__ );
$icon = get_site_icon_url ( 32 , $default );
$blog_name = get_option ( 'blogname' ) !== '' ? get_option ( 'blogname' ) : $this -> domain ;
$status = new Status ();
$is_private_site = $status -> is_private_site ();
$is_coming_soon = $status -> is_coming_soon ();
2021-04-27 08:32:47 +02:00
if ( $default === $icon && blavatar_exists ( $this -> domain ) ) {
$icon = blavatar_url ( $this -> domain , 'img' , 32 );
}
$badge = '' ;
2023-04-26 17:39:43 +02:00
if ( $is_private_site || $is_coming_soon ) {
2021-04-27 08:32:47 +02:00
$badge .= sprintf (
'<span class="site__badge site__badge-private">%s</span>' ,
2021-08-17 08:33:07 +02:00
$is_coming_soon ? esc_html__ ( 'Coming Soon' , 'jetpack' ) : esc_html__ ( 'Private' , 'jetpack' )
2021-04-27 08:32:47 +02:00
);
}
2021-07-23 11:58:50 +02:00
if ( function_exists ( 'is_simple_site_redirect' ) && is_simple_site_redirect ( $this -> domain ) ) {
2021-04-27 08:32:47 +02:00
$badge .= '<span class="site__badge site__badge-redirect">' . esc_html__ ( 'Redirect' , 'jetpack' ) . '</span>' ;
}
if ( ! empty ( get_option ( 'options' )[ 'is_domain_only' ] ) ) {
$badge .= '<span class="site__badge site__badge-domain-only">' . esc_html__ ( 'Domain' , 'jetpack' ) . '</span>' ;
}
$site_card = '
< div class = " site__info " >
< div class = " site__title " >% 1 $s </ div >
< div class = " site__domain " >% 2 $s </ div >
% 3 $s
</ div > ' ;
$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' ;
if ( blavatar_exists ( $this -> domain ) ) {
$classes .= ' has-site-icon' ;
}
$menu [ $key ][ 4 ] = $menu_item [ 4 ] . $classes ;
$menu [ $key ][ 5 ] = 'toplevel_page_site_card' ;
break ;
}
return $menu ;
}
2021-07-23 11:58:50 +02:00
/**
* Returns the first available upsell nudge .
*
* @ return array
*/
public function get_upsell_nudge () {
require_lib ( 'jetpack-jitm/jitm-engine' );
$jitm_engine = new JITM\Engine ();
$message_path = 'calypso:sites:sidebar_notice' ;
$current_user = wp_get_current_user ();
$user_id = $current_user -> ID ;
$user_roles = implode ( ',' , $current_user -> roles );
$query_string = array (
'message_path' => $message_path ,
);
// Get the top message only.
$message = $jitm_engine -> get_top_messages ( $message_path , $user_id , $user_roles , $query_string );
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' ],
2022-04-02 10:26:41 +02:00
'dismissible' => $message -> is_dismissible ,
'feature_class' => $message -> feature_class ,
'id' => $message -> id ,
2021-07-23 11:58:50 +02:00
);
}
}
2021-04-27 08:32:47 +02:00
/**
* Adds Stats menu .
*/
public function add_stats_menu () {
$menu_title = __ ( 'Stats' , 'jetpack' );
if ( ! $this -> is_api_request ) {
$menu_title .= sprintf (
'<img class="sidebar-unified__sparkline" width="80" height="20" src="%1$s" alt="%2$s">' ,
esc_url ( site_url ( 'wp-includes/charts/admin-bar-hours-scale-2x.php?masterbar=1&s=' . get_current_blog_id () ) ),
esc_attr__ ( 'Hourly views' , 'jetpack' )
);
}
add_menu_page ( __ ( 'Stats' , 'jetpack' ), $menu_title , 'edit_posts' , 'https://wordpress.com/stats/day/' . $this -> domain , null , 'dashicons-chart-bar' , 3 );
}
2022-04-02 10:26:41 +02:00
/**
* Gets the current plan and stores it in $this -> current_plan so the database is only called once per request .
*
* @ return array
*/
private function get_current_plan () {
if ( empty ( $this -> current_plan ) && class_exists ( 'WPCOM_Store_API' ) ) {
$this -> current_plan = \WPCOM_Store_API :: get_current_plan ( get_current_blog_id () );
}
return $this -> current_plan ;
}
2021-04-27 08:32:47 +02:00
/**
* Adds Upgrades menu .
2021-07-23 11:58:50 +02:00
*
* @ param string $plan The current WPCOM plan of the blog .
2021-04-27 08:32:47 +02:00
*/
2021-07-23 11:58:50 +02:00
public function add_upgrades_menu ( $plan = null ) {
2022-04-02 10:26:41 +02:00
$current_plan = $this -> get_current_plan ();
if ( ! empty ( $current_plan [ 'product_name_short' ] ) ) {
$plan = $current_plan [ 'product_name_short' ];
2021-07-23 11:58:50 +02:00
}
2022-04-02 10:26:41 +02:00
2021-07-23 11:58:50 +02:00
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 );
2021-04-27 08:32:47 +02:00
2021-07-23 11:58:50 +02:00
/** This filter is already documented in modules/masterbar/admin-menu/class-atomic-admin-menu.php */
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 );
}
2022-12-15 17:41:53 +01:00
if ( defined ( 'WPCOM_ENABLE_ADD_ONS_MENU_ITEM' ) && WPCOM_ENABLE_ADD_ONS_MENU_ITEM ) {
add_submenu_page ( 'paid-upgrades.php' , __ ( 'Add-Ons' , 'jetpack' ), __ ( 'Add-Ons' , 'jetpack' ), 'manage_options' , 'https://wordpress.com/add-ons/' . $this -> domain , null , 1 );
}
2021-04-27 08:32:47 +02:00
}
/**
* Adds Appearance menu .
*/
2021-07-23 11:58:50 +02:00
public function add_appearance_menu () {
$customize_url = parent :: add_appearance_menu ();
2021-04-27 08:32:47 +02:00
2021-07-23 11:58:50 +02:00
$this -> hide_submenu_page ( 'themes.php' , 'theme-editor.php' );
2021-04-27 08:32:47 +02:00
$user_can_customize = current_user_can ( 'customize' );
2023-09-26 10:24:36 +02:00
if ( wp_is_block_theme () ) {
add_filter ( 'safecss_is_freetrial' , '__return_false' , PHP_INT_MAX );
if ( class_exists ( 'Jetpack_Custom_CSS' ) && empty ( Jetpack_Custom_CSS :: get_css () ) ) {
$user_can_customize = false ;
}
remove_filter ( 'safecss_is_freetrial' , '__return_false' , PHP_INT_MAX );
}
2021-04-27 08:32:47 +02:00
if ( $user_can_customize ) {
2021-07-23 11:58:50 +02:00
$customize_custom_css_url = add_query_arg ( array ( 'autofocus' => array ( 'section' => 'jetpack_custom_css' ) ), $customize_url );
add_submenu_page ( 'themes.php' , esc_attr__ ( 'Additional CSS' , 'jetpack' ), __ ( 'Additional CSS' , 'jetpack' ), 'customize' , esc_url ( $customize_custom_css_url ), null , 20 );
2021-04-27 08:32:47 +02:00
}
}
/**
* Adds Users menu .
*/
2021-07-23 11:58:50 +02:00
public function add_users_menu () {
$submenus_to_update = array (
'grofiles-editor' => 'https://wordpress.com/me' ,
'grofiles-user-settings' => 'https://wordpress.com/me/account' ,
);
if ( self :: DEFAULT_VIEW === $this -> get_preferred_view ( 'users.php' ) ) {
$submenus_to_update [ 'users.php' ] = 'https://wordpress.com/people/team/' . $this -> domain ;
2021-04-27 08:32:47 +02:00
}
2021-07-23 11:58:50 +02:00
$slug = current_user_can ( 'list_users' ) ? 'users.php' : 'profile.php' ;
$this -> update_submenus ( $slug , $submenus_to_update );
add_submenu_page ( 'users.php' , esc_attr__ ( 'Add New' , 'jetpack' ), __ ( 'Add New' , 'jetpack' ), 'promote_users' , 'https://wordpress.com/people/new/' . $this -> domain , null , 1 );
2023-09-26 10:24:36 +02:00
add_submenu_page ( 'users.php' , esc_attr__ ( 'Subscribers' , 'jetpack' ), __ ( 'Subscribers' , 'jetpack' ), 'list_users' , 'https://wordpress.com/subscribers/' . $this -> domain , null , 3 );
2021-04-27 08:32:47 +02:00
}
/**
* Adds Settings menu .
*/
2021-07-23 11:58:50 +02:00
public function add_options_menu () {
parent :: add_options_menu ();
2021-04-27 08:32:47 +02:00
2021-07-23 11:58:50 +02:00
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 );
2021-04-27 08:32:47 +02:00
}
/**
* Also remove the Gutenberg plugin menu .
*/
2023-05-23 23:18:12 +02:00
public function remove_gutenberg_menu () {
2021-04-27 08:32:47 +02:00
// Always remove the Gutenberg menu.
remove_menu_page ( 'gutenberg' );
}
/**
* Whether to use wp - admin pages rather than Calypso .
*
* @ return bool
*/
public function should_link_to_wp_admin () {
$result = false ; // Calypso.
$user_attribute = get_user_attribute ( get_current_user_id (), 'calypso_preferences' );
if ( ! empty ( $user_attribute [ 'linkDestination' ] ) ) {
$result = $user_attribute [ 'linkDestination' ];
}
return $result ;
}
/**
* Adds Plugins menu .
*/
2021-07-23 11:58:50 +02:00
public function add_plugins_menu () {
2021-04-27 08:32:47 +02:00
// TODO: Remove wpcom_menu (/wp-content/admin-plugins/wpcom-misc.php).
$count = '' ;
if ( ! is_multisite () && current_user_can ( 'update_plugins' ) ) {
$update_data = wp_get_update_data ();
$count = sprintf (
'<span class="update-plugins count-%s"><span class="plugin-count">%s</span></span>' ,
$update_data [ 'counts' ][ 'plugins' ],
number_format_i18n ( $update_data [ 'counts' ][ 'plugins' ] )
);
}
/* translators: %s: Number of pending plugin updates. */
add_menu_page ( esc_attr__ ( 'Plugins' , 'jetpack' ), sprintf ( __ ( 'Plugins %s' , 'jetpack' ), $count ), 'activate_plugins' , 'plugins.php' , null , 'dashicons-admin-plugins' , 65 );
2021-07-23 11:58:50 +02:00
parent :: add_plugins_menu ();
}
/**
* Saves the sidebar state ( expanded / collapsed ) via an ajax request .
*/
public function ajax_sidebar_state () {
2022-06-16 14:01:47 +02:00
$expanded = isset ( $_REQUEST [ 'expanded' ] ) ? filter_var ( wp_unslash ( $_REQUEST [ 'expanded' ] ), FILTER_VALIDATE_BOOLEAN ) : false ; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
2021-07-23 11:58:50 +02:00
$user_id = get_current_user_id ();
$preferences = get_user_attribute ( $user_id , 'calypso_preferences' );
if ( empty ( $preferences ) ) {
$preferences = array ();
}
$value = array_merge ( ( array ) $preferences , array ( 'sidebarCollapsed' => ! $expanded ) );
$value = array_filter (
$value ,
function ( $preference ) {
return null !== $preference ;
}
);
update_user_attribute ( $user_id , 'calypso_preferences' , $value );
die ();
}
2022-04-02 10:26:41 +02:00
/**
* Handle ajax requests to dismiss a just - in - time - message
*/
public function wp_ajax_jitm_dismiss () {
check_ajax_referer ( 'jitm_dismiss' );
require_lib ( 'jetpack-jitm/jitm-engine' );
2022-06-16 14:01:47 +02:00
if ( isset ( $_REQUEST [ 'id' ] ) && isset ( $_REQUEST [ 'feature_class' ] ) ) {
JITM\Engine :: dismiss ( sanitize_text_field ( wp_unslash ( $_REQUEST [ 'id' ] ) ), sanitize_text_field ( wp_unslash ( $_REQUEST [ 'feature_class' ] ) ) );
}
2022-04-02 10:26:41 +02:00
wp_die ();
}
2021-07-23 11:58:50 +02:00
/**
* Syncs the sidebar collapsed state from Calypso Preferences .
*/
public function sync_sidebar_collapsed_state () {
$calypso_preferences = get_user_attribute ( get_current_user_id (), 'calypso_preferences' );
$sidebar_collapsed = isset ( $calypso_preferences [ 'sidebarCollapsed' ] ) ? $calypso_preferences [ 'sidebarCollapsed' ] : false ;
2022-12-15 17:41:53 +01:00
// Read the current stored setting and convert it to boolean in order to be able to compare the values later.
$current_sidebar_collapsed_setting = ( 'f' === get_user_setting ( 'mfold' ) ) ? true : false ;
// Only set the setting if the value differs, as `set_user_setting` always updates at least the timestamp
// which leads to unnecessary user meta cache purging on all wp-admin screen requests.
if ( $current_sidebar_collapsed_setting !== $sidebar_collapsed ) {
set_user_setting ( 'mfold' , $sidebar_collapsed ? 'f' : 'o' );
}
2021-07-23 11:58:50 +02:00
}
/**
* Removes unwanted submenu items .
*
* These submenus are added across wp - content and should be removed together with these function calls .
*/
public function remove_submenus () {
global $_registered_pages ;
remove_submenu_page ( 'index.php' , 'akismet-stats' );
remove_submenu_page ( 'index.php' , 'my-comments' );
remove_submenu_page ( 'index.php' , 'stats' );
remove_submenu_page ( 'index.php' , 'subscriptions' );
/* @see https://github.com/Automattic/wp-calypso/issues/49210 */
remove_submenu_page ( 'index.php' , 'my-blogs' );
$_registered_pages [ 'admin_page_my-blogs' ] = true ; // phpcs:ignore
remove_submenu_page ( 'paid-upgrades.php' , 'premium-themes' );
remove_submenu_page ( 'paid-upgrades.php' , 'domains' );
remove_submenu_page ( 'paid-upgrades.php' , 'my-upgrades' );
remove_submenu_page ( 'paid-upgrades.php' , 'billing-history' );
remove_submenu_page ( 'themes.php' , 'customize.php?autofocus[panel]=amp_panel&return=' . rawurlencode ( admin_url () ) );
remove_submenu_page ( 'users.php' , 'wpcom-invite-users' ); // Wpcom_Invite_Users::action_admin_menu.
remove_submenu_page ( 'options-general.php' , 'adcontrol' );
// Remove menu item but continue allowing access.
foreach ( array ( 'openidserver' , 'webhooks' ) as $page_slug ) {
remove_submenu_page ( 'options-general.php' , $page_slug );
$_registered_pages [ 'admin_page_' . $page_slug ] = true ; // phpcs:ignore
}
2021-04-27 08:32:47 +02:00
}
}