| @@ -1,18 +1,6 @@ | ||
| 1 | -<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName | |
| 1 | +<?php | |
| 2 | 2 | /** |
| 3 | - * Adds the PSH functionality to Jetpack. | |
| 4 | - * | |
| 5 | - * @package automattic/jetpack | |
| 6 | - */ | |
| 7 | - | |
| 8 | -// phpcs:disable Universal.Files.SeparateFunctionsFromOO.Mixed -- TODO: Move classes to appropriately-named class files. | |
| 9 | - | |
| 10 | -use Automattic\Jetpack\Constants; | |
| 11 | -use Automattic\Jetpack\Redirect; | |
| 12 | -use Automattic\Jetpack\Tracking; | |
| 13 | - | |
| 14 | -/** | |
| 15 | 3 | * Disable direct access and execution. |
| 16 | 4 | */ |
| 17 | 5 | if ( ! defined( 'ABSPATH' ) ) { |
| 18 | 6 | exit; |
| @@ -17,15 +5,14 @@ | ||
| 17 | 5 | if ( ! defined( 'ABSPATH' ) ) { |
| 18 | 6 | exit; |
| 19 | 7 | } |
| 20 | 8 | |
| 9 | + | |
| 21 | 10 | if ( |
| 22 | 11 | is_admin() && |
| 23 | - Jetpack::is_connection_ready() && | |
| 12 | + Jetpack::is_active() && | |
| 24 | 13 | /** This filter is documented in _inc/lib/admin-pages/class.jetpack-react-page.php */ |
| 25 | 14 | apply_filters( 'jetpack_show_promotions', true ) && |
| 26 | - // Disable feature hints when plugins cannot be installed. | |
| 27 | - ! Constants::is_true( 'DISALLOW_FILE_MODS' ) && | |
| 28 | 15 | jetpack_is_psh_active() |
| 29 | 16 | ) { |
| 30 | 17 | Jetpack_Plugin_Search::init(); |
| 31 | 18 | } |
| @@ -40,24 +27,15 @@ | ||
| 40 | 27 | * @since 7.1.0 |
| 41 | 28 | */ |
| 42 | 29 | class Jetpack_Plugin_Search { |
| 43 | 30 | |
| 44 | - /** | |
| 45 | - * PSH slug name. | |
| 46 | - * | |
| 47 | - * @var string | |
| 48 | - */ | |
| 49 | - public static $slug = 'jetpack-plugin-search'; | |
| 31 | + static $slug = 'jetpack-plugin-search'; | |
| 50 | 32 | |
| 51 | - /** | |
| 52 | - * Singleton constructor. | |
| 53 | - * | |
| 54 | - * @return Jetpack_Plugin_Search | |
| 55 | - */ | |
| 56 | 33 | public static function init() { |
| 57 | 34 | static $instance = null; |
| 58 | 35 | |
| 59 | 36 | if ( ! $instance ) { |
| 37 | + jetpack_require_lib( 'tracks/client' ); | |
| 60 | 38 | $instance = new Jetpack_Plugin_Search(); |
| 61 | 39 | } |
| 62 | 40 | |
| 63 | 41 | return $instance; |
| @@ -62,11 +40,8 @@ | ||
| 62 | 40 | |
| 63 | 41 | return $instance; |
| 64 | 42 | } |
| 65 | 43 | |
| 66 | - /** | |
| 67 | - * Jetpack_Plugin_Search constructor. | |
| 68 | - */ | |
| 69 | 44 | public function __construct() { |
| 70 | 45 | add_action( 'current_screen', array( $this, 'start' ) ); |
| 71 | 46 | } |
| 72 | 47 | |
| @@ -72,14 +47,14 @@ | ||
| 72 | 47 | |
| 73 | 48 | /** |
| 74 | 49 | * Add actions and filters only if this is the plugin installation screen and it's the first page. |
| 75 | 50 | * |
| 76 | - * @param object $screen WP SCreen object. | |
| 51 | + * @param object $screen | |
| 77 | 52 | * |
| 78 | 53 | * @since 7.1.0 |
| 79 | 54 | */ |
| 80 | 55 | public function start( $screen ) { |
| 81 | - if ( 'plugin-install' === $screen->base && ( ! isset( $_GET['paged'] ) || 1 === intval( $_GET['paged'] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended | |
| 56 | + if ( 'plugin-install' === $screen->base && ( ! isset( $_GET['paged'] ) || 1 == $_GET['paged'] ) ) { | |
| 82 | 57 | add_action( 'admin_enqueue_scripts', array( $this, 'load_plugins_search_script' ) ); |
| 83 | 58 | add_filter( 'plugins_api_result', array( $this, 'inject_jetpack_module_suggestion' ), 10, 3 ); |
| 84 | 59 | add_filter( 'self_admin_url', array( $this, 'plugin_details' ) ); |
| 85 | 60 | add_filter( 'plugin_install_action_links', array( $this, 'insert_module_related_links' ), 10, 2 ); |
| @@ -106,25 +81,21 @@ | ||
| 106 | 81 | * |
| 107 | 82 | * @since 7.1.0 |
| 108 | 83 | */ |
| 109 | 84 | public static function register_endpoints() { |
| 110 | - register_rest_route( | |
| 111 | - 'jetpack/v4', | |
| 112 | - '/hints', | |
| 113 | - array( | |
| 114 | - 'methods' => WP_REST_Server::EDITABLE, | |
| 115 | - 'callback' => __CLASS__ . '::dismiss', | |
| 116 | - 'permission_callback' => __CLASS__ . '::can_request', | |
| 117 | - 'args' => array( | |
| 118 | - 'hint' => array( | |
| 119 | - 'default' => '', | |
| 120 | - 'type' => 'string', | |
| 121 | - 'required' => true, | |
| 122 | - 'validate_callback' => __CLASS__ . '::is_hint_id', | |
| 123 | - ), | |
| 85 | + register_rest_route( 'jetpack/v4', '/hints', array( | |
| 86 | + 'methods' => WP_REST_Server::EDITABLE, | |
| 87 | + 'callback' => __CLASS__ . '::dismiss', | |
| 88 | + 'permission_callback' => __CLASS__ . '::can_request', | |
| 89 | + 'args' => array( | |
| 90 | + 'hint' => array( | |
| 91 | + 'default' => '', | |
| 92 | + 'type' => 'string', | |
| 93 | + 'required' => true, | |
| 94 | + 'validate_callback' => __CLASS__ . '::is_hint_id', | |
| 124 | 95 | ), |
| 125 | 96 | ) |
| 126 | - ); | |
| 97 | + ) ); | |
| 127 | 98 | } |
| 128 | 99 | |
| 129 | 100 | /** |
| 130 | 101 | * A WordPress REST API permission callback method that accepts a request object and |
| @@ -142,11 +113,11 @@ | ||
| 142 | 113 | * Validates that the ID of the hint to dismiss is a string. |
| 143 | 114 | * |
| 144 | 115 | * @since 7.1.0 |
| 145 | 116 | * |
| 146 | - * @param string|bool $value Value to check. | |
| 117 | + * @param string|bool $value Value to check. | |
| 147 | 118 | * @param WP_REST_Request $request The request sent to the WP REST API. |
| 148 | - * @param string $param Name of the parameter passed to endpoint holding $value. | |
| 119 | + * @param string $param Name of the parameter passed to endpoint holding $value. | |
| 149 | 120 | * |
| 150 | 121 | * @return bool|WP_Error |
| 151 | 122 | */ |
| 152 | 123 | public static function is_hint_id( $value, $request, $param ) { |
| @@ -151,9 +122,8 @@ | ||
| 151 | 122 | */ |
| 152 | 123 | public static function is_hint_id( $value, $request, $param ) { |
| 153 | 124 | return in_array( $value, Jetpack::get_available_modules(), true ) |
| 154 | 125 | ? true |
| 155 | - /* translators: %s is the name of a parameter passed to an endpoint. */ | |
| 156 | 126 | : new WP_Error( 'invalid_param', sprintf( esc_html__( '%s must be an alphanumeric string.', 'jetpack' ), $param ) ); |
| 157 | 127 | } |
| 158 | 128 | |
| 159 | 129 | /** |
| @@ -213,9 +183,9 @@ | ||
| 213 | 183 | * |
| 214 | 184 | * @return bool True if $hint should be displayed. |
| 215 | 185 | */ |
| 216 | 186 | protected function should_display_hint( $hint ) { |
| 217 | - $dismissed_hints = static::get_dismissed_hints(); | |
| 187 | + $dismissed_hints = $this->get_dismissed_hints(); | |
| 218 | 188 | // If more than 2 hints have been dismissed, then show no more. |
| 219 | 189 | if ( 2 < count( $dismissed_hints ) ) { |
| 220 | 190 | return false; |
| 221 | 191 | } |
| @@ -227,11 +197,8 @@ | ||
| 227 | 197 | |
| 228 | 198 | return ! in_array( $hint, $dismissed_hints, true ); |
| 229 | 199 | } |
| 230 | 200 | |
| 231 | - /** | |
| 232 | - * Load the search scripts and CSS for PSH. | |
| 233 | - */ | |
| 234 | 201 | public function load_plugins_search_script() { |
| 235 | 202 | wp_enqueue_script( self::$slug, plugins_url( 'modules/plugin-search/plugin-search.js', JETPACK__PLUGIN_FILE ), array( 'jquery' ), JETPACK__VERSION, true ); |
| 236 | 203 | wp_localize_script( |
| 237 | 204 | self::$slug, |
| @@ -253,14 +220,14 @@ | ||
| 253 | 220 | 'supportText' => esc_html__( |
| 254 | 221 | 'Learn more about these suggestions.', |
| 255 | 222 | 'jetpack' |
| 256 | 223 | ), |
| 257 | - 'supportLink' => Redirect::get_url( 'plugin-hint-learn-support' ), | |
| 224 | + 'supportLink' => 'https://jetpack.com/redirect/?source=plugin-hint-learn-support', | |
| 258 | 225 | 'hideText' => esc_html__( 'Hide this suggestion', 'jetpack' ), |
| 259 | 226 | ) |
| 260 | 227 | ); |
| 261 | 228 | |
| 262 | - wp_enqueue_style( self::$slug, plugins_url( 'modules/plugin-search/plugin-search.css', JETPACK__PLUGIN_FILE ), array(), JETPACK__VERSION ); | |
| 229 | + wp_enqueue_style( self::$slug, plugins_url( 'modules/plugin-search/plugin-search.css', JETPACK__PLUGIN_FILE ) ); | |
| 263 | 230 | } |
| 264 | 231 | |
| 265 | 232 | /** |
| 266 | 233 | * Get the plugin repo's data for Jetpack to populate the fields with. |
| @@ -270,23 +237,20 @@ | ||
| 270 | 237 | public static function get_jetpack_plugin_data() { |
| 271 | 238 | $data = get_transient( 'jetpack_plugin_data' ); |
| 272 | 239 | |
| 273 | 240 | if ( false === $data || is_wp_error( $data ) ) { |
| 274 | - include_once ABSPATH . 'wp-admin/includes/plugin-install.php'; | |
| 275 | - $data = plugins_api( | |
| 276 | - 'plugin_information', | |
| 277 | - array( | |
| 278 | - 'slug' => 'jetpack', | |
| 279 | - 'is_ssl' => is_ssl(), | |
| 280 | - 'fields' => array( | |
| 281 | - 'banners' => true, | |
| 282 | - 'reviews' => true, | |
| 283 | - 'active_installs' => true, | |
| 284 | - 'versions' => false, | |
| 285 | - 'sections' => false, | |
| 286 | - ), | |
| 287 | - ) | |
| 288 | - ); | |
| 241 | + include_once( ABSPATH . 'wp-admin/includes/plugin-install.php' ); | |
| 242 | + $data = plugins_api( 'plugin_information', array( | |
| 243 | + 'slug' => 'jetpack', | |
| 244 | + 'is_ssl' => is_ssl(), | |
| 245 | + 'fields' => array( | |
| 246 | + 'banners' => true, | |
| 247 | + 'reviews' => true, | |
| 248 | + 'active_installs' => true, | |
| 249 | + 'versions' => false, | |
| 250 | + 'sections' => false, | |
| 251 | + ), | |
| 252 | + ) ); | |
| 289 | 253 | set_transient( 'jetpack_plugin_data', $data, DAY_IN_SECONDS ); |
| 290 | 254 | } |
| 291 | 255 | |
| 292 | 256 | return $data; |
| @@ -301,16 +265,16 @@ | ||
| 301 | 265 | */ |
| 302 | 266 | public function get_extra_features() { |
| 303 | 267 | return array( |
| 304 | 268 | 'akismet' => array( |
| 305 | - 'name' => 'Akismet', | |
| 306 | - 'search_terms' => 'akismet, anti-spam, antispam, comments, spam, spam protection, form spam, captcha, no captcha, nocaptcha, recaptcha, phising, google', | |
| 307 | - 'short_description' => esc_html__( 'Keep your visitors and search engines happy by stopping comment and contact form spam with Akismet.', 'jetpack' ), | |
| 269 | + 'name' => 'Akismet', | |
| 270 | + 'search_terms' => 'akismet, anti-spam, antispam, comments, spam, spam protection, form spam, captcha, no captcha, nocaptcha, recaptcha, phising, google', | |
| 271 | + 'short_description' => esc_html__( 'Keep your visitors and search engines happy by stopping comment and contact form spam with Akismet.', 'jetpack' ), | |
| 308 | 272 | 'requires_connection' => true, |
| 309 | - 'module' => 'akismet', | |
| 310 | - 'sort' => '16', | |
| 311 | - 'learn_more_button' => Redirect::get_url( 'plugin-hint-upgrade-akismet' ), | |
| 312 | - 'configure_url' => admin_url( 'admin.php?page=akismet-key-config' ), | |
| 273 | + 'module' => 'akismet', | |
| 274 | + 'sort' => '16', | |
| 275 | + 'learn_more_button' => 'https://jetpack.com/features/security/spam-filtering/', | |
| 276 | + 'configure_url' => admin_url( 'admin.php?page=akismet-key-config' ), | |
| 313 | 277 | ), |
| 314 | 278 | ); |
| 315 | 279 | } |
| 316 | 280 | |
| @@ -315,59 +279,44 @@ | ||
| 315 | 279 | } |
| 316 | 280 | |
| 317 | 281 | /** |
| 318 | 282 | * Intercept the plugins API response and add in an appropriate card for Jetpack |
| 319 | - * | |
| 320 | - * @param object $result Plugin search results. | |
| 321 | - * @param string $action unused. | |
| 322 | - * @param object $args Search args. | |
| 323 | 283 | */ |
| 324 | 284 | public function inject_jetpack_module_suggestion( $result, $action, $args ) { |
| 325 | - /* | |
| 326 | - * Bail if something else hooks into the Plugins' API response | |
| 327 | - * and does not return results. | |
| 328 | - */ | |
| 329 | - if ( empty( $result->plugins ) || is_wp_error( $result ) ) { | |
| 330 | - return $result; | |
| 331 | - } | |
| 332 | - | |
| 333 | - // Looks like a search query; it's matching time. | |
| 285 | + // Looks like a search query; it's matching time | |
| 334 | 286 | if ( ! empty( $args->search ) ) { |
| 335 | 287 | require_once JETPACK__PLUGIN_DIR . 'class.jetpack-admin.php'; |
| 336 | - $tracking = new Tracking(); | |
| 337 | 288 | $jetpack_modules_list = array_intersect_key( |
| 338 | 289 | array_merge( $this->get_extra_features(), Jetpack_Admin::init()->get_modules() ), |
| 339 | - array_flip( | |
| 340 | - array( | |
| 341 | - 'contact-form', | |
| 342 | - 'lazy-images', | |
| 343 | - 'monitor', | |
| 344 | - 'photon', | |
| 345 | - 'photon-cdn', | |
| 346 | - 'protect', | |
| 347 | - 'publicize', | |
| 348 | - 'related-posts', | |
| 349 | - 'sharedaddy', | |
| 350 | - 'akismet', | |
| 351 | - 'vaultpress', | |
| 352 | - 'videopress', | |
| 353 | - 'search', | |
| 354 | - ) | |
| 355 | - ) | |
| 290 | + array_flip( array( | |
| 291 | + 'contact-form', | |
| 292 | + 'lazy-images', | |
| 293 | + 'monitor', | |
| 294 | + 'photon', | |
| 295 | + 'photon-cdn', | |
| 296 | + 'protect', | |
| 297 | + 'publicize', | |
| 298 | + 'related-posts', | |
| 299 | + 'sharedaddy', | |
| 300 | + 'akismet', | |
| 301 | + 'vaultpress', | |
| 302 | + 'videopress', | |
| 303 | + 'search', | |
| 304 | + ) ) | |
| 356 | 305 | ); |
| 357 | 306 | uasort( $jetpack_modules_list, array( $this, 'by_sorting_option' ) ); |
| 358 | 307 | |
| 359 | - // Record event when user searches for a term over 3 chars (less than 3 is not very useful). | |
| 308 | + // Record event when user searches for a term over 3 chars (less than 3 is not very useful.) | |
| 360 | 309 | if ( strlen( $args->search ) >= 3 ) { |
| 361 | - $tracking->record_user_event( 'wpa_plugin_search_term', array( 'search_term' => $args->search ) ); | |
| 310 | + JetpackTracking::record_user_event( 'wpa_plugin_search_term', array( 'search_term' => $args->search ) ); | |
| 362 | 311 | } |
| 363 | 312 | |
| 364 | - // Lowercase, trim, remove punctuation/special chars, decode url, remove 'jetpack'. | |
| 313 | + // Lowercase, trim, remove punctuation/special chars, decode url, remove 'jetpack' | |
| 365 | 314 | $normalized_term = $this->sanitize_search_term( $args->search ); |
| 366 | 315 | |
| 367 | 316 | $matching_module = null; |
| 368 | 317 | |
| 369 | - // Try to match a passed search term with module's search terms. | |
| 318 | + // Try to match a passed search term with module's search terms | |
| 370 | 319 | foreach ( $jetpack_modules_list as $module_slug => $module_opts ) { |
| 371 | 320 | /* |
| 372 | 321 | * Does the site's current plan support the feature? |
| 373 | 322 | * We don't use Jetpack_Plan::supports() here because |
| @@ -386,25 +335,24 @@ | ||
| 386 | 335 | } |
| 387 | 336 | } |
| 388 | 337 | |
| 389 | 338 | if ( isset( $matching_module ) && $this->should_display_hint( $matching_module ) ) { |
| 390 | - // Record event when a matching feature is found. | |
| 391 | - $tracking->record_user_event( 'wpa_plugin_search_match_found', array( 'feature' => $matching_module ) ); | |
| 339 | + // Record event when a matching feature is found | |
| 340 | + JetpackTracking::record_user_event( 'wpa_plugin_search_match_found', array( 'feature' => $matching_module ) ); | |
| 392 | 341 | |
| 393 | - $inject = (array) self::get_jetpack_plugin_data(); | |
| 342 | + $inject = (array) self::get_jetpack_plugin_data(); | |
| 394 | 343 | $image_url = plugins_url( 'modules/plugin-search/psh', JETPACK__PLUGIN_FILE ); |
| 395 | 344 | $overrides = array( |
| 396 | - 'plugin-search' => true, // Helps to determine if that an injected card. | |
| 397 | - 'name' => sprintf( // Supplement name/description so that they clearly indicate this was added. | |
| 398 | - /* translators: Jetpack module name */ | |
| 345 | + 'plugin-search' => true, // Helps to determine if that an injected card. | |
| 346 | + 'name' => sprintf( // Supplement name/description so that they clearly indicate this was added. | |
| 399 | 347 | esc_html_x( 'Jetpack: %s', 'Jetpack: Module Name', 'jetpack' ), |
| 400 | 348 | $jetpack_modules_list[ $matching_module ]['name'] |
| 401 | 349 | ), |
| 402 | - 'short_description' => $jetpack_modules_list[ $matching_module ]['short_description'], | |
| 350 | + 'short_description' => $jetpack_modules_list[ $matching_module ]['short_description'], | |
| 403 | 351 | 'requires_connection' => (bool) $jetpack_modules_list[ $matching_module ]['requires_connection'], |
| 404 | - 'slug' => self::$slug, | |
| 405 | - 'version' => JETPACK__VERSION, | |
| 406 | - 'icons' => array( | |
| 352 | + 'slug' => self::$slug, | |
| 353 | + 'version' => JETPACK__VERSION, | |
| 354 | + 'icons' => array( | |
| 407 | 355 | '1x' => "$image_url-128.png", |
| 408 | 356 | '2x' => "$image_url-256.png", |
| 409 | 357 | 'svg' => "$image_url.svg", |
| 410 | 358 | ), |
| @@ -409,12 +357,12 @@ | ||
| 409 | 357 | 'svg' => "$image_url.svg", |
| 410 | 358 | ), |
| 411 | 359 | ); |
| 412 | 360 | |
| 413 | - // Splice in the base module data. | |
| 361 | + // Splice in the base module data | |
| 414 | 362 | $inject = array_merge( $inject, $jetpack_modules_list[ $matching_module ], $overrides ); |
| 415 | 363 | |
| 416 | - // Add it to the top of the list. | |
| 364 | + // Add it to the top of the list | |
| 417 | 365 | $result->plugins = array_filter( $result->plugins, array( $this, 'filter_cards' ) ); |
| 418 | 366 | array_unshift( $result->plugins, $inject ); |
| 419 | 367 | } |
| 420 | 368 | } |
| @@ -425,29 +373,17 @@ | ||
| 425 | 373 | * Remove cards for Jetpack plugins since we don't want duplicates. |
| 426 | 374 | * |
| 427 | 375 | * @since 7.1.0 |
| 428 | 376 | * @since 7.2.0 Only remove Jetpack. |
| 429 | - * @since 7.4.0 Simplify for WordPress 5.1+. | |
| 430 | 377 | * |
| 431 | - * @param array|object $plugin WordPress search result card. | |
| 378 | + * @param array|object $plugin | |
| 432 | 379 | * |
| 433 | 380 | * @return bool |
| 434 | 381 | */ |
| 435 | - public function filter_cards( $plugin ) { | |
| 436 | - /* | |
| 437 | - * $plugin is normally an array. | |
| 438 | - * However, since the response data can be filtered, | |
| 439 | - * we cannot fully trust its format. | |
| 440 | - * Let's handle both arrays and objects, and bail if it's neither. | |
| 441 | - */ | |
| 442 | - if ( is_array( $plugin ) && ! empty( $plugin['slug'] ) ) { | |
| 443 | - $slug = $plugin['slug']; | |
| 444 | - } elseif ( is_object( $plugin ) && ! empty( $plugin->slug ) ) { | |
| 445 | - $slug = $plugin->slug; | |
| 446 | - } else { | |
| 447 | - return false; | |
| 448 | - } | |
| 449 | - | |
| 382 | + function filter_cards( $plugin ) { | |
| 383 | + // Take in account that before WordPress 5.1, the list of plugins is an array of objects. | |
| 384 | + // With WordPress 5.1 the list of plugins is an array of arrays. | |
| 385 | + $slug = is_array( $plugin ) ? $plugin['slug'] : $plugin->slug; | |
| 450 | 386 | return ! in_array( $slug, array( 'jetpack' ), true ); |
| 451 | 387 | } |
| 452 | 388 | |
| 453 | 389 | /** |
| @@ -453,10 +389,10 @@ | ||
| 453 | 389 | /** |
| 454 | 390 | * Take a raw search query and return something a bit more standardized and |
| 455 | 391 | * easy to work with. |
| 456 | 392 | * |
| 457 | - * @param string $term The raw search term. | |
| 458 | - * @return string A simplified/sanitized version. | |
| 393 | + * @param String $term The raw search term | |
| 394 | + * @return String A simplified/sanitized version. | |
| 459 | 395 | */ |
| 460 | 396 | private function sanitize_search_term( $term ) { |
| 461 | 397 | $term = strtolower( urldecode( $term ) ); |
| 462 | 398 | |
| @@ -470,11 +406,8 @@ | ||
| 470 | 406 | } |
| 471 | 407 | |
| 472 | 408 | /** |
| 473 | 409 | * Callback function to sort the array of modules by the sort option. |
| 474 | - * | |
| 475 | - * @param array $m1 Array 1 to sort. | |
| 476 | - * @param array $m2 Array 2 to sort. | |
| 477 | 410 | */ |
| 478 | 411 | private function by_sorting_option( $m1, $m2 ) { |
| 479 | 412 | return $m1['sort'] - $m2['sort']; |
| 480 | 413 | } |
| @@ -479,42 +412,51 @@ | ||
| 479 | 412 | return $m1['sort'] - $m2['sort']; |
| 480 | 413 | } |
| 481 | 414 | |
| 482 | 415 | /** |
| 416 | + * Builds a URL to purchase and upgrade inserting the site fragment and the affiliate code if it exists. | |
| 417 | + * | |
| 418 | + * @param string $feature Module slug (or forged one for extra features). | |
| 419 | + * | |
| 420 | + * @since 7.1.0 | |
| 421 | + * | |
| 422 | + * @return string URL to upgrade. | |
| 423 | + */ | |
| 424 | + private function get_upgrade_url( $feature ) { | |
| 425 | + $site_raw_url = Jetpack::build_raw_urls( get_home_url() ); | |
| 426 | + $affiliateCode = Jetpack_Affiliate::init()->get_affiliate_code(); | |
| 427 | + $user = wp_get_current_user()->ID; | |
| 428 | + return "https://jetpack.com/redirect/?source=plugin-hint-upgrade-$feature&site=$site_raw_url&u=$user" . | |
| 429 | + ( $affiliateCode ? "&aff=$affiliateCode" : '' ); | |
| 430 | + } | |
| 431 | + | |
| 432 | + /** | |
| 483 | 433 | * Modify the URL to the feature settings, for example Publicize. |
| 484 | 434 | * Sharing is included here because while we still have a page in WP Admin, |
| 485 | 435 | * we prefer to send users to Calypso. |
| 486 | 436 | * |
| 487 | - * @param string $feature Feature. | |
| 488 | - * @param string $configure_url URL to configure feature. | |
| 437 | + * @param string $feature | |
| 438 | + * @param string $configure_url | |
| 489 | 439 | * |
| 490 | 440 | * @return string |
| 491 | 441 | * @since 7.1.0 |
| 442 | + * | |
| 492 | 443 | */ |
| 493 | 444 | private function get_configure_url( $feature, $configure_url ) { |
| 445 | + $siteFragment = Jetpack::build_raw_urls( get_home_url() ); | |
| 494 | 446 | switch ( $feature ) { |
| 495 | 447 | case 'sharing': |
| 496 | 448 | case 'publicize': |
| 497 | - $configure_url = Redirect::get_url( 'calypso-marketing-connections' ); | |
| 449 | + $configure_url = "https://wordpress.com/sharing/$siteFragment"; | |
| 498 | 450 | break; |
| 499 | 451 | case 'seo-tools': |
| 500 | - $configure_url = Redirect::get_url( | |
| 501 | - 'calypso-marketing-traffic', | |
| 502 | - array( | |
| 503 | - 'anchor' => 'seo', | |
| 504 | - ) | |
| 505 | - ); | |
| 452 | + $configure_url = "https://wordpress.com/settings/traffic/$siteFragment#seo"; | |
| 506 | 453 | break; |
| 507 | 454 | case 'google-analytics': |
| 508 | - $configure_url = Redirect::get_url( | |
| 509 | - 'calypso-marketing-traffic', | |
| 510 | - array( | |
| 511 | - 'anchor' => 'analytics', | |
| 512 | - ) | |
| 513 | - ); | |
| 455 | + $configure_url = "https://wordpress.com/settings/traffic/$siteFragment#analytics"; | |
| 514 | 456 | break; |
| 515 | 457 | case 'wordads': |
| 516 | - $configure_url = Redirect::get_url( 'wpcom-ads-settings' ); | |
| 458 | + $configure_url = "https://wordpress.com/ads/settings/$siteFragment"; | |
| 517 | 459 | break; |
| 518 | 460 | } |
| 519 | 461 | return $configure_url; |
| 520 | 462 | } |
| @@ -520,11 +462,8 @@ | ||
| 520 | 462 | } |
| 521 | 463 | |
| 522 | 464 | /** |
| 523 | 465 | * Put some more appropriate links on our custom result cards. |
| 524 | - * | |
| 525 | - * @param array $links Related links. | |
| 526 | - * @param array $plugin Plugin result information. | |
| 527 | 466 | */ |
| 528 | 467 | public function insert_module_related_links( $links, $plugin ) { |
| 529 | 468 | if ( self::$slug !== $plugin['slug'] ) { |
| 530 | 469 | return $links; |
| @@ -538,9 +477,9 @@ | ||
| 538 | 477 | if ( 'akismet' === $plugin['module'] || 'vaultpress' === $plugin['module'] ) { |
| 539 | 478 | $links['jp_get_started'] = '<a |
| 540 | 479 | id="plugin-select-settings" |
| 541 | 480 | class="jetpack-plugin-search__primary jetpack-plugin-search__get-started button" |
| 542 | - href="' . esc_url( Redirect::get_url( 'plugin-hint-learn-' . $plugin['module'] ) ) . '" | |
| 481 | + href="https://jetpack.com/redirect/?source=plugin-hint-learn-' . $plugin['module'] . '" | |
| 543 | 482 | data-module="' . esc_attr( $plugin['module'] ) . '" |
| 544 | 483 | data-track="get_started" |
| 545 | 484 | >' . esc_html__( 'Get started', 'jetpack' ) . '</a>'; |
| 546 | 485 | // Jetpack installed, active, feature not enabled; prompt to enable. |
| @@ -570,14 +509,14 @@ | ||
| 570 | 509 | href="' . esc_url( $this->get_configure_url( $plugin['module'], $plugin['configure_url'] ) ) . '" |
| 571 | 510 | data-module="' . esc_attr( $plugin['module'] ) . '" |
| 572 | 511 | data-track="configure" |
| 573 | 512 | >' . esc_html__( 'Configure', 'jetpack' ) . '</a>'; |
| 574 | - // Module is active, doesn't have options to configure. | |
| 513 | + // Module is active, doesn't have options to configure | |
| 575 | 514 | } elseif ( Jetpack::is_module_active( $plugin['module'] ) ) { |
| 576 | 515 | $links['jp_get_started'] = '<a |
| 577 | 516 | id="plugin-select-settings" |
| 578 | 517 | class="jetpack-plugin-search__primary jetpack-plugin-search__get-started button" |
| 579 | - href="' . esc_url( Redirect::get_url( 'plugin-hint-learn-' . $plugin['module'] ) ) . '" | |
| 518 | + href="https://jetpack.com/redirect/?source=plugin-hint-learn-' . $plugin['module'] . '" | |
| 580 | 519 | data-module="' . esc_attr( $plugin['module'] ) . '" |
| 581 | 520 | data-track="get_started" |
| 582 | 521 | >' . esc_html__( 'Get started', 'jetpack' ) . '</a>'; |
| 583 | 522 | } |
| @@ -592,9 +531,9 @@ | ||
| 592 | 531 | data-track="learn_more" |
| 593 | 532 | >' . esc_html__( 'Learn more', 'jetpack' ) . '</a>'; |
| 594 | 533 | } |
| 595 | 534 | |
| 596 | - // Dismiss link. | |
| 535 | + // Dismiss link | |
| 597 | 536 | $links[] = '<a |
| 598 | 537 | class="jetpack-plugin-search__dismiss" |
| 599 | 538 | data-module="' . esc_attr( $plugin['module'] ) . '" |
| 600 | 539 | >' . esc_html__( 'Hide this suggestion', 'jetpack' ) . '</a>'; |
| @@ -611,13 +550,53 @@ | ||
| 611 | 550 | * |
| 612 | 551 | * @return bool True if PSH is active. |
| 613 | 552 | */ |
| 614 | 553 | function jetpack_is_psh_active() { |
| 615 | - /** | |
| 616 | - * Disables the Plugin Search Hints feature found when searching the plugins page. | |
| 617 | - * | |
| 618 | - * @since 8.7.0 | |
| 619 | - * | |
| 620 | - * @param bool Set false to disable the feature. | |
| 621 | - */ | |
| 622 | - return apply_filters( 'jetpack_psh_active', true ); | |
| 554 | + // false means unset, 1 means active, 0 means inactive. | |
| 555 | + $status = get_transient( 'jetpack_psh_status' ); | |
| 556 | + | |
| 557 | + if ( false === $status ) { | |
| 558 | + $error = false; | |
| 559 | + $status = jetpack_get_remote_is_psh_active( $error ); | |
| 560 | + set_transient( | |
| 561 | + 'jetpack_psh_status', | |
| 562 | + // Cache as int | |
| 563 | + (int) $status, | |
| 564 | + // If there was an error, still cache but for a shorter time | |
| 565 | + ( $error ? 5 : 15 ) * MINUTE_IN_SECONDS | |
| 566 | + ); | |
| 567 | + } | |
| 568 | + | |
| 569 | + return (bool) $status; | |
| 570 | +} | |
| 571 | + | |
| 572 | +/** | |
| 573 | + * Makes remote request to determine if Plugin search hints is active. | |
| 574 | + * | |
| 575 | + * @since 7.1.1 | |
| 576 | + * @internal | |
| 577 | + * | |
| 578 | + * @param bool &$error Did the remote request result in an error? | |
| 579 | + * @return bool True if PSH is active. | |
| 580 | + */ | |
| 581 | +function jetpack_get_remote_is_psh_active( &$error ) { | |
| 582 | + $response = wp_remote_get( 'https://jetpack.com/psh-status/' ); | |
| 583 | + if ( is_wp_error( $response ) ) { | |
| 584 | + $error = true; | |
| 585 | + return true; | |
| 586 | + } | |
| 587 | + | |
| 588 | + $body = wp_remote_retrieve_body( $response ); | |
| 589 | + if ( empty( $body ) ) { | |
| 590 | + $error = true; | |
| 591 | + return true; | |
| 592 | + } | |
| 593 | + | |
| 594 | + $json = json_decode( $body ); | |
| 595 | + if ( ! isset( $json->active ) ) { | |
| 596 | + $error = true; | |
| 597 | + return true; | |
| 598 | + } | |
| 599 | + | |
| 600 | + $error = false; | |
| 601 | + return (bool) $json->active; | |
| 623 | 602 | } |