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