← All changes
|
jetpack_vendor/automattic/jetpack-stats-admin/src/class-dashboard.php
+124
-230
12.0.3
→
16.3-beta
View file →
| @@ -7,12 +7,11 @@ | ||
| 7 | 7 | |
| 8 | 8 | namespace Automattic\Jetpack\Stats_Admin; |
| 9 | 9 | |
| 10 | 10 | use Automattic\Jetpack\Admin_UI\Admin_Menu; |
| 11 | -use Automattic\Jetpack\Assets; | |
| 12 | -use Automattic\Jetpack\Modules; | |
| 11 | +use Automattic\Jetpack\Connection\Initial_State as Connection_Initial_State; | |
| 12 | +use Automattic\Jetpack\Current_Plan as Jetpack_Plan; | |
| 13 | 13 | use Automattic\Jetpack\Stats\Options as Stats_Options; |
| 14 | -use Jetpack_Options; | |
| 15 | 14 | |
| 16 | 15 | /** |
| 17 | 16 | * Responsible for adding a stats dashboard to wp-admin. |
| 18 | 17 | * |
| @@ -18,30 +17,28 @@ | ||
| 18 | 17 | * |
| 19 | 18 | * @package jetpack-stats-admin |
| 20 | 19 | */ |
| 21 | 20 | class Dashboard { |
| 22 | - // This is a fixed list @see https://github.com/Automattic/wp-calypso/pull/71442/ | |
| 23 | - const JS_DEPENDENCIES = array( 'lodash', 'react', 'react-dom', 'wp-api-fetch', 'wp-components', 'wp-compose', 'wp-element', 'wp-html-entities', 'wp-i18n', 'wp-is-shallow-equal', 'wp-polyfill', 'wp-primitives', 'wp-url', 'wp-warning', 'moment' ); | |
| 24 | - const ODYSSEY_CDN_URL = 'https://widgets.wp.com/odyssey-stats/%s/%s'; | |
| 25 | - const OPT_OUT_NEW_STATS_FEATURE_CLASS = 'opt-out-new-stats'; | |
| 26 | 21 | /** |
| 27 | - * We bump the asset version when the Jetpack back end is not compatible anymore. | |
| 22 | + * Whether the class has been initialized | |
| 23 | + * | |
| 24 | + * @var boolean | |
| 28 | 25 | */ |
| 29 | - const ODYSSEY_STATS_VERSION = 'v1'; | |
| 30 | - const ODYSSEY_STATS_CACHE_BUSTER_CACHE_KEY = 'odyssey_stats_admin_asset_cache_buster'; | |
| 26 | + private static $initialized = false; | |
| 31 | 27 | |
| 32 | 28 | /** |
| 33 | - * Whether the class has been initialized | |
| 29 | + * Transient that throttles the plan refresh below. | |
| 34 | 30 | * |
| 35 | - * @var boolean | |
| 31 | + * @var string | |
| 36 | 32 | */ |
| 37 | - private static $initialized = false; | |
| 33 | + private const PLAN_REFRESH_TRANSIENT = 'jetpack_stats_admin_plan_refresh'; | |
| 38 | 34 | |
| 39 | 35 | /** |
| 40 | 36 | * Priority for the dashboard menu |
| 41 | 37 | * For Jetpack sites: Jetpack uses 998 and 'Admin_Menu' uses 1000, so we need to use 999. |
| 42 | - * For simple site: the value is overriden in a child class with value 100000 to wait for all menus to be registered. | |
| 43 | 38 | * |
| 39 | + * Admin_Menu registers what it has queued at priority 1000, so this has to stay below it. | |
| 40 | + * | |
| 44 | 41 | * @var int |
| 45 | 42 | */ |
| 46 | 43 | protected $menu_priority = 999; |
| 47 | 44 | |
| @@ -60,36 +57,77 @@ | ||
| 60 | 57 | */ |
| 61 | 58 | public function init_hooks() { |
| 62 | 59 | self::$initialized = true; |
| 63 | 60 | // Jetpack uses 998 and 'Admin_Menu' uses 1000. |
| 64 | - add_action( 'admin_menu', array( $this, 'add_wp_admin_submenu' ), $this->menu_priority ); | |
| 61 | + add_action( 'admin_menu', array( $this, 'add_wp_admin_menu' ), $this->menu_priority ); | |
| 65 | 62 | } |
| 66 | 63 | |
| 67 | 64 | /** |
| 68 | - * The page to be added to submenu | |
| 65 | + * Add a "Stats" top-level admin menu. | |
| 66 | + * | |
| 67 | + * Declares no `product` gate: that resolves false without the Jetpack plugin, which is | |
| 68 | + * exactly when the standalone Stats plugin registers this page. | |
| 69 | + * | |
| 70 | + * @return void | |
| 69 | 71 | */ |
| 70 | - public function add_wp_admin_submenu() { | |
| 71 | - $page_suffix = Admin_Menu::add_menu( | |
| 72 | - __( 'Stats App', 'jetpack-stats-admin' ), | |
| 73 | - _x( 'Stats App', 'product name shown in menu', 'jetpack-stats-admin' ), | |
| 74 | - 'manage_options', | |
| 75 | - 'jetpack-stats-app', | |
| 76 | - array( $this, 'render' ), | |
| 77 | - 100 | |
| 78 | - ); | |
| 72 | + public function add_wp_admin_menu() { | |
| 73 | + /** | |
| 74 | + * Disable this menu for dashboard.wordpress.com because older versions of Jetpack need to fetch the old Stats UI. | |
| 75 | + * | |
| 76 | + * If this menu is registered, it will conflict with the back-end and break non-odyssey Stats. | |
| 77 | + */ | |
| 78 | + if ( defined( 'IS_WPCOM' ) && IS_WPCOM && 120742 === get_current_blog_id() ) { | |
| 79 | + return; | |
| 80 | + } | |
| 79 | 81 | |
| 82 | + $page_title = __( 'Stats', 'jetpack-stats-admin' ); | |
| 83 | + $menu_title = _x( 'Stats', 'product name shown in menu', 'jetpack-stats-admin' ); | |
| 84 | + $capability = $this->get_capability(); | |
| 85 | + $callback = array( $this, 'render' ); | |
| 86 | + | |
| 87 | + // An older admin-ui, loaded first by another plugin, may predate add_top_level_menu(). | |
| 88 | + if ( method_exists( Admin_Menu::class, 'add_top_level_menu' ) ) { | |
| 89 | + // The key the legacy Stats screen in the Jetpack plugin also declares, so hosts name Stats once. | |
| 90 | + $page_suffix = Admin_Menu::add_top_level_menu( $page_title, $menu_title, $capability, 'stats', $callback, 'dashicons-chart-bar', 2, array( 'key' => 'jetpack-stats' ) ); | |
| 91 | + } else { | |
| 92 | + $page_suffix = add_menu_page( $page_title, $menu_title, $capability, 'stats', $callback, 'dashicons-chart-bar', 2 ); | |
| 93 | + } | |
| 94 | + | |
| 80 | 95 | if ( $page_suffix ) { |
| 81 | 96 | add_action( 'load-' . $page_suffix, array( $this, 'admin_init' ) ); |
| 97 | + // The dashboard renders full bleed, so core notices stacked above it look broken. | |
| 98 | + if ( method_exists( Admin_Menu::class, 'hide_core_admin_notices' ) ) { | |
| 99 | + add_action( 'load-' . $page_suffix, array( Admin_Menu::class, 'hide_core_admin_notices' ) ); | |
| 100 | + } | |
| 82 | 101 | } |
| 83 | 102 | } |
| 84 | 103 | |
| 85 | 104 | /** |
| 105 | + * Capability a user needs to reach the dashboard. | |
| 106 | + * | |
| 107 | + * Until the site is connected the page exists to pick a plan and connect, which only a user | |
| 108 | + * who can manage the connection can act on. Once connected it is a reporting page, open to | |
| 109 | + * everyone allowed to view stats. | |
| 110 | + * | |
| 111 | + * Pre-connection that is `jetpack_connect`: it maps to `manage_options` on a normal site, | |
| 112 | + * but is `do_not_allow` in offline mode and honours the same multisite/filter rules as the | |
| 113 | + * register endpoint, so the menu is not offered where the connection cannot be completed. | |
| 114 | + * | |
| 115 | + * @return string | |
| 116 | + */ | |
| 117 | + protected function get_capability() { | |
| 118 | + return Main::is_site_connected() ? 'view_stats' : 'jetpack_connect'; | |
| 119 | + } | |
| 120 | + | |
| 121 | + /** | |
| 86 | 122 | * Override render funtion |
| 87 | 123 | */ |
| 88 | 124 | public function render() { |
| 89 | - // Record the number of views of the stats dashboard on the initial several loads for the purpose of showing feedback notice. | |
| 125 | + // Record the number of views of the stats dashboard on the initial several loads for the | |
| 126 | + // purpose of showing feedback notice. Views before the site is connected show the plan | |
| 127 | + // choice rather than the dashboard, and there is nothing to give feedback on yet. | |
| 90 | 128 | $views = intval( Stats_Options::get_option( 'views' ) ) + 1; |
| 91 | - if ( $views <= Notices::VIEWS_TO_SHOW_FEEDBACK ) { | |
| 129 | + if ( $views <= Notices::VIEWS_TO_SHOW_FEEDBACK && Main::is_site_connected() ) { | |
| 92 | 130 | Stats_Options::set_option( 'views', $views ); |
| 93 | 131 | } |
| 94 | 132 | |
| 95 | 133 | ?> |
| @@ -105,236 +143,92 @@ | ||
| 105 | 143 | src="//en.wordpress.com/i/loading/loading-64.gif" |
| 106 | 144 | /> |
| 107 | 145 | </div> |
| 108 | 146 | </div> |
| 109 | - <script> | |
| 110 | - jQuery(document).ready(function($) { | |
| 111 | - // Load SVG sprite. | |
| 112 | - $.get("https://widgets.wp.com/odyssey-stats/common/gridicons-506499ddac13811fee8e.svg", function(data) { | |
| 113 | - var div = document.createElement("div"); | |
| 114 | - div.innerHTML = new XMLSerializer().serializeToString(data.documentElement); | |
| 115 | - div.style = 'display: none'; | |
| 116 | - document.body.insertBefore(div, document.body.childNodes[0]); | |
| 117 | - }); | |
| 118 | - // we intercept on all anchor tags and change it to hashbang style. | |
| 119 | - $("#wpcom").on('click', 'a', function (e) { | |
| 120 | - const link = e && e.currentTarget && e.currentTarget.attributes && e.currentTarget.attributes.href && e.currentTarget.attributes.href.value; | |
| 121 | - if( link && link.startsWith( '/stats' ) ) { | |
| 122 | - location.hash = `#!${link}`; | |
| 123 | - return false; | |
| 124 | - } | |
| 125 | - }); | |
| 126 | - }); | |
| 127 | - </script> | |
| 128 | 147 | <?php |
| 129 | 148 | } |
| 130 | 149 | |
| 131 | 150 | /** |
| 132 | - * Initialize the admin resources. | |
| 151 | + * The dashboard bootstrap: load the icon sprite, and keep in-app links inside the dashboard. | |
| 152 | + * | |
| 153 | + * @return string | |
| 133 | 154 | */ |
| 134 | - public function admin_init() { | |
| 135 | - add_action( 'admin_enqueue_scripts', array( $this, 'load_admin_scripts' ) ); | |
| 155 | + private function get_bootstrap_script() { | |
| 156 | + return <<<'JS' | |
| 157 | +jQuery(document).ready(function($) { | |
| 158 | + // Load SVG sprite. | |
| 159 | + $.get("https://widgets.wp.com/odyssey-stats/common/gridicons-506499ddac13811fee8e.svg", function(data) { | |
| 160 | + var div = document.createElement("div"); | |
| 161 | + div.innerHTML = new XMLSerializer().serializeToString(data.documentElement); | |
| 162 | + div.style = 'display: none'; | |
| 163 | + document.body.insertBefore(div, document.body.childNodes[0]); | |
| 164 | + }); | |
| 165 | + // we intercept on all anchor tags and change it to hashbang style. | |
| 166 | + $("#wpcom").on('click', 'a', function (e) { | |
| 167 | + const link = e && e.currentTarget && e.currentTarget.attributes && e.currentTarget.attributes.href && e.currentTarget.attributes.href.value; | |
| 168 | + if( link && link.startsWith( '/stats' ) ) { | |
| 169 | + location.hash = `#!${link}`; | |
| 170 | + return false; | |
| 171 | + } | |
| 172 | + }); | |
| 173 | +}); | |
| 174 | +JS; | |
| 136 | 175 | } |
| 137 | 176 | |
| 138 | 177 | /** |
| 139 | - * Enqueue admin scripts. | |
| 178 | + * Initialize the admin resources. | |
| 140 | 179 | */ |
| 141 | - public function load_admin_scripts() { | |
| 142 | - if ( file_exists( __DIR__ . '/../dist/build.min.js' ) ) { | |
| 143 | - // Load local assets for the convinience of development. | |
| 144 | - Assets::register_script( | |
| 145 | - 'jp-stats-dashboard', | |
| 146 | - '../dist/build.min.js', | |
| 147 | - __FILE__, | |
| 148 | - array( | |
| 149 | - 'in_footer' => true, | |
| 150 | - 'textdomain' => 'jetpack-stats-admin', | |
| 151 | - ) | |
| 152 | - ); | |
| 153 | - Assets::enqueue_script( 'jp-stats-dashboard' ); | |
| 154 | - } else { | |
| 155 | - // In production, we load the assets from our CDN. | |
| 156 | - $css_url = 'build.min' . ( is_rtl() ? '.rtl' : '' ) . '.css'; | |
| 157 | - wp_register_script( 'jp-stats-dashboard', sprintf( self::ODYSSEY_CDN_URL, self::ODYSSEY_STATS_VERSION, 'build.min.js' ), self::JS_DEPENDENCIES, $this->get_cdn_asset_cache_buster(), true ); | |
| 158 | - wp_register_style( 'jp-stats-dashboard-style', sprintf( self::ODYSSEY_CDN_URL, self::ODYSSEY_STATS_VERSION, $css_url ), array(), $this->get_cdn_asset_cache_buster() ); | |
| 159 | - wp_enqueue_script( 'jp-stats-dashboard' ); | |
| 160 | - wp_enqueue_style( 'jp-stats-dashboard-style' ); | |
| 161 | - } | |
| 162 | - | |
| 163 | - wp_add_inline_script( | |
| 164 | - 'jp-stats-dashboard', | |
| 165 | - $this->get_config_data_js(), | |
| 166 | - 'before' | |
| 167 | - ); | |
| 180 | + public function admin_init() { | |
| 181 | + $this->maybe_refresh_plan(); | |
| 182 | + add_action( 'admin_enqueue_scripts', array( $this, 'load_admin_scripts' ) ); | |
| 168 | 183 | } |
| 169 | 184 | |
| 170 | 185 | /** |
| 171 | - * Returns cache buster string for assets. | |
| 172 | - * Development mode doesn't need this, as it's handled by `Assets` class. | |
| 186 | + * Fill an empty plan cache before the config data that reads it is printed. | |
| 187 | + * | |
| 188 | + * The app cannot refresh the plan it paywalls on, so a site that never stored one renders as | |
| 189 | + * free. Throttled and time-boxed, because WordPress.com can keep answering without a plan. | |
| 173 | 190 | */ |
| 174 | - protected function get_cdn_asset_cache_buster() { | |
| 175 | - // Use cached cache buster in production. | |
| 176 | - $remote_asset_version = get_transient( self::ODYSSEY_STATS_CACHE_BUSTER_CACHE_KEY ); | |
| 177 | - if ( ! empty( $remote_asset_version ) ) { | |
| 178 | - return $remote_asset_version; | |
| 191 | + private function maybe_refresh_plan() { | |
| 192 | + if ( ! Main::is_site_connected() ) { | |
| 193 | + return; | |
| 179 | 194 | } |
| 180 | 195 | |
| 181 | - // If no cached cache buster, we fetch it from CDN and set to transient. | |
| 182 | - $response = wp_remote_get( sprintf( self::ODYSSEY_CDN_URL, self::ODYSSEY_STATS_VERSION, 'build_meta.json' ), array( 'timeout' => 5 ) ); | |
| 183 | - | |
| 184 | - if ( is_wp_error( $response ) ) { | |
| 185 | - // fallback to the package version. | |
| 186 | - return Main::VERSION; | |
| 196 | + // method_exists guard: an older plans package may win the autoloader on another plugin. | |
| 197 | + if ( method_exists( Jetpack_Plan::class, 'get_wpcom_site_specific_features' ) | |
| 198 | + && null !== Jetpack_Plan::get_wpcom_site_specific_features() ) { | |
| 199 | + return; | |
| 187 | 200 | } |
| 188 | 201 | |
| 189 | - $build_meta = json_decode( wp_remote_retrieve_body( $response ), true ); | |
| 190 | - if ( ! empty( $build_meta['cache_buster'] ) ) { | |
| 191 | - // Cache the cache buster for a day. | |
| 192 | - set_transient( self::ODYSSEY_STATS_CACHE_BUSTER_CACHE_KEY, $build_meta['cache_buster'], 15 * MINUTE_IN_SECONDS ); | |
| 193 | - return $build_meta['cache_buster']; | |
| 202 | + $plan = Jetpack_Plan::get(); | |
| 203 | + if ( ! empty( $plan['features']['active'] ) || get_transient( self::PLAN_REFRESH_TRANSIENT ) ) { | |
| 204 | + return; | |
| 194 | 205 | } |
| 195 | 206 | |
| 196 | - // fallback to the package version. | |
| 197 | - return Main::VERSION; | |
| 198 | - } | |
| 207 | + set_transient( self::PLAN_REFRESH_TRANSIENT, 1, 15 * MINUTE_IN_SECONDS ); | |
| 199 | 208 | |
| 200 | - /** | |
| 201 | - * Set configData to window.configData. | |
| 202 | - */ | |
| 203 | - protected function get_config_data_js() { | |
| 204 | - return 'window.configData = ' . wp_json_encode( | |
| 205 | - $this->config_data() | |
| 206 | - ) . ';'; | |
| 209 | + Jetpack_Plan::refresh_from_wpcom( array( 'timeout' => 5 ) ); | |
| 207 | 210 | } |
| 208 | 211 | |
| 209 | 212 | /** |
| 210 | - * Return the config for the app. | |
| 213 | + * Load the admin scripts. | |
| 211 | 214 | */ |
| 212 | - protected function config_data() { | |
| 213 | - $blog_id = Jetpack_Options::get_option( 'id' ); | |
| 214 | - $empty_object = json_decode( '{}' ); | |
| 215 | - return array( | |
| 216 | - 'admin_page_base' => static::get_admin_path(), | |
| 217 | - 'api_root' => esc_url_raw( rest_url() ), | |
| 218 | - 'blog_id' => Jetpack_Options::get_option( 'id' ), | |
| 219 | - 'enable_all_sections' => false, | |
| 220 | - 'env_id' => 'production', | |
| 221 | - 'google_analytics_key' => 'UA-10673494-15', | |
| 222 | - 'google_maps_and_places_api_key' => '', | |
| 223 | - 'hostname' => wp_parse_url( get_site_url(), PHP_URL_HOST ), | |
| 224 | - 'i18n_default_locale_slug' => 'en', | |
| 225 | - 'i18n_locale_slug' => static::get_site_locale(), | |
| 226 | - 'mc_analytics_enabled' => false, | |
| 227 | - 'meta' => array(), | |
| 228 | - 'nonce' => wp_create_nonce( 'wp_rest' ), | |
| 229 | - 'site_name' => \get_bloginfo( 'name' ), | |
| 230 | - 'sections' => array(), | |
| 231 | - // Features are inlined @see https://github.com/Automattic/wp-calypso/pull/70122 | |
| 232 | - 'features' => array(), | |
| 233 | - 'intial_state' => array( | |
| 234 | - 'currentUser' => array( | |
| 235 | - 'id' => 1000, | |
| 236 | - 'user' => array( | |
| 237 | - 'ID' => 1000, | |
| 238 | - 'username' => 'no-user', | |
| 239 | - ), | |
| 240 | - 'capabilities' => array( | |
| 241 | - "$blog_id" => self::get_current_user_capabilities(), | |
| 242 | - ), | |
| 243 | - ), | |
| 244 | - 'sites' => array( | |
| 245 | - 'items' => array( | |
| 246 | - "$blog_id" => array( | |
| 247 | - 'ID' => $blog_id, | |
| 248 | - 'URL' => site_url(), | |
| 249 | - 'jetpack' => true, | |
| 250 | - 'visible' => true, | |
| 251 | - 'capabilities' => $empty_object, | |
| 252 | - 'products' => array(), | |
| 253 | - 'plan' => $empty_object, // we need this empty object, otherwise the front end would crash on insight page. | |
| 254 | - 'options' => array( | |
| 255 | - 'wordads' => ( new Modules() )->is_active( 'wordads' ), | |
| 256 | - 'admin_url' => admin_url(), | |
| 257 | - ), | |
| 258 | - 'stats_notices' => ( new Notices() )->get_notices_to_show(), | |
| 259 | - ), | |
| 260 | - ), | |
| 261 | - 'features' => array( "$blog_id" => array( 'data' => self::get_plan_features() ) ), | |
| 262 | - ), | |
| 263 | - ), | |
| 264 | - ); | |
| 265 | - } | |
| 215 | + public function load_admin_scripts() { | |
| 216 | + ( new Odyssey_Assets() )->load_admin_scripts( 'jp-stats-dashboard', 'build.min', array( 'config_variable_name' => 'jetpackStatsOdysseyAppConfigData' ) ); | |
| 266 | 217 | |
| 267 | - /** | |
| 268 | - * Page base for the Calypso admin page. | |
| 269 | - */ | |
| 270 | - protected static function get_admin_path() { | |
| 271 | - // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized | |
| 272 | - if ( ! isset( $_SERVER['PHP_SELF'] ) || ! isset( $_SERVER['QUERY_STRING'] ) ) { | |
| 273 | - $parsed = wp_parse_url( admin_url( 'admin.php?page=stats' ) ); | |
| 274 | - return $parsed['path'] . '?' . $parsed['query']; | |
| 275 | - } | |
| 276 | - // We do this because page.js requires the exactly page base to be set otherwise it will not work properly. | |
| 277 | - // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized | |
| 278 | - return wp_unslash( $_SERVER['PHP_SELF'] ) . '?' . wp_unslash( $_SERVER['QUERY_STRING'] ); | |
| 279 | - } | |
| 218 | + // The bootstrap runs on jQuery, which the Odyssey bundle does not depend on. It gets its own | |
| 219 | + // handle rather than jQuery being added to that bundle, which the dashboard widget shares | |
| 220 | + // and which has no use for it. | |
| 221 | + wp_register_script( 'jp-stats-dashboard-bootstrap', false, array( 'jquery' ), Main::VERSION, true ); | |
| 222 | + wp_enqueue_script( 'jp-stats-dashboard-bootstrap' ); | |
| 223 | + wp_add_inline_script( 'jp-stats-dashboard-bootstrap', $this->get_bootstrap_script() ); | |
| 280 | 224 | |
| 281 | - /** | |
| 282 | - * Get locale acceptable by Calypso. | |
| 283 | - */ | |
| 284 | - protected static function get_site_locale() { | |
| 285 | - // Stolen from `projects/plugins/jetpack/modules/sitemaps/sitemap-builder.php` | |
| 286 | - | |
| 287 | - /* | |
| 288 | - * Trim the locale to an ISO 639 language code as required by Google. | |
| 289 | - * Special cases are zh-cn (Simplified Chinese) and zh-tw (Traditional Chinese). | |
| 290 | - * @link https://www.loc.gov/standards/iso639-2/php/code_list.php | |
| 291 | - */ | |
| 292 | - $locale = strtolower( get_locale() ); | |
| 293 | - | |
| 294 | - if ( in_array( $locale, array( 'zh_tw', 'zh_cn' ), true ) ) { | |
| 295 | - $locale = str_replace( '_', '-', $locale ); | |
| 296 | - } else { | |
| 297 | - $locale = preg_replace( '/(_.*)$/i', '', $locale ); | |
| 225 | + // The app is served from our CDN and so cannot bundle the connection package. Print the | |
| 226 | + // state Search and Protect print on their own pages, so it can read the connection status | |
| 227 | + // and register the site through the connection REST API itself. Connected sites fetch | |
| 228 | + // `jetpack/v4/connection` over REST instead, and must not receive registrationNonce and | |
| 229 | + // the connected-plugin list on a page that `view_stats` users can open. | |
| 230 | + if ( ! Main::is_site_connected() ) { | |
| 231 | + Connection_Initial_State::render_script( 'jp-stats-dashboard' ); | |
| 298 | 232 | } |
| 299 | - return $locale; | |
| 300 | 233 | } |
| 301 | - | |
| 302 | - /** | |
| 303 | - * Get the features of the current plan. | |
| 304 | - */ | |
| 305 | - protected static function get_plan_features() { | |
| 306 | - if ( ! class_exists( 'Jetpack_Plan' ) ) { | |
| 307 | - return array(); | |
| 308 | - } | |
| 309 | - $plan = \Jetpack_Plan::get(); | |
| 310 | - if ( empty( $plan['features'] ) ) { | |
| 311 | - return array(); | |
| 312 | - } | |
| 313 | - return $plan['features']; | |
| 314 | - } | |
| 315 | - | |
| 316 | - /** | |
| 317 | - * Get the capabilities of the current user. | |
| 318 | - * | |
| 319 | - * @return array An array of capabilities. | |
| 320 | - */ | |
| 321 | - protected static function get_current_user_capabilities() { | |
| 322 | - $user = wp_get_current_user(); | |
| 323 | - if ( ! $user || is_wp_error( $user ) ) { | |
| 324 | - return array(); | |
| 325 | - } | |
| 326 | - return $user->allcaps; | |
| 327 | - } | |
| 328 | - | |
| 329 | - /** | |
| 330 | - * Return ture if the opt-out notice should be shown. | |
| 331 | - * | |
| 332 | - * @return bool | |
| 333 | - */ | |
| 334 | - protected static function has_opt_out_new_stats_notice() { | |
| 335 | - $new_stats_enabled = Stats_Options::get_option( 'enable_odyssey_stats' ); | |
| 336 | - $hidden_jitms = \Jetpack_Options::get_option( 'hide_jitm' ); | |
| 337 | - return $new_stats_enabled && ! isset( $hidden_jitms[ self::OPT_OUT_NEW_STATS_FEATURE_CLASS ] ); | |
| 338 | - } | |
| 339 | - | |
| 340 | 234 | } |