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