Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
26.51% covered (danger)
26.51%
22 / 83
0.00% covered (danger)
0.00%
0 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
UI
26.51% covered (danger)
26.51%
22 / 83
0.00% covered (danger)
0.00%
0 / 7
492.89
0.00% covered (danger)
0.00%
0 / 1
 init
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
12
 enqueue_scripts
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
6
 render_container
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 get_initial_state
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 get_initial_state_data
0.00% covered (danger)
0.00%
0 / 25
0.00% covered (danger)
0.00%
0 / 1
56
 get_consumer_data
84.62% covered (warning)
84.62%
22 / 26
0.00% covered (danger)
0.00%
0 / 1
16.93
 get_platform
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
20
1<?php
2/**
3 * Identity_Crisis UI class of the Connection package.
4 *
5 * @package automattic/jetpack-connection
6 */
7
8namespace Automattic\Jetpack\IdentityCrisis;
9
10use Automattic\Jetpack\Assets;
11use Automattic\Jetpack\Identity_Crisis;
12use Automattic\Jetpack\Status;
13use Automattic\Jetpack\Status\Host;
14use Automattic\Jetpack\Tracking;
15use Jetpack_Options;
16use Jetpack_Tracks_Client;
17
18/**
19 * The Identity Crisis UI handling.
20 */
21class UI {
22
23    /**
24     * Temporary storage for consumer data.
25     *
26     * @var array
27     */
28    private static $consumers;
29
30    /**
31     * Initialization.
32     */
33    public static function init() {
34        if ( did_action( 'jetpack_identity_crisis_ui_init' ) ) {
35            return;
36        }
37
38        /**
39         * Action called after initializing Identity Crisis UI.
40         *
41         * @since 0.6.0
42         */
43        do_action( 'jetpack_identity_crisis_ui_init' );
44
45        $idc_data = Identity_Crisis::check_identity_crisis();
46
47        if ( false === $idc_data ) {
48            return;
49        }
50
51        add_action( 'admin_enqueue_scripts', array( static::class, 'enqueue_scripts' ) );
52
53        Tracking::register_tracks_functions_scripts( true );
54    }
55
56    /**
57     * Enqueue scripts!
58     */
59    public static function enqueue_scripts() {
60        if ( is_admin() ) {
61            Assets::register_script(
62                'jp_identity_crisis_banner',
63                '../../dist/identity-crisis.js',
64                __FILE__,
65                array(
66                    'in_footer'  => true,
67                    'textdomain' => 'jetpack-connection',
68                )
69            );
70            Assets::enqueue_script( 'jp_identity_crisis_banner' );
71            wp_add_inline_script( 'jp_identity_crisis_banner', static::get_initial_state(), 'before' );
72
73            add_action( 'admin_notices', array( static::class, 'render_container' ) );
74        }
75    }
76
77    /**
78     * Create the container element for the IDC banner.
79     */
80    public static function render_container() {
81        ?>
82        <div id="jp-identity-crisis-container" class="notice"></div>
83        <?php
84    }
85
86    /**
87     * Return the rendered initial state JavaScript code.
88     *
89     * @return string
90     */
91    private static function get_initial_state() {
92        return 'var JP_IDENTITY_CRISIS__INITIAL_STATE=' . wp_json_encode( static::get_initial_state_data(), JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_HEX_AMP ) . ';';
93    }
94
95    /**
96     * Get the initial state data.
97     *
98     * @return array
99     */
100    private static function get_initial_state_data() {
101        $idc_urls                           = Identity_Crisis::get_mismatched_urls();
102        $current_screen                     = get_current_screen();
103        $is_admin                           = current_user_can( 'jetpack_disconnect' );
104        $possible_dynamic_site_url_detected = (bool) Identity_Crisis::detect_possible_dynamic_site_url();
105        $is_development_site                = (bool) Status::is_development_site();
106
107        return array(
108            'WP_API_root'                    => esc_url_raw( rest_url() ),
109            'WP_API_nonce'                   => wp_create_nonce( 'wp_rest' ),
110            'wpcomHomeUrl'                   => ( is_array( $idc_urls ) && array_key_exists( 'wpcom_url', $idc_urls ) ) ? $idc_urls['wpcom_url'] : null,
111            'currentUrl'                     => ( is_array( $idc_urls ) && array_key_exists( 'current_url', $idc_urls ) ) ? $idc_urls['current_url'] : null,
112            'redirectUri'                    => isset( $_SERVER['REQUEST_URI'] ) ? str_replace( '/wp-admin/', '/', filter_var( wp_unslash( $_SERVER['REQUEST_URI'] ) ) ) : '',
113            'tracksUserData'                 => Jetpack_Tracks_Client::get_connected_user_tracks_identity(),
114            'tracksEventData'                => array(
115                'isAdmin'       => $is_admin,
116                'currentScreen' => $current_screen ? $current_screen->id : false,
117                'blogID'        => Jetpack_Options::get_option( 'id' ),
118                'platform'      => static::get_platform(),
119            ),
120            'isSafeModeConfirmed'            => Identity_Crisis::$is_safe_mode_confirmed,
121            'consumerData'                   => static::get_consumer_data(),
122            'isAdmin'                        => $is_admin,
123            'possibleDynamicSiteUrlDetected' => $possible_dynamic_site_url_detected,
124            'isDevelopmentSite'              => $is_development_site,
125
126            /**
127             * Use the filter to provide custom HTML container element ID.
128             *
129             * The element may be added after the page loads, within 60 seconds of it;
130             * the screen is rendered into it once.
131             *
132             * @since 0.10.0
133             *
134             * @param string|null $containerID The container ID.
135             */
136            'containerID'                    => apply_filters( 'identity_crisis_container_id', null ),
137        );
138    }
139
140    /**
141     * Get the package consumer data.
142     *
143     * @return array
144     */
145    public static function get_consumer_data() {
146        if ( null !== static::$consumers ) {
147            return static::$consumers;
148        }
149
150        $consumers = apply_filters( 'jetpack_idc_consumers', array() );
151
152        if ( ! $consumers ) {
153            return array();
154        }
155
156        usort(
157            $consumers,
158            function ( $c1, $c2 ) {
159                $priority1 = ( array_key_exists( 'priority', $c1 ) && (int) $c1['priority'] ) ? (int) $c1['priority'] : 10;
160                $priority2 = ( array_key_exists( 'priority', $c2 ) && (int) $c2['priority'] ) ? (int) $c2['priority'] : 10;
161
162                return $priority1 <=> $priority2;
163            }
164        );
165
166        $consumer_chosen     = null;
167        $consumer_url_length = 0;
168        foreach ( $consumers as &$consumer ) {
169            if ( empty( $consumer['admin_page'] ) || ! is_string( $consumer['admin_page'] ) ) {
170                continue;
171            }
172
173            if ( isset( $consumer['customContent'] ) && is_callable( $consumer['customContent'] ) ) {
174                $consumer['customContent'] = call_user_func( $consumer['customContent'] );
175            }
176
177            if ( isset( $_SERVER['REQUEST_URI'] ) && str_starts_with( filter_var( wp_unslash( $_SERVER['REQUEST_URI'] ) ), $consumer['admin_page'] ) && strlen( $consumer['admin_page'] ) > $consumer_url_length ) {
178                $consumer_chosen     = $consumer;
179                $consumer_url_length = strlen( $consumer['admin_page'] );
180            }
181        }
182        unset( $consumer );
183
184        static::$consumers = $consumer_chosen ? $consumer_chosen : array_shift( $consumers );
185
186        return static::$consumers;
187    }
188
189    /**
190     * Get the site platform.
191     *
192     * @since 9.15.0 Public, so the Connectors card can send the same value to Tracks.
193     *
194     * @return string
195     */
196    public static function get_platform() {
197        $host = new Host();
198
199        if ( $host->is_woa_site() ) {
200            return 'woa';
201        }
202
203        if ( $host->is_vip_site() ) {
204            return 'vip';
205        }
206
207        if ( $host->is_newspack_site() ) {
208            return 'newspack';
209        }
210
211        return 'self-hosted';
212    }
213}