Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 117
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 / 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
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    $link = ! empty( $notice['link'] ) ? $notice['link'] : '';
141    if ( str_starts_with( $link, '/' ) ) {
142        $link = 'https://wordpress.com' . $link;
143    }
144
145    $user_id    = null;
146    $user_login = null;
147
148    if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
149        global $current_user;
150        $user_id    = $current_user->ID;
151        $user_login = $current_user->user_login;
152    } else {
153        $connection_manager = new Connection_Manager();
154        $wpcom_user_data    = $connection_manager->get_connected_user_data();
155        if ( $wpcom_user_data ) {
156            $user_id    = $wpcom_user_data['ID'];
157            $user_login = $wpcom_user_data['login'];
158        }
159    }
160
161    return array(
162        'dismissNonce' => wp_create_nonce( 'wpcom_dismiss_sidebar_notice' ),
163        'tracks'       => $notice['tracks'] ?? null,
164        'user'         => array(
165            'ID'       => $user_id,
166            'username' => $user_login,
167        ),
168    );
169}
170
171/**
172 * Add a menu page to the admin menu.
173 */
174function wpcom_add_sidebar_notice_menu_page() {
175    $notice = wpcom_get_sidebar_notice();
176    if ( ! $notice ) {
177        return;
178    }
179
180    $link = ! empty( $notice['link'] ) ? $notice['link'] : '';
181    if ( str_starts_with( $link, '/' ) ) {
182        $link = 'https://wordpress.com' . $link;
183    }
184
185    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'] ) . '">';
186    echo '<div class="upsell_banner">';
187    echo '<div class="upsell_banner__text">' . wp_kses( $notice['content'] ?? '', array() ) . '</div>';
188    echo '<a href="' . esc_url( $link ) . '" class="upsell_banner__action button">' . wp_kses( $notice['cta'] ?? '', array() ) . '</a>';
189    echo $notice['dismissible'] ? '<button type="button" class="upsell_banner__dismiss button button-link">' . esc_html__( 'Dismiss', 'jetpack-mu-wpcom' ) . '</button>' : '';
190    echo '</div>';
191    echo '</li>';
192    echo '<script>(function(el){el.parentNode.prepend(el)})(document.getElementById( "toplevel_page_site-notices" ))</script>';
193}
194add_action( 'adminmenu', 'wpcom_add_sidebar_notice_menu_page' );
195
196/**
197 * Handle AJAX requests to dismiss a sidebar notice.
198 */
199function wpcom_dismiss_sidebar_notice() {
200    check_ajax_referer( 'wpcom_dismiss_sidebar_notice' );
201    if ( isset( $_REQUEST['id'] ) && isset( $_REQUEST['feature_class'] ) ) {
202        $id            = sanitize_text_field( wp_unslash( $_REQUEST['id'] ) );
203        $feature_class = sanitize_text_field( wp_unslash( $_REQUEST['feature_class'] ) );
204        if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
205            require_lib( 'jetpack-jitm/jitm-engine' );
206            \JITM\Engine::dismiss( $id, $feature_class );
207        } else {
208            $jitm = \Automattic\Jetpack\JITMS\JITM::get_instance();
209            $jitm->dismiss( $id, $feature_class );
210        }
211    }
212    wp_die();
213}
214add_action( 'wp_ajax_wpcom_dismiss_sidebar_notice', 'wpcom_dismiss_sidebar_notice' );