Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
78.57% covered (warning)
78.57%
11 / 14
100.00% covered (success)
100.00%
3 / 3
CRAP
100.00% covered (success)
100.00%
1 / 1
WPCOM_Scan
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
3 / 3
8
100.00% covered (success)
100.00%
1 / 1
 get_live_feature_url
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 filter_available_modules
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 filter_admin_menu_visibility
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
5
1<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName -- Feature entry file, named after the feature, also holds the WPCOM_Scan bootstrap class.
2/**
3 * An in-wp-admin Protect page for WordPress.com Simple and WoA sites.
4 * Prompts for a plan upgrade or activation of Scan.
5 *
6 * @package automattic/jetpack-mu-wpcom
7 */
8
9namespace Automattic\Jetpack\Jetpack_Mu_Wpcom;
10
11require_once __DIR__ . '/../wpcom-hosting-feature-page/class-wpcom-hosting-feature-page.php';
12
13/**
14 * Registers the Protect admin page and its wp-build assets.
15 */
16class WPCOM_Scan extends WPCOM_Hosting_Feature_Page {
17
18    /**
19     * The slug the Jetpack plugin is expected to serve Protect from on WoA once Scan is live.
20     */
21    const MENU_SLUG = 'jetpack-protect';
22
23    /**
24     * The Jetpack plugin module that serves MENU_SLUG with the Protect package's dashboard.
25     */
26    const DASHBOARD_MODULE = 'protect-dashboard';
27
28    /**
29     * As declared in routes/wpcom-scan/package.json.
30     */
31    const WP_BUILD_PAGE = 'wpcom-scan';
32
33    /**
34     * Product name, do not translate.
35     */
36    const PAGE_TITLE = 'Jetpack Protect';
37
38    /**
39     * Product name, do not translate.
40     */
41    const MENU_TITLE = 'Protect';
42
43    /**
44     * SCAN_SELF_SERVE, not SCAN: SCAN also covers Personal and Premium plans, which run scans
45     * without exposing Scan's UI. It is also what the dashboard's Scan page gates on.
46     */
47    const FEATURE = 'SCAN_SELF_SERVE';
48
49    /**
50     * Calypso's Scan page, since nothing serves this slug on WoA once Scan is live.
51     *
52     * Drop this override to land back on `jetpack-protect` once the Jetpack plugin serves it.
53     *
54     * @param string|null $new_host The site's address after a transfer, when it changes.
55     * @return string
56     */
57    public static function get_live_feature_url( $new_host = null ) {
58        $host = $new_host ?? wp_parse_url( home_url(), PHP_URL_HOST );
59
60        return 'https://wordpress.com/scan/' . rawurlencode( (string) $host );
61    }
62
63    /**
64     * Keep the Jetpack plugin's Protect dashboard off a WoA site whose plan lacks Scan, so this page's upgrade prompt keeps the slug.
65     *
66     * @param array $modules Available modules, keyed by slug.
67     * @return array
68     */
69    public static function filter_available_modules( $modules ) {
70        if ( ! self::has_feature() ) {
71            unset( $modules[ self::DASHBOARD_MODULE ] );
72        }
73
74        return $modules;
75    }
76
77    /**
78     * Keep the Jetpack plugin's Protect page out of the sidebar while Calypso's Scan owns the nav.
79     *
80     * Matched on the item's module: the standalone Protect plugin shares the slug and keeps its entry.
81     *
82     * @param array $states     Map of Jetpack menu item key to visibility state.
83     * @param array $menu_items The registered Jetpack menu items.
84     * @return array
85     */
86    public static function filter_admin_menu_visibility( $states, $menu_items ) {
87        // With the standalone Protect plugin active, its users keep a Protect entry, whichever page serves it.
88        if ( class_exists( 'Jetpack_Protect' ) ) {
89            return $states;
90        }
91
92        foreach ( (array) $menu_items as $item ) {
93            if ( self::MENU_SLUG === ( $item['menu_slug'] ?? null ) && self::DASHBOARD_MODULE === ( $item['args']['module'] ?? null ) ) {
94                $states[ $item['args']['key'] ?? self::MENU_SLUG ] = 'hidden';
95            }
96        }
97
98        return $states;
99    }
100}
101
102add_action( 'init', array( WPCOM_Scan::class, 'init' ) );
103add_filter( 'jetpack_admin_menu_visibility', array( WPCOM_Scan::class, 'filter_admin_menu_visibility' ), 10, 2 );