Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
4.49% covered (danger)
4.49%
4 / 89
0.00% covered (danger)
0.00%
0 / 10
CRAP
n/a
0 / 0
wpcomsh_is_admin_menu_api_request
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
wpcomsh_mimic_admin_page_load
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
6
wpcomsh_admin_color_scheme_picker_disabled
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
2
wpcomsh_set_connected_user_data_as_user_options
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
56
wpcomsh_activate_nav_unification
0.00% covered (danger)
0.00%
0 / 17
0.00% covered (danger)
0.00%
0 / 1
56
wpcomsh_is_site_sticker_active
66.67% covered (warning)
66.67%
4 / 6
0.00% covered (danger)
0.00%
0 / 1
3.33
wpcomsh_update_plugin_link_destination
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
30
wpcomsh_update_plugin_add_filter
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
12
wpcomsh_get_wpcom_admin_interface_option
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
12
wpcomsh_unsync_color_schemes_on_save
0.00% covered (danger)
0.00%
0 / 19
0.00% covered (danger)
0.00%
0 / 1
12
1<?php
2/**
3 * Customizations to the Masterbar module available in Jetpack.
4 * We want that feature to always be available on Atomic sites.
5 *
6 * @package wpcomsh
7 */
8
9use Automattic\Jetpack\Connection\Manager as Connection_Manager;
10
11/**
12 * Check if the current request is an API request to the `wpcom/v2/admin-menu` endpoint.
13 *
14 * @return bool
15 */
16function wpcomsh_is_admin_menu_api_request() {
17    // phpcs:ignore WordPress.Security
18    return 0 === strpos( $_SERVER['REQUEST_URI'], '/?rest_route=%2Fwpcom%2Fv2%2Fadmin-menu' );
19}
20
21/**
22 * Sets WP_ADMIN constant on API requests for admin menus.
23 *
24 * Attempt to increase our chances that third-party plugins will
25 * register their menu items based on `is_admin()` returning true.
26 *
27 * This has to run before plugins are loaded.
28 */
29function wpcomsh_mimic_admin_page_load() {
30    if ( wpcomsh_is_admin_menu_api_request() ) {
31        // Display errors can cause the API request to fail due to the PHP notice
32        // triggered by `$pagenow` not being correctly determined when `WP_ADMIN`
33        // is forced on a non-WP Admin page.
34        @ini_set( 'display_errors', false ); // phpcs:ignore
35
36        define( 'WP_ADMIN', true );
37        add_action(
38            'wp_loaded',
39            function () {
40                require_once ABSPATH . 'wp-admin/includes/admin.php';
41            }
42        );
43    }
44}
45add_action( 'muplugins_loaded', 'wpcomsh_mimic_admin_page_load' );
46
47/**
48 * Prints the calypso page link for changing a color scheme.
49 **/
50function wpcomsh_admin_color_scheme_picker_disabled() {
51    printf(
52        '<a target="_blank" href="%1$s">%2$s</a>',
53        esc_url( 'https://wordpress.com/me/account' ),
54        esc_html( __( 'Set your color scheme on WordPress.com.', 'wpcomsh' ) )
55    );
56}
57
58/**
59 * Gets data from the `wpcom.getUser` XMLRPC response and set it as user options. This is hooked
60 * into the `set_transient` action that is triggered everytime the XMLRPC response is read.
61 *
62 * @see https://github.com/Automattic/jetpack/blob/57ca1d524a6f6e446c5a3891d3024c71a6b0684b/projects/packages/connection/src/class-manager.php#L676
63 *
64 * @param string $transient  The name of the transient.
65 * @param mixed  $value      Transient value.
66 */
67function wpcomsh_set_connected_user_data_as_user_options( $transient, $value ) {
68    if ( 0 !== strpos( $transient, 'jetpack_connected_user_data_' . get_current_user_id() ) ) {
69        return;
70    }
71
72    if ( ! $value || ! is_array( $value ) ) {
73        return;
74    }
75
76    if ( isset( $value['site_count'] ) ) {
77        update_user_option( get_current_user_id(), 'wpcom_site_count', $value['site_count'] );
78    }
79
80    if ( isset( $value['sidebar_collapsed'] ) ) {
81        set_user_setting( 'mfold', $value['sidebar_collapsed'] ? 'f' : 'o' );
82    }
83}
84
85add_action( 'set_transient', 'wpcomsh_set_connected_user_data_as_user_options', 10, 2 );
86
87/**
88 * Determines whether Nav Unification should be enabled (pbAPfg-Ou-p2).
89 *
90 * This function is hooked into the `jetpack_load_admin_menu_class` filter that lives in Jetpack.
91 * See https://github.com/Automattic/jetpack/blob/507142b09bae12b58e84c0c2b7d20024563f170d/modules%2Fmasterbar.php#L29.
92 *
93 * @return bool Whether Nav Unification should be enabled.
94 */
95function wpcomsh_activate_nav_unification() {
96    remove_filter( 'pre_option_wpcom_admin_interface', 'wpcom_admin_interface_pre_get_option' );
97    $is_wp_admin_menu = get_option( 'wpcom_admin_interface' ) === 'wp-admin';
98
99    if ( function_exists( 'wpcom_admin_interface_pre_get_option' ) ) {
100        add_filter( 'pre_option_wpcom_admin_interface', 'wpcom_admin_interface_pre_get_option', 10 );
101    }
102
103    // Disable when in the redesigned nav.
104    if ( $is_wp_admin_menu ) {
105        return false;
106    }
107
108    $user_id = get_current_user_id();
109
110    // Loads for all API requests to the admin-menu endpoint (i.e. Calypso).
111    if ( wpcomsh_is_admin_menu_api_request() ) {
112        return true;
113    }
114
115    // Disable when explicitly requested. This is an escape hatch for HEs. See paYJgx-1p8-p2.
116    if ( isset( $_GET['disable-nav-unification'] ) ) { // phpcs:ignore WordPress.Security
117        return false;
118    }
119
120    // Disable for users not connected to WP.com.
121    if ( ! class_exists( 'Automattic\Jetpack\Connection\Manager' ) ) {
122        return false;
123    }
124    $connection_manager = new Connection_Manager( 'jetpack' );
125    if ( ! $connection_manager->is_user_connected( $user_id ) ) {
126        return false;
127    }
128
129    // Enabled by default.
130    return true;
131}
132add_filter( 'jetpack_load_admin_menu_class', 'wpcomsh_activate_nav_unification' );
133
134/**
135 * Checks if site sticker is toggled on/off.
136 * For further information/context on Atomic_Persistent_Data and site_stickers please also see this diff: D66496-code
137 *
138 * @param string $sticker_name Name of the site sticker to check.
139 * @return boolean
140 */
141function wpcomsh_is_site_sticker_active( $sticker_name ) {
142    if ( ! class_exists( '\Atomic_Persistent_Data' ) ) {
143        return false;
144    }
145
146    $persistent_data = new \Atomic_Persistent_Data();
147
148    if ( $persistent_data->{"site_sticker_{$sticker_name}"} ) {
149        return true;
150    }
151
152    return false;
153}
154
155/**
156 * Forces the Add New (plugin install) link to be Calypso.
157 *
158 * @param string $url  The complete URL including scheme and path.
159 * @param string $path Path relative to the URL. Blank string if no path is specified.
160 *
161 * @return string
162 */
163function wpcomsh_update_plugin_link_destination( $url, $path ) {
164    // Run only for plugin-install.php links.
165    if ( ! strpos( $url, '/plugin-install.php' ) ) {
166        return $url;
167    }
168
169    // If Jetpack doesn't exist, stay in wp-admin
170    if ( ! class_exists( 'Jetpack' ) ) {
171        return $url;
172    }
173
174    // Run only if SSO is active
175    if ( ! Jetpack::is_module_active( 'sso' ) ) {
176        return $url;
177    }
178
179    // Return WP Admin url for example: plugin-install.php?tab=plugin-information&plugin=classic-editor&TB_iframe=true&width=600&height=550
180    if ( strpos( $path, '?' ) ) {
181        return $url;
182    }
183
184    return 'https://wordpress.com/plugins/' . ( new Automattic\Jetpack\Status() )->get_site_suffix();
185}
186
187/**
188 * Adds filters so that Add New menu & button
189 * redirect to Calypso.
190 *
191 * @return void
192 */
193function wpcomsh_update_plugin_add_filter() {
194    // If site is not connected or nav redesign is enabled, return early.
195    if ( ! class_exists( 'Automattic\Jetpack\Status' ) || get_option( 'wpcom_admin_interface' ) === 'wp-admin' ) {
196        return;
197    }
198
199    // Update any plugin-install.php links appearing in /wp-admin/plugins.php or elsewhere.
200    add_filter( 'self_admin_url', 'wpcomsh_update_plugin_link_destination', 10, 2 );
201}
202add_action( 'admin_menu', 'wpcomsh_update_plugin_add_filter' );
203
204/**
205 * Enable the mailbox in WPCOMSH sites.
206 */
207add_filter( 'jetpack_show_wpcom_inbox_menu', '__return_true' );
208
209/**
210 * Ensure that when getting the wpcom_admin_interface option, we return a value from the persistent data store if
211 * available, otherwise fall back to the option value.
212 *
213 * @return false|string|null
214 */
215function wpcomsh_get_wpcom_admin_interface_option() {
216
217    if ( class_exists( '\Atomic_Persistent_Data' ) ) {
218        $persistent_data = new \Atomic_Persistent_Data();
219
220        // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
221        if ( isset( $persistent_data->WPCOM_ADMIN_INTERFACE ) ) {
222            // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
223            return $persistent_data->WPCOM_ADMIN_INTERFACE;
224        }
225    }
226
227    // Fallback to the current option value.
228    return false;
229}
230// This pre_option_{$option} hook runs before the option is retrieved from the database with get_option().
231add_filter( 'pre_option_wpcom_admin_interface', 'wpcomsh_get_wpcom_admin_interface_option' );
232
233/**
234 * Color scheme from Calypso (/me/account) is stored as user option,
235 * while color scheme from /wp-admin/profile.php is stored as user meta.
236 *
237 * When saving the color scheme from /wp-admin/profile.php, we want to unsync them:
238 *
239 * 1. Read the current color scheme from Calypso (if there's still any).
240 * 2. Delete the color scheme from Calypso, effectively only using color scheme
241 *    from wp-admin going forward.
242 */
243function wpcomsh_unsync_color_schemes_on_save() {
244    // Returns Calypso color scheme (if still exists),
245    // or wp-admin color scheme otherwise.
246    $maybe_synced_color_scheme = get_user_option( 'admin_color' );
247
248    // Always return the (maybe) synced color scheme above.
249    add_filter(
250        'get_user_metadata',
251        function ( $value, $user_id, $meta_key ) use ( $maybe_synced_color_scheme ) {
252            if ( $meta_key === 'admin_color' ) {
253                return $maybe_synced_color_scheme;
254            }
255        },
256        999999,
257        3
258    );
259
260    // Delete the synced color scheme.
261    add_filter(
262        'update_user_metadata',
263        function ( $check, $user_id, $meta_key ) {
264            if ( $meta_key === 'admin_color' ) {
265                delete_user_option( $user_id, 'admin_color' );
266            }
267        },
268        10,
269        3
270    );
271}
272add_action( 'wp_ajax_save-user-color-scheme', 'wpcomsh_unsync_color_schemes_on_save', 1 );