Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
85.71% covered (warning)
85.71%
36 / 42
88.24% covered (warning)
88.24%
15 / 17
CRAP
0.00% covered (danger)
0.00%
0 / 1
Scan
87.50% covered (warning)
87.50%
35 / 40
88.24% covered (warning)
88.24%
15 / 17
27.32
0.00% covered (danger)
0.00%
0 / 1
 get_name
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 get_title
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 get_description
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 get_long_description
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 get_features
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
1
 get_pricing_for_ui
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
1
 get_wpcom_product_slug
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 is_active
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 do_product_specific_activation
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
12
 is_module_active
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 get_paid_plan_product_slugs
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
 has_paid_plan_for_product
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 get_status
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
3
 is_upgradable_by_bundle
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 get_post_activation_url
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 get_manage_url
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
4
 get_post_checkout_url
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2/**
3 * Scan product
4 *
5 * @package my-jetpack
6 */
7
8namespace Automattic\Jetpack\My_Jetpack\Products;
9
10use Automattic\Jetpack\My_Jetpack\Module_Product;
11use Automattic\Jetpack\My_Jetpack\Products;
12use Automattic\Jetpack\My_Jetpack\Wpcom_Products;
13use Automattic\Jetpack\Protect_Status\Plan;
14use Automattic\Jetpack\Redirect;
15use WP_Error;
16
17if ( ! defined( 'ABSPATH' ) ) {
18    exit( 0 );
19}
20
21/**
22 * Class responsible for handling the Scan product
23 */
24class Scan extends Module_Product {
25
26    /**
27     * The product slug
28     *
29     * @var string
30     */
31    public static $slug = 'scan';
32
33    /**
34     * The Jetpack module name
35     *
36     * @var string
37     */
38    public static $module_name = 'scan';
39
40    /**
41     * The category of the product
42     *
43     * @var string
44     */
45    public static $category = 'security';
46
47    /**
48     * The feature slug that identifies the paid plan
49     *
50     * @var string
51     */
52    public static $feature_identifying_paid_plan = 'scan';
53
54    /**
55     * Get the product name
56     *
57     * @return string
58     */
59    public static function get_name() {
60        return 'Scan';
61    }
62
63    /**
64     * Get the product title
65     *
66     * @return string
67     */
68    public static function get_title() {
69        return 'Jetpack Scan';
70    }
71
72    /**
73     * Get the internationalized product description
74     *
75     * @return string
76     */
77    public static function get_description() {
78        return __( 'Around‑the‑clock web application firewall, and automated malware scanning.', 'jetpack-my-jetpack' );
79    }
80
81    /**
82     * Get the internationalized product long description
83     *
84     * @return string
85     */
86    public static function get_long_description() {
87        return __( 'Automatic scanning and one-click fixes keep your site one step ahead of security threats and malware.', 'jetpack-my-jetpack' );
88    }
89
90    /**
91     * Get the internationalized features list
92     *
93     * @return array Scan features list
94     */
95    public static function get_features() {
96        return array(
97            _x( 'Automated daily scanning', 'Scan Product Feature', 'jetpack-my-jetpack' ),
98            _x( 'One-click fixes for most issues', 'Scan Product Feature', 'jetpack-my-jetpack' ),
99            _x( 'Instant email notifications', 'Scan Product Feature', 'jetpack-my-jetpack' ),
100            _x( 'Access to latest Firewall rules', 'Scan Product Feature', 'jetpack-my-jetpack' ),
101        );
102    }
103
104    /**
105     * Get the product princing details
106     *
107     * @return array Pricing details
108     */
109    public static function get_pricing_for_ui() {
110        return array_merge(
111            array(
112                'available'          => true,
113                'wpcom_product_slug' => static::get_wpcom_product_slug(),
114            ),
115            Wpcom_Products::get_product_pricing( static::get_wpcom_product_slug() )
116        );
117    }
118
119    /**
120     * Get the WPCOM product slug used to make the purchase
121     *
122     * @return ?string
123     */
124    public static function get_wpcom_product_slug() {
125        return 'jetpack_scan';
126    }
127
128    /**
129     * Checks whether the Product is active
130     *
131     * Scan is not actually a module. Activation takes place on WPCOM. So lets consider it active if jetpack is active and has the plan.
132     *
133     * @return boolean
134     */
135    public static function is_active() {
136        return static::is_jetpack_plugin_active();
137    }
138
139    /**
140     * Activates the product by installing and activating its plugin
141     *
142     * @param bool|WP_Error $current_result Is the result of the top level activation actions. You probably won't do anything if it is an WP_Error.
143     * @return boolean|\WP_Error
144     */
145    public static function do_product_specific_activation( $current_result ) {
146
147        $product_activation = parent::do_product_specific_activation( $current_result );
148
149        if ( is_wp_error( $product_activation ) && 'module_activation_failed' === $product_activation->get_error_code() ) {
150            // Scan is not a module. There's nothing in the plugin to be activated, so it's ok to fail to activate the module.
151            $product_activation = true;
152        }
153
154        return $product_activation;
155    }
156
157    /**
158     * Checks whether the Jetpack module is active
159     *
160     * Scan is not a module. Nothing needs to be active. Let's always consider it active.
161     *
162     * @return bool
163     */
164    public static function is_module_active() {
165        return true;
166    }
167
168    /**
169     * Get the product-slugs of the paid plans for this product.
170     * (Do not include bundle plans, unless it's a bundle plan itself).
171     *
172     * @return array
173     */
174    public static function get_paid_plan_product_slugs() {
175        // Consumers match by substring, so the prefix covers every Scan product. An older Protect Status may lack it.
176        return array( defined( Plan::class . '::SCAN_PRODUCT_PREFIX' ) ? Plan::SCAN_PRODUCT_PREFIX : 'jetpack_scan' );
177    }
178
179    /**
180     * Whether the site pays for Scan, by the same check as the Protect page.
181     *
182     * @return bool
183     */
184    public static function has_paid_plan_for_product() {
185        return Plan::has_required_plan();
186    }
187
188    /**
189     * Get the card's status, Expired for a lapsed purchase, as Protect::get_status() does.
190     *
191     * @return string
192     */
193    public static function get_status() {
194        $status = parent::get_status();
195
196        if ( Products::STATUS_CAN_UPGRADE === $status && static::is_paid_plan_expired() ) {
197            return Products::STATUS_EXPIRED;
198        }
199
200        return $status;
201    }
202
203    /**
204     * Return product bundles list
205     * that supports the product.
206     *
207     * @return boolean|array Products bundle list.
208     */
209    public static function is_upgradable_by_bundle() {
210        return array( 'security', 'complete' );
211    }
212
213    /**
214     * Get the URL the user is taken after activating the product
215     *
216     * @return ?string
217     */
218    public static function get_post_activation_url() {
219        return ''; // stay in My Jetpack page.
220    }
221
222    /**
223     * Get the URL where the user manages the product
224     *
225     * @return ?string
226     */
227    public static function get_manage_url() {
228        // The Protect page lists Scan's threats.
229        // An older plugin's copy of Protect, loaded earlier in the same request, may not have this method.
230        if ( method_exists( Protect::class, 'has_protect_page' ) && Protect::has_protect_page() ) {
231            return admin_url( 'admin.php?page=jetpack-protect' );
232        }
233
234        if ( method_exists( Protect::class, 'get_scan_dashboard_url' ) ) {
235            return Protect::get_scan_dashboard_url();
236        }
237
238        return Redirect::get_url( 'my-jetpack-manage-scan' );
239    }
240
241    /**
242     * Get the URL where the user should be redirected after checkout
243     */
244    public static function get_post_checkout_url() {
245        if ( static::is_jetpack_plugin_active() ) {
246            return static::get_manage_url();
247        }
248
249        // If Jetpack is not active, it means that the user has another standalone plugin active
250        // and it follows the `Protect` plugin flow instead of `Scan` so for now it would be safe
251        // to return null and let the user go back to the My Jetpack page.
252        return null;
253    }
254}