masterbar.php 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026
  1. <?php
  2. require_once dirname( __FILE__ ) . '/rtl-admin-bar.php';
  3. class A8C_WPCOM_Masterbar {
  4. /**
  5. * Use for testing changes made to remotely enqueued scripts and styles on your sandbox.
  6. * If not set it will default to loading the ones from WordPress.com.
  7. *
  8. * @var string $sandbox_url
  9. */
  10. private $sandbox_url = '';
  11. private $locale;
  12. private $user_id;
  13. private $user_data;
  14. private $user_login;
  15. private $user_email;
  16. private $display_name;
  17. private $primary_site_slug;
  18. private $user_text_direction;
  19. private $user_site_count;
  20. function __construct() {
  21. $this->locale = $this->get_locale();
  22. $this->user_id = get_current_user_id();
  23. // Limit the masterbar to be shown only to connected Jetpack users.
  24. if ( ! Jetpack::is_user_connected( $this->user_id ) ) {
  25. return;
  26. }
  27. Jetpack::dns_prefetch( array(
  28. '//s0.wp.com',
  29. '//s1.wp.com',
  30. '//s2.wp.com',
  31. '//0.gravatar.com',
  32. '//1.gravatar.com',
  33. '//2.gravatar.com',
  34. ) );
  35. // Atomic only
  36. if ( jetpack_is_atomic_site() ) {
  37. // override user setting that hides masterbar from site's front.
  38. // https://github.com/Automattic/jetpack/issues/7667
  39. add_filter( 'show_admin_bar', '__return_true' );
  40. }
  41. $this->user_data = Jetpack::get_connected_user_data( $this->user_id );
  42. $this->user_login = $this->user_data['login'];
  43. $this->user_email = $this->user_data['email'];
  44. $this->display_name = $this->user_data['display_name'];
  45. $this->user_site_count = $this->user_data['site_count'];
  46. // Used to build menu links that point directly to Calypso.
  47. $this->primary_site_slug = Jetpack::build_raw_urls( get_home_url() );
  48. // Used for display purposes and for building WP Admin links.
  49. $this->primary_site_url = str_replace( '::', '/', $this->primary_site_slug );
  50. // We need to use user's setting here, instead of relying on current blog's text direction
  51. $this->user_text_direction = $this->user_data['text_direction'];
  52. if ( $this->is_rtl() ) {
  53. // Extend core WP_Admin_Bar class in order to add rtl styles
  54. add_filter( 'wp_admin_bar_class', array( $this, 'get_rtl_admin_bar_class' ) );
  55. }
  56. add_filter( 'admin_body_class', array( $this, 'admin_body_class' ) );
  57. add_action( 'wp_before_admin_bar_render', array( $this, 'replace_core_masterbar' ), 99999 );
  58. add_action( 'wp_enqueue_scripts', array( $this, 'add_styles_and_scripts' ) );
  59. add_action( 'admin_enqueue_scripts', array( $this, 'add_styles_and_scripts' ) );
  60. add_action( 'wp_enqueue_scripts', array( $this, 'remove_core_styles' ) );
  61. add_action( 'admin_enqueue_scripts', array( $this, 'remove_core_styles' ) );
  62. if ( Jetpack::is_module_active( 'notes' ) && $this->is_rtl() ) {
  63. // Override Notification module to include RTL styles
  64. add_action( 'a8c_wpcom_masterbar_enqueue_rtl_notification_styles', '__return_true' );
  65. }
  66. add_action( 'wp_logout', array( $this, 'maybe_logout_user_from_wpcom' ) );
  67. }
  68. public function maybe_logout_user_from_wpcom() {
  69. /**
  70. * Whether we should sign out from wpcom too when signing out from the masterbar.
  71. *
  72. * @since 5.9.0
  73. *
  74. * @param bool $masterbar_should_logout_from_wpcom True by default.
  75. */
  76. $masterbar_should_logout_from_wpcom = apply_filters( 'jetpack_masterbar_should_logout_from_wpcom', true );
  77. if (
  78. isset( $_GET['context'] ) &&
  79. 'masterbar' === $_GET['context'] &&
  80. $masterbar_should_logout_from_wpcom
  81. ) {
  82. do_action( 'wp_masterbar_logout' );
  83. }
  84. }
  85. public function get_rtl_admin_bar_class() {
  86. return 'RTL_Admin_Bar';
  87. }
  88. /**
  89. * Adds CSS classes to admin body tag.
  90. *
  91. * @since 5.1
  92. *
  93. * @param string $admin_body_classes CSS classes that will be added.
  94. *
  95. * @return string
  96. */
  97. public function admin_body_class( $admin_body_classes ) {
  98. return "$admin_body_classes jetpack-masterbar";
  99. }
  100. public function remove_core_styles() {
  101. wp_dequeue_style( 'admin-bar' );
  102. }
  103. public function is_rtl() {
  104. return $this->user_text_direction === 'rtl' ? true : false;
  105. }
  106. public function add_styles_and_scripts() {
  107. if ( $this->is_rtl() ) {
  108. wp_enqueue_style( 'a8c-wpcom-masterbar-rtl', $this->wpcom_static_url( '/wp-content/mu-plugins/admin-bar/rtl/wpcom-admin-bar-rtl.css' ), array(), JETPACK__VERSION );
  109. wp_enqueue_style( 'a8c-wpcom-masterbar-overrides-rtl', $this->wpcom_static_url( '/wp-content/mu-plugins/admin-bar/masterbar-overrides/rtl/masterbar-rtl.css' ), array(), JETPACK__VERSION );
  110. } else {
  111. wp_enqueue_style( 'a8c-wpcom-masterbar', $this->wpcom_static_url( '/wp-content/mu-plugins/admin-bar/wpcom-admin-bar.css' ), array(), JETPACK__VERSION );
  112. wp_enqueue_style( 'a8c-wpcom-masterbar-overrides', $this->wpcom_static_url( '/wp-content/mu-plugins/admin-bar/masterbar-overrides/masterbar.css' ), array(), JETPACK__VERSION );
  113. }
  114. // Local overrides
  115. wp_enqueue_style( 'a8c_wpcom_css_override', plugins_url( 'overrides.css', __FILE__ ), array(), JETPACK__VERSION );
  116. if ( ! Jetpack::is_module_active( 'notes ' ) ) {
  117. // Masterbar is relying on some icons from noticons.css
  118. wp_enqueue_style( 'noticons', $this->wpcom_static_url( '/i/noticons/noticons.css' ), array(), JETPACK__VERSION . '-' . gmdate( 'oW' ) );
  119. }
  120. wp_enqueue_script(
  121. 'jetpack-accessible-focus',
  122. Jetpack::get_file_url_for_environment( '_inc/build/accessible-focus.min.js', '_inc/accessible-focus.js' ),
  123. array(),
  124. JETPACK__VERSION
  125. );
  126. wp_enqueue_script(
  127. 'a8c_wpcom_masterbar_tracks_events',
  128. Jetpack::get_file_url_for_environment(
  129. '_inc/build/masterbar/tracks-events.min.js',
  130. 'modules/masterbar/tracks-events.js'
  131. ),
  132. array( 'jquery' ),
  133. JETPACK__VERSION
  134. );
  135. wp_enqueue_script( 'a8c_wpcom_masterbar_overrides', $this->wpcom_static_url( '/wp-content/mu-plugins/admin-bar/masterbar-overrides/masterbar.js' ), array( 'jquery' ), JETPACK__VERSION );
  136. }
  137. function wpcom_static_url( $file ) {
  138. if ( ! empty( $this->sandbox_url ) ) {
  139. // For testing undeployed changes to remotely enqueued scripts and styles.
  140. return set_url_scheme( $this->sandbox_url . $file, 'https');
  141. }
  142. $i = hexdec( substr( md5( $file ), - 1 ) ) % 2;
  143. $url = 'https://s' . $i . '.wp.com' . $file;
  144. return set_url_scheme( $url, 'https');
  145. }
  146. public function replace_core_masterbar() {
  147. global $wp_admin_bar;
  148. if ( ! is_object( $wp_admin_bar ) ) {
  149. return false;
  150. }
  151. $this->clear_core_masterbar( $wp_admin_bar );
  152. $this->build_wpcom_masterbar( $wp_admin_bar );
  153. }
  154. // Remove all existing toolbar entries from core Masterbar
  155. public function clear_core_masterbar( $wp_admin_bar ) {
  156. foreach ( $wp_admin_bar->get_nodes() as $node ) {
  157. $wp_admin_bar->remove_node( $node->id );
  158. }
  159. }
  160. // Add entries corresponding to WordPress.com Masterbar
  161. public function build_wpcom_masterbar( $wp_admin_bar ) {
  162. // Menu groups
  163. $this->wpcom_adminbar_add_secondary_groups( $wp_admin_bar );
  164. // Left part
  165. $this->add_my_sites_submenu( $wp_admin_bar );
  166. $this->add_reader_submenu( $wp_admin_bar );
  167. // Right part
  168. if ( Jetpack::is_module_active( 'notes' ) ) {
  169. $this->add_notifications( $wp_admin_bar );
  170. }
  171. $this->add_me_submenu( $wp_admin_bar );
  172. $this->add_write_button( $wp_admin_bar );
  173. }
  174. public function get_locale() {
  175. $wpcom_locale = get_locale();
  176. if ( ! class_exists( 'GP_Locales' ) ) {
  177. if ( defined( 'JETPACK__GLOTPRESS_LOCALES_PATH' ) && file_exists( JETPACK__GLOTPRESS_LOCALES_PATH ) ) {
  178. require JETPACK__GLOTPRESS_LOCALES_PATH;
  179. }
  180. }
  181. if ( class_exists( 'GP_Locales' ) ) {
  182. $wpcom_locale_object = GP_Locales::by_field( 'wp_locale', get_locale() );
  183. if ( $wpcom_locale_object instanceof GP_Locale ) {
  184. $wpcom_locale = $wpcom_locale_object->slug;
  185. }
  186. }
  187. return $wpcom_locale;
  188. }
  189. public function add_notifications( $wp_admin_bar ) {
  190. $wp_admin_bar->add_node( array(
  191. 'id' => 'notes',
  192. 'title' => '<span id="wpnt-notes-unread-count" class="wpnt-loading wpn-read"></span>
  193. <span class="screen-reader-text">' . esc_html__( 'Notifications', 'jetpack' ) . '</span>
  194. <span class="noticon noticon-bell"></span>',
  195. 'meta' => array(
  196. 'html' => '<div id="wpnt-notes-panel2" style="display:none" lang="'. esc_attr( $this->locale ) . '" dir="' . ( $this->is_rtl() ? 'rtl' : 'ltr' ) . '">' .
  197. '<div class="wpnt-notes-panel-header">' .
  198. '<span class="wpnt-notes-header">' .
  199. esc_html__( 'Notifications', 'jetpack' ) .
  200. '</span>' .
  201. '<span class="wpnt-notes-panel-link">' .
  202. '</span>' .
  203. '</div>' .
  204. '</div>',
  205. 'class' => 'menupop mb-trackable',
  206. ),
  207. 'parent' => 'top-secondary',
  208. ) );
  209. }
  210. public function add_reader_submenu( $wp_admin_bar ) {
  211. $wp_admin_bar->add_menu( array(
  212. 'parent' => 'root-default',
  213. 'id' => 'newdash',
  214. 'title' => esc_html__( 'Reader', 'jetpack' ),
  215. 'href' => '#',
  216. 'meta' => array(
  217. 'class' => 'mb-trackable',
  218. )
  219. ) );
  220. $wp_admin_bar->add_menu( array(
  221. 'parent' => 'newdash',
  222. 'id' => 'streams-header',
  223. 'title' => esc_html_x(
  224. 'Streams',
  225. 'Title for Reader sub-menu that contains followed sites, likes, and recommendations',
  226. 'jetpack'
  227. ),
  228. 'meta' => array(
  229. 'class' => 'ab-submenu-header',
  230. )
  231. ) );
  232. $following_title = $this->create_menu_item_pair(
  233. array(
  234. 'url' => 'https://wordpress.com/',
  235. 'id' => 'wp-admin-bar-followed-sites',
  236. 'label' => esc_html__( 'Followed Sites', 'jetpack' ),
  237. ),
  238. array(
  239. 'url' => 'https://wordpress.com/following/edit',
  240. 'id' => 'wp-admin-bar-reader-followed-sites-manage',
  241. 'label' => esc_html__( 'Manage', 'jetpack' ),
  242. )
  243. );
  244. $wp_admin_bar->add_menu( array(
  245. 'parent' => 'newdash',
  246. 'id' => 'following',
  247. 'title' => $following_title,
  248. 'meta' => array( 'class' => 'inline-action' )
  249. ) );
  250. $wp_admin_bar->add_menu( array(
  251. 'parent' => 'newdash',
  252. 'id' => 'discover-discover',
  253. 'title' => esc_html__( 'Discover', 'jetpack' ),
  254. 'href' => 'https://wordpress.com/discover',
  255. 'meta' => array(
  256. 'class' => 'mb-icon-spacer',
  257. )
  258. ) );
  259. $wp_admin_bar->add_menu( array(
  260. 'parent' => 'newdash',
  261. 'id' => 'discover-search',
  262. 'title' => esc_html__( 'Search', 'jetpack' ),
  263. 'href' => 'https://wordpress.com/read/search',
  264. 'meta' => array(
  265. 'class' => 'mb-icon-spacer',
  266. )
  267. ) );
  268. $wp_admin_bar->add_menu( array(
  269. 'parent' => 'newdash',
  270. 'id' => 'discover-recommended-blogs',
  271. 'title' => esc_html__( 'Recommendations', 'jetpack' ),
  272. 'href' => 'https://wordpress.com/recommendations',
  273. 'meta' => array(
  274. 'class' => 'mb-icon-spacer',
  275. )
  276. ) );
  277. $wp_admin_bar->add_menu( array(
  278. 'parent' => 'newdash',
  279. 'id' => 'my-activity-my-likes',
  280. 'title' => esc_html__( 'My Likes', 'jetpack' ),
  281. 'href' => 'https://wordpress.com/activities/likes',
  282. 'meta' => array(
  283. 'class' => 'mb-icon-spacer',
  284. )
  285. ) );
  286. }
  287. public function create_menu_item_pair( $primary, $secondary ) {
  288. $primary_class = 'ab-item ab-primary mb-icon';
  289. $secondary_class = 'ab-secondary';
  290. $primary_anchor = $this->create_menu_item_anchor( $primary_class, $primary['url'], $primary['label'], $primary['id'] );
  291. $secondary_anchor = $this->create_menu_item_anchor( $secondary_class, $secondary['url'], $secondary['label'], $secondary['id'] );
  292. return $primary_anchor . $secondary_anchor;
  293. }
  294. public function create_menu_item_anchor( $class, $url, $label, $id ) {
  295. return '<a href="' . $url . '" class="' . $class . '" id="' . $id . '">' . $label . '</a>';
  296. }
  297. public function wpcom_adminbar_add_secondary_groups( $wp_admin_bar ) {
  298. $wp_admin_bar->add_group( array(
  299. 'id' => 'root-default',
  300. 'meta' => array(
  301. 'class' => 'ab-top-menu',
  302. ),
  303. ) );
  304. $wp_admin_bar->add_group( array(
  305. 'parent' => 'blog',
  306. 'id' => 'blog-secondary',
  307. 'meta' => array(
  308. 'class' => 'ab-sub-secondary',
  309. ),
  310. ) );
  311. $wp_admin_bar->add_group( array(
  312. 'id' => 'top-secondary',
  313. 'meta' => array(
  314. 'class' => 'ab-top-secondary',
  315. ),
  316. ) );
  317. }
  318. public function add_me_submenu( $wp_admin_bar ) {
  319. $user_id = get_current_user_id();
  320. if ( empty( $user_id ) ) {
  321. return;
  322. }
  323. $avatar = get_avatar( $this->user_email, 32, 'mm', '', array( 'force_display' => true ) );
  324. $class = empty( $avatar ) ? 'mb-trackable' : 'with-avatar mb-trackable';
  325. // Add the 'Me' menu
  326. $wp_admin_bar->add_menu( array(
  327. 'id' => 'my-account',
  328. 'parent' => 'top-secondary',
  329. 'title' => $avatar . '<span class="ab-text">' . esc_html__( 'Me', 'jetpack' ) . '</span>',
  330. 'href' => '#',
  331. 'meta' => array(
  332. 'class' => $class,
  333. ),
  334. ) );
  335. $id = 'user-actions';
  336. $wp_admin_bar->add_group( array(
  337. 'parent' => 'my-account',
  338. 'id' => $id,
  339. ) );
  340. $settings_url = 'https://wordpress.com/me/account';
  341. $logout_url = wp_logout_url();
  342. $logout_url = add_query_arg( 'context', 'masterbar', $logout_url );
  343. $user_info = get_avatar( $this->user_email, 128, 'mm', '', array( 'force_display' => true ) );
  344. $user_info .= '<span class="display-name">' . $this->display_name . '</span>';
  345. $user_info .= '<a class="username" href="http://gravatar.com/' . $this->user_login . '">@' . $this->user_login . '</a>';
  346. $user_info .= sprintf(
  347. '<div><a href="%s" class="ab-sign-out">%s</a></div>',
  348. $logout_url,
  349. esc_html__( 'Sign Out', 'jetpack' )
  350. );
  351. $wp_admin_bar->add_menu( array(
  352. 'parent' => $id,
  353. 'id' => 'user-info',
  354. 'title' => $user_info,
  355. 'meta' => array(
  356. 'class' => 'user-info user-info-item',
  357. 'tabindex' => -1,
  358. ),
  359. ) );
  360. $wp_admin_bar->add_menu( array(
  361. 'parent' => $id,
  362. 'id' => 'profile-header',
  363. 'title' => esc_html__( 'Profile', 'jetpack' ),
  364. 'meta' => array(
  365. 'class' => 'ab-submenu-header',
  366. ),
  367. ) );
  368. $wp_admin_bar->add_menu( array(
  369. 'parent' => $id,
  370. 'id' => 'my-profile',
  371. 'title' => esc_html__( 'My Profile', 'jetpack' ),
  372. 'href' => 'https://wordpress.com/me',
  373. 'meta' => array(
  374. 'class' => 'mb-icon',
  375. ),
  376. ) );
  377. $wp_admin_bar->add_menu( array(
  378. 'parent' => $id,
  379. 'id' => 'account-settings',
  380. 'title' => esc_html__( 'Account Settings', 'jetpack' ),
  381. 'href' => $settings_url,
  382. 'meta' => array(
  383. 'class' => 'mb-icon',
  384. ),
  385. ) );
  386. $wp_admin_bar->add_menu( array(
  387. 'parent' => $id,
  388. 'id' => 'billing',
  389. 'title' => esc_html__( 'Manage Purchases', 'jetpack' ),
  390. 'href' => 'https://wordpress.com/me/purchases',
  391. 'meta' => array(
  392. 'class' => 'mb-icon',
  393. ),
  394. ) );
  395. $wp_admin_bar->add_menu( array(
  396. 'parent' => $id,
  397. 'id' => 'security',
  398. 'title' => esc_html__( 'Security', 'jetpack' ),
  399. 'href' => 'https://wordpress.com/me/security',
  400. 'meta' => array(
  401. 'class' => 'mb-icon',
  402. ),
  403. ) );
  404. $wp_admin_bar->add_menu( array(
  405. 'parent' => $id,
  406. 'id' => 'notifications',
  407. 'title' => esc_html__( 'Notifications', 'jetpack' ),
  408. 'href' => 'https://wordpress.com/me/notifications',
  409. 'meta' => array(
  410. 'class' => 'mb-icon',
  411. ),
  412. ) );
  413. $wp_admin_bar->add_menu( array(
  414. 'parent' => $id,
  415. 'id' => 'special-header',
  416. 'title' => esc_html_x(
  417. 'Special',
  418. 'Title for Me sub-menu that contains Get Apps, Next Steps, and Help options',
  419. 'jetpack'
  420. ),
  421. 'meta' => array(
  422. 'class' => 'ab-submenu-header',
  423. ),
  424. ) );
  425. $wp_admin_bar->add_menu( array(
  426. 'parent' => $id,
  427. 'id' => 'get-apps',
  428. 'title' => esc_html__( 'Get Apps', 'jetpack' ),
  429. 'href' => 'https://wordpress.com/me/get-apps',
  430. 'meta' => array(
  431. 'class' => 'mb-icon user-info-item',
  432. ),
  433. ) );
  434. $help_link = 'https://jetpack.com/support/';
  435. if ( jetpack_is_atomic_site() ) {
  436. $help_link = 'https://wordpress.com/help';
  437. }
  438. $wp_admin_bar->add_menu( array(
  439. 'parent' => $id,
  440. 'id' => 'help',
  441. 'title' => esc_html__( 'Help', 'jetpack' ),
  442. 'href' => $help_link,
  443. 'meta' => array(
  444. 'class' => 'mb-icon user-info-item',
  445. ),
  446. ) );
  447. }
  448. public function add_write_button( $wp_admin_bar ) {
  449. $current_user = wp_get_current_user();
  450. $posting_blog_id = get_current_blog_id();
  451. if ( ! is_user_member_of_blog( get_current_user_id(), get_current_blog_id() ) ) {
  452. $posting_blog_id = $current_user->primary_blog;
  453. }
  454. $user_can_post = current_user_can_for_blog( $posting_blog_id, 'publish_posts' );
  455. if ( ! $posting_blog_id || ! $user_can_post ) {
  456. return;
  457. }
  458. $blog_post_page = 'https://wordpress.com/post/' . esc_attr( $this->primary_site_slug );
  459. $wp_admin_bar->add_menu( array(
  460. 'parent' => 'top-secondary',
  461. 'id' => 'ab-new-post',
  462. 'href' => $blog_post_page,
  463. 'title' => '<span>' . esc_html__( 'Write', 'jetpack' ) . '</span>',
  464. 'meta' => array(
  465. 'class' => 'mb-trackable',
  466. )
  467. ) );
  468. }
  469. public function add_my_sites_submenu( $wp_admin_bar ) {
  470. $current_user = wp_get_current_user();
  471. $blog_name = get_bloginfo( 'name' );
  472. if ( empty( $blog_name ) ) {
  473. $blog_name = $this->primary_site_slug;
  474. }
  475. if ( mb_strlen( $blog_name ) > 20 ) {
  476. $blog_name = mb_substr( html_entity_decode( $blog_name, ENT_QUOTES ), 0, 20 ) . '&hellip;';
  477. }
  478. $wp_admin_bar->add_menu( array(
  479. 'parent' => 'root-default',
  480. 'id' => 'blog',
  481. 'title' => _n( 'My Site', 'My Sites', $this->user_site_count, 'jetpack' ),
  482. 'href' => '#',
  483. 'meta' => array(
  484. 'class' => 'my-sites mb-trackable',
  485. ),
  486. ) );
  487. if ( $this->user_site_count > 1 ) {
  488. $wp_admin_bar->add_menu( array(
  489. 'parent' => 'blog',
  490. 'id' => 'switch-site',
  491. 'title' => esc_html__( 'Switch Site', 'jetpack' ),
  492. 'href' => 'https://wordpress.com/sites',
  493. ) );
  494. } else {
  495. $wp_admin_bar->add_menu( array(
  496. 'parent' => 'blog',
  497. 'id' => 'new-site',
  498. 'title' => esc_html__( '+ Add New WordPress', 'jetpack' ),
  499. 'href' => 'https://wordpress.com/start?ref=admin-bar-logged-in',
  500. ) );
  501. }
  502. if ( is_user_member_of_blog( $current_user->ID ) ) {
  503. $blavatar = '';
  504. $class = 'current-site';
  505. if ( has_site_icon() ) {
  506. $src = get_site_icon_url();
  507. $blavatar = '<img class="avatar" src="'. esc_attr( $src ) . '" alt="Current site avatar">';
  508. $class = 'has-blavatar';
  509. }
  510. $blog_info = '<div class="ab-site-icon">' . $blavatar . '</div>';
  511. $blog_info .= '<span class="ab-site-title">' . esc_html( $blog_name ) . '</span>';
  512. $blog_info .= '<span class="ab-site-description">' . esc_html( $this->primary_site_url ) . '</span>';
  513. $wp_admin_bar->add_menu( array(
  514. 'parent' => 'blog',
  515. 'id' => 'blog-info',
  516. 'title' => $blog_info,
  517. 'href' => esc_url( trailingslashit( $this->primary_site_url ) ),
  518. 'meta' => array(
  519. 'class' => $class,
  520. ),
  521. ) );
  522. }
  523. // Site Preview
  524. if ( is_admin() ) {
  525. $wp_admin_bar->add_menu( array(
  526. 'parent' => 'blog',
  527. 'id' => 'site-view',
  528. 'title' => __( 'View Site', 'jetpack' ),
  529. 'href' => home_url(),
  530. 'meta' => array(
  531. 'class' => 'mb-icon',
  532. 'target' => '_blank',
  533. ),
  534. ) );
  535. }
  536. // Stats
  537. if ( Jetpack::is_module_active( 'stats' ) ) {
  538. $wp_admin_bar->add_menu( array(
  539. 'parent' => 'blog',
  540. 'id' => 'blog-stats',
  541. 'title' => esc_html__( 'Stats', 'jetpack' ),
  542. 'href' => 'https://wordpress.com/stats/' . esc_attr( $this->primary_site_slug ),
  543. 'meta' => array(
  544. 'class' => 'mb-icon',
  545. ),
  546. ) );
  547. }
  548. // Add Calypso plans link and plan type indicator
  549. if ( is_user_member_of_blog( $current_user->ID ) ) {
  550. $plans_url = 'https://wordpress.com/plans/' . esc_attr( $this->primary_site_slug );
  551. $label = esc_html__( 'Plan', 'jetpack' );
  552. $plan = Jetpack::get_active_plan();
  553. $plan_title = $this->create_menu_item_pair(
  554. array(
  555. 'url' => $plans_url,
  556. 'id' => 'wp-admin-bar-plan',
  557. 'label' => $label,
  558. ),
  559. array(
  560. 'url' => $plans_url,
  561. 'id' => 'wp-admin-bar-plan-badge',
  562. 'label' => $plan['product_name_short']
  563. )
  564. );
  565. $wp_admin_bar->add_menu( array(
  566. 'parent' => 'blog',
  567. 'id' => 'plan',
  568. 'title' => $plan_title,
  569. 'meta' => array(
  570. 'class' => 'inline-action',
  571. ),
  572. ) );
  573. }
  574. // Publish group
  575. $wp_admin_bar->add_group( array(
  576. 'parent' => 'blog',
  577. 'id' => 'publish',
  578. ) );
  579. // Publish header
  580. $wp_admin_bar->add_menu( array(
  581. 'parent' => 'publish',
  582. 'id' => 'publish-header',
  583. 'title' => esc_html_x( 'Manage', 'admin bar menu group label', 'jetpack' ),
  584. 'meta' => array(
  585. 'class' => 'ab-submenu-header',
  586. ),
  587. ) );
  588. // Pages
  589. $pages_title = $this->create_menu_item_pair(
  590. array(
  591. 'url' => 'https://wordpress.com/pages/' . esc_attr( $this->primary_site_slug ),
  592. 'id' => 'wp-admin-bar-edit-page',
  593. 'label' => esc_html__( 'Site Pages', 'jetpack' ),
  594. ),
  595. array(
  596. 'url' => 'https://wordpress.com/page/' . esc_attr( $this->primary_site_slug ),
  597. 'id' => 'wp-admin-bar-new-page-badge',
  598. 'label' => esc_html_x( 'Add', 'admin bar menu new item label', 'jetpack' ),
  599. )
  600. );
  601. if ( ! current_user_can( 'edit_pages' ) ) {
  602. $pages_title = $this->create_menu_item_anchor(
  603. 'ab-item ab-primary mb-icon',
  604. 'https://wordpress.com/pages/' . esc_attr( $this->primary_site_slug ),
  605. esc_html__( 'Site Pages', 'jetpack' ),
  606. 'wp-admin-bar-edit-page'
  607. );
  608. }
  609. $wp_admin_bar->add_menu( array(
  610. 'parent' => 'publish',
  611. 'id' => 'new-page',
  612. 'title' => $pages_title,
  613. 'meta' => array(
  614. 'class' => 'inline-action',
  615. ),
  616. ) );
  617. // Blog Posts
  618. $posts_title = $this->create_menu_item_pair(
  619. array(
  620. 'url' => 'https://wordpress.com/posts/' . esc_attr( $this->primary_site_slug ),
  621. 'id' => 'wp-admin-bar-edit-post',
  622. 'label' => esc_html__( 'Blog Posts', 'jetpack' ),
  623. ),
  624. array(
  625. 'url' => 'https://wordpress.com/post/' . esc_attr( $this->primary_site_slug ),
  626. 'id' => 'wp-admin-bar-new-post-badge',
  627. 'label' => esc_html_x( 'Add', 'admin bar menu new item label', 'jetpack' ),
  628. )
  629. );
  630. if ( ! current_user_can( 'edit_posts' ) ) {
  631. $posts_title = $this->create_menu_item_anchor(
  632. 'ab-item ab-primary mb-icon',
  633. 'https://wordpress.com/posts/' . esc_attr( $this->primary_site_slug ),
  634. esc_html__( 'Blog Posts', 'jetpack' ),
  635. 'wp-admin-bar-edit-post'
  636. );
  637. }
  638. $wp_admin_bar->add_menu( array(
  639. 'parent' => 'publish',
  640. 'id' => 'new-post',
  641. 'title' => $posts_title,
  642. 'meta' => array(
  643. 'class' => 'inline-action mb-trackable',
  644. ),
  645. ) );
  646. // Comments
  647. if ( current_user_can( 'moderate_comments' ) ) {
  648. $wp_admin_bar->add_menu( array(
  649. 'parent' => 'publish',
  650. 'id' => 'comments',
  651. 'title' => __( 'Comments' ),
  652. 'href' => 'https://wordpress.com/comments/' . esc_attr( $this->primary_site_slug ),
  653. 'meta' => array(
  654. 'class' => 'mb-icon',
  655. ),
  656. ) );
  657. }
  658. // Testimonials
  659. if ( Jetpack::is_module_active( 'custom-content-types' ) && get_option( 'jetpack_testimonial' ) ) {
  660. $testimonials_title = $this->create_menu_item_pair(
  661. array(
  662. 'url' => 'https://wordpress.com/types/jetpack-testimonial/' . esc_attr( $this->primary_site_slug ),
  663. 'id' => 'wp-admin-bar-edit-testimonial',
  664. 'label' => esc_html__( 'Testimonials', 'jetpack' ),
  665. ),
  666. array(
  667. 'url' => 'https://wordpress.com/edit/jetpack-testimonial/' . esc_attr( $this->primary_site_slug ),
  668. 'id' => 'wp-admin-bar-new-testimonial',
  669. 'label' => esc_html_x( 'Add', 'Button label for adding a new item via the toolbar menu', 'jetpack' ),
  670. )
  671. );
  672. if ( ! current_user_can( 'edit_pages' ) ) {
  673. $testimonials_title = $this->create_menu_item_anchor(
  674. 'ab-item ab-primary mb-icon',
  675. 'https://wordpress.com/types/jetpack-testimonial/' . esc_attr( $this->primary_site_slug ),
  676. esc_html__( 'Testimonials', 'jetpack' ),
  677. 'wp-admin-bar-edit-testimonial'
  678. );
  679. }
  680. $wp_admin_bar->add_menu( array(
  681. 'parent' => 'publish',
  682. 'id' => 'new-jetpack-testimonial',
  683. 'title' => $testimonials_title,
  684. 'meta' => array(
  685. 'class' => 'inline-action',
  686. ),
  687. ) );
  688. }
  689. // Portfolio
  690. if ( Jetpack::is_module_active( 'custom-content-types' ) && get_option( 'jetpack_portfolio' ) ) {
  691. $portfolios_title = $this->create_menu_item_pair(
  692. array(
  693. 'url' => 'https://wordpress.com/types/jetpack-portfolio/' . esc_attr( $this->primary_site_slug ),
  694. 'id' => 'wp-admin-bar-edit-portfolio',
  695. 'label' => esc_html__( 'Portfolio', 'jetpack' ),
  696. ),
  697. array(
  698. 'url' => 'https://wordpress.com/edit/jetpack-portfolio/' . esc_attr( $this->primary_site_slug ),
  699. 'id' => 'wp-admin-bar-new-portfolio',
  700. 'label' => esc_html_x( 'Add', 'Button label for adding a new item via the toolbar menu', 'jetpack' ),
  701. )
  702. );
  703. if ( ! current_user_can( 'edit_pages' ) ) {
  704. $portfolios_title = $this->create_menu_item_anchor(
  705. 'ab-item ab-primary mb-icon',
  706. 'https://wordpress.com/types/jetpack-portfolio/' . esc_attr( $this->primary_site_slug ),
  707. esc_html__( 'Portfolio', 'jetpack' ),
  708. 'wp-admin-bar-edit-portfolio'
  709. );
  710. }
  711. $wp_admin_bar->add_menu( array(
  712. 'parent' => 'publish',
  713. 'id' => 'new-jetpack-portfolio',
  714. 'title' => $portfolios_title,
  715. 'meta' => array(
  716. 'class' => 'inline-action',
  717. ),
  718. ) );
  719. }
  720. if ( current_user_can( 'edit_theme_options' ) ) {
  721. // Look and Feel group
  722. $wp_admin_bar->add_group( array(
  723. 'parent' => 'blog',
  724. 'id' => 'look-and-feel',
  725. ) );
  726. // Look and Feel header
  727. $wp_admin_bar->add_menu( array(
  728. 'parent' => 'look-and-feel',
  729. 'id' => 'look-and-feel-header',
  730. 'title' => esc_html_x( 'Personalize', 'admin bar menu group label', 'jetpack' ),
  731. 'meta' => array(
  732. 'class' => 'ab-submenu-header',
  733. ),
  734. ) );
  735. if ( is_admin() ) {
  736. // In wp-admin the `return` query arg will return to that page after closing the Customizer
  737. $customizer_url = add_query_arg( array( 'return' => urlencode( site_url( $_SERVER['REQUEST_URI'] ) ) ), wp_customize_url() );
  738. } else {
  739. // On the frontend the `url` query arg will load that page in the Customizer and also return to it after closing
  740. // non-home URLs won't work unless we undo domain mapping since the Customizer preview is unmapped to always have HTTPS
  741. $current_page = '//' . $this->primary_site_slug . $_SERVER['REQUEST_URI'];
  742. $customizer_url = add_query_arg( array( 'url' => urlencode( $current_page ) ), wp_customize_url() );
  743. }
  744. $theme_title = $this->create_menu_item_pair(
  745. array(
  746. 'url' => $customizer_url,
  747. 'id' => 'wp-admin-bar-cmz',
  748. 'label' => esc_html_x( 'Customize', 'admin bar customize item label', 'jetpack' ),
  749. ),
  750. array(
  751. 'url' => 'https://wordpress.com/themes/' . esc_attr( $this->primary_site_slug ),
  752. 'id' => 'wp-admin-bar-themes',
  753. 'label' => esc_html__( 'Themes', 'jetpack' ),
  754. )
  755. );
  756. $meta = array( 'class' => 'mb-icon', 'class' => 'inline-action' );
  757. $href = false;
  758. $wp_admin_bar->add_menu( array(
  759. 'parent' => 'look-and-feel',
  760. 'id' => 'themes',
  761. 'title' => $theme_title,
  762. 'href' => $href,
  763. 'meta' => $meta
  764. ) );
  765. }
  766. if ( current_user_can( 'manage_options' ) ) {
  767. // Configuration group
  768. $wp_admin_bar->add_group( array(
  769. 'parent' => 'blog',
  770. 'id' => 'configuration',
  771. ) );
  772. // Configuration header
  773. $wp_admin_bar->add_menu( array(
  774. 'parent' => 'configuration',
  775. 'id' => 'configuration-header',
  776. 'title' => esc_html__( 'Configure', 'admin bar menu group label', 'jetpack' ),
  777. 'meta' => array(
  778. 'class' => 'ab-submenu-header',
  779. ),
  780. ) );
  781. if ( Jetpack::is_module_active( 'publicize' ) || Jetpack::is_module_active( 'sharedaddy' ) ) {
  782. $wp_admin_bar->add_menu( array(
  783. 'parent' => 'configuration',
  784. 'id' => 'sharing',
  785. 'title' => esc_html__( 'Sharing', 'jetpack' ),
  786. 'href' => 'https://wordpress.com/sharing/' . esc_attr( $this->primary_site_slug ),
  787. 'meta' => array(
  788. 'class' => 'mb-icon',
  789. ),
  790. ) );
  791. }
  792. $people_title = $this->create_menu_item_pair(
  793. array(
  794. 'url' => 'https://wordpress.com/people/team/' . esc_attr( $this->primary_site_slug ),
  795. 'id' => 'wp-admin-bar-people',
  796. 'label' => esc_html__( 'People', 'jetpack' ),
  797. ),
  798. array(
  799. 'url' => admin_url( 'user-new.php' ),
  800. 'id' => 'wp-admin-bar-people-add',
  801. 'label' => esc_html_x( 'Add', 'admin bar people item label', 'jetpack' ),
  802. )
  803. );
  804. $wp_admin_bar->add_menu( array(
  805. 'parent' => 'configuration',
  806. 'id' => 'users-toolbar',
  807. 'title' => $people_title,
  808. 'href' => false,
  809. 'meta' => array(
  810. 'class' => 'inline-action',
  811. ),
  812. ) );
  813. $plugins_title = $this->create_menu_item_pair(
  814. array(
  815. 'url' => 'https://wordpress.com/plugins/' . esc_attr( $this->primary_site_slug ),
  816. 'id' => 'wp-admin-bar-plugins',
  817. 'label' => esc_html__( 'Plugins', 'jetpack' ),
  818. ),
  819. array(
  820. 'url' => 'https://wordpress.com/plugins/manage/' . esc_attr( $this->primary_site_slug ),
  821. 'id' => 'wp-admin-bar-plugins-add',
  822. 'label' => esc_html_x( 'Manage', 'Label for the button on the Masterbar to manage plugins', 'jetpack' ),
  823. )
  824. );
  825. $wp_admin_bar->add_menu( array(
  826. 'parent' => 'configuration',
  827. 'id' => 'plugins',
  828. 'title' => $plugins_title,
  829. 'href' => false,
  830. 'meta' => array(
  831. 'class' => 'inline-action',
  832. ),
  833. ) );
  834. if ( jetpack_is_atomic_site() ) {
  835. $domain_title = $this->create_menu_item_pair(
  836. array(
  837. 'url' => 'https://wordpress.com/domains/' . esc_attr( $this->primary_site_slug ),
  838. 'id' => 'wp-admin-bar-domains',
  839. 'label' => esc_html__( 'Domains', 'jetpack' ),
  840. ),
  841. array(
  842. 'url' => 'https://wordpress.com/domains/add/' . esc_attr( $this->primary_site_slug ),
  843. 'id' => 'wp-admin-bar-domains-add',
  844. 'label' => esc_html_x( 'Add', 'Label for the button on the Masterbar to add a new domain', 'jetpack' ),
  845. )
  846. );
  847. $wp_admin_bar->add_menu( array(
  848. 'parent' => 'configuration',
  849. 'id' => 'domains',
  850. 'title' => $domain_title,
  851. 'href' => false,
  852. 'meta' => array(
  853. 'class' => 'inline-action',
  854. ),
  855. ) );
  856. }
  857. $wp_admin_bar->add_menu( array(
  858. 'parent' => 'configuration',
  859. 'id' => 'blog-settings',
  860. 'title' => esc_html__( 'Settings', 'jetpack' ),
  861. 'href' => 'https://wordpress.com/settings/general/' . esc_attr( $this->primary_site_slug ),
  862. 'meta' => array(
  863. 'class' => 'mb-icon',
  864. ),
  865. ) );
  866. if ( ! is_admin() ) {
  867. $wp_admin_bar->add_menu( array(
  868. 'parent' => 'configuration',
  869. 'id' => 'legacy-dashboard',
  870. 'title' => esc_html__( 'Dashboard', 'jetpack' ),
  871. 'href' => admin_url(),
  872. 'meta' => array(
  873. 'class' => 'mb-icon',
  874. ),
  875. ) );
  876. }
  877. // Restore dashboard menu toggle that is needed on mobile views.
  878. if ( is_admin() ) {
  879. $wp_admin_bar->add_menu( array(
  880. 'id' => 'menu-toggle',
  881. 'title' => '<span class="ab-icon"></span><span class="screen-reader-text">' . esc_html__( 'Menu', 'jetpack' ) . '</span>',
  882. 'href' => '#',
  883. ) );
  884. }
  885. /**
  886. * Fires when menu items are added to the masterbar "My Sites" menu.
  887. *
  888. * @since 5.4
  889. */
  890. do_action( 'jetpack_masterbar' );
  891. }
  892. }
  893. }