PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 7.8
Jetpack – WP Security, Backup, Speed, & Growth v7.8
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 13.9.2 14.0.1 14.1.1 14.2.2 14.3.1 All 501 releases
jetpack / modules / masterbar / masterbar.php

masterbar.php in Jetpack – WP Security, Backup, Speed, & Growth 7.8, at modules/masterbar/masterbar.php

1,324 lines 35.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
2
3 use Automattic\Jetpack\Assets;
4
5 require_once dirname( __FILE__ ) . '/rtl-admin-bar.php';
6
7 /**
8 * Custom Admin bar displayed instead of the default WordPress admin bar.
9 */
10 class A8C_WPCOM_Masterbar {
11 /**
12 * Use for testing changes made to remotely enqueued scripts and styles on your sandbox.
13 * If not set it will default to loading the ones from WordPress.com.
14 *
15 * @var string $sandbox_url
16 */
17 private $sandbox_url = '';
18
19 /**
20 * Current locale.
21 *
22 * @var string
23 */
24 private $locale;
25
26 /**
27 * Current User ID.
28 *
29 * @var int
30 */
31 private $user_id;
32 /**
33 * WordPress.com user data of the connected user.
34 *
35 * @var array
36 */
37 private $user_data;
38 /**
39 * WordPress.com username for the connected user.
40 *
41 * @var string
42 */
43 private $user_login;
44 /**
45 * WordPress.com email address for the connected user.
46 *
47 * @var string
48 */
49 private $user_email;
50 /**
51 * WordPress.com display name for the connected user.
52 *
53 * @var string
54 */
55 private $display_name;
56 /**
57 * Site URL sanitized for usage in WordPress.com slugs.
58 *
59 * @var string
60 */
61 private $primary_site_slug;
62 /**
63 * Text direction (ltr or rtl) based on connected WordPress.com user's interface settings.
64 *
65 * @var string
66 */
67 private $user_text_direction;
68 /**
69 * Number of sites owned by connected WordPress.com user.
70 *
71 * @var int
72 */
73 private $user_site_count;
74
75 /**
76 * Constructor
77 */
78 public function __construct() {
79 add_action( 'admin_bar_init', array( $this, 'init' ) );
80
81 // Post logout on the site, also log the user out of WordPress.com.
82 add_action( 'wp_logout', array( $this, 'maybe_logout_user_from_wpcom' ) );
83 }
84
85 /**
86 * Initialize our masterbar.
87 */
88 public function init() {
89 $this->locale = $this->get_locale();
90 $this->user_id = get_current_user_id();
91
92 // Limit the masterbar to be shown only to connected Jetpack users.
93 if ( ! Jetpack::is_user_connected( $this->user_id ) ) {
94 return;
95 }
96
97 // Don't show the masterbar on WordPress mobile apps.
98 if ( Jetpack_User_Agent_Info::is_mobile_app() ) {
99 add_filter( 'show_admin_bar', '__return_false' );
100 return;
101 }
102
103 // Disable the Masterbar on AMP views.
104 if (
105 class_exists( 'Jetpack_AMP_Support' )
106 && Jetpack_AMP_Support::is_amp_request()
107 ) {
108 return;
109 }
110
111 Jetpack::dns_prefetch(
112 array(
113 '//s0.wp.com',
114 '//s1.wp.com',
115 '//s2.wp.com',
116 '//0.gravatar.com',
117 '//1.gravatar.com',
118 '//2.gravatar.com',
119 )
120 );
121
122 // Atomic only.
123 if ( jetpack_is_atomic_site() ) {
124 /*
125 * override user setting that hides masterbar from site's front.
126 * https://github.com/Automattic/jetpack/issues/7667
127 */
128 add_filter( 'show_admin_bar', '__return_true' );
129 }
130
131 $this->user_data = Jetpack::get_connected_user_data( $this->user_id );
132 $this->user_login = $this->user_data['login'];
133 $this->user_email = $this->user_data['email'];
134 $this->display_name = $this->user_data['display_name'];
135 $this->user_site_count = $this->user_data['site_count'];
136
137 // Used to build menu links that point directly to Calypso.
138 $this->primary_site_slug = Jetpack::build_raw_urls( get_home_url() );
139
140 // Used for display purposes and for building WP Admin links.
141 $this->primary_site_url = str_replace( '::', '/', $this->primary_site_slug );
142
143 // We need to use user's setting here, instead of relying on current blog's text direction.
144 $this->user_text_direction = $this->user_data['text_direction'];
145
146 if ( $this->is_rtl() ) {
147 // Extend core WP_Admin_Bar class in order to add rtl styles.
148 add_filter( 'wp_admin_bar_class', array( $this, 'get_rtl_admin_bar_class' ) );
149 }
150 add_filter( 'admin_body_class', array( $this, 'admin_body_class' ) );
151
152 add_action( 'wp_before_admin_bar_render', array( $this, 'replace_core_masterbar' ), 99999 );
153
154 add_action( 'wp_enqueue_scripts', array( $this, 'add_styles_and_scripts' ) );
155 add_action( 'admin_enqueue_scripts', array( $this, 'add_styles_and_scripts' ) );
156
157 add_action( 'wp_enqueue_scripts', array( $this, 'remove_core_styles' ) );
158 add_action( 'admin_enqueue_scripts', array( $this, 'remove_core_styles' ) );
159
160 if ( Jetpack::is_module_active( 'notes' ) && $this->is_rtl() ) {
161 // Override Notification module to include RTL styles.
162 add_action( 'a8c_wpcom_masterbar_enqueue_rtl_notification_styles', '__return_true' );
163 }
164 }
165
166 /**
167 * Log out from WordPress.com when logging out of the local site.
168 */
169 public function maybe_logout_user_from_wpcom() {
170 /**
171 * Whether we should sign out from wpcom too when signing out from the masterbar.
172 *
173 * @since 5.9.0
174 *
175 * @param bool $masterbar_should_logout_from_wpcom True by default.
176 */
177 $masterbar_should_logout_from_wpcom = apply_filters( 'jetpack_masterbar_should_logout_from_wpcom', true );
178 if (
179 // No need to check for a nonce here, it happens further up.
180 isset( $_GET['context'] ) // phpcs:ignore WordPress.Security.NonceVerification.Recommended
181 && 'masterbar' === $_GET['context'] // phpcs:ignore WordPress.Security.NonceVerification.Recommended
182 && $masterbar_should_logout_from_wpcom
183 ) {
184 do_action( 'wp_masterbar_logout' );
185 }
186 }
187
188 /**
189 * Get class name for RTL sites.
190 */
191 public function get_rtl_admin_bar_class() {
192 return 'RTL_Admin_Bar';
193 }
194
195 /**
196 * Adds CSS classes to admin body tag.
197 *
198 * @since 5.1
199 *
200 * @param string $admin_body_classes CSS classes that will be added.
201 *
202 * @return string
203 */
204 public function admin_body_class( $admin_body_classes ) {
205 return "$admin_body_classes jetpack-masterbar";
206 }
207
208 /**
209 * Remove the default Admin Bar CSS.
210 */
211 public function remove_core_styles() {
212 wp_dequeue_style( 'admin-bar' );
213 }
214
215 /**
216 * Check if the user settings are for an RTL language or not.
217 */
218 public function is_rtl() {
219 return 'rtl' === $this->user_text_direction ? true : false;
220 }
221
222 /**
223 * Enqueue our own CSS and JS to display our custom admin bar.
224 */
225 public function add_styles_and_scripts() {
226
227 if ( $this->is_rtl() ) {
228 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 );
229 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 );
230 } else {
231 wp_enqueue_style( 'a8c-wpcom-masterbar', $this->wpcom_static_url( '/wp-content/mu-plugins/admin-bar/wpcom-admin-bar.css' ), array(), JETPACK__VERSION );
232 wp_enqueue_style( 'a8c-wpcom-masterbar-overrides', $this->wpcom_static_url( '/wp-content/mu-plugins/admin-bar/masterbar-overrides/masterbar.css' ), array(), JETPACK__VERSION );
233 }
234
235 // Local overrides.
236 wp_enqueue_style( 'a8c_wpcom_css_override', plugins_url( 'overrides.css', __FILE__ ), array(), JETPACK__VERSION );
237
238 if ( ! Jetpack::is_module_active( 'notes ' ) ) {
239 // Masterbar is relying on some icons from noticons.css.
240 wp_enqueue_style( 'noticons', $this->wpcom_static_url( '/i/noticons/noticons.css' ), array(), JETPACK__VERSION . '-' . gmdate( 'oW' ) );
241 }
242
243 wp_enqueue_script(
244 'jetpack-accessible-focus',
245 Assets::get_file_url_for_environment( '_inc/build/accessible-focus.min.js', '_inc/accessible-focus.js' ),
246 array(),
247 JETPACK__VERSION,
248 false
249 );
250 wp_enqueue_script(
251 'a8c_wpcom_masterbar_tracks_events',
252 Assets::get_file_url_for_environment(
253 '_inc/build/masterbar/tracks-events.min.js',
254 'modules/masterbar/tracks-events.js'
255 ),
256 array( 'jquery' ),
257 JETPACK__VERSION,
258 false
259 );
260
261 wp_enqueue_script(
262 'a8c_wpcom_masterbar_overrides',
263 $this->wpcom_static_url( '/wp-content/mu-plugins/admin-bar/masterbar-overrides/masterbar.js' ),
264 array( 'jquery' ),
265 JETPACK__VERSION,
266 false
267 );
268 }
269
270 /**
271 * Get base URL where our CSS and JS will come from.
272 *
273 * @param string $file File path for a static resource.
274 */
275 private function wpcom_static_url( $file ) {
276 if ( ! empty( $this->sandbox_url ) ) {
277 // For testing undeployed changes to remotely enqueued scripts and styles.
278 return set_url_scheme( $this->sandbox_url . $file, 'https' );
279 }
280
281 $i = hexdec( substr( md5( $file ), - 1 ) ) % 2;
282 $url = 'https://s' . $i . '.wp.com' . $file;
283
284 return set_url_scheme( $url, 'https' );
285 }
286
287 /**
288 * Remove the default admin bar items and replace it with our own admin bar.
289 */
290 public function replace_core_masterbar() {
291 global $wp_admin_bar;
292
293 if ( ! is_object( $wp_admin_bar ) ) {
294 return false;
295 }
296
297 $this->clear_core_masterbar( $wp_admin_bar );
298 $this->build_wpcom_masterbar( $wp_admin_bar );
299 }
300
301 /**
302 * Remove all existing toolbar entries from core Masterbar
303 *
304 * @param WP_Admin_Bar $wp_admin_bar Admin Bar instance.
305 */
306 public function clear_core_masterbar( $wp_admin_bar ) {
307 foreach ( $wp_admin_bar->get_nodes() as $node ) {
308 $wp_admin_bar->remove_node( $node->id );
309 }
310 }
311
312 /**
313 * Add entries corresponding to WordPress.com Masterbar
314 *
315 * @param WP_Admin_Bar $wp_admin_bar Admin Bar instance.
316 */
317 public function build_wpcom_masterbar( $wp_admin_bar ) {
318 // Menu groups.
319 $this->wpcom_adminbar_add_secondary_groups( $wp_admin_bar );
320
321 // Left part.
322 $this->add_my_sites_submenu( $wp_admin_bar );
323 $this->add_reader_submenu( $wp_admin_bar );
324
325 // Right part.
326 if ( Jetpack::is_module_active( 'notes' ) ) {
327 $this->add_notifications( $wp_admin_bar );
328 }
329
330 $this->add_me_submenu( $wp_admin_bar );
331 $this->add_write_button( $wp_admin_bar );
332
333 // Recovery mode exit.
334 if ( function_exists( 'wp_admin_bar_recovery_mode_menu' ) ) {
335 wp_admin_bar_recovery_mode_menu( $wp_admin_bar );
336 }
337 }
338
339 /**
340 * Get WordPress.com current locale name.
341 */
342 public function get_locale() {
343 $wpcom_locale = get_locale();
344
345 if ( ! class_exists( 'GP_Locales' ) ) {
346 if ( defined( 'JETPACK__GLOTPRESS_LOCALES_PATH' ) && file_exists( JETPACK__GLOTPRESS_LOCALES_PATH ) ) {
347 require JETPACK__GLOTPRESS_LOCALES_PATH;
348 }
349 }
350
351 if ( class_exists( 'GP_Locales' ) ) {
352 $wpcom_locale_object = GP_Locales::by_field( 'wp_locale', get_locale() );
353 if ( $wpcom_locale_object instanceof GP_Locale ) {
354 $wpcom_locale = $wpcom_locale_object->slug;
355 }
356 }
357
358 return $wpcom_locale;
359 }
360
361 /**
362 * Add the Notifications menu item.
363 *
364 * @param WP_Admin_Bar $wp_admin_bar Admin Bar instance.
365 */
366 public function add_notifications( $wp_admin_bar ) {
367 $wp_admin_bar->add_node(
368 array(
369 'id' => 'notes',
370 'title' => '<span id="wpnt-notes-unread-count" class="wpnt-loading wpn-read"></span>
371 <span class="screen-reader-text">' . esc_html__( 'Notifications', 'jetpack' ) . '</span>
372 <span class="noticon noticon-bell"></span>',
373 'meta' => array(
374 'html' => '<div id="wpnt-notes-panel2" style="display:none" lang="' . esc_attr( $this->locale ) . '" dir="' . ( $this->is_rtl() ? 'rtl' : 'ltr' ) . '">' .
375 '<div class="wpnt-notes-panel-header">' .
376 '<span class="wpnt-notes-header">' .
377 esc_html__( 'Notifications', 'jetpack' ) .
378 '</span>' .
379 '<span class="wpnt-notes-panel-link">' .
380 '</span>' .
381 '</div>' .
382 '</div>',
383 'class' => 'menupop mb-trackable',
384 ),
385 'parent' => 'top-secondary',
386 )
387 );
388 }
389
390 /**
391 * Add the "Reader" menu item in the root default group.
392 *
393 * @param WP_Admin_Bar $wp_admin_bar Admin Bar instance.
394 */
395 public function add_reader_submenu( $wp_admin_bar ) {
396 $wp_admin_bar->add_menu(
397 array(
398 'parent' => 'root-default',
399 'id' => 'newdash',
400 'title' => esc_html__( 'Reader', 'jetpack' ),
401 'href' => '#',
402 'meta' => array(
403 'class' => 'mb-trackable',
404 ),
405 )
406 );
407
408 $wp_admin_bar->add_menu(
409 array(
410 'parent' => 'newdash',
411 'id' => 'streams-header',
412 'title' => esc_html_x(
413 'Streams',
414 'Title for Reader sub-menu that contains followed sites, likes, and recommendations',
415 'jetpack'
416 ),
417 'meta' => array(
418 'class' => 'ab-submenu-header',
419 ),
420 )
421 );
422
423 $following_title = $this->create_menu_item_pair(
424 array(
425 'url' => 'https://wordpress.com/',
426 'id' => 'wp-admin-bar-followed-sites',
427 'label' => esc_html__( 'Followed Sites', 'jetpack' ),
428 ),
429 array(
430 'url' => 'https://wordpress.com/following/edit',
431 'id' => 'wp-admin-bar-reader-followed-sites-manage',
432 'label' => esc_html__( 'Manage', 'jetpack' ),
433 )
434 );
435
436 $wp_admin_bar->add_menu(
437 array(
438 'parent' => 'newdash',
439 'id' => 'following',
440 'title' => $following_title,
441 'meta' => array( 'class' => 'inline-action' ),
442 )
443 );
444
445 $wp_admin_bar->add_menu(
446 array(
447 'parent' => 'newdash',
448 'id' => 'discover-discover',
449 'title' => esc_html__( 'Discover', 'jetpack' ),
450 'href' => 'https://wordpress.com/discover',
451 'meta' => array(
452 'class' => 'mb-icon-spacer',
453 ),
454 )
455 );
456
457 $wp_admin_bar->add_menu(
458 array(
459 'parent' => 'newdash',
460 'id' => 'discover-search',
461 'title' => esc_html__( 'Search', 'jetpack' ),
462 'href' => 'https://wordpress.com/read/search',
463 'meta' => array(
464 'class' => 'mb-icon-spacer',
465 ),
466 )
467 );
468
469 $wp_admin_bar->add_menu(
470 array(
471 'parent' => 'newdash',
472 'id' => 'discover-recommended-blogs',
473 'title' => esc_html__( 'Recommendations', 'jetpack' ),
474 'href' => 'https://wordpress.com/recommendations',
475 'meta' => array(
476 'class' => 'mb-icon-spacer',
477 ),
478 )
479 );
480
481 $wp_admin_bar->add_menu(
482 array(
483 'parent' => 'newdash',
484 'id' => 'my-activity-my-likes',
485 'title' => esc_html__( 'My Likes', 'jetpack' ),
486 'href' => 'https://wordpress.com/activities/likes',
487 'meta' => array(
488 'class' => 'mb-icon-spacer',
489 ),
490 )
491 );
492
493 }
494
495 /**
496 * Merge 2 menu items together into 2 link tags.
497 *
498 * @param array $primary Array of menu information.
499 * @param array $secondary Array of menu information.
500 */
501 public function create_menu_item_pair( $primary, $secondary ) {
502 $primary_class = 'ab-item ab-primary mb-icon';
503 $secondary_class = 'ab-secondary';
504
505 $primary_anchor = $this->create_menu_item_anchor( $primary_class, $primary['url'], $primary['label'], $primary['id'] );
506 $secondary_anchor = $this->create_menu_item_anchor( $secondary_class, $secondary['url'], $secondary['label'], $secondary['id'] );
507
508 return $primary_anchor . $secondary_anchor;
509 }
510
511 /**
512 * Create a link tag based on information about a menu item.
513 *
514 * @param string $class Menu item CSS class.
515 * @param string $url URL you go to when clicking on the menu item.
516 * @param string $label Menu item title.
517 * @param string $id Menu item slug.
518 */
519 public function create_menu_item_anchor( $class, $url, $label, $id ) {
520 return '<a href="' . $url . '" class="' . $class . '" id="' . $id . '">' . $label . '</a>';
521 }
522
523 /**
524 * Add Secondary groups for submenu items.
525 *
526 * @param WP_Admin_Bar $wp_admin_bar Admin Bar instance.
527 */
528 public function wpcom_adminbar_add_secondary_groups( $wp_admin_bar ) {
529 $wp_admin_bar->add_group(
530 array(
531 'id' => 'root-default',
532 'meta' => array(
533 'class' => 'ab-top-menu',
534 ),
535 )
536 );
537
538 $wp_admin_bar->add_group(
539 array(
540 'parent' => 'blog',
541 'id' => 'blog-secondary',
542 'meta' => array(
543 'class' => 'ab-sub-secondary',
544 ),
545 )
546 );
547
548 $wp_admin_bar->add_group(
549 array(
550 'id' => 'top-secondary',
551 'meta' => array(
552 'class' => 'ab-top-secondary',
553 ),
554 )
555 );
556 }
557
558 /**
559 * Add User info menu item.
560 *
561 * @param WP_Admin_Bar $wp_admin_bar Admin Bar instance.
562 */
563 public function add_me_submenu( $wp_admin_bar ) {
564 $user_id = get_current_user_id();
565 if ( empty( $user_id ) ) {
566 return;
567 }
568
569 $avatar = get_avatar( $this->user_email, 32, 'mm', '', array( 'force_display' => true ) );
570 $class = empty( $avatar ) ? 'mb-trackable' : 'with-avatar mb-trackable';
571
572 // Add the 'Me' menu.
573 $wp_admin_bar->add_menu(
574 array(
575 'id' => 'my-account',
576 'parent' => 'top-secondary',
577 'title' => $avatar . '<span class="ab-text">' . esc_html__( 'Me', 'jetpack' ) . '</span>',
578 'href' => '#',
579 'meta' => array(
580 'class' => $class,
581 ),
582 )
583 );
584
585 $id = 'user-actions';
586 $wp_admin_bar->add_group(
587 array(
588 'parent' => 'my-account',
589 'id' => $id,
590 )
591 );
592
593 $settings_url = 'https://wordpress.com/me/account';
594
595 $logout_url = wp_logout_url();
596 $logout_url = add_query_arg( 'context', 'masterbar', $logout_url );
597
598 $user_info = get_avatar( $this->user_email, 128, 'mm', '', array( 'force_display' => true ) );
599 $user_info .= '<span class="display-name">' . $this->display_name . '</span>';
600 $user_info .= '<a class="username" href="https://gravatar.com/' . $this->user_login . '">@' . $this->user_login . '</a>';
601
602 $user_info .= sprintf(
603 '<div><a href="%s" class="ab-sign-out">%s</a></div>',
604 $logout_url,
605 esc_html__( 'Sign Out', 'jetpack' )
606 );
607
608 $wp_admin_bar->add_menu(
609 array(
610 'parent' => $id,
611 'id' => 'user-info',
612 'title' => $user_info,
613 'meta' => array(
614 'class' => 'user-info user-info-item',
615 'tabindex' => -1,
616 ),
617 )
618 );
619
620 $wp_admin_bar->add_menu(
621 array(
622 'parent' => $id,
623 'id' => 'profile-header',
624 'title' => esc_html__( 'Profile', 'jetpack' ),
625 'meta' => array(
626 'class' => 'ab-submenu-header',
627 ),
628 )
629 );
630
631 $wp_admin_bar->add_menu(
632 array(
633 'parent' => $id,
634 'id' => 'my-profile',
635 'title' => esc_html__( 'My Profile', 'jetpack' ),
636 'href' => 'https://wordpress.com/me',
637 'meta' => array(
638 'class' => 'mb-icon',
639 ),
640 )
641 );
642
643 $wp_admin_bar->add_menu(
644 array(
645 'parent' => $id,
646 'id' => 'account-settings',
647 'title' => esc_html__( 'Account Settings', 'jetpack' ),
648 'href' => $settings_url,
649 'meta' => array(
650 'class' => 'mb-icon',
651 ),
652 )
653 );
654
655 $wp_admin_bar->add_menu(
656 array(
657 'parent' => $id,
658 'id' => 'billing',
659 'title' => esc_html__( 'Manage Purchases', 'jetpack' ),
660 'href' => 'https://wordpress.com/me/purchases',
661 'meta' => array(
662 'class' => 'mb-icon',
663 ),
664 )
665 );
666
667 $wp_admin_bar->add_menu(
668 array(
669 'parent' => $id,
670 'id' => 'security',
671 'title' => esc_html__( 'Security', 'jetpack' ),
672 'href' => 'https://wordpress.com/me/security',
673 'meta' => array(
674 'class' => 'mb-icon',
675 ),
676 )
677 );
678
679 $wp_admin_bar->add_menu(
680 array(
681 'parent' => $id,
682 'id' => 'notifications',
683 'title' => esc_html__( 'Notifications', 'jetpack' ),
684 'href' => 'https://wordpress.com/me/notifications',
685 'meta' => array(
686 'class' => 'mb-icon',
687 ),
688 )
689 );
690
691 $wp_admin_bar->add_menu(
692 array(
693 'parent' => $id,
694 'id' => 'special-header',
695 'title' => esc_html_x(
696 'Special',
697 'Title for Me sub-menu that contains Get Apps, Next Steps, and Help options',
698 'jetpack'
699 ),
700 'meta' => array(
701 'class' => 'ab-submenu-header',
702 ),
703 )
704 );
705
706 $wp_admin_bar->add_menu(
707 array(
708 'parent' => $id,
709 'id' => 'get-apps',
710 'title' => esc_html__( 'Get Apps', 'jetpack' ),
711 'href' => 'https://wordpress.com/me/get-apps',
712 'meta' => array(
713 'class' => 'mb-icon user-info-item',
714 ),
715 )
716 );
717
718 $help_link = 'https://jetpack.com/support/';
719
720 if ( jetpack_is_atomic_site() ) {
721 $help_link = 'https://wordpress.com/help';
722 }
723
724 $wp_admin_bar->add_menu(
725 array(
726 'parent' => $id,
727 'id' => 'help',
728 'title' => esc_html__( 'Help', 'jetpack' ),
729 'href' => $help_link,
730 'meta' => array(
731 'class' => 'mb-icon user-info-item',
732 ),
733 )
734 );
735 }
736
737 /**
738 * Add Write Menu item.
739 *
740 * @param WP_Admin_Bar $wp_admin_bar Admin Bar instance.
741 */
742 public function add_write_button( $wp_admin_bar ) {
743 $current_user = wp_get_current_user();
744
745 $posting_blog_id = get_current_blog_id();
746 if ( ! is_user_member_of_blog( get_current_user_id(), get_current_blog_id() ) ) {
747 $posting_blog_id = $current_user->primary_blog;
748 }
749
750 $user_can_post = current_user_can_for_blog( $posting_blog_id, 'publish_posts' );
751
752 if ( ! $posting_blog_id || ! $user_can_post ) {
753 return;
754 }
755
756 $blog_post_page = 'https://wordpress.com/post/' . esc_attr( $this->primary_site_slug );
757
758 $wp_admin_bar->add_menu(
759 array(
760 'parent' => 'top-secondary',
761 'id' => 'ab-new-post',
762 'href' => $blog_post_page,
763 'title' => '<span>' . esc_html__( 'Write', 'jetpack' ) . '</span>',
764 'meta' => array(
765 'class' => 'mb-trackable',
766 ),
767 )
768 );
769 }
770
771 /**
772 * Add the "My Site" menu item in the root default group.
773 *
774 * @param WP_Admin_Bar $wp_admin_bar Admin Bar instance.
775 */
776 public function add_my_sites_submenu( $wp_admin_bar ) {
777 $current_user = wp_get_current_user();
778
779 $blog_name = get_bloginfo( 'name' );
780 if ( empty( $blog_name ) ) {
781 $blog_name = $this->primary_site_slug;
782 }
783
784 if ( mb_strlen( $blog_name ) > 20 ) {
785 $blog_name = mb_substr( html_entity_decode( $blog_name, ENT_QUOTES ), 0, 20 ) . '&hellip;';
786 }
787
788 $wp_admin_bar->add_menu(
789 array(
790 'parent' => 'root-default',
791 'id' => 'blog',
792 'title' => _n( 'My Site', 'My Sites', $this->user_site_count, 'jetpack' ),
793 'href' => '#',
794 'meta' => array(
795 'class' => 'my-sites mb-trackable',
796 ),
797 )
798 );
799
800 if ( $this->user_site_count > 1 ) {
801 $wp_admin_bar->add_menu(
802 array(
803 'parent' => 'blog',
804 'id' => 'switch-site',
805 'title' => esc_html__( 'Switch Site', 'jetpack' ),
806 'href' => 'https://wordpress.com/sites',
807 )
808 );
809 } else {
810 $wp_admin_bar->add_menu(
811 array(
812 'parent' => 'blog',
813 'id' => 'new-site',
814 'title' => esc_html__( '+ Add New WordPress', 'jetpack' ),
815 'href' => 'https://wordpress.com/start?ref=admin-bar-logged-in',
816 )
817 );
818 }
819
820 if ( is_user_member_of_blog( $current_user->ID ) ) {
821 $blavatar = '';
822 $class = 'current-site';
823
824 if ( has_site_icon() ) {
825 $src = get_site_icon_url();
826 $blavatar = '<img class="avatar" src="' . esc_attr( $src ) . '" alt="Current site avatar">';
827 $class = 'has-blavatar';
828 }
829
830 $blog_info = '<div class="ab-site-icon">' . $blavatar . '</div>';
831 $blog_info .= '<span class="ab-site-title">' . esc_html( $blog_name ) . '</span>';
832 $blog_info .= '<span class="ab-site-description">' . esc_html( $this->primary_site_url ) . '</span>';
833
834 $wp_admin_bar->add_menu(
835 array(
836 'parent' => 'blog',
837 'id' => 'blog-info',
838 'title' => $blog_info,
839 'href' => esc_url( trailingslashit( $this->primary_site_url ) ),
840 'meta' => array(
841 'class' => $class,
842 ),
843 )
844 );
845 }
846
847 // Site Preview.
848 if ( is_admin() ) {
849 $wp_admin_bar->add_menu(
850 array(
851 'parent' => 'blog',
852 'id' => 'site-view',
853 'title' => __( 'View Site', 'jetpack' ),
854 'href' => home_url(),
855 'meta' => array(
856 'class' => 'mb-icon',
857 'target' => '_blank',
858 ),
859 )
860 );
861 }
862
863 // Stats.
864 if ( Jetpack::is_module_active( 'stats' ) && current_user_can( 'view_stats' ) ) {
865 $wp_admin_bar->add_menu(
866 array(
867 'parent' => 'blog',
868 'id' => 'blog-stats',
869 'title' => esc_html__( 'Stats', 'jetpack' ),
870 'href' => 'https://wordpress.com/stats/' . esc_attr( $this->primary_site_slug ),
871 'meta' => array(
872 'class' => 'mb-icon',
873 ),
874 )
875 );
876 }
877
878 if ( current_user_can( 'manage_options' ) ) {
879 $wp_admin_bar->add_menu(
880 array(
881 'parent' => 'blog',
882 'id' => 'activity',
883 'title' => esc_html__( 'Activity', 'jetpack' ),
884 'href' => 'https://wordpress.com/activity-log/' . esc_attr( $this->primary_site_slug ),
885 'meta' => array(
886 'class' => 'mb-icon',
887 ),
888 )
889 );
890 }
891
892 // Add Calypso plans link and plan type indicator.
893 if ( is_user_member_of_blog( $current_user->ID ) && current_user_can( 'manage_options' ) ) {
894 $plans_url = 'https://wordpress.com/plans/' . esc_attr( $this->primary_site_slug );
895 $label = esc_html__( 'Plan', 'jetpack' );
896 $plan = Jetpack_Plan::get();
897
898 $plan_title = $this->create_menu_item_pair(
899 array(
900 'url' => $plans_url,
901 'id' => 'wp-admin-bar-plan',
902 'label' => $label,
903 ),
904 array(
905 'url' => $plans_url,
906 'id' => 'wp-admin-bar-plan-badge',
907 'label' => $plan['product_name_short'],
908 )
909 );
910
911 $wp_admin_bar->add_menu(
912 array(
913 'parent' => 'blog',
914 'id' => 'plan',
915 'title' => $plan_title,
916 'meta' => array(
917 'class' => 'inline-action',
918 ),
919 )
920 );
921 }
922
923 // Publish group.
924 $wp_admin_bar->add_group(
925 array(
926 'parent' => 'blog',
927 'id' => 'publish',
928 )
929 );
930
931 // Publish header.
932 $wp_admin_bar->add_menu(
933 array(
934 'parent' => 'publish',
935 'id' => 'publish-header',
936 'title' => esc_html_x( 'Manage', 'admin bar menu group label', 'jetpack' ),
937 'meta' => array(
938 'class' => 'ab-submenu-header',
939 ),
940 )
941 );
942
943 // Pages.
944 $pages_title = $this->create_menu_item_pair(
945 array(
946 'url' => 'https://wordpress.com/pages/' . esc_attr( $this->primary_site_slug ),
947 'id' => 'wp-admin-bar-edit-page',
948 'label' => esc_html__( 'Site Pages', 'jetpack' ),
949 ),
950 array(
951 'url' => 'https://wordpress.com/page/' . esc_attr( $this->primary_site_slug ),
952 'id' => 'wp-admin-bar-new-page-badge',
953 'label' => esc_html_x( 'Add', 'admin bar menu new item label', 'jetpack' ),
954 )
955 );
956
957 if ( ! current_user_can( 'edit_pages' ) ) {
958 $pages_title = $this->create_menu_item_anchor(
959 'ab-item ab-primary mb-icon',
960 'https://wordpress.com/pages/' . esc_attr( $this->primary_site_slug ),
961 esc_html__( 'Site Pages', 'jetpack' ),
962 'wp-admin-bar-edit-page'
963 );
964 }
965
966 $wp_admin_bar->add_menu(
967 array(
968 'parent' => 'publish',
969 'id' => 'new-page',
970 'title' => $pages_title,
971 'meta' => array(
972 'class' => 'inline-action',
973 ),
974 )
975 );
976
977 // Blog Posts.
978 $posts_title = $this->create_menu_item_pair(
979 array(
980 'url' => 'https://wordpress.com/posts/' . esc_attr( $this->primary_site_slug ),
981 'id' => 'wp-admin-bar-edit-post',
982 'label' => esc_html__( 'Blog Posts', 'jetpack' ),
983 ),
984 array(
985 'url' => 'https://wordpress.com/post/' . esc_attr( $this->primary_site_slug ),
986 'id' => 'wp-admin-bar-new-post-badge',
987 'label' => esc_html_x( 'Add', 'admin bar menu new item label', 'jetpack' ),
988 )
989 );
990
991 if ( ! current_user_can( 'edit_posts' ) ) {
992 $posts_title = $this->create_menu_item_anchor(
993 'ab-item ab-primary mb-icon',
994 'https://wordpress.com/posts/' . esc_attr( $this->primary_site_slug ),
995 esc_html__( 'Blog Posts', 'jetpack' ),
996 'wp-admin-bar-edit-post'
997 );
998 }
999
1000 $wp_admin_bar->add_menu(
1001 array(
1002 'parent' => 'publish',
1003 'id' => 'new-post',
1004 'title' => $posts_title,
1005 'meta' => array(
1006 'class' => 'inline-action mb-trackable',
1007 ),
1008 )
1009 );
1010
1011 // Comments.
1012 if ( current_user_can( 'moderate_comments' ) ) {
1013 $wp_admin_bar->add_menu(
1014 array(
1015 'parent' => 'publish',
1016 'id' => 'comments',
1017 'title' => __( 'Comments', 'jetpack' ),
1018 'href' => 'https://wordpress.com/comments/' . esc_attr( $this->primary_site_slug ),
1019 'meta' => array(
1020 'class' => 'mb-icon',
1021 ),
1022 )
1023 );
1024 }
1025
1026 // Testimonials.
1027 if ( Jetpack::is_module_active( 'custom-content-types' ) && get_option( 'jetpack_testimonial' ) ) {
1028 $testimonials_title = $this->create_menu_item_pair(
1029 array(
1030 'url' => 'https://wordpress.com/types/jetpack-testimonial/' . esc_attr( $this->primary_site_slug ),
1031 'id' => 'wp-admin-bar-edit-testimonial',
1032 'label' => esc_html__( 'Testimonials', 'jetpack' ),
1033 ),
1034 array(
1035 'url' => 'https://wordpress.com/edit/jetpack-testimonial/' . esc_attr( $this->primary_site_slug ),
1036 'id' => 'wp-admin-bar-new-testimonial',
1037 'label' => esc_html_x( 'Add', 'Button label for adding a new item via the toolbar menu', 'jetpack' ),
1038 )
1039 );
1040
1041 if ( ! current_user_can( 'edit_pages' ) ) {
1042 $testimonials_title = $this->create_menu_item_anchor(
1043 'ab-item ab-primary mb-icon',
1044 'https://wordpress.com/types/jetpack-testimonial/' . esc_attr( $this->primary_site_slug ),
1045 esc_html__( 'Testimonials', 'jetpack' ),
1046 'wp-admin-bar-edit-testimonial'
1047 );
1048 }
1049
1050 $wp_admin_bar->add_menu(
1051 array(
1052 'parent' => 'publish',
1053 'id' => 'new-jetpack-testimonial',
1054 'title' => $testimonials_title,
1055 'meta' => array(
1056 'class' => 'inline-action',
1057 ),
1058 )
1059 );
1060 }
1061
1062 // Portfolio.
1063 if ( Jetpack::is_module_active( 'custom-content-types' ) && get_option( 'jetpack_portfolio' ) ) {
1064 $portfolios_title = $this->create_menu_item_pair(
1065 array(
1066 'url' => 'https://wordpress.com/types/jetpack-portfolio/' . esc_attr( $this->primary_site_slug ),
1067 'id' => 'wp-admin-bar-edit-portfolio',
1068 'label' => esc_html__( 'Portfolio', 'jetpack' ),
1069 ),
1070 array(
1071 'url' => 'https://wordpress.com/edit/jetpack-portfolio/' . esc_attr( $this->primary_site_slug ),
1072 'id' => 'wp-admin-bar-new-portfolio',
1073 'label' => esc_html_x( 'Add', 'Button label for adding a new item via the toolbar menu', 'jetpack' ),
1074 )
1075 );
1076
1077 if ( ! current_user_can( 'edit_pages' ) ) {
1078 $portfolios_title = $this->create_menu_item_anchor(
1079 'ab-item ab-primary mb-icon',
1080 'https://wordpress.com/types/jetpack-portfolio/' . esc_attr( $this->primary_site_slug ),
1081 esc_html__( 'Portfolio', 'jetpack' ),
1082 'wp-admin-bar-edit-portfolio'
1083 );
1084 }
1085
1086 $wp_admin_bar->add_menu(
1087 array(
1088 'parent' => 'publish',
1089 'id' => 'new-jetpack-portfolio',
1090 'title' => $portfolios_title,
1091 'meta' => array(
1092 'class' => 'inline-action',
1093 ),
1094 )
1095 );
1096 }
1097
1098 if ( current_user_can( 'edit_theme_options' ) ) {
1099 // Look and Feel group.
1100 $wp_admin_bar->add_group(
1101 array(
1102 'parent' => 'blog',
1103 'id' => 'look-and-feel',
1104 )
1105 );
1106
1107 // Look and Feel header.
1108 $wp_admin_bar->add_menu(
1109 array(
1110 'parent' => 'look-and-feel',
1111 'id' => 'look-and-feel-header',
1112 'title' => esc_html_x( 'Personalize', 'admin bar menu group label', 'jetpack' ),
1113 'meta' => array(
1114 'class' => 'ab-submenu-header',
1115 ),
1116 )
1117 );
1118
1119 if ( is_admin() ) {
1120 // In wp-admin the `return` query arg will return to that page after closing the Customizer.
1121 $customizer_url = add_query_arg(
1122 array(
1123 'return' => rawurlencode( site_url( $_SERVER['REQUEST_URI'] ) ),
1124 ),
1125 wp_customize_url()
1126 );
1127 } else {
1128 /*
1129 * On the frontend the `url` query arg will load that page in the Customizer
1130 * and also return to it after closing
1131 * non-home URLs won't work unless we undo domain mapping
1132 * since the Customizer preview is unmapped to always have HTTPS.
1133 */
1134 $current_page = '//' . $this->primary_site_slug . $_SERVER['REQUEST_URI'];
1135 $customizer_url = add_query_arg( array( 'url' => rawurlencode( $current_page ) ), wp_customize_url() );
1136 }
1137
1138 $theme_title = $this->create_menu_item_pair(
1139 array(
1140 'url' => $customizer_url,
1141 'id' => 'wp-admin-bar-cmz',
1142 'label' => esc_html_x( 'Customize', 'admin bar customize item label', 'jetpack' ),
1143 ),
1144 array(
1145 'url' => 'https://wordpress.com/themes/' . esc_attr( $this->primary_site_slug ),
1146 'id' => 'wp-admin-bar-themes',
1147 'label' => esc_html__( 'Themes', 'jetpack' ),
1148 )
1149 );
1150 $meta = array(
1151 'class' => 'mb-icon',
1152 'class' => 'inline-action',
1153 );
1154 $href = false;
1155
1156 $wp_admin_bar->add_menu(
1157 array(
1158 'parent' => 'look-and-feel',
1159 'id' => 'themes',
1160 'title' => $theme_title,
1161 'href' => $href,
1162 'meta' => $meta,
1163 )
1164 );
1165 }
1166
1167 if ( current_user_can( 'manage_options' ) ) {
1168 // Configuration group.
1169 $wp_admin_bar->add_group(
1170 array(
1171 'parent' => 'blog',
1172 'id' => 'configuration',
1173 )
1174 );
1175
1176 // Configuration header.
1177 $wp_admin_bar->add_menu(
1178 array(
1179 'parent' => 'configuration',
1180 'id' => 'configuration-header',
1181 'title' => esc_html_x( 'Configure', 'admin bar menu group label', 'jetpack' ),
1182 'meta' => array(
1183 'class' => 'ab-submenu-header',
1184 ),
1185 )
1186 );
1187
1188 if ( Jetpack::is_module_active( 'publicize' ) || Jetpack::is_module_active( 'sharedaddy' ) ) {
1189 $wp_admin_bar->add_menu(
1190 array(
1191 'parent' => 'configuration',
1192 'id' => 'sharing',
1193 'title' => esc_html__( 'Sharing', 'jetpack' ),
1194 'href' => 'https://wordpress.com/sharing/' . esc_attr( $this->primary_site_slug ),
1195 'meta' => array(
1196 'class' => 'mb-icon',
1197 ),
1198 )
1199 );
1200 }
1201
1202 $people_title = $this->create_menu_item_pair(
1203 array(
1204 'url' => 'https://wordpress.com/people/team/' . esc_attr( $this->primary_site_slug ),
1205 'id' => 'wp-admin-bar-people',
1206 'label' => esc_html__( 'People', 'jetpack' ),
1207 ),
1208 array(
1209 'url' => admin_url( 'user-new.php' ),
1210 'id' => 'wp-admin-bar-people-add',
1211 'label' => esc_html_x( 'Add', 'admin bar people item label', 'jetpack' ),
1212 )
1213 );
1214
1215 $wp_admin_bar->add_menu(
1216 array(
1217 'parent' => 'configuration',
1218 'id' => 'users-toolbar',
1219 'title' => $people_title,
1220 'href' => false,
1221 'meta' => array(
1222 'class' => 'inline-action',
1223 ),
1224 )
1225 );
1226
1227 $plugins_title = $this->create_menu_item_pair(
1228 array(
1229 'url' => 'https://wordpress.com/plugins/' . esc_attr( $this->primary_site_slug ),
1230 'id' => 'wp-admin-bar-plugins',
1231 'label' => esc_html__( 'Plugins', 'jetpack' ),
1232 ),
1233 array(
1234 'url' => 'https://wordpress.com/plugins/manage/' . esc_attr( $this->primary_site_slug ),
1235 'id' => 'wp-admin-bar-plugins-add',
1236 'label' => esc_html_x( 'Manage', 'Label for the button on the Masterbar to manage plugins', 'jetpack' ),
1237 )
1238 );
1239
1240 $wp_admin_bar->add_menu(
1241 array(
1242 'parent' => 'configuration',
1243 'id' => 'plugins',
1244 'title' => $plugins_title,
1245 'href' => false,
1246 'meta' => array(
1247 'class' => 'inline-action',
1248 ),
1249 )
1250 );
1251
1252 if ( jetpack_is_atomic_site() ) {
1253 $domain_title = $this->create_menu_item_pair(
1254 array(
1255 'url' => 'https://wordpress.com/domains/' . esc_attr( $this->primary_site_slug ),
1256 'id' => 'wp-admin-bar-domains',
1257 'label' => esc_html__( 'Domains', 'jetpack' ),
1258 ),
1259 array(
1260 'url' => 'https://wordpress.com/domains/add/' . esc_attr( $this->primary_site_slug ),
1261 'id' => 'wp-admin-bar-domains-add',
1262 'label' => esc_html_x( 'Add', 'Label for the button on the Masterbar to add a new domain', 'jetpack' ),
1263 )
1264 );
1265 $wp_admin_bar->add_menu(
1266 array(
1267 'parent' => 'configuration',
1268 'id' => 'domains',
1269 'title' => $domain_title,
1270 'href' => false,
1271 'meta' => array(
1272 'class' => 'inline-action',
1273 ),
1274 )
1275 );
1276 }
1277
1278 $wp_admin_bar->add_menu(
1279 array(
1280 'parent' => 'configuration',
1281 'id' => 'blog-settings',
1282 'title' => esc_html__( 'Settings', 'jetpack' ),
1283 'href' => 'https://wordpress.com/settings/general/' . esc_attr( $this->primary_site_slug ),
1284 'meta' => array(
1285 'class' => 'mb-icon',
1286 ),
1287 )
1288 );
1289
1290 if ( ! is_admin() ) {
1291 $wp_admin_bar->add_menu(
1292 array(
1293 'parent' => 'configuration',
1294 'id' => 'legacy-dashboard',
1295 'title' => esc_html__( 'Dashboard', 'jetpack' ),
1296 'href' => admin_url(),
1297 'meta' => array(
1298 'class' => 'mb-icon',
1299 ),
1300 )
1301 );
1302 }
1303
1304 // Restore dashboard menu toggle that is needed on mobile views.
1305 if ( is_admin() ) {
1306 $wp_admin_bar->add_menu(
1307 array(
1308 'id' => 'menu-toggle',
1309 'title' => '<span class="ab-icon"></span><span class="screen-reader-text">' . esc_html__( 'Menu', 'jetpack' ) . '</span>',
1310 'href' => '#',
1311 )
1312 );
1313 }
1314
1315 /**
1316 * Fires when menu items are added to the masterbar "My Sites" menu.
1317 *
1318 * @since 5.4.0
1319 */
1320 do_action( 'jetpack_masterbar' );
1321 }
1322 }
1323 }
1324