PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 9.1.2
Jetpack – WP Security, Backup, Speed, & Growth v9.1.2
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 9.1.2, at modules/masterbar/masterbar.php

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