Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 109
0.00% covered (danger)
0.00%
0 / 5
CRAP
n/a
0 / 0
wpcom_enqueue_sidebar_notice_assets
0.00% covered (danger)
0.00%
0 / 22
0.00% covered (danger)
0.00%
0 / 1
6
wpcom_get_sidebar_notice
0.00% covered (danger)
0.00%
0 / 30
0.00% covered (danger)
0.00%
0 / 1
30
wpcom_get_sidebar_notice_data
0.00% covered (danger)
0.00%
0 / 25
0.00% covered (danger)
0.00%
0 / 1
56
wpcom_add_sidebar_notice_menu_page
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
30
wpcom_dismiss_sidebar_notice
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
30
1<?php
2/**
3 * WordPress.com sidebar notice
4 *
5 * Adds WordPress.com upsell notice to WordPress sidebar.
6 *
7 * @package automattic/jetpack-mu-wpcom
8 */
9
10use Automattic\Jetpack\Connection\Manager as Connection_Manager;
11use Automattic\Jetpack\Jetpack_Mu_Wpcom;
12
13remove_filter( 'pre_option_wpcom_admin_interface', 'wpcom_admin_interface_pre_get_option' );
14$is_wp_admin = get_option( 'wpcom_admin_interface' ) === 'wp-admin';
15add_filter( 'pre_option_wpcom_admin_interface', 'wpcom_admin_interface_pre_get_option', 10 );
16
17if ( ! $is_wp_admin ) {
18    return;
19}
20
21/**
22 * Enqueue assets needed by the WordPress.com sidebar notice.
23 */
24function wpcom_enqueue_sidebar_notice_assets() {
25    $data = wpcom_get_sidebar_notice_data();
26    if ( ! $data ) {
27        return;
28    }
29
30    $asset_file = include Jetpack_Mu_Wpcom::BASE_DIR . 'build/wpcom-sidebar-notice/wpcom-sidebar-notice.asset.php';
31
32    wp_enqueue_script(
33        'wpcom-sidebar-notice',
34        plugins_url( 'build/wpcom-sidebar-notice/wpcom-sidebar-notice.js', Jetpack_Mu_Wpcom::BASE_FILE ),
35        $asset_file['dependencies'] ?? array(),
36        $asset_file['version'] ?? filemtime( Jetpack_Mu_Wpcom::BASE_DIR . 'build/wpcom-sidebar-notice/wpcom-sidebar-notice.js' ),
37        array(
38            'strategy'  => 'defer',
39            'in_footer' => true,
40        )
41    );
42
43    wp_enqueue_style(
44        'wpcom-sidebar-notice',
45        plugins_url( 'build/wpcom-sidebar-notice/wpcom-sidebar-notice.css', Jetpack_Mu_Wpcom::BASE_FILE ),
46        array(),
47        $asset_file['version'] ?? filemtime( Jetpack_Mu_Wpcom::BASE_DIR . 'build/wpcom-sidebar-notice/wpcom-sidebar-notice.css' )
48    );
49
50    $inline_script = 'const wpcomSidebarNoticeData = ' . wp_json_encode( $data, JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_HEX_AMP ) . ';';
51    wp_add_inline_script( 'wpcom-sidebar-notice', $inline_script, 'before' );
52}
53add_action( 'admin_enqueue_scripts', 'wpcom_enqueue_sidebar_notice_assets' );
54
55/**
56 * Returns the first available sidebar notice.
57 *
58 * @return array | null
59 */
60function wpcom_get_sidebar_notice() {
61    static $cached_notice = null;
62    static $cache_loaded  = false;
63
64    if ( $cache_loaded ) {
65        return $cached_notice;
66    }
67
68    $message_path = 'calypso:sites:sidebar_notice';
69
70    if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
71        require_lib( 'jetpack-jitm/jitm-engine' );
72        $jitm_engine = new \JITM\Engine();
73
74        $current_user = wp_get_current_user();
75        $user_id      = $current_user->ID;
76        $user_roles   = implode( ',', $current_user->roles );
77        $query_string = array( 'message_path' => $message_path );
78
79        $message = $jitm_engine->get_top_messages( $message_path, $user_id, $user_roles, $query_string );
80    } else {
81        $jitm    = \Automattic\Jetpack\JITMS\JITM::get_instance();
82        $message = $jitm->get_messages( $message_path, array( 'message_path' => $message_path ), false );
83    }
84
85    $cache_loaded = true;
86
87    if ( ! isset( $message[0] ) ) {
88        $cached_notice = null;
89        return null;
90    }
91
92    // Serialize message as object (on Simple sites we have an array, on Atomic sites we have an object).
93    $message = json_decode( wp_json_encode( $message[0], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE ) );
94
95    $cached_notice = array(
96        'content'       => $message->content->message,
97        'cta'           => $message->CTA->message, // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
98        'link'          => $message->CTA->link, // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
99        'dismissible'   => $message->is_dismissible,
100        'feature_class' => $message->feature_class,
101        'id'            => $message->id,
102        'tracks'        => $message->tracks ?? null,
103    );
104
105    return $cached_notice;
106}
107
108/**
109 * Get sidebar notice data.
110 */
111function wpcom_get_sidebar_notice_data() {
112    $notice = wpcom_get_sidebar_notice();
113    if ( ! $notice ) {
114        return;
115    }
116
117    $link = ! empty( $notice['link'] ) ? $notice['link'] : '';
118    if ( str_starts_with( $link, '/' ) ) {
119        $link = 'https://wordpress.com' . $link;
120    }
121
122    $user_id    = null;
123    $user_login = null;
124
125    if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
126        global $current_user;
127        $user_id    = $current_user->ID;
128        $user_login = $current_user->user_login;
129    } else {
130        $connection_manager = new Connection_Manager();
131        $wpcom_user_data    = $connection_manager->get_connected_user_data();
132        if ( $wpcom_user_data ) {
133            $user_id    = $wpcom_user_data['ID'];
134            $user_login = $wpcom_user_data['login'];
135        }
136    }
137
138    return array(
139        'dismissNonce' => wp_create_nonce( 'wpcom_dismiss_sidebar_notice' ),
140        'tracks'       => $notice['tracks'] ?? null,
141        'user'         => array(
142            'ID'       => $user_id,
143            'username' => $user_login,
144        ),
145    );
146}
147
148/**
149 * Add a menu page to the admin menu.
150 */
151function wpcom_add_sidebar_notice_menu_page() {
152    $notice = wpcom_get_sidebar_notice();
153    if ( ! $notice ) {
154        return;
155    }
156
157    $link = ! empty( $notice['link'] ) ? $notice['link'] : '';
158    if ( str_starts_with( $link, '/' ) ) {
159        $link = 'https://wordpress.com' . $link;
160    }
161
162    echo '<li id="toplevel_page_site-notices" class="toplevel_page_site-notices" data-id="' . esc_attr( $notice['id'] ) . '" data-feature-class="' . esc_attr( $notice['feature_class'] ) . '">';
163    echo '<div class="upsell_banner">';
164    echo '<div class="upsell_banner__text">' . wp_kses( $notice['content'] ?? '', array() ) . '</div>';
165    echo '<a href="' . esc_url( $link ) . '" class="upsell_banner__action button">' . wp_kses( $notice['cta'] ?? '', array() ) . '</a>';
166    echo $notice['dismissible'] ? '<button type="button" class="upsell_banner__dismiss button button-link">' . esc_html__( 'Dismiss', 'jetpack-mu-wpcom' ) . '</button>' : '';
167    echo '</div>';
168    echo '</li>';
169    echo '<script>(function(el){el.parentNode.prepend(el)})(document.getElementById( "toplevel_page_site-notices" ))</script>';
170}
171add_action( 'adminmenu', 'wpcom_add_sidebar_notice_menu_page' );
172
173/**
174 * Handle AJAX requests to dismiss a sidebar notice.
175 */
176function wpcom_dismiss_sidebar_notice() {
177    check_ajax_referer( 'wpcom_dismiss_sidebar_notice' );
178    if ( isset( $_REQUEST['id'] ) && isset( $_REQUEST['feature_class'] ) ) {
179        $id            = sanitize_text_field( wp_unslash( $_REQUEST['id'] ) );
180        $feature_class = sanitize_text_field( wp_unslash( $_REQUEST['feature_class'] ) );
181        if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
182            require_lib( 'jetpack-jitm/jitm-engine' );
183            \JITM\Engine::dismiss( $id, $feature_class );
184        } else {
185            $jitm = \Automattic\Jetpack\JITMS\JITM::get_instance();
186            $jitm->dismiss( $id, $feature_class );
187        }
188    }
189    wp_die();
190}
191add_action( 'wp_ajax_wpcom_dismiss_sidebar_notice', 'wpcom_dismiss_sidebar_notice' );