Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
61 / 61
100.00% covered (success)
100.00%
5 / 5
CRAP
100.00% covered (success)
100.00%
1 / 1
Initial_State
100.00% covered (success)
100.00%
61 / 61
100.00% covered (success)
100.00%
5 / 5
19
100.00% covered (success)
100.00%
1 / 1
 get_data
100.00% covered (success)
100.00%
41 / 41
100.00% covered (success)
100.00%
1 / 1
12
 get_wpcom_upgrade_url
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
1
 get_wpcom_hidden_groups
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
3
 get_wpcom_tracks_user_data
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
2
 render
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2/**
3 * The Activity Log React initial state.
4 *
5 * @package automattic/jetpack-activity-log
6 */
7
8namespace Automattic\Jetpack\Activity_Log;
9
10use Automattic\Jetpack\Connection\Manager as Connection_Manager;
11use Automattic\Jetpack\My_Jetpack\Products as My_Jetpack_Products;
12use Automattic\Jetpack\Status;
13use function add_query_arg;
14use function admin_url;
15use function apply_filters;
16use function esc_url_raw;
17use function function_exists;
18use function get_bloginfo;
19use function get_current_blog_id;
20use function get_locale;
21use function get_option;
22use function get_site_url;
23use function rawurlencode;
24use function wp_create_nonce;
25use function wp_get_current_user;
26use function wp_json_encode;
27use function wp_parse_url;
28
29/**
30 * The Activity Log React initial state.
31 */
32class Initial_State {
33    /**
34     * Get the initial state data.
35     *
36     * @return array
37     */
38    private function get_data() {
39        $gmt_offset      = get_option( 'gmt_offset' );
40        $timezone_string = get_option( 'timezone_string' );
41        $home_host       = wp_parse_url( get_site_url(), PHP_URL_HOST );
42        $site_suffix     = ( new Status() )->get_site_suffix();
43        $is_wpcom_simple = Jetpack_Activity_Log::is_wpcom_simple();
44        $has_access      = REST_Controller::has_activity_logs_access();
45        $upgrade         = array(
46            'slug'               => 'security',
47            'title'              => 'Jetpack Security',
48            'wpcom_product_slug' => 'jetpack_security_t1_yearly',
49        );
50        if ( ! $has_access && ! $is_wpcom_simple && method_exists( My_Jetpack_Products::class, 'get_bundle_offer' ) ) {
51            $upgrade = My_Jetpack_Products::get_bundle_offer( 'security' );
52        }
53
54        return array(
55            'upgrade'       => $upgrade,
56            'jetpackStatus' => array(
57                'calypsoSlug'        => $site_suffix,
58                /**
59                 * Filters the in-admin address "Restore backup" opens, with `{rewindId}` as the placeholder.
60                 * Empty keeps the Jetpack Cloud restore flow.
61                 *
62                 * @since 0.7.0
63                 *
64                 * @param string $template Restore URL template, or an empty string.
65                 */
66                'restoreUrlTemplate' => (string) apply_filters( 'jetpack_activity_log_restore_url_template', '' ),
67                /**
68                 * Filters the in-admin address a link to a backup opens, with `{rewindId}` as the placeholder.
69                 * Empty leaves such links as plain text.
70                 *
71                 * @since 0.7.0
72                 *
73                 * @param string $template Backup URL template, or an empty string.
74                 */
75                'backupUrlTemplate'  => (string) apply_filters( 'jetpack_activity_log_backup_url_template', '' ),
76            ),
77            'config'        => array(
78                // Simple sites have no Jetpack REST API to proxy through, so the app calls WordPress.com directly.
79                'apiSource'             => $is_wpcom_simple ? 'wpcom' : 'jetpack',
80                'wpcomUpgradeUrl'       => $is_wpcom_simple ? self::get_wpcom_upgrade_url( $site_suffix ) : '',
81                'tracksUserData'        => $is_wpcom_simple ? self::get_wpcom_tracks_user_data() : null,
82                'knownThreatsAvailable' => REST_Controller::known_threats_available(),
83                'hiddenGroups'          => $is_wpcom_simple ? self::get_wpcom_hidden_groups() : array(),
84            ),
85            'siteData'      => array(
86                'id'                    => Connection_Manager::get_site_id( true ),
87                'title'                 => get_bloginfo( 'name' ) ? get_bloginfo( 'name' ) : get_site_url(),
88                'adminUrl'              => esc_url_raw( admin_url() ),
89                'slug'                  => is_string( $home_host ) ? $home_host : '',
90                'gmtOffset'             => is_numeric( $gmt_offset ) ? (float) $gmt_offset : 0.0,
91                'timezoneString'        => is_string( $timezone_string ) ? $timezone_string : '',
92                'locale'                => str_replace( '_', '-', (string) get_locale() ),
93                // The paid-plan capability check. Drives the free-tier
94                // upsell callout and matches the server-side clamp in
95                // REST_Controller::get_activity_log(). The result is
96                // cached in a site transient by the REST controller
97                // (5-minute TTL); on a cache miss this call issues a
98                // synchronous WPCOM request (~200–800ms typical, up to
99                // the 2s internal timeout) that blocks page rendering
100                // until it returns.
101                'hasActivityLogsAccess' => $has_access,
102            ),
103            'nonces'        => array(
104                // Consumed by `UpsellCallout` to build a `redirect_to`
105                // URL that invalidates the access cache on return from
106                // checkout. See `Jetpack_Activity_Log::admin_init()`.
107                'refreshAccess' => wp_create_nonce( Jetpack_Activity_Log::REFRESH_ACCESS_NONCE_ACTION ),
108            ),
109        );
110    }
111
112    /**
113     * WordPress.com plan selection, returning here after checkout or cancel.
114     *
115     * @param string $site_suffix The site's Calypso slug.
116     * @return string
117     */
118    private static function get_wpcom_upgrade_url( $site_suffix ) {
119        $page_url = rawurlencode( admin_url( 'admin.php?page=' . Jetpack_Activity_Log::PAGE_SLUG ) );
120
121        return add_query_arg(
122            array(
123                'siteSlug'    => rawurlencode( $site_suffix ),
124                'redirect_to' => $page_url,
125                'cancel_to'   => $page_url,
126            ),
127            'https://wordpress.com/setup/plan-upgrade/'
128        );
129    }
130
131    /**
132     * Activity groups to hide on a Simple site without backups, such as events left over from an Atomic past.
133     *
134     * @return string[]
135     */
136    private static function get_wpcom_hidden_groups() {
137        if ( function_exists( 'wpcom_site_has_feature' ) && wpcom_site_has_feature( 'backups-self-serve', get_current_blog_id() ) ) {
138            return array();
139        }
140
141        return array( 'rewind', 'scan' );
142    }
143
144    /**
145     * The Tracks identity of the current user, who on Simple is the WordPress.com user.
146     *
147     * @return array{userid: int, username: string}|null
148     */
149    private static function get_wpcom_tracks_user_data() {
150        $user = wp_get_current_user();
151        if ( ! $user->exists() ) {
152            return null;
153        }
154
155        return array(
156            'userid'   => $user->ID,
157            'username' => $user->user_login,
158        );
159    }
160
161    /**
162     * Render the initial state into a JavaScript variable.
163     *
164     * @return string
165     */
166    public function render() {
167        return 'var JPACTIVITYLOG_INITIAL_STATE=' . wp_json_encode( $this->get_data(), JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_HEX_AMP ) . ';';
168    }
169}