Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
52.00% covered (warning)
52.00%
39 / 75
33.33% covered (danger)
33.33%
2 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
WPCOM_Features
52.00% covered (warning)
52.00%
39 / 75
33.33% covered (danger)
33.33%
2 / 6
376.49
0.00% covered (danger)
0.00%
0 / 1
 feature_exists
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 in_array_recursive
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
5
 has_feature
90.00% covered (success)
90.00%
9 / 10
0.00% covered (danger)
0.00%
0 / 1
8.06
 add_free_plan_purchase
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 purchase_in_products_map
42.31% covered (danger)
42.31%
22 / 52
0.00% covered (danger)
0.00%
0 / 1
315.28
 get_feature_slugs
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2/**
3 * THIS FILE EXISTS VERBATIM IN WPCOM AND WPCOMSH.
4 *
5 * DANGER DANGER DANGER!!!
6 * If you make any changes to this class you must MANUALLY update this file in both WPCOM and WPCOMSH.
7 *
8 * @package WPCOM_Features
9 */
10
11/**
12 * Map features to purchases.
13 */
14class WPCOM_Features {
15
16    /**
17     * Key used to exclude plans from features.
18     */
19    public const EXCLUDE_PLANS = 'exclude_plans';
20
21    /*
22     * Private const for every mapped purchase, sorted by product_id.
23     */
24    private const SPACE_1GB                                   = 'wordpress_com_1gb_space_addon_yearly';
25    private const SPACE_10GB                                  = '1gb_space_upgrade'; // 9
26    private const SPACE_25GB                                  = '5gb_space_upgrade'; // 10
27    private const SPACE_50GB                                  = '10gb_space_upgrade'; // 11
28    private const NO_ADS                                      = 'no-adverts/no-adverts.php'; // 12
29    private const WPCOM_VIDEOPRESS                            = 'videopress'; // 15
30    private const SPACE_100GB                                 = '50gb_space_upgrade'; // 19
31    private const SPACE_200GB                                 = '100gb_space_upgrade'; // 20
32    private const SPACE_3GB                                   = '3gb_space_upgrade'; // 21
33    private const WPCOM_CUSTOM_DESIGN                         = 'custom-design'; // 45
34    private const WPCOM_VIDEOPRESS_PRO                        = 'videopress-pro'; // 47
35    private const WPCOM_UNLIMITED_THEMES                      = 'unlimited_themes'; // 49
36    private const GAPPS                                       = 'gapps'; // 69
37    private const GAPPS_UNLIMITED                             = 'gapps_unlimited'; // 70
38    private const WP_TITAN_MAIL_MONTHLY                       = 'wp_titan_mail_monthly'; // 400
39    private const WP_TITAN_MAIL_YEARLY                        = 'wp_titan_mail_yearly'; // 401
40    private const WP_TITAN_MAIL_PREMIUM_MONTHLY               = 'wp_titan_mail_premium_monthly'; // 402
41    private const WP_TITAN_MAIL_PREMIUM_YEARLY                = 'wp_titan_mail_premium_yearly'; // 403
42    private const WP_TITAN_MAIL_ULTRA_MONTHLY                 = 'wp_titan_mail_ultra_monthly'; // 404
43    private const WP_TITAN_MAIL_ULTRA_YEARLY                  = 'wp_titan_mail_ultra_yearly'; // 405
44    private const WP_GOOGLE_WORKSPACE_BUSINESS_STARTER_YEARLY = 'wp_google_workspace_business_starter_yearly'; // 690
45    private const WPCOM_SEARCH                                = 'wpcom_search'; // 800
46    private const WPCOM_SEARCH_MONTHLY                        = 'wpcom_search_monthly'; // 801
47    private const YOAST_PREMIUM                               = 'yoast_premium'; // 900
48    private const VALUE_BUNDLE                                = 'value_bundle'; // 1003
49    private const BUNDLE_PRO                                  = 'bundle_pro'; // 1004
50    private const BUNDLE_SUPER                                = 'bundle_super'; // 1005
51    private const BUNDLE_ENTERPRISE                           = 'wpcom-enterprise'; // 1007
52    private const BUSINESS_BUNDLE                             = 'business-bundle'; // 1008
53    private const PERSONAL_BUNDLE                             = 'personal-bundle'; // 1009
54    private const BLOGGER_BUNDLE                              = 'blogger-bundle'; // 1010
55    private const ECOMMERCE_BUNDLE                            = 'ecommerce-bundle'; // 1011
56    private const VALUE_BUNDLE_MONTHLY                        = 'value_bundle_monthly'; // 1013
57    private const PRO_PLAN_MONTHLY                            = 'pro-plan-monthly'; // 1034
58    private const BUSINESS_BUNDLE_MONTHLY                     = 'business-bundle-monthly'; // 1018
59    private const PERSONAL_BUNDLE_MONTHLY                     = 'personal-bundle-monthly'; // 1019
60    private const ECOMMERCE_BUNDLE_MONTHLY                    = 'ecommerce-bundle-monthly'; // 1021
61    private const VALUE_BUNDLE_2Y                             = 'value_bundle-2y'; // 1023
62    private const BUSINESS_BUNDLE_2Y                          = 'business-bundle-2y'; // 1028
63    private const PERSONAL_BUNDLE_2Y                          = 'personal-bundle-2y'; // 1029
64    private const BLOGGER_BUNDLE_2Y                           = 'blogger-bundle-2y'; // 1030
65    private const ECOMMERCE_BUNDLE_2Y                         = 'ecommerce-bundle-2y'; // 1031
66    private const VALUE_BUNDLE_3Y                             = 'value_bundle-3y'; // 1043
67    private const BUSINESS_BUNDLE_3Y                          = 'business-bundle-3y'; // 1048
68    private const PERSONAL_BUNDLE_3Y                          = 'personal-bundle-3y'; // 1049
69    private const ECOMMERCE_BUNDLE_3Y                         = 'ecommerce-bundle-3y'; // 1051
70    private const PRO_PLAN_2Y                                 = 'pro-plan-2y'; // 1035
71    private const PRO_PLAN                                    = 'pro-plan'; // 1032
72    private const STARTER_PLAN                                = 'starter-plan'; // 1033
73    private const WP_P2_PLUS_MONTHLY                          = 'wp_p2_plus_monthly'; // 1040
74    private const ECOMMERCE_TRIAL_BUNDLE_MONTHLY              = 'ecommerce-trial-bundle-monthly'; // 1052
75    private const WPCOM_WOOEXPRESS_MEDIUM_BUNDLE_MONTHLY      = 'wooexpress-medium-bundle-monthly'; // 1053
76    private const WPCOM_WOOEXPRESS_MEDIUM_BUNDLE_YEARLY       = 'wooexpress-medium-bundle-yearly'; // 1055
77    private const WPCOM_WOOEXPRESS_SMALL_BUNDLE_MONTHLY       = 'wooexpress-small-bundle-monthly'; // 1054
78    private const WPCOM_WOOEXPRESS_SMALL_BUNDLE_YEARLY        = 'wooexpress-small-bundle-yearly'; // 1056
79    private const WOO_HOSTED_BASIC_PLAN_MONTHLY               = 'woo_hosted_basic_plan_monthly'; // 4001
80    private const WOO_HOSTED_BASIC_PLAN_YEARLY                = 'woo_hosted_basic_plan_yearly'; // 4002
81    private const WOO_HOSTED_PRO_PLAN_MONTHLY                 = 'woo_hosted_pro_plan_monthly'; // 4003
82    private const WOO_HOSTED_PRO_PLAN_YEARLY                  = 'woo_hosted_pro_plan_yearly'; // 4004
83    private const WPCOM_MIGRATION_TRIAL_BUNDLE_MONTHLY        = 'wp_bundle_migration_trial_monthly'; // 1057
84    private const WPCOM_HOSTING_TRIAL_BUNDLE_MONTHLY          = 'wp_bundle_hosting_trial_monthly'; // 1058
85    private const WPCOM_STAGING_PRODUCT                       = 'wp_staging_site_lifetime'; // 1060
86    private const WPCOM_HUNDRED_YEAR_BUNDLE                   = 'wp_com_hundred_year_bundle_centennially'; // 1061
87    private const STUDENT_BUNDLE                              = 'wp_bundle_student_yearly'; // 1090
88    private const JETPACK_PREMIUM                             = 'jetpack_premium'; // 2000
89    private const JETPACK_BUSINESS                            = 'jetpack_business'; // 2001
90    private const JETPACK_FREE                                = 'jetpack_free'; // 2002
91    private const JETPACK_PREMIUM_MONTHLY                     = 'jetpack_premium_monthly'; // 2003
92    private const JETPACK_BUSINESS_MONTHLY                    = 'jetpack_business_monthly'; // 2004
93    private const JETPACK_PERSONAL                            = 'jetpack_personal'; // 2005
94    private const JETPACK_PERSONAL_MONTHLY                    = 'jetpack_personal_monthly'; // 2006
95    private const JETPACK_SECURITY_DAILY                      = 'jetpack_security_daily'; // 2010
96    private const JETPACK_SECURITY_DAILY_MONTHLY              = 'jetpack_security_daily_monthly'; // 2011
97    private const JETPACK_SECURITY_REALTIME                   = 'jetpack_security_realtime'; // 2012
98    private const JETPACK_SECURITY_REALTIME_MONTHLY           = 'jetpack_security_realtime_monthly'; // 2013
99    private const JETPACK_GROWTH_BI_YEARLY                    = 'jetpack_growth_bi_yearly'; // 2023
100    private const JETPACK_GROWTH_YEARLY                       = 'jetpack_growth_yearly'; // 2022
101    private const JETPACK_GROWTH_MONTHLY                      = 'jetpack_growth_monthly'; // 2021
102    private const JETPACK_COMPLETE_BI_YEARLY                  = 'jetpack_complete_bi_yearly'; // 2035
103    private const JETPACK_COMPLETE                            = 'jetpack_complete'; // 2014
104    private const JETPACK_COMPLETE_MONTHLY                    = 'jetpack_complete_monthly'; // 2015
105    private const JETPACK_SECURITY_T0_YEARLY                  = 'jetpack_security_t0_yearly'; // 10237
106    private const JETPACK_SECURITY_T0_MONTHLY                 = 'jetpack_security_t0_monthly'; // 10238
107    private const JETPACK_SECURITY_T1_BI_YEARLY               = 'jetpack_security_t1_bi_yearly'; // 2034
108    private const JETPACK_SECURITY_T1_YEARLY                  = 'jetpack_security_t1_yearly'; // 2016
109    private const JETPACK_SECURITY_T1_MONTHLY                 = 'jetpack_security_t1_monthly'; // 2017
110    private const JETPACK_SECURITY_T2_YEARLY                  = 'jetpack_security_t2_yearly'; // 2019
111    private const JETPACK_SECURITY_T2_MONTHLY                 = 'jetpack_security_t2_monthly'; // 2020
112    private const JETPACK_STARTER_YEARLY                      = 'jetpack_starter_yearly'; // 2030
113    private const JETPACK_STARTER_MONTHLY                     = 'jetpack_starter_monthly'; // 2031
114    private const JETPACK_BACKUP_DAILY                        = 'jetpack_backup_daily'; // 2100
115    private const JETPACK_BACKUP_DAILY_MONTHLY                = 'jetpack_backup_daily_monthly'; // 2101
116    private const JETPACK_BACKUP_REALTIME                     = 'jetpack_backup_realtime'; // 2102
117    private const JETPACK_BACKUP_REALTIME_MONTHLY             = 'jetpack_backup_realtime_monthly'; // 2103
118    private const JETPACK_SEARCH_BI_YEARLY                    = 'jetpack_search_bi_yearly'; // 2031
119    private const JETPACK_SEARCH                              = 'jetpack_search'; // 2104
120    private const JETPACK_SEARCH_MONTHLY                      = 'jetpack_search_monthly'; // 2105
121    private const JETPACK_SCAN_BI_YEARLY                      = 'jetpack_scan_bi_yearly'; // 2038
122    private const JETPACK_SCAN                                = 'jetpack_scan'; // 2106
123    private const JETPACK_SCAN_MONTHLY                        = 'jetpack_scan_monthly'; // 2107
124    private const JETPACK_SCAN_REALTIME                       = 'jetpack_scan_realtime'; // 2108
125    private const JETPACK_SCAN_REALTIME_MONTHLY               = 'jetpack_scan_realtime_monthly'; // 2109
126    private const JETPACK_ANTI_SPAM_BI_YEARLY                 = 'jetpack_anti_spam_bi_yearly'; // 2039
127    private const JETPACK_ANTI_SPAM                           = 'jetpack_anti_spam'; // 2110
128    private const JETPACK_ANTI_SPAM_MONTHLY                   = 'jetpack_anti_spam_monthly'; // 2111
129    private const JETPACK_BACKUP_T1_BI_YEARLY                 = 'jetpack_backup_t1_bi_yearly'; // 2123
130    private const JETPACK_BACKUP_T1_YEARLY                    = 'jetpack_backup_t1_yearly'; // 2112
131    private const JETPACK_BACKUP_T1_MONTHLY                   = 'jetpack_backup_t1_monthly'; // 2113
132    private const JETPACK_BACKUP_T2_YEARLY                    = 'jetpack_backup_t2_yearly'; // 2114
133    private const JETPACK_BACKUP_T2_MONTHLY                   = 'jetpack_backup_t2_monthly'; // 2115
134    private const JETPACK_BACKUP_ADDON_STORAGE_10GB_MONTHLY   = 'jetpack_backup_addon_storage_10gb_monthly'; // 2040
135    private const JETPACK_BACKUP_ADDON_STORAGE_100GB_MONTHLY  = 'jetpack_backup_addon_storage_100gb_monthly'; // 2044
136    private const JETPACK_BACKUP_ADDON_STORAGE_1TB_MONTHLY    = 'jetpack_backup_addon_storage_1tb_monthly'; // 2048
137    private const JETPACK_BACKUP_ADDON_STORAGE_3TB_MONTHLY    = 'jetpack_backup_addon_storage_3tb_monthly'; // 2052
138    private const JETPACK_BACKUP_ADDON_STORAGE_5TB_MONTHLY    = 'jetpack_backup_addon_storage_5tb_monthly'; // 2056
139    private const JETPACK_VIDEOPRESS_BI_YEARLY                = 'jetpack_videopress_bi_yearly'; // 2119
140    private const JETPACK_VIDEOPRESS                          = 'jetpack_videopress'; // 2116
141    private const JETPACK_VIDEOPRESS_MONTHLY                  = 'jetpack_videopress_monthly'; // 2117
142    private const JETPACK_BACKUP_T0_YEARLY                    = 'jetpack_backup_t0_yearly'; // 2120
143    private const JETPACK_BACKUP_T0_MONTHLY                   = 'jetpack_backup_t0_monthly'; // 2121
144    private const JETPACK_SEARCH_FREE                         = 'jetpack_search_free'; // 2130
145    private const JETPACK_BACKUP_ONE_TIME                     = 'jetpack_backup_one_time'; // 2201
146    private const JETPACK_STATS_FREE                          = 'jetpack_stats_free_yearly'; // 2221
147    private const JETPACK_STATS_PWYW                          = 'jetpack_stats_pwyw_yearly'; // 2222
148    private const JETPACK_STATS_MONTHLY                       = 'jetpack_stats_monthly'; // 2220
149    private const JETPACK_STATS_YEARLY                        = 'jetpack_stats_yearly'; // 2219
150    private const JETPACK_STATS_BI_YEARLY                     = 'jetpack_stats_bi_yearly'; // 2223
151    private const JETPACK_MONITOR_MONTHLY                     = 'jetpack_monitor_monthly'; // 2241
152    private const JETPACK_MONITOR_YEARLY                      = 'jetpack_monitor_yearly'; // 2242
153    private const AKISMET_FREE                                = 'ak_free_yearly'; // 2300
154    private const AKISMET_PERSONAL_MONTHLY                    = 'ak_personal_monthly'; // 2309
155    private const AKISMET_PERSONAL_YEARLY                     = 'ak_personal_yearly'; // 2310
156    private const AKISMET_PLUS_BI_YEARLY                      = 'ak_plus_bi_yearly_1'; // 2327
157    private const AKISMET_PLUS_YEARLY                         = 'ak_plus_yearly_1'; // 2311
158    private const AKISMET_PLUS_MONTHLY                        = 'ak_plus_monthly_1'; // 2312
159    private const AKISMET_PLUS_20K_BI_YEARLY                  = 'ak_plus_bi_yearly_2'; // 2328
160    private const AKISMET_PLUS_20K_YEARLY                     = 'ak_plus_yearly_2'; // 2313
161    private const AKISMET_PLUS_20K_MONTHLY                    = 'ak_plus_monthly_2'; // 2314
162    private const AKISMET_PLUS_30K_BI_YEARLY                  = 'ak_plus_bi_yearly_3'; // 2329
163    private const AKISMET_PLUS_30K_YEARLY                     = 'ak_plus_yearly_3'; // 2315
164    private const AKISMET_PLUS_30K_MONTHLY                    = 'ak_plus_monthly_3'; // 2316
165    private const AKISMET_PLUS_40K_BI_YEARLY                  = 'ak_plus_bi_yearly_4'; // 2330
166    private const AKISMET_PLUS_40K_YEARLY                     = 'ak_plus_yearly_4'; // 2317
167    private const AKISMET_PLUS_40K_MONTHLY                    = 'ak_plus_monthly_4'; // 2318
168    private const AKISMET_ENTERPRISE_BI_YEARLY                = 'ak_ent_bi_yearly_1'; // 2331
169    private const AKISMET_ENTERPRISE_YEARLY                   = 'ak_ent_yearly_1'; // 2319
170    private const AKISMET_ENTERPRISE_MONTHLY                  = 'ak_ent_monthly_1'; // 2320
171    private const AKISMET_ENTERPRISE_350K_YEARLY              = 'ak_ep350k_yearly_1'; // 2321
172    private const AKISMET_ENTERPRISE_350K_MONTHLY             = 'ak_ep350k_monthly_1'; // 2322
173    private const AKISMET_ENTERPRISE_2M_YEARLY                = 'ak_ep2m_yearly_1'; // 2323
174    private const AKISMET_ENTERPRISE_2M_MONTHLY               = 'ak_ep2m_monthly_1'; // 2324
175    private const AKISMET_ENTERPRISE_GT2M_YEARLY              = 'ak_epgt2m_yearly_1'; // 2325
176    private const AKISMET_ENTERPRISE_GT2M_MONTHLY             = 'ak_epgt2m_monthly_1'; // 2326
177    private const AKISMET_PRO_500_MONTHLY                     = 'ak_pro5h_monthly'; // 2332
178    private const AKISMET_PRO_500_YEARLY                      = 'ak_pro5h_yearly'; // 2333
179    private const AKISMET_PRO_500_BI_YEARLY                   = 'ak_pro5h_bi_yearly'; // 2334
180    private const AKISMET_BUSINESS_5K_MONTHLY                 = 'ak_bus5k_monthly'; // 2335
181    private const AKISMET_BUSINESS_5K_YEARLY                  = 'ak_bus5k_yearly'; // 2336
182    private const AKISMET_BUSINESS_5K_BI_YEARLY               = 'ak_bus5k_bi_yearly'; // 2337
183    private const AKISMET_ENTERPRISE_15K_MONTHLY              = 'ak_ep15k_monthly'; // 2338
184    private const AKISMET_ENTERPRISE_15K_YEARLY               = 'ak_ep15k_yearly'; // 2339
185    private const AKISMET_ENTERPRISE_15K_BI_YEARLY            = 'ak_ep15k_bi_yearly'; // 2340
186    private const AKISMET_ENTERPRISE_25K_MONTHLY              = 'ak_ep25k_monthly'; // 2341
187    private const AKISMET_ENTERPRISE_25K_YEARLY               = 'ak_ep25k_yearly'; // 2342
188    private const AKISMET_ENTERPRISE_25K_BI_YEARLY            = 'ak_ep25k_bi_yearly'; // 2343
189    private const JETPACK_BOOST_BI_YEARLY                     = 'jetpack_boost_bi_yearly'; // 2036
190    private const JETPACK_BOOST                               = 'jetpack_boost_yearly'; // 2401
191    private const JETPACK_BOOST_MONTHLY                       = 'jetpack_boost_monthly'; // 2400
192    private const JETPACK_AI_MONTHLY                          = 'jetpack_ai_monthly'; // 2450
193    private const JETPACK_AI_YEARLY                           = 'jetpack_ai_yearly'; // 2451
194    private const JETPACK_AI_BI_YEARLY                        = 'jetpack_ai_bi_yearly'; // 2452
195    private const JETPACK_SOCIAL_BASIC_MONTHLY_LEGACY         = 'jetpack_social_monthly'; // 2500
196    private const JETPACK_SOCIAL_BASIC_BI_YEARLY              = 'jetpack_social_basic_bi_yearly'; // 2037
197    private const JETPACK_SOCIAL_BASIC                        = 'jetpack_social_basic_yearly'; // 2503
198    private const JETPACK_SOCIAL_BASIC_MONTHLY                = 'jetpack_social_basic_monthly'; // 2504
199    private const JETPACK_SOCIAL_ADVANCED_BI_YEARLY           = 'jetpack_social_advanced_bi_yearly'; // 2604
200    private const JETPACK_SOCIAL_ADVANCED                     = 'jetpack_social_advanced_yearly'; // 2602
201    private const JETPACK_SOCIAL_ADVANCED_MONTHLY             = 'jetpack_social_advanced_monthly'; // 2603
202    private const JETPACK_GOLDEN_TOKEN                        = 'jetpack_golden_token_lifetime'; // 2900
203    private const JETPACK_CREATOR_MONTHLY                     = 'jetpack_creator_monthly'; // 2610
204    private const JETPACK_CREATOR_YEARLY                      = 'jetpack_creator_yearly'; // 2611
205    private const JETPACK_CREATOR_BI_YEARLY                   = 'jetpack_creator_bi_yearly'; // 2612
206    private const JETPACK_SOCIAL_V1_MONTHLY                   = 'jetpack_social_v1_monthly'; // 2606
207    private const JETPACK_SOCIAL_V1_YEARLY                    = 'jetpack_social_v1_yearly'; // 2605
208    private const JETPACK_SOCIAL_V1_BI_YEARLY                 = 'jetpack_social_v1_bi_yearly'; // 2607
209    private const A4A_WPCOM_BUSINESS_BUNDLE_YEARLY            = 'a4a_wp_bundle_business_yearly'; // 3300
210    private const A4A_WPCOM_BUSINESS_BUNDLE_MONTHLY           = 'a4a_wp_bundle_business_monthly'; // 3301
211    private const A4A_JETPACK_COMPLETE_YEARLY                 = 'a4a_jetpack_complete_yearly'; // 3302
212    private const A4A_JETPACK_COMPLETE_MONTHLY                = 'a4a_jetpack_complete_monthly'; // 3303
213    private const A4A_JETPACK_SECURITY_TIER_1_YEARLY          = 'a4a_jetpack_security_t1_yearly'; // 3304
214    private const A4A_JETPACK_SECURITY_TIER_1_MONTHLY         = 'a4a_jetpack_security_t1_monthly'; // 3305
215    private const A4A_JETPACK_SECURITY_TIER_2_YEARLY          = 'a4a_jetpack_security_t2_yearly'; // 3306
216    private const A4A_JETPACK_SECURITY_TIER_2_MONTHLY         = 'a4a_jetpack_security_t2_monthly'; // 3307
217    private const A4A_JETPACK_SEARCH_YEARLY                   = 'a4a_jetpack_search_yearly'; // 3318
218    private const A4A_JETPACK_SEARCH_MONTHLY                  = 'a4a_jetpack_search_monthly'; // 3319
219    private const A4A_JETPACK_SCAN_YEARLY                     = 'a4a_jetpack_scan_yearly'; // 3320
220    private const A4A_JETPACK_SCAN_MONTHLY                    = 'a4a_jetpack_scan_monthly'; // 3321
221    private const A4A_JETPACK_ANTI_SPAM_YEARLY                = 'a4a_jetpack_anti_spam_yearly'; // 3322
222    private const A4A_JETPACK_ANTI_SPAM_MONTHLY               = 'a4a_jetpack_anti_spam_monthly'; // 3323
223    private const A4A_JETPACK_BACKUP_TIER_1_YEARLY            = 'a4a_jetpack_backup_t1_yearly'; // 3324
224    private const A4A_JETPACK_BACKUP_TIER_1_MONTHLY           = 'a4a_jetpack_backup_t1_monthly'; // 3325
225    private const A4A_JETPACK_BACKUP_TIER_2_YEARLY            = 'a4a_jetpack_backup_t2_yearly'; // 3326
226    private const A4A_JETPACK_BACKUP_TIER_2_MONTHLY           = 'a4a_jetpack_backup_t2_monthly'; // 3327
227    private const A4A_JETPACK_VIDEOPRESS_YEARLY               = 'a4a_jetpack_videopress_yearly'; // 3328
228    private const A4A_JETPACK_VIDEOPRESS_MONTHLY              = 'a4a_jetpack_videopress_monthly'; // 3329
229    private const A4A_JETPACK_STATS_YEARLY                    = 'a4a_jetpack_stats_yearly'; // 3330
230    private const A4A_JETPACK_STATS_MONTHLY                   = 'a4a_jetpack_stats_monthly'; // 3331
231    private const A4A_JETPACK_MONITOR_YEARLY                  = 'a4a_jetpack_monitor_yearly'; // 3332
232    private const A4A_JETPACK_MONITOR_MONTHLY                 = 'a4a_jetpack_monitor_monthly'; // 3333
233    private const A4A_JETPACK_BOOST_YEARLY                    = 'a4a_jetpack_boost_yearly'; // 3334
234    private const A4A_JETPACK_BOOST_MONTHLY                   = 'a4a_jetpack_boost_monthly'; // 3335
235    private const A4A_JETPACK_AI_YEARLY                       = 'a4a_jetpack_ai_yearly'; // 3336
236    private const A4A_JETPACK_AI_MONTHLY                      = 'a4a_jetpack_ai_monthly'; // 3337
237    private const A4A_JETPACK_SOCIAL_V1_YEARLY                = 'a4a_jetpack_social_v1_yearly'; // 3338
238    private const A4A_JETPACK_SOCIAL_V1_MONTHLY               = 'a4a_jetpack_social_v1_monthly'; // 3339
239    private const A4A_JETPACK_CREATOR_YEARLY                  = 'a4a_jetpack_creator_yearly'; // 3340
240    private const A4A_JETPACK_CREATOR_MONTHLY                 = 'a4a_jetpack_creator_monthly'; // 3341
241
242    // WPCOM "Level 2": Groups of level 1s.
243    private const WPCOM_BLOGGER_PLANS           = array( self::BLOGGER_BUNDLE, self::BLOGGER_BUNDLE_2Y );
244    private const WPCOM_PERSONAL_PLANS          = array( self::PERSONAL_BUNDLE, self::PERSONAL_BUNDLE_MONTHLY, self::PERSONAL_BUNDLE_2Y, self::PERSONAL_BUNDLE_3Y );
245    private const WPCOM_STARTER_PLANS           = array( self::STARTER_PLAN );
246    private const WPCOM_PREMIUM_PLANS           = array( self::BUNDLE_PRO, self::VALUE_BUNDLE, self::VALUE_BUNDLE_MONTHLY, self::VALUE_BUNDLE_2Y, self::VALUE_BUNDLE_3Y );
247    private const WPCOM_PRO_PLANS               = array( self::PRO_PLAN, self::PRO_PLAN_MONTHLY, self::PRO_PLAN_2Y );
248    private const WPCOM_MIGRATION_TRIAL_PLANS   = array( self::WPCOM_MIGRATION_TRIAL_BUNDLE_MONTHLY );
249    private const WPCOM_HOSTING_TRIAL_PLANS     = array( self::WPCOM_HOSTING_TRIAL_BUNDLE_MONTHLY );
250    private const WPCOM_STUDENT_PLANS           = array( self::STUDENT_BUNDLE );
251    private const WPCOM_BUSINESS_PLANS          = array( self::BUSINESS_BUNDLE, self::BUSINESS_BUNDLE_MONTHLY, self::BUSINESS_BUNDLE_2Y, self::BUSINESS_BUNDLE_3Y, self::WPCOM_MIGRATION_TRIAL_PLANS, self::WPCOM_HUNDRED_YEAR_BUNDLE, self::WPCOM_HOSTING_TRIAL_BUNDLE_MONTHLY, self::A4A_WPCOM_BUSINESS_BUNDLE_YEARLY, self::A4A_WPCOM_BUSINESS_BUNDLE_MONTHLY, self::WPCOM_STUDENT_PLANS );
252    private const WPCOM_ECOMMERCE_PLANS         = array( self::ECOMMERCE_BUNDLE, self::ECOMMERCE_BUNDLE_MONTHLY, self::ECOMMERCE_BUNDLE_2Y, self::ECOMMERCE_BUNDLE_3Y );
253    private const WPCOM_ECOMMERCE_TRIAL_PLANS   = array( self::ECOMMERCE_TRIAL_BUNDLE_MONTHLY );
254    private const WPCOM_WOOEXPRESS_MEDIUM_PLANS = array( self::WPCOM_WOOEXPRESS_MEDIUM_BUNDLE_MONTHLY, self::WPCOM_WOOEXPRESS_MEDIUM_BUNDLE_YEARLY );
255    private const WPCOM_WOOEXPRESS_SMALL_PLANS  = array( self::WPCOM_WOOEXPRESS_SMALL_BUNDLE_MONTHLY, self::WPCOM_WOOEXPRESS_SMALL_BUNDLE_YEARLY );
256    private const WOO_HOSTED_PLANS              = array( self::WOO_HOSTED_BASIC_PLAN_MONTHLY, self::WOO_HOSTED_BASIC_PLAN_YEARLY, self::WOO_HOSTED_PRO_PLAN_MONTHLY, self::WOO_HOSTED_PRO_PLAN_YEARLY );
257    private const GOOGLE_WORKSPACE_PRODUCTS     = array( self::WP_GOOGLE_WORKSPACE_BUSINESS_STARTER_YEARLY );
258    private const GSUITE_PRODUCTS               = array( self::GAPPS, self::GAPPS_UNLIMITED );
259    private const WPCOM_TITAN_MAIL_PRODUCTS     = array( self::WP_TITAN_MAIL_MONTHLY, self::WP_TITAN_MAIL_YEARLY, self::WP_TITAN_MAIL_PREMIUM_MONTHLY, self::WP_TITAN_MAIL_PREMIUM_YEARLY, self::WP_TITAN_MAIL_ULTRA_MONTHLY, self::WP_TITAN_MAIL_ULTRA_YEARLY );
260
261    private const WPCOM_PERSONAL_AND_PREMIUM_PLANS = array( self::WPCOM_PERSONAL_PLANS, self::WPCOM_PREMIUM_PLANS );
262    // Unlock Business-gated features for sites with the flex-cache-site sticker via the free plan.
263    private const WPCOM_FLEX_CACHE_SITE_FREE_PLANS = array(
264        'required_sticker' => 'flex-cache-site',
265        self::JETPACK_ALL_SITES,
266    );
267
268    // WPCOM "Level 3" A: Groups of level 2s.
269    private const WPCOM_BLOGGER_AND_HIGHER_PLANS  = array( self::WPCOM_BLOGGER_PLANS, self::WPCOM_PERSONAL_PLANS, self::WPCOM_STARTER_PLANS, self::WPCOM_PREMIUM_PLANS, self::WPCOM_PRO_PLANS, self::WPCOM_BUSINESS_PLANS, self::WPCOM_ECOMMERCE_PLANS, self::WPCOM_ECOMMERCE_TRIAL_PLANS, self::WPCOM_WOOEXPRESS_PLANS );
270    private const WPCOM_PERSONAL_AND_HIGHER_PLANS = array( self::WPCOM_PERSONAL_PLANS, self::WPCOM_STARTER_PLANS, self::WPCOM_PREMIUM_PLANS, self::WPCOM_PRO_PLANS, self::WPCOM_BUSINESS_PLANS, self::WPCOM_ECOMMERCE_PLANS, self::WPCOM_ECOMMERCE_TRIAL_PLANS, self::WPCOM_WOOEXPRESS_PLANS );
271    private const WPCOM_STARTER_AND_HIGHER_PLANS  = array( self::WPCOM_STARTER_PLANS, self::WPCOM_PREMIUM_PLANS, self::WPCOM_PRO_PLANS, self::WPCOM_BUSINESS_PLANS, self::WPCOM_ECOMMERCE_PLANS, self::WPCOM_ECOMMERCE_TRIAL_PLANS, self::WPCOM_WOOEXPRESS_PLANS );
272    private const WPCOM_PREMIUM_AND_HIGHER_PLANS  = array( self::WPCOM_PREMIUM_PLANS, self::WPCOM_PRO_PLANS, self::WPCOM_BUSINESS_PLANS, self::WPCOM_ECOMMERCE_PLANS, self::WPCOM_ECOMMERCE_TRIAL_PLANS, self::WPCOM_WOOEXPRESS_PLANS );
273    private const WPCOM_BUSINESS_AND_HIGHER_PLANS = array( self::WPCOM_BUSINESS_PLANS, self::WPCOM_ECOMMERCE_PLANS, self::WPCOM_ECOMMERCE_TRIAL_PLANS, self::WPCOM_WOOEXPRESS_PLANS );
274    private const WPCOM_WOOEXPRESS_PLANS          = array( self::WPCOM_WOOEXPRESS_MEDIUM_PLANS, self::WPCOM_WOOEXPRESS_SMALL_PLANS );
275
276    // WPCOM "Level 3" C: Misc product groupings unrelated to free plan trials.
277    private const WPCOM_EMAIL_PRODUCTS = array( self::GOOGLE_WORKSPACE_PRODUCTS, self::GSUITE_PRODUCTS, self::WPCOM_TITAN_MAIL_PRODUCTS );
278
279    // Jetpack "Level 2": Groups of level 1s.
280    private const JETPACK_BUSINESS_PLANS = array( self::JETPACK_BUSINESS, self::JETPACK_BUSINESS_MONTHLY );
281    private const JETPACK_PREMIUM_PLANS  = array( self::JETPACK_PREMIUM, self::JETPACK_PREMIUM_MONTHLY );
282    private const JETPACK_PERSONAL_PLANS = array( self::JETPACK_PERSONAL, self::JETPACK_PERSONAL_MONTHLY );
283    private const JETPACK_GROWTH_PLANS   = array( self::JETPACK_GROWTH_BI_YEARLY, self::JETPACK_GROWTH_YEARLY, self::JETPACK_GROWTH_MONTHLY );
284    private const JETPACK_COMPLETE_PLANS = array( self::JETPACK_COMPLETE_BI_YEARLY, self::JETPACK_COMPLETE, self::JETPACK_COMPLETE_MONTHLY, self::A4A_JETPACK_COMPLETE_YEARLY, self::A4A_JETPACK_COMPLETE_MONTHLY );
285    private const JETPACK_STARTER_PLANS  = array( self::JETPACK_STARTER_YEARLY, self::JETPACK_STARTER_MONTHLY );
286
287    private const JETPACK_SECURITY_DAILY_PLANS    = array( self::JETPACK_SECURITY_DAILY, self::JETPACK_SECURITY_DAILY_MONTHLY );
288    private const JETPACK_SECURITY_REALTIME_PLANS = array( self::JETPACK_SECURITY_REALTIME, self::JETPACK_SECURITY_REALTIME_MONTHLY );
289    private const JETPACK_SECURITY_T0_PLANS       = array( self::JETPACK_SECURITY_T0_MONTHLY, self::JETPACK_SECURITY_T0_YEARLY );
290    private const JETPACK_SECURITY_T1_PLANS       = array( self::JETPACK_SECURITY_T1_MONTHLY, self::JETPACK_SECURITY_T1_YEARLY, self::JETPACK_SECURITY_T1_BI_YEARLY, self::A4A_JETPACK_SECURITY_TIER_1_MONTHLY, self::A4A_JETPACK_SECURITY_TIER_1_YEARLY );
291    private const JETPACK_SECURITY_T2_PLANS       = array( self::JETPACK_SECURITY_T2_MONTHLY, self::JETPACK_SECURITY_T2_YEARLY, self::A4A_JETPACK_SECURITY_TIER_2_MONTHLY, self::A4A_JETPACK_SECURITY_TIER_2_YEARLY );
292
293    private const JETPACK_SCAN_PLANS = array( self::JETPACK_SCAN_BI_YEARLY, self::JETPACK_SCAN, self::JETPACK_SCAN_MONTHLY, self::JETPACK_SCAN_REALTIME, self::JETPACK_SCAN_REALTIME_MONTHLY, self::A4A_JETPACK_SCAN_YEARLY, self::A4A_JETPACK_SCAN_MONTHLY );
294
295    private const JETPACK_SOCIAL_PLANS          = array( self::JETPACK_SOCIAL_BASIC_BI_YEARLY, self::JETPACK_SOCIAL_BASIC, self::JETPACK_SOCIAL_BASIC_MONTHLY, self::JETPACK_SOCIAL_BASIC_MONTHLY_LEGACY );
296    private const JETPACK_SOCIAL_ADVANCED_PLANS = array( self::JETPACK_SOCIAL_ADVANCED_BI_YEARLY, self::JETPACK_SOCIAL_ADVANCED, self::JETPACK_SOCIAL_ADVANCED_MONTHLY );
297    private const JETPACK_SOCIAL_V1_PLANS       = array( self::JETPACK_SOCIAL_V1_YEARLY, self::JETPACK_SOCIAL_V1_MONTHLY, self::JETPACK_SOCIAL_V1_BI_YEARLY, self::A4A_JETPACK_SOCIAL_V1_YEARLY, self::A4A_JETPACK_SOCIAL_V1_MONTHLY );
298
299    private const JETPACK_STATS_PLANS = array( self::JETPACK_STATS_BI_YEARLY, self::JETPACK_STATS_YEARLY, self::JETPACK_STATS_MONTHLY, self::JETPACK_STATS_PWYW, self::JETPACK_STATS_FREE, self::A4A_JETPACK_STATS_YEARLY, self::A4A_JETPACK_STATS_MONTHLY );
300
301    private const JETPACK_VIDEOPRESS_PLANS = array( self::JETPACK_VIDEOPRESS_BI_YEARLY, self::JETPACK_VIDEOPRESS, self::JETPACK_VIDEOPRESS_MONTHLY, self::A4A_JETPACK_VIDEOPRESS_YEARLY, self::A4A_JETPACK_VIDEOPRESS_MONTHLY );
302
303    private const JETPACK_SEARCH_PLANS = array( self::JETPACK_SEARCH_FREE, self::JETPACK_SEARCH_BI_YEARLY, self::JETPACK_SEARCH, self::JETPACK_SEARCH_MONTHLY, self::A4A_JETPACK_SEARCH_YEARLY, self::A4A_JETPACK_SEARCH_MONTHLY );
304
305    private const JETPACK_AI_PLANS = array( self::JETPACK_AI_BI_YEARLY, self::JETPACK_AI_YEARLY, self::JETPACK_AI_MONTHLY, self::A4A_JETPACK_AI_YEARLY, self::A4A_JETPACK_AI_MONTHLY );
306
307    private const JETPACK_BOOST_PLANS = array( self::JETPACK_BOOST_BI_YEARLY, self::JETPACK_BOOST, self::JETPACK_BOOST_MONTHLY, self::A4A_JETPACK_BOOST_YEARLY, self::A4A_JETPACK_BOOST_MONTHLY );
308
309    private const JETPACK_BACKUP_DAILY_PLANS    = array( self::JETPACK_BACKUP_DAILY, self::JETPACK_BACKUP_DAILY_MONTHLY );
310    private const JETPACK_BACKUP_REALTIME_PLANS = array( self::JETPACK_BACKUP_REALTIME, self::JETPACK_BACKUP_REALTIME_MONTHLY );
311    private const JETPACK_BACKUP_T0_PLANS       = array( self::JETPACK_BACKUP_T0_MONTHLY, self::JETPACK_BACKUP_T0_YEARLY );
312    private const JETPACK_BACKUP_T1_PLANS       = array( self::JETPACK_BACKUP_T1_MONTHLY, self::JETPACK_BACKUP_T1_YEARLY, self::JETPACK_BACKUP_T1_BI_YEARLY, self::A4A_JETPACK_BACKUP_TIER_1_YEARLY, self::A4A_JETPACK_BACKUP_TIER_1_MONTHLY );
313    private const JETPACK_BACKUP_T2_PLANS       = array( self::JETPACK_BACKUP_T2_MONTHLY, self::JETPACK_BACKUP_T2_YEARLY, self::A4A_JETPACK_BACKUP_TIER_2_YEARLY, self::A4A_JETPACK_BACKUP_TIER_2_MONTHLY );
314
315    private const JETPACK_CREATOR_PLANS = array( self::JETPACK_CREATOR_MONTHLY, self::JETPACK_CREATOR_YEARLY, self::JETPACK_CREATOR_BI_YEARLY, self::A4A_JETPACK_CREATOR_YEARLY, self::A4A_JETPACK_CREATOR_MONTHLY );
316
317    // Jetpack "Level 3": Groups of level 2.
318    private const JETPACK_PERSONAL_AND_HIGHER = array(
319        self::JETPACK_PERSONAL_PLANS,
320        self::JETPACK_PREMIUM_PLANS,
321        self::JETPACK_BUSINESS_PLANS,
322        self::JETPACK_COMPLETE_PLANS,
323        self::JETPACK_SECURITY_DAILY_PLANS,
324        self::JETPACK_SECURITY_REALTIME_PLANS,
325        self::JETPACK_SECURITY_T0_PLANS,
326        self::JETPACK_SECURITY_T1_PLANS,
327        self::JETPACK_SECURITY_T2_PLANS,
328        self::JETPACK_STARTER_PLANS,
329    );
330    private const JETPACK_PREMIUM_AND_HIGHER  = array(
331        self::JETPACK_PREMIUM_PLANS,
332        self::JETPACK_BUSINESS_PLANS,
333        self::JETPACK_COMPLETE_PLANS,
334        self::JETPACK_SECURITY_DAILY_PLANS,
335        self::JETPACK_SECURITY_REALTIME_PLANS,
336        self::JETPACK_SECURITY_T0_PLANS,
337        self::JETPACK_SECURITY_T1_PLANS,
338        self::JETPACK_SECURITY_T2_PLANS,
339    );
340
341    private const AKISMET_PLANS = array(
342        self::AKISMET_FREE,
343        self::AKISMET_PERSONAL_MONTHLY,
344        self::AKISMET_PERSONAL_YEARLY,
345        self::AKISMET_PLUS_MONTHLY,
346        self::AKISMET_PLUS_YEARLY,
347        self::AKISMET_PLUS_BI_YEARLY,
348        self::AKISMET_PLUS_20K_MONTHLY,
349        self::AKISMET_PLUS_20K_YEARLY,
350        self::AKISMET_PLUS_20K_BI_YEARLY,
351        self::AKISMET_PLUS_30K_MONTHLY,
352        self::AKISMET_PLUS_30K_YEARLY,
353        self::AKISMET_PLUS_30K_BI_YEARLY,
354        self::AKISMET_PLUS_40K_MONTHLY,
355        self::AKISMET_PLUS_40K_YEARLY,
356        self::AKISMET_PLUS_40K_BI_YEARLY,
357        self::AKISMET_ENTERPRISE_MONTHLY,
358        self::AKISMET_ENTERPRISE_YEARLY,
359        self::AKISMET_ENTERPRISE_BI_YEARLY,
360        self::AKISMET_ENTERPRISE_350K_MONTHLY,
361        self::AKISMET_ENTERPRISE_350K_YEARLY,
362        self::AKISMET_ENTERPRISE_2M_MONTHLY,
363        self::AKISMET_ENTERPRISE_2M_YEARLY,
364        self::AKISMET_PRO_500_MONTHLY,
365        self::AKISMET_PRO_500_YEARLY,
366        self::AKISMET_PRO_500_BI_YEARLY,
367        self::AKISMET_BUSINESS_5K_MONTHLY,
368        self::AKISMET_BUSINESS_5K_YEARLY,
369        self::AKISMET_BUSINESS_5K_BI_YEARLY,
370        self::AKISMET_ENTERPRISE_15K_MONTHLY,
371        self::AKISMET_ENTERPRISE_15K_YEARLY,
372        self::AKISMET_ENTERPRISE_15K_BI_YEARLY,
373        self::AKISMET_ENTERPRISE_25K_MONTHLY,
374        self::AKISMET_ENTERPRISE_25K_YEARLY,
375        self::AKISMET_ENTERPRISE_25K_BI_YEARLY,
376    );
377
378    // Features automatically granted to all sites regardless of their purchases are mapped to these constants.
379    private const WPCOM_ALL_SITES   = 'wpcom-all-sites';
380    private const JETPACK_ALL_SITES = 'jetpack-all-sites';
381
382    /*
383     * Public const for every mapped feature, sorted alphabetically.
384     */
385    public const AI_ASSISTANT                      = 'ai-assistant';
386    public const AI_SEO_ENHANCER                   = 'ai-seo-enhancer';
387    public const AD_CREDIT_VOUCHERS                = 'ad-credit';
388    public const ADVANCED_SEO                      = 'advanced-seo';
389    public const AKISMET                           = 'akismet';
390    public const ANTISPAM                          = 'antispam';
391    public const ARCHIVE_CONTENT                   = 'archive-content';
392    public const ATOMIC                            = 'atomic';
393    public const BACKUPS                           = 'backups';
394    public const BACKUPS_DAILY                     = 'backups-daily';
395    public const BACKUPS_RESTORE                   = 'restore';
396    public const BACKUPS_SELF_SERVE                = 'backups-self-serve';
397    public const BACKUP_ONE_TIME                   = 'backup-one-time';
398    public const BIG_SKY                           = 'big-sky';
399    public const BLAZE_CREDITS_VOUCHER             = 'blaze-credits-voucher';
400    public const BLOG_DOMAIN_ONLY                  = 'blog-domain-only';
401    public const CALENDLY                          = 'calendly';
402    public const CDN                               = 'cdn';
403    public const CLASSIC_SEARCH                    = 'search';
404    public const CLOUD_CRITICAL_CSS                = 'cloud-critical-css';
405    public const CORNERSTONE_TEN_PAGES             = 'cornerstone-10-pages';
406    public const CLOUDFLARE_ANALYTICS              = 'cloudflare-analytics';
407    public const CLOUDFLARE_CDN                    = 'cloudflare-cdn';
408    public const CONCIERGE                         = 'concierge';
409    public const CONCIERGE_BUSINESS                = 'concierge-business';
410    public const COPY_SITE                         = 'copy-site';
411    public const CORE_AUDIO                        = 'core/audio';
412    public const CORE_COVER                        = 'core/cover';
413    public const CORE_VIDEO                        = 'core/video';
414    public const CREDIT_VOUCHERS                   = 'credit-vouchers';
415    public const CUSTOM_DESIGN                     = 'custom-design';
416    public const CUSTOM_DOMAIN                     = 'custom-domain';
417    public const DOMAIN_MAPPING                    = 'domain-mapping';
418    public const DONATIONS                         = 'donations';
419    public const ECOMMERCE_MANAGED_PLUGINS         = 'ecommerce-managed-plugins';
420    public const ECOMMERCE_MANAGED_PLUGINS_SMALL   = 'ecommerce-managed-plugins-small';
421    public const ECOMMERCE_MANAGED_PLUGINS_MEDIUM  = 'ecommerce-managed-plugins-medium';
422    public const ECOMMERCE_MANAGED_PLUGINS_TRIAL   = 'ecommerce-managed-plugins-trial';
423    public const EDIT_PLUGINS                      = 'edit-plugins';
424    public const EDIT_THEMES                       = 'edit-themes';
425    public const EMAIL_PROFESSIONAL                = 'email-professional';
426    public const EMAIL_SUBSCRIPTION                = 'email-subscription';
427    public const EMAIL_FORWARDS_EXTENDED_LIMIT     = 'email-forwards-extended-limit';
428    public const FIELD_FILE                        = 'field-file';
429    public const FORM_INTEGRATIONS                 = 'form-integrations';
430    public const FORM_WEBHOOKS                     = 'form-webhooks';
431    public const FREE_BLOG                         = 'free-blog';
432    public const FULL_ACTIVITY_LOG                 = 'full-activity-log';
433    public const GITHUB_DEPLOYMENTS                = 'github-deployments';
434    public const GLOBAL_STYLES                     = 'global-styles';
435    public const GOOGLE_ANALYTICS                  = 'google-analytics';
436    public const GOOGLE_MY_BUSINESS                = 'google-my-business';
437    public const IMAGE_CDN_LIAR                    = 'image-cdn-liar';
438    public const IMAGE_CDN_QUALITY                 = 'image-cdn-quality';
439    public const IMAGE_SIZE_ANALYSIS               = 'image-size-analysis';
440    public const INSTALL_PLUGINS                   = 'install-plugins';
441    public const INSTALL_PURCHASED_PLUGINS         = 'install-purchased-plugins';
442    public const INSTALL_THEMES                    = 'install-themes';
443    public const INSTALL_WOO_ONBOARDING_PLUGINS    = 'install-woo-onboarding-plugins';
444    public const INSTANT_SEARCH                    = 'instant-search';
445    public const JETPACK_DASHBOARD                 = 'jetpack-dashboard';
446    public const LEGACY_CONTACT                    = 'legacy-contact';
447    public const LIST_INSTALLED_PLUGINS            = 'list-installed-plugins';
448    public const LIVE_SUPPORT                      = 'live_support';
449    public const LOCKED_MODE                       = 'locked-mode';
450    public const LOGS                              = 'logs';
451    public const MAILPOET_BUSINESS                 = 'mailpoet-business';
452    public const MANAGE_PLUGINS                    = 'manage-plugins';
453    public const MONITORING                        = 'monitoring';
454    public const MONITOR_1_MINUTE_CHECK_INTERVAL   = 'monitor-1-minute-check-interval';
455    public const MONITOR_MULTIPLE_EMAIL_RECIPIENTS = 'monitor-multiple-email-recipients';
456    public const MONITOR_SMS_NOTIFICATIONS         = 'monitor-sms-notifications';
457    public const MULTISTEP_FORM                    = 'multistep-form';
458    public const NO_ADVERTS_NO_ADVERTS_PHP         = 'no-adverts/no-adverts.php';
459    public const NO_WPCOM_BRANDING                 = 'no-wpcom-branding';
460    public const OPENTABLE                         = 'opentable';
461    public const PAYMENTS                          = 'payments';
462    public const PAYMENT_BUTTONS                   = 'payment-buttons';
463    public const PAYPAL_PAYMENT_BUTTONS            = 'paypal-payment-buttons';
464    public const PERFORMANCE                       = 'performance';
465    public const PERFORMANCE_HISTORY               = 'performance-history';
466    public const PODCASTING                        = 'podcasting';
467    public const POLLDADDY                         = 'polldaddy';
468    public const POSTS_TO_PODCAST_TIER_1           = 'posts-to-podcast-tier-1';
469    public const POSTS_TO_PODCAST_TIER_2           = 'posts-to-podcast-tier-2';
470    public const POSTS_TO_PODCAST_TIER_3           = 'posts-to-podcast-tier-3';
471    public const PREMIUM_CONTENT_CONTAINER         = 'premium-content/container';
472    public const PERSONAL_THEMES                   = 'personal-themes';
473    public const PREMIUM_THEMES                    = 'premium-themes';
474    public const PARTNER_THEMES                    = 'partner-themes';
475    public const COMMUNITY_THEMES                  = 'community-themes';
476    public const WOOCOMMERCE_THEMES                = 'woocommerce-themes';
477    public const SENSEI_THEMES                     = 'sensei-themes';
478    public const PRIORITY_SUPPORT                  = 'priority_support';
479    public const PRIVATE_WHOIS                     = 'private_whois';
480    public const REAL_TIME_BACKUPS                 = 'real-time-backups';
481    public const REAL_TIME_COLLABORATION           = 'real-time-collaboration';
482    public const RECURRING_PAYMENTS                = 'recurring-payments';
483    public const REDUCED_ATOMIC_EMAIL_PRIORITY     = 'reduced-email-priority';
484    public const REPUBLICIZE                       = 'republicize';
485    public const SCAN                              = 'scan';
486    public const SCAN_MANAGED                      = 'scan-managed';
487    public const SCAN_SELF_SERVE                   = 'scan-self-serve';
488    public const SCHEDULED_UPDATES                 = 'scheduled-updates';
489    public const SECURITY_SETTINGS                 = 'security-settings';
490    public const SEO_ADMIN_UI                      = 'seo-admin-ui';
491    public const SEO_PREVIEW_TOOLS                 = 'seo-preview-tools';
492    public const SEND_A_MESSAGE                    = 'send-a-message';
493    public const SET_PRIMARY_CUSTOM_DOMAIN         = 'set-primary-custom-domain';
494    public const SFTP                              = 'sftp';
495    public const SIMPLE_PAYMENTS                   = 'simple-payments';
496    public const SITE_PREVIEW_LINKS                = 'site-preview-links';
497    public const SOCIAL_ADMIN_UI_V2                = 'social-admin-ui-v2';
498    public const SOCIAL_IMAGE_FOCAL_POINT          = 'social-image-focal-point';
499    public const SOCIAL_IMAGE_GENERATOR            = 'social-image-generator';
500    public const SOCIAL_MESSAGE_TEMPLATES          = 'social-message-templates';
501    public const SOCIAL_SHARES_1000                = 'social-shares-1000';
502    public const SOCIAL_ENHANCED_PUBLISHING        = 'social-enhanced-publishing';
503    public const SOCIAL_IMAGE_AUTO_CONVERT         = 'social-image-auto-convert';
504    public const SPACE                             = 'space';
505    public const SPACE_UPGRADED_STORAGE            = 'space-upgraded-storage';
506    public const SSH                               = 'ssh';
507    public const STAGING_SITES                     = 'staging-sites';
508    public const STATS_BASIC_TEMP                  = 'stats-basic';
509    public const STATS_COMMERCIAL                  = 'stats-commercial';
510    public const STATS_FREE                        = 'stats-free';
511    public const STATS_PAID                        = 'stats-paid';
512    public const STUDIO_SYNC                       = 'studio-sync';
513    public const SUBSCRIBER_UNLIMITED_IMPORTS      = 'subscriber-unlimited-imports';
514    public const SUBSCRIPTION_GIFTING              = 'subscription-gifting';
515    public const SUPPORT                           = 'support';
516    public const TITAN_MAIL_1YEAR_TRIAL            = 'titan_mail_1year_trial';
517    public const UPGRADED_UPLOAD_FILETYPES         = 'upgraded_upload_filetypes';
518    public const UPLOAD_AUDIO_FILES                = 'upload-audio-files';
519    public const UPLOAD_PLUGINS                    = 'upload-plugins';
520    public const UPLOAD_SPACE_1GB                  = 'upload-space-1gb-addon';
521    public const UPLOAD_SPACE_3GB                  = 'upload-space-3gb';
522    public const UPLOAD_SPACE_10GB                 = 'upload-space-10gb';
523    public const UPLOAD_SPACE_25GB                 = 'upload-space-25gb';
524    public const UPLOAD_SPACE_50GB                 = 'upload-space-50gb';
525    public const UPLOAD_SPACE_100GB                = 'upload-space-100gb';
526    public const UPLOAD_SPACE_200GB                = 'upload-space-200gb';
527    public const UPLOAD_SPACE_UNLIMITED            = 'upload-space-unlimited';
528    public const UPLOAD_THEMES                     = 'upload-themes';
529    public const UPLOAD_VIDEO_FILES                = 'upload-video-files';
530    public const VAULTPRESS_AUTOMATED_RESTORES     = 'vaultpress-automated-restores';
531    public const VAULTPRESS_BACKUP_ARCHIVE         = 'vaultpress-backup-archive';
532    public const VAULTPRESS_BACKUPS                = 'vaultpress-backups';
533    public const VAULTPRESS_SECURITY_SCANNING      = 'vaultpress-security-scanning';
534    public const VAULTPRESS_STORAGE_SPACE          = 'vaultpress-storage-space';
535    public const VIDEO_HOSTING                     = 'video-hosting';
536    public const VIDEOPRESS                        = 'videopress';
537    public const VIDEOPRESS_1TB_STORAGE            = 'videopress-1tb-storage';
538    public const VIDEOPRESS_VIDEO                  = 'videopress/video';
539    public const VIDEOPRESS_UNLIMITED_STORAGE      = 'videopress-unlimited-storage';
540    public const WHATSAPP_BUTTON                   = 'whatsapp-button';
541    public const WOOP                              = 'woop';
542    public const WORDADS                           = 'wordads';
543    public const WORDADS_JETPACK                   = 'wordads-jetpack';
544    public const WORDPRESS_LABS                    = 'wordpress-labs';
545
546    /*
547     * Private const array of features with sub-array of purchases that include that feature. Sorted alphabetically.
548     */
549    private const FEATURES_MAP = array(
550        self::AI_ASSISTANT                      => array(
551            self::JETPACK_AI_PLANS,
552            self::WPCOM_PERSONAL_AND_HIGHER_PLANS,
553            self::JETPACK_COMPLETE_PLANS,
554        ),
555        self::AI_SEO_ENHANCER                   => array(
556            self::WPCOM_BUSINESS_AND_HIGHER_PLANS,
557            array(
558                'required_sticker' => 'gating-business-q1',
559                self::WPCOM_PREMIUM_PLANS,
560            ),
561            self::JETPACK_COMPLETE_PLANS,
562        ),
563        self::AD_CREDIT_VOUCHERS                => array(
564            self::WPCOM_BUSINESS_AND_HIGHER_PLANS,
565            self::WPCOM_PRO_PLANS,
566        ),
567
568        /*
569         * ADVANCED_SEO - Called seo-tools in Jetpack.
570         *
571         * Active for:
572         * - Simple and Atomic sites with Business or up plan.
573         * - Jetpack sites with any plan.
574         * - Not VIP sites.
575         */
576        self::ADVANCED_SEO                      => array(
577            array(
578                'required_sticker' => 'gating-business-q1',
579                self::WPCOM_PREMIUM_PLANS,
580            ),
581            self::WPCOM_PRO_PLANS,
582            self::WPCOM_BUSINESS_AND_HIGHER_PLANS,
583            self::JETPACK_ALL_SITES,
584        ),
585        self::AKISMET                           => array(
586            self::AKISMET_PLANS,
587            self::JETPACK_PERSONAL_AND_HIGHER,
588            self::WPCOM_ALL_SITES,
589        ),
590        self::ANTISPAM                          => array(
591            self::JETPACK_ANTI_SPAM_BI_YEARLY,
592            self::JETPACK_ANTI_SPAM,
593            self::JETPACK_ANTI_SPAM_MONTHLY,
594            self::A4A_JETPACK_ANTI_SPAM_YEARLY,
595            self::A4A_JETPACK_ANTI_SPAM_MONTHLY,
596            self::JETPACK_PERSONAL_AND_HIGHER,
597            self::WPCOM_BUSINESS_AND_HIGHER_PLANS,
598            self::WPCOM_PRO_PLANS,
599        ),
600
601        // Automatically syncs content to the Internet Archive on publish and update.
602        self::ARCHIVE_CONTENT                   => array(
603            self::WPCOM_HUNDRED_YEAR_BUNDLE,
604        ),
605
606        self::ATOMIC                            => array(
607            self::WPCOM_PRO_PLANS,
608            self::WPCOM_PERSONAL_AND_HIGHER_PLANS,
609            self::WPCOM_STAGING_PRODUCT,
610            array( 'product_type' => array( 'marketplace_plugin', 'saas_plugin' ) ),
611            self::WPCOM_FLEX_CACHE_SITE_FREE_PLANS,
612        ),
613        // BACKUPS - Site has *any* kind of backups.
614        self::BACKUPS                           => array(
615            self::JETPACK_BACKUP_DAILY_PLANS,
616            self::JETPACK_BACKUP_ONE_TIME,
617            self::JETPACK_BACKUP_REALTIME_PLANS,
618            self::JETPACK_BACKUP_T0_PLANS,
619            self::JETPACK_BACKUP_T1_PLANS,
620            self::JETPACK_BACKUP_T2_PLANS,
621            self::JETPACK_PERSONAL_AND_HIGHER,
622            self::JETPACK_GOLDEN_TOKEN,
623            self::WPCOM_PRO_PLANS,
624            self::WPCOM_STAGING_PRODUCT,
625            self::WPCOM_PERSONAL_AND_HIGHER_PLANS,
626            self::WPCOM_FLEX_CACHE_SITE_FREE_PLANS,
627        ),
628        // BACKUPS_DAILY - Site has product that includes daily backups.
629        self::BACKUPS_DAILY                     => array(
630            self::JETPACK_BACKUP_DAILY_PLANS,
631            self::JETPACK_PERSONAL_AND_HIGHER,
632            self::JETPACK_SECURITY_DAILY_PLANS,
633        ),
634        self::BACKUPS_RESTORE                   => array(
635            self::WPCOM_PRO_PLANS,
636            self::WPCOM_PERSONAL_AND_HIGHER_PLANS,
637            self::WPCOM_FLEX_CACHE_SITE_FREE_PLANS,
638        ),
639        self::BACKUPS_SELF_SERVE                => array(
640            self::JETPACK_BACKUP_DAILY_PLANS,
641            self::JETPACK_BACKUP_ONE_TIME,
642            self::JETPACK_BACKUP_REALTIME_PLANS,
643            self::JETPACK_BACKUP_T0_PLANS,
644            self::JETPACK_BACKUP_T1_PLANS,
645            self::JETPACK_BACKUP_T2_PLANS,
646            self::JETPACK_PERSONAL_AND_HIGHER,
647            self::JETPACK_GOLDEN_TOKEN,
648            self::WPCOM_PRO_PLANS,
649            self::WPCOM_STAGING_PRODUCT,
650            // Business and higher can self serve restoring backups.
651            self::WPCOM_BUSINESS_AND_HIGHER_PLANS,
652            self::WPCOM_FLEX_CACHE_SITE_FREE_PLANS,
653        ),
654
655        /*
656         * BACKUP_ONE_TIME - Site has purchased a one-time backup.
657         * Note the jetpack_backup_one_time product never expires. So any feature gated with BACKUP_ONE_TIME will
658         * likewise, never expire.
659         */
660        self::BACKUP_ONE_TIME                   => array(
661            self::JETPACK_BACKUP_ONE_TIME,
662        ),
663        // Plans that grant unlimited Big Sky usage and exit the Big Sky free trial.
664        self::BIG_SKY                           => array(
665            self::WPCOM_PERSONAL_AND_HIGHER_PLANS,
666        ),
667        self::BLAZE_CREDITS_VOUCHER             => array(
668            array(
669                'required_sticker' => 'gating-business-q1',
670                // Business (Excluding Monthly).
671                self::BUSINESS_BUNDLE,
672                self::BUSINESS_BUNDLE_2Y,
673                self::BUSINESS_BUNDLE_3Y,
674                // Ecommerce (Excluding Monthly).
675                self::ECOMMERCE_BUNDLE,
676                self::ECOMMERCE_BUNDLE_2Y,
677                self::ECOMMERCE_BUNDLE_3Y,
678            ),
679        ),
680        // BLOG_DOMAIN_ONLY - Users on Blogger plan can only purchase .blog domains.
681        self::BLOG_DOMAIN_ONLY                  => array(
682            self::WPCOM_BLOGGER_PLANS,
683        ),
684        self::CALENDLY                          => array(
685            self::WPCOM_PREMIUM_AND_HIGHER_PLANS,
686            self::JETPACK_BUSINESS_PLANS,
687            self::JETPACK_PREMIUM_PLANS,
688            self::WP_P2_PLUS_MONTHLY,
689        ),
690        self::CDN                               => array(
691            self::JETPACK_ALL_SITES,
692            self::WPCOM_BUSINESS_AND_HIGHER_PLANS,
693            self::WPCOM_PRO_PLANS,
694        ),
695        self::CLASSIC_SEARCH                    => array(
696            self::WPCOM_BUSINESS_AND_HIGHER_PLANS,
697            self::WPCOM_PRO_PLANS,
698            self::JETPACK_SEARCH_PLANS,
699            self::JETPACK_COMPLETE_PLANS,
700            self::JETPACK_BUSINESS_PLANS,
701            self::WPCOM_SEARCH,
702            self::WPCOM_SEARCH_MONTHLY,
703            self::WP_P2_PLUS_MONTHLY,
704        ),
705        self::CLOUD_CRITICAL_CSS                => array(
706            self::JETPACK_BOOST_PLANS,
707            self::JETPACK_COMPLETE_PLANS,
708        ),
709        self::CORNERSTONE_TEN_PAGES             => array(
710            self::JETPACK_BOOST_PLANS,
711            self::JETPACK_COMPLETE_PLANS,
712        ),
713        self::CLOUDFLARE_ANALYTICS              => array(
714            self::JETPACK_PREMIUM_AND_HIGHER,
715            self::WPCOM_PREMIUM_AND_HIGHER_PLANS,
716            self::WPCOM_PRO_PLANS,
717        ),
718        self::CLOUDFLARE_CDN                    => array(
719            self::JETPACK_PREMIUM_AND_HIGHER,
720            self::WPCOM_PREMIUM_AND_HIGHER_PLANS,
721            self::WPCOM_PRO_PLANS,
722        ),
723        self::CONCIERGE                         => array(
724            self::WPCOM_BUSINESS_PLANS,
725            self::WPCOM_ECOMMERCE_PLANS,
726        ),
727        self::CONCIERGE_BUSINESS                => array(
728            self::WPCOM_BUSINESS_PLANS,
729        ),
730        self::COPY_SITE                         => array(
731            self::WPCOM_PRO_PLANS,
732            self::EXCLUDE_PLANS => array(
733                self::WPCOM_ECOMMERCE_TRIAL_PLANS,
734            ),
735            // Copy a site requires an Atomic site, so this mirrors the plans that can be
736            // Atomic: Personal, Premium, and Business or higher plans (not all paid plans).
737            self::WPCOM_BUSINESS_AND_HIGHER_PLANS,
738            self::WPCOM_PERSONAL_AND_PREMIUM_PLANS,
739            self::WPCOM_FLEX_CACHE_SITE_FREE_PLANS,
740        ),
741        // CORE_AUDIO - core/audio requires a paid plan for uploading audio files.
742        self::CORE_AUDIO                        => array(
743            self::WP_P2_PLUS_MONTHLY,
744            self::WPCOM_PERSONAL_AND_HIGHER_PLANS,
745            self::JETPACK_PERSONAL_AND_HIGHER,
746        ),
747        // CORE_COVER - core/cover requires a paid plan for uploading video files.
748        self::CORE_COVER                        => array(
749            self::WP_P2_PLUS_MONTHLY,
750            self::WPCOM_PREMIUM_AND_HIGHER_PLANS,
751            self::JETPACK_BUSINESS_PLANS,
752            self::JETPACK_PREMIUM_PLANS,
753        ),
754        // CORE_VIDEO - core/video requires a paid plan.
755        self::CORE_VIDEO                        => array(
756            self::WP_P2_PLUS_MONTHLY,
757            self::WPCOM_PREMIUM_AND_HIGHER_PLANS,
758            self::JETPACK_BUSINESS_PLANS,
759            self::JETPACK_PREMIUM_PLANS,
760        ),
761        self::CREDIT_VOUCHERS                   => array(
762            self::BUNDLE_PRO,
763            self::BUNDLE_SUPER,
764            self::BUNDLE_ENTERPRISE,
765            self::WPCOM_PREMIUM_AND_HIGHER_PLANS,
766        ),
767        self::CUSTOM_DESIGN                     => array(
768            self::WPCOM_CUSTOM_DESIGN,
769            self::WPCOM_PREMIUM_AND_HIGHER_PLANS,
770        ),
771        self::CUSTOM_DOMAIN                     => array(
772            self::WPCOM_BLOGGER_AND_HIGHER_PLANS,
773            self::WOO_HOSTED_PLANS,
774        ),
775        self::DOMAIN_MAPPING                    => array(
776            self::WPCOM_BLOGGER_AND_HIGHER_PLANS,
777            self::WPCOM_PRO_PLANS,
778            self::WOO_HOSTED_PLANS,
779        ),
780        self::DONATIONS                         => array(
781            array(
782                'sticker_not_present' => 'gating-business-q1',
783                self::WPCOM_ALL_SITES,
784            ),
785            array(
786                'sticker_not_present' => 'gating-business-q1',
787                self::WPCOM_PERSONAL_AND_HIGHER_PLANS,
788            ),
789            self::WPCOM_PREMIUM_AND_HIGHER_PLANS,
790            self::JETPACK_ALL_SITES,
791        ),
792        // ECOMMERCE_MANAGED_PLUGINS - Can install the plugin bundle that comes with eCommerce plans.
793        self::ECOMMERCE_MANAGED_PLUGINS         => array(
794            self::WPCOM_ECOMMERCE_PLANS,
795            self::WPCOM_ECOMMERCE_TRIAL_PLANS,
796            self::WPCOM_WOOEXPRESS_PLANS,
797        ),
798        // ECOMMERCE_MANAGED_PLUGINS_SMALL - Can install the plugin bundle that comes with eCommerce Small plans.
799        self::ECOMMERCE_MANAGED_PLUGINS_SMALL   => array(
800            self::WPCOM_WOOEXPRESS_SMALL_PLANS,
801        ),
802        // ECOMMERCE_MANAGED_PLUGINS_MEDIUM - Can install the plugin bundle that comes with eCommerce Medium plans.
803        self::ECOMMERCE_MANAGED_PLUGINS_MEDIUM  => array(
804            self::WPCOM_ECOMMERCE_PLANS,
805            self::WPCOM_WOOEXPRESS_MEDIUM_PLANS,
806        ),
807        // ECOMMERCE_MANAGED_PLUGINS_TRIAL - Can install the plugin bundle that comes with eCommerce Trial plans.
808        self::ECOMMERCE_MANAGED_PLUGINS_TRIAL   => array(
809            self::WPCOM_ECOMMERCE_TRIAL_PLANS,
810        ),
811        // EDIT_PLUGINS - Provides the edit_plugins capability on atomic sites, does nothing on simple sites.
812        self::EDIT_PLUGINS                      => array(
813            self::WPCOM_PRO_PLANS,
814            self::EXCLUDE_PLANS => array(
815                self::WPCOM_ECOMMERCE_TRIAL_PLANS,
816            ),
817            self::WPCOM_PERSONAL_AND_HIGHER_PLANS,
818            self::WPCOM_FLEX_CACHE_SITE_FREE_PLANS,
819        ),
820        // EDIT_THEMES - Provides the edit_themes capability on atomic sites, does nothing on simple sites.
821        self::EDIT_THEMES                       => array(
822            self::WPCOM_PRO_PLANS,
823            self::EXCLUDE_PLANS => array(
824                self::WPCOM_ECOMMERCE_TRIAL_PLANS,
825            ),
826            self::WPCOM_PERSONAL_AND_HIGHER_PLANS,
827            self::WPCOM_FLEX_CACHE_SITE_FREE_PLANS,
828        ),
829        // EMAIL_PROFESSIONAL - Access to Titan email hosting, often referred to as WordPress.com "Professional Email".
830        self::EMAIL_PROFESSIONAL                => array(
831            self::WPCOM_TITAN_MAIL_PRODUCTS,
832        ),
833        // EMAIL_SUBSCRIPTION - Represents having at least one product providing email.
834        self::EMAIL_SUBSCRIPTION                => array(
835            self::WPCOM_EMAIL_PRODUCTS,
836        ),
837        self::EMAIL_FORWARDS_EXTENDED_LIMIT     => array(
838            self::BUNDLE_ENTERPRISE,
839            self::WPCOM_BUSINESS_AND_HIGHER_PLANS,
840            self::WPCOM_PRO_PLANS,
841        ),
842        // FIELD_FILE - Premium block/feature (jetpack/field-file) for uploading files with cloud backend.
843        // See: https://github.com/Automattic/jetpack/pull/43177 / https://github.a8c.com/Automattic/wpcom/pull/179247
844        self::FIELD_FILE                        => array(
845            array(
846                'sticker_not_present' => 'gating-business-q1',
847                self::WPCOM_PERSONAL_PLANS,
848                self::WPCOM_PREMIUM_PLANS,
849            ),
850            self::WPCOM_PRO_PLANS,
851            self::WPCOM_BUSINESS_AND_HIGHER_PLANS,
852            self::JETPACK_COMPLETE_PLANS,
853        ),
854        self::FORM_INTEGRATIONS                 => array(
855            array(
856                'sticker_not_present' => 'gating-business-q1',
857                self::WPCOM_PERSONAL_AND_HIGHER_PLANS,
858            ),
859            self::WPCOM_PRO_PLANS,
860            self::WPCOM_BUSINESS_AND_HIGHER_PLANS,
861            self::JETPACK_ALL_SITES,
862        ),
863        self::FORM_WEBHOOKS                     => array(
864            self::WPCOM_BUSINESS_AND_HIGHER_PLANS,
865            self::JETPACK_ALL_SITES,
866        ),
867        self::FREE_BLOG                         => array(
868            self::WPCOM_ALL_SITES,
869        ),
870        self::FULL_ACTIVITY_LOG                 => array(
871            self::JETPACK_BACKUP_DAILY_PLANS,
872            self::JETPACK_BACKUP_REALTIME_PLANS,
873            self::JETPACK_BACKUP_T0_PLANS,
874            self::JETPACK_BACKUP_T1_PLANS,
875            self::JETPACK_BACKUP_T2_PLANS,
876            self::JETPACK_PERSONAL_AND_HIGHER,
877            self::JETPACK_GOLDEN_TOKEN,
878            self::WPCOM_BLOGGER_AND_HIGHER_PLANS,
879            self::WPCOM_PRO_PLANS,
880        ),
881        self::GITHUB_DEPLOYMENTS                => array(
882            self::WPCOM_BUSINESS_AND_HIGHER_PLANS,
883            self::EXCLUDE_PLANS => array(
884                self::WPCOM_ECOMMERCE_TRIAL_PLANS,
885            ),
886        ),
887        self::GLOBAL_STYLES                     => array(
888            self::WPCOM_PERSONAL_AND_HIGHER_PLANS,
889        ),
890        self::GOOGLE_ANALYTICS                  => array(
891            self::JETPACK_PREMIUM_AND_HIGHER,
892            self::WPCOM_STARTER_AND_HIGHER_PLANS,
893        ),
894        self::GOOGLE_MY_BUSINESS                => array(
895            self::WPCOM_PRO_PLANS,
896            self::WPCOM_BUSINESS_AND_HIGHER_PLANS,
897            self::JETPACK_BUSINESS_PLANS,
898            self::JETPACK_SECURITY_REALTIME_PLANS,
899            self::JETPACK_COMPLETE_PLANS,
900            self::JETPACK_SECURITY_T1_PLANS,
901            self::JETPACK_SECURITY_T2_PLANS,
902        ),
903        self::IMAGE_CDN_LIAR                    => array(
904            self::JETPACK_BOOST_PLANS,
905            self::JETPACK_COMPLETE_PLANS,
906        ),
907        self::IMAGE_CDN_QUALITY                 => array(
908            self::JETPACK_BOOST_PLANS,
909            self::JETPACK_COMPLETE_PLANS,
910        ),
911        self::IMAGE_SIZE_ANALYSIS               => array(
912            self::JETPACK_BOOST_PLANS,
913            self::JETPACK_COMPLETE_PLANS,
914        ),
915        self::INSTALL_PLUGINS                   => array(
916            self::WPCOM_PRO_PLANS,
917            self::EXCLUDE_PLANS => array(
918                self::WPCOM_ECOMMERCE_TRIAL_PLANS,
919            ),
920            self::WPCOM_PERSONAL_AND_HIGHER_PLANS,
921            self::WPCOM_FLEX_CACHE_SITE_FREE_PLANS,
922        ),
923        self::INSTALL_PURCHASED_PLUGINS         => array(
924            self::WPCOM_PRO_PLANS,
925            self::WPCOM_STARTER_PLANS,
926            self::EXCLUDE_PLANS => array(
927                self::WPCOM_ECOMMERCE_TRIAL_PLANS,
928            ),
929            self::WPCOM_PERSONAL_AND_HIGHER_PLANS,
930            self::WPCOM_FLEX_CACHE_SITE_FREE_PLANS,
931        ),
932        self::INSTALL_THEMES                    => array(
933            self::WPCOM_PRO_PLANS,
934            self::JETPACK_ALL_SITES,
935            self::EXCLUDE_PLANS => array(
936                self::WPCOM_ECOMMERCE_TRIAL_PLANS,
937            ),
938            self::WPCOM_PERSONAL_AND_HIGHER_PLANS,
939            self::WPCOM_FLEX_CACHE_SITE_FREE_PLANS,
940        ),
941        self::INSTALL_WOO_ONBOARDING_PLUGINS    => array(
942            self::WPCOM_ECOMMERCE_TRIAL_PLANS,
943        ),
944        self::INSTANT_SEARCH                    => array(
945            self::WPCOM_SEARCH,
946            self::WPCOM_SEARCH_MONTHLY,
947            self::WP_P2_PLUS_MONTHLY,
948            self::JETPACK_SEARCH_PLANS,
949            self::JETPACK_COMPLETE_PLANS,
950        ),
951        self::JETPACK_DASHBOARD                 => array(
952            self::WPCOM_PRO_PLANS,
953            self::WPCOM_BUSINESS_AND_HIGHER_PLANS,
954            self::JETPACK_ALL_SITES,
955        ),
956
957        // Allows sites to designate a contact person to look after their site after they pass away.
958        self::LEGACY_CONTACT                    => array(
959            self::WPCOM_HUNDRED_YEAR_BUNDLE,
960        ),
961        self::LIST_INSTALLED_PLUGINS            => array(
962            self::WPCOM_PRO_PLANS,
963            self::WPCOM_STARTER_PLANS,
964            self::WPCOM_PERSONAL_AND_HIGHER_PLANS,
965            self::WPCOM_FLEX_CACHE_SITE_FREE_PLANS,
966        ),
967        // LIVE_SUPPORT - Monthly plans do not get live support. p7DVsv-a9N-p2.
968        self::LIVE_SUPPORT                      => array(
969            // Premium (Excluding Monthly).
970            self::BUNDLE_PRO,
971            self::VALUE_BUNDLE,
972            self::VALUE_BUNDLE_2Y,
973            self::VALUE_BUNDLE_3Y,
974            // Pro.
975            self::PRO_PLAN,
976            self::PRO_PLAN_2Y,
977            // Business (Excluding Monthly).
978            self::BUSINESS_BUNDLE,
979            self::BUSINESS_BUNDLE_2Y,
980            self::BUSINESS_BUNDLE_3Y,
981            // Student (yearly).
982            self::STUDENT_BUNDLE,
983            // Ecommerce (Excluding Monthly).
984            self::ECOMMERCE_BUNDLE,
985            self::ECOMMERCE_BUNDLE_2Y,
986            self::ECOMMERCE_BUNDLE_3Y,
987            // Woo Express (Small and Medium plans), excluding monthly.
988            self::WPCOM_WOOEXPRESS_MEDIUM_BUNDLE_YEARLY,
989            self::WPCOM_WOOEXPRESS_SMALL_BUNDLE_YEARLY,
990        ),
991
992        // Enables a setting to lock the site content to prevent changes (incl. disabling comments site-wide).
993        self::LOCKED_MODE                       => array(
994            self::WPCOM_HUNDRED_YEAR_BUNDLE,
995        ),
996        self::LOGS                              => array(
997            self::WPCOM_BUSINESS_AND_HIGHER_PLANS,
998            self::WPCOM_PRO_PLANS,
999        ),
1000        self::MAILPOET_BUSINESS                 => array(
1001            array(
1002                'required_sticker' => 'gating-business-q1',
1003                self::WPCOM_BUSINESS_PLANS,
1004            ),
1005            self::WPCOM_ECOMMERCE_PLANS,
1006            self::WPCOM_WOOEXPRESS_PLANS,
1007            self::WOO_HOSTED_PLANS,
1008        ),
1009        // MANAGE_PLUGINS - Atomic only feature. Can upload, install, and activate any 3rd party plugin.
1010        self::MANAGE_PLUGINS                    => array(
1011            self::WPCOM_PRO_PLANS,
1012            self::EXCLUDE_PLANS => array(
1013                self::WPCOM_ECOMMERCE_TRIAL_PLANS,
1014            ),
1015            self::WPCOM_PERSONAL_AND_HIGHER_PLANS,
1016            self::WPCOM_FLEX_CACHE_SITE_FREE_PLANS,
1017        ),
1018        self::MONITORING                        => array(
1019            self::WPCOM_BUSINESS_AND_HIGHER_PLANS,
1020            self::WPCOM_PRO_PLANS,
1021        ),
1022
1023        // MONITOR_1_MINUTE_CHECK_INTERVAL - Jetpack Monitor checks site uptime once per minute
1024        self::MONITOR_1_MINUTE_CHECK_INTERVAL   => array(
1025            self::JETPACK_MONITOR_MONTHLY,
1026            self::JETPACK_MONITOR_YEARLY,
1027            self::A4A_JETPACK_MONITOR_MONTHLY,
1028            self::A4A_JETPACK_MONITOR_YEARLY,
1029        ),
1030        // MONITOR_MULTIPLE_EMAIL_RECIPIENTS - Jetpack Monitor can email more than one recipient when a site goes down
1031        self::MONITOR_MULTIPLE_EMAIL_RECIPIENTS => array(
1032            self::JETPACK_MONITOR_MONTHLY,
1033            self::JETPACK_MONITOR_YEARLY,
1034            self::A4A_JETPACK_MONITOR_MONTHLY,
1035            self::A4A_JETPACK_MONITOR_YEARLY,
1036        ),
1037        // MONITOR_SMS_NOTIFICATIONS - Jetpack Monitor can send notifications via SMS when a site goes down
1038        self::MONITOR_SMS_NOTIFICATIONS         => array(
1039            self::JETPACK_MONITOR_MONTHLY,
1040            self::JETPACK_MONITOR_YEARLY,
1041            self::A4A_JETPACK_MONITOR_MONTHLY,
1042            self::A4A_JETPACK_MONITOR_YEARLY,
1043        ),
1044        self::MULTISTEP_FORM                    => array(
1045            array(
1046                'sticker_not_present' => 'gating-business-q1',
1047                self::WPCOM_PERSONAL_PLANS,
1048                self::WPCOM_PREMIUM_PLANS,
1049            ),
1050            self::WPCOM_PRO_PLANS,
1051            self::WPCOM_BUSINESS_AND_HIGHER_PLANS,
1052            self::JETPACK_ALL_SITES,
1053        ),
1054        self::NO_ADVERTS_NO_ADVERTS_PHP         => array(
1055            self::NO_ADS,
1056            // Deliberately leaves out the Starter plan.
1057            self::WPCOM_BLOGGER_PLANS,
1058            self::WPCOM_PERSONAL_PLANS,
1059            self::WPCOM_PREMIUM_AND_HIGHER_PLANS,
1060        ),
1061        // NO_WPCOM_BRANDING - Enable the ability to hide the WP.com branding in the site footer.
1062        self::NO_WPCOM_BRANDING                 => array(
1063            self::WPCOM_PRO_PLANS,
1064            self::WPCOM_BUSINESS_AND_HIGHER_PLANS,
1065            self::WPCOM_FLEX_CACHE_SITE_FREE_PLANS,
1066        ),
1067        self::OPENTABLE                         => array(
1068            self::WPCOM_PREMIUM_AND_HIGHER_PLANS,
1069            self::JETPACK_BUSINESS_PLANS,
1070            self::JETPACK_PREMIUM_PLANS,
1071        ),
1072        self::PAYMENTS                          => array(
1073            array(
1074                'sticker_not_present' => 'gating-business-q1',
1075                self::WPCOM_PERSONAL_PLANS,
1076            ),
1077            self::WPCOM_STARTER_PLANS,
1078            self::WPCOM_PREMIUM_AND_HIGHER_PLANS,
1079        ),
1080        self::PAYMENT_BUTTONS                   => array(
1081            array(
1082                'sticker_not_present' => 'gating-business-q1',
1083                self::WPCOM_ALL_SITES,
1084            ),
1085            array(
1086                'sticker_not_present' => 'gating-business-q1',
1087                self::WPCOM_PERSONAL_AND_HIGHER_PLANS,
1088            ),
1089            self::WPCOM_PREMIUM_AND_HIGHER_PLANS,
1090            self::JETPACK_ALL_SITES,
1091        ),
1092        self::PAYPAL_PAYMENT_BUTTONS            => array(
1093            array(
1094                'sticker_not_present' => 'gating-business-q1',
1095                self::WPCOM_ALL_SITES,
1096            ),
1097            array(
1098                'sticker_not_present' => 'gating-business-q1',
1099                self::WPCOM_PERSONAL_AND_HIGHER_PLANS,
1100            ),
1101            self::WPCOM_PREMIUM_AND_HIGHER_PLANS,
1102            self::JETPACK_ALL_SITES,
1103        ),
1104        self::PERFORMANCE                       => array(
1105            self::WPCOM_BUSINESS_AND_HIGHER_PLANS,
1106            self::WPCOM_PRO_PLANS,
1107        ),
1108        self::PERFORMANCE_HISTORY               => array(
1109            self::JETPACK_BOOST_PLANS,
1110            self::JETPACK_COMPLETE_PLANS,
1111        ),
1112        self::PODCASTING                        => array(
1113            self::WPCOM_PREMIUM_AND_HIGHER_PLANS,
1114            self::JETPACK_ALL_SITES,
1115        ),
1116        self::POLLDADDY                         => array(
1117            self::JETPACK_BUSINESS_PLANS,
1118        ),
1119        // POSTS_TO_PODCAST_TIER_{1,2,3} â€” generates a podcast-style episode
1120        // from recent posts. Monthly quotas: TIER_1 = 5, TIER_2 = 10,
1121        // TIER_3 = 20. Sites accumulate tiers via the _AND_HIGHER cascades;
1122        // the lib's quota helper takes the highest tier present.
1123        self::POSTS_TO_PODCAST_TIER_1           => array(
1124            self::WPCOM_PERSONAL_AND_HIGHER_PLANS,
1125        ),
1126        self::POSTS_TO_PODCAST_TIER_2           => array(
1127            self::WPCOM_PREMIUM_AND_HIGHER_PLANS,
1128        ),
1129        self::POSTS_TO_PODCAST_TIER_3           => array(
1130            self::WPCOM_BUSINESS_AND_HIGHER_PLANS,
1131        ),
1132        // PREMIUM_CONTENT_CONTAINER - premium-content requires a paid wpcom plan.
1133        self::PREMIUM_CONTENT_CONTAINER         => array(
1134            self::WPCOM_PERSONAL_AND_HIGHER_PLANS,
1135            self::WP_P2_PLUS_MONTHLY,
1136        ),
1137        self::PERSONAL_THEMES                   => array(
1138            self::WPCOM_UNLIMITED_THEMES,
1139            self::BUNDLE_ENTERPRISE,
1140            self::WPCOM_PRO_PLANS,
1141            self::WPCOM_PERSONAL_AND_HIGHER_PLANS,
1142            self::JETPACK_BUSINESS_PLANS,
1143        ),
1144        self::PREMIUM_THEMES                    => array(
1145            self::WPCOM_UNLIMITED_THEMES,
1146            self::BUNDLE_ENTERPRISE,
1147            self::WPCOM_PRO_PLANS,
1148            self::WPCOM_PREMIUM_AND_HIGHER_PLANS,
1149            self::JETPACK_BUSINESS_PLANS,
1150        ),
1151        self::PARTNER_THEMES                    => array(
1152            self::WPCOM_BUSINESS_AND_HIGHER_PLANS,
1153            self::WPCOM_PRO_PLANS,
1154            self::EXCLUDE_PLANS => array(
1155                self::WPCOM_ECOMMERCE_TRIAL_PLANS,
1156            ),
1157        ),
1158        self::COMMUNITY_THEMES                  => array(
1159            self::WPCOM_BUSINESS_AND_HIGHER_PLANS,
1160            self::WPCOM_PRO_PLANS,
1161            self::EXCLUDE_PLANS => array(
1162                self::WPCOM_ECOMMERCE_TRIAL_PLANS,
1163            ),
1164            self::WPCOM_FLEX_CACHE_SITE_FREE_PLANS,
1165        ),
1166        self::WOOCOMMERCE_THEMES                => array(
1167            self::WPCOM_BUSINESS_AND_HIGHER_PLANS,
1168            self::WPCOM_PRO_PLANS,
1169            self::EXCLUDE_PLANS => array(
1170                self::WPCOM_ECOMMERCE_TRIAL_PLANS,
1171            ),
1172            self::WPCOM_FLEX_CACHE_SITE_FREE_PLANS,
1173        ),
1174        self::SENSEI_THEMES                     => array(
1175            self::WPCOM_BUSINESS_AND_HIGHER_PLANS,
1176            self::WPCOM_PRO_PLANS,
1177            self::EXCLUDE_PLANS => array(
1178                self::WPCOM_ECOMMERCE_TRIAL_PLANS,
1179            ),
1180        ),
1181        self::PRIORITY_SUPPORT                  => array(
1182            self::JETPACK_BACKUP_T1_PLANS,
1183            self::JETPACK_BACKUP_T2_PLANS,
1184            self::JETPACK_PERSONAL_AND_HIGHER,
1185            self::JETPACK_GOLDEN_TOKEN,
1186            self::WPCOM_BUSINESS_AND_HIGHER_PLANS,
1187            self::WPCOM_PRO_PLANS,
1188        ),
1189        self::PRIVATE_WHOIS                     => array(
1190            self::WPCOM_PREMIUM_AND_HIGHER_PLANS,
1191        ),
1192        self::REAL_TIME_BACKUPS                 => array(
1193            self::JETPACK_BACKUP_REALTIME_PLANS,
1194            self::JETPACK_BACKUP_T0_PLANS,
1195            self::JETPACK_BACKUP_T1_PLANS,
1196            self::JETPACK_BACKUP_T2_PLANS,
1197            self::JETPACK_BUSINESS_PLANS,
1198            self::JETPACK_COMPLETE_PLANS,
1199            self::JETPACK_SECURITY_REALTIME_PLANS,
1200            self::JETPACK_SECURITY_T0_PLANS,
1201            self::JETPACK_SECURITY_T1_PLANS,
1202            self::JETPACK_SECURITY_T2_PLANS,
1203            self::JETPACK_STARTER_PLANS,
1204            self::JETPACK_GOLDEN_TOKEN,
1205            self::WPCOM_BUSINESS_AND_HIGHER_PLANS,
1206            self::WPCOM_PRO_PLANS,
1207            self::WPCOM_FLEX_CACHE_SITE_FREE_PLANS,
1208        ),
1209
1210        self::REAL_TIME_COLLABORATION           => array(
1211            self::WPCOM_PERSONAL_AND_HIGHER_PLANS,
1212        ),
1213
1214        self::RECURRING_PAYMENTS                => array(
1215            self::WPCOM_ALL_SITES,
1216            self::WPCOM_STARTER_PLANS,
1217            self::WPCOM_PREMIUM_AND_HIGHER_PLANS,
1218            self::JETPACK_ALL_SITES,
1219        ),
1220
1221        /*
1222         * Reduced email priority when sending emails via SMTP via the Atomic platform.
1223         */
1224        self::REDUCED_ATOMIC_EMAIL_PRIORITY     => array(
1225            self::WPCOM_ECOMMERCE_TRIAL_PLANS,
1226            self::WPCOM_MIGRATION_TRIAL_PLANS,
1227            self::WPCOM_HOSTING_TRIAL_PLANS,
1228        ),
1229
1230        /*
1231         * REPUBLICIZE
1232         *
1233         * Active for:
1234         * - Simple and Atomic sites with Premium or up plan.
1235         * - Jetpack sites with Premium or up plan, or a Jetpack Social plan.
1236         */
1237        self::REPUBLICIZE                       => array(
1238            self::WP_P2_PLUS_MONTHLY,
1239            self::WPCOM_PREMIUM_AND_HIGHER_PLANS,
1240            self::JETPACK_ALL_SITES,
1241        ),
1242        self::SCAN                              => array(
1243            self::JETPACK_PREMIUM_AND_HIGHER,
1244            self::JETPACK_SCAN_PLANS,
1245            self::JETPACK_GOLDEN_TOKEN,
1246            self::WPCOM_PERSONAL_AND_PREMIUM_PLANS,
1247            self::WPCOM_BUSINESS_AND_HIGHER_PLANS,
1248            self::WPCOM_PRO_PLANS,
1249            self::WPCOM_FLEX_CACHE_SITE_FREE_PLANS,
1250        ),
1251
1252        /*
1253         * SCAN_MANAGED - Scan results are managed internally by Atomic guild HEs and not shown in user UI.
1254         * See D57207-code.
1255         */
1256        self::SCAN_MANAGED                      => array(
1257            self::WPCOM_PERSONAL_AND_PREMIUM_PLANS,
1258            self::WPCOM_BUSINESS_AND_HIGHER_PLANS,
1259            self::WPCOM_PRO_PLANS,
1260            self::WPCOM_FLEX_CACHE_SITE_FREE_PLANS,
1261        ),
1262
1263        // This governs UI access to Jetpack Scan.
1264        // All WoW sites should perform scans, however we don't want to expose the UI to sites on lower wpcom plans.
1265        // It's not completely clear how this differs from SCAN_MANAGED.
1266        self::SCAN_SELF_SERVE                   => array(
1267            self::JETPACK_PREMIUM_AND_HIGHER,
1268            self::JETPACK_SCAN_PLANS,
1269            self::JETPACK_GOLDEN_TOKEN,
1270            self::WPCOM_BUSINESS_AND_HIGHER_PLANS,
1271            self::WPCOM_PRO_PLANS,
1272            self::WPCOM_FLEX_CACHE_SITE_FREE_PLANS,
1273        ),
1274
1275        /*
1276         * SCHEDULED_UPDATES - Allows users to schedule plugin and (eventually) theme updates for their sites.
1277         *
1278         * @see pcmemI-2O3-p2
1279         */
1280        self::SCHEDULED_UPDATES                 => array(
1281            self::WPCOM_BUSINESS_AND_HIGHER_PLANS,
1282            self::WPCOM_FLEX_CACHE_SITE_FREE_PLANS,
1283        ),
1284
1285        /*
1286         * SECURITY_SETTINGS - Initially added to determine whether to show /settings/security.
1287         * More info: https://github.com/Automattic/wp-calypso/issues/51820
1288         *
1289         * Active for:
1290         * - Simple and Atomic sites with Business or up plan.
1291         * - Jetpack sites with any plan.
1292         */
1293        self::SECURITY_SETTINGS                 => array(
1294            self::WPCOM_PRO_PLANS,
1295            self::WPCOM_BUSINESS_AND_HIGHER_PLANS,
1296            self::JETPACK_ALL_SITES,
1297            self::WPCOM_FLEX_CACHE_SITE_FREE_PLANS,
1298        ),
1299        self::SEO_ADMIN_UI                      => array(
1300            // For now, this is controlled via a blog sticker in Store_Product_List.
1301            array(
1302                'before' => '2004-12-12',
1303                self::WPCOM_ALL_SITES,
1304            ),
1305        ),
1306        self::SEO_PREVIEW_TOOLS                 => array(
1307            array(
1308                'required_sticker' => 'gating-business-q1',
1309                self::WPCOM_PREMIUM_PLANS,
1310            ),
1311            self::BUNDLE_ENTERPRISE,
1312            self::JETPACK_ALL_SITES,
1313            self::WPCOM_BUSINESS_AND_HIGHER_PLANS,
1314            self::WPCOM_PRO_PLANS,
1315            self::WPCOM_FLEX_CACHE_SITE_FREE_PLANS,
1316        ),
1317        self::SEND_A_MESSAGE                    => array(
1318            self::WPCOM_PREMIUM_AND_HIGHER_PLANS,
1319            self::JETPACK_ALL_SITES,
1320        ),
1321
1322        /*
1323         * SET_PRIMARY_CUSTOM_DOMAIN - Set custom domain as primary.
1324         * It allows to set a custom domain of the site as primary.
1325         *
1326         * Active for:
1327         * - Simple and Atomic sites with any standard WordPress.com plan
1328         */
1329        self::SET_PRIMARY_CUSTOM_DOMAIN         => array(
1330            self::WPCOM_BLOGGER_AND_HIGHER_PLANS,
1331            self::WOO_HOSTED_PLANS,
1332            self::YOAST_PREMIUM,
1333        ),
1334        // Hosting Configuration.
1335        self::SFTP                              => array(
1336            self::WPCOM_BUSINESS_AND_HIGHER_PLANS,
1337            self::WPCOM_PRO_PLANS,
1338            self::EXCLUDE_PLANS => array(
1339                self::WPCOM_ECOMMERCE_TRIAL_PLANS,
1340            ),
1341            self::WPCOM_FLEX_CACHE_SITE_FREE_PLANS,
1342        ),
1343
1344        self::SSH                               => array(
1345            self::WPCOM_BUSINESS_AND_HIGHER_PLANS,
1346            self::EXCLUDE_PLANS => array(
1347                self::WPCOM_ECOMMERCE_TRIAL_PLANS,
1348            ),
1349            self::WPCOM_FLEX_CACHE_SITE_FREE_PLANS,
1350        ),
1351        self::SIMPLE_PAYMENTS                   => array(
1352            self::WPCOM_PREMIUM_AND_HIGHER_PLANS,
1353            self::JETPACK_PREMIUM_AND_HIGHER,
1354            self::JETPACK_CREATOR_PLANS,
1355            self::JETPACK_GROWTH_PLANS,
1356        ),
1357        self::SITE_PREVIEW_LINKS                => array(
1358            self::WPCOM_BUSINESS_AND_HIGHER_PLANS,
1359        ),
1360
1361        /*
1362         * SOCIAL_SHARES_1000 - This feature is linked to the ability to share upto 1000 social media shares on the Jetpack Social Plugin.
1363         *
1364         */
1365        self::SOCIAL_SHARES_1000                => array(
1366            self::JETPACK_ALL_SITES,
1367            self::BUNDLE_ENTERPRISE,
1368        ),
1369
1370        self::SOCIAL_ENHANCED_PUBLISHING        => array(
1371            self::JETPACK_SOCIAL_ADVANCED_PLANS,
1372            self::JETPACK_COMPLETE_PLANS,
1373            self::BUNDLE_ENTERPRISE,
1374            self::JETPACK_SOCIAL_V1_PLANS,
1375            self::JETPACK_SOCIAL_PLANS,
1376            self::JETPACK_GROWTH_PLANS,
1377            self::WPCOM_BUSINESS_AND_HIGHER_PLANS,
1378        ),
1379        self::SOCIAL_ADMIN_UI_V2                => array(
1380            // For now, this is controlled via a blog sticker in Store_Product_List.
1381            array(
1382                'before' => '2004-12-12',
1383                self::WPCOM_ALL_SITES,
1384            ),
1385        ),
1386        self::SOCIAL_IMAGE_FOCAL_POINT          => array(
1387            // For now, this is controlled via a blog sticker in Store_Product_List.
1388            array(
1389                'before' => '2004-12-12',
1390                self::WPCOM_ALL_SITES,
1391            ),
1392        ),
1393        self::SOCIAL_IMAGE_GENERATOR            => array(
1394            self::JETPACK_SOCIAL_ADVANCED_PLANS,
1395            self::JETPACK_COMPLETE_PLANS,
1396            self::BUNDLE_ENTERPRISE,
1397            self::JETPACK_SOCIAL_V1_PLANS,
1398            self::JETPACK_SOCIAL_PLANS,
1399            self::JETPACK_GROWTH_PLANS,
1400            self::WPCOM_BUSINESS_AND_HIGHER_PLANS,
1401        ),
1402        self::SOCIAL_MESSAGE_TEMPLATES          => array(
1403            // Gated on the paid social plans, matching SOCIAL_ENHANCED_PUBLISHING.
1404            self::JETPACK_SOCIAL_ADVANCED_PLANS,
1405            self::JETPACK_COMPLETE_PLANS,
1406            self::BUNDLE_ENTERPRISE,
1407            self::JETPACK_SOCIAL_V1_PLANS,
1408            self::JETPACK_SOCIAL_PLANS,
1409            self::JETPACK_GROWTH_PLANS,
1410            self::WPCOM_BUSINESS_AND_HIGHER_PLANS,
1411        ),
1412        self::SOCIAL_IMAGE_AUTO_CONVERT         => array(
1413            self::WPCOM_ALL_SITES,
1414        ),
1415        self::SPACE                             => array(
1416            self::WPCOM_ALL_SITES,
1417        ),
1418
1419        /*
1420         * Products that have upgraded storage space on WordPress.com, beyond
1421         * the bare minimum advertised for free sites. This list includes all
1422         * WordPress.com plans and space upgrade products.
1423         */
1424        self::SPACE_UPGRADED_STORAGE            => array(
1425            self::WPCOM_BLOGGER_AND_HIGHER_PLANS,
1426            self::BUNDLE_SUPER,
1427            self::BUNDLE_ENTERPRISE,
1428            self::WP_P2_PLUS_MONTHLY,
1429            self::SPACE_1GB,
1430            self::SPACE_3GB,
1431            self::SPACE_10GB,
1432            self::SPACE_25GB,
1433            self::SPACE_50GB,
1434            self::SPACE_100GB,
1435            self::SPACE_200GB,
1436            self::EXCLUDE_PLANS => array(
1437                self::WPCOM_HOSTING_TRIAL_PLANS,
1438            ),
1439        ),
1440        self::STAGING_SITES                     => array(
1441            self::WPCOM_BUSINESS_AND_HIGHER_PLANS,
1442            self::EXCLUDE_PLANS => array(
1443                self::WPCOM_ECOMMERCE_TRIAL_PLANS,
1444            ),
1445            self::WPCOM_FLEX_CACHE_SITE_FREE_PLANS,
1446        ),
1447        // Gives near full access to all stats features. All features except new commercial level modules like UTM and device stats.
1448        self::STATS_FREE                        => array(
1449            self::JETPACK_STATS_PLANS,
1450            self::JETPACK_GROWTH_PLANS,
1451            // Provides legacy access for free and personal sites created before 2024-01-09.
1452            // Can be removed once we are ready to paywall all free and/or old personal sites.
1453            array(
1454                'before' => '2024-01-09',
1455                self::WPCOM_PERSONAL_AND_HIGHER_PLANS,
1456                self::WPCOM_ALL_SITES,
1457            ),
1458        ),
1459        // Provides limited stats for free and personal sites created before 2024-12-06.
1460        // Features: Posts/Locations/Emails/File downloads
1461        // Can be removed once we are ready to paywall all free sites.
1462        self::STATS_BASIC_TEMP                  => array(
1463            array(
1464                'before' => '2024-12-12',
1465                self::WPCOM_ALL_SITES,
1466            ),
1467        ),
1468        // Provides personal sites and higher access to all stats features except commercial level modules.
1469        // Features: Posts/Locations/Emails/File downloads/Referrers/Clicks
1470        self::STATS_PAID                        => array(
1471            self::WPCOM_PERSONAL_AND_HIGHER_PLANS,
1472            self::WP_P2_PLUS_MONTHLY,
1473            self::JETPACK_STATS_PWYW,
1474            self::JETPACK_STATS_MONTHLY,
1475            self::JETPACK_STATS_BI_YEARLY,
1476            self::JETPACK_STATS_YEARLY,
1477            self::JETPACK_COMPLETE_PLANS,
1478            self::JETPACK_BUSINESS_PLANS,
1479            self::JETPACK_GROWTH_PLANS,
1480        ),
1481        // Provides premium sites and higher access to all stats features.
1482        // Features: STATS_PAID + UTM & Devices modules
1483        self::STATS_COMMERCIAL                  => array(
1484            self::WPCOM_PREMIUM_AND_HIGHER_PLANS,
1485            self::JETPACK_STATS_MONTHLY,
1486            self::JETPACK_STATS_BI_YEARLY,
1487            self::JETPACK_STATS_YEARLY,
1488            self::JETPACK_COMPLETE_PLANS,
1489            self::JETPACK_BUSINESS_PLANS,
1490            self::JETPACK_GROWTH_PLANS,
1491            // A4A Jetpack Stats plans
1492            self::A4A_JETPACK_STATS_MONTHLY,
1493            self::A4A_JETPACK_STATS_YEARLY,
1494        ),
1495        self::STUDIO_SYNC                       => array(
1496            self::WPCOM_PRO_PLANS,
1497            self::WPCOM_PERSONAL_AND_PREMIUM_PLANS,
1498            self::WPCOM_BUSINESS_AND_HIGHER_PLANS,
1499            self::WPCOM_FLEX_CACHE_SITE_FREE_PLANS,
1500        ),
1501
1502        // Importing subscribers to the site without limits.
1503        self::SUBSCRIBER_UNLIMITED_IMPORTS      => array(
1504            self::WP_P2_PLUS_MONTHLY,
1505            self::WPCOM_PERSONAL_AND_HIGHER_PLANS,
1506            self::JETPACK_PERSONAL_AND_HIGHER,
1507            self::JETPACK_SOCIAL_PLANS,
1508            self::JETPACK_SOCIAL_ADVANCED_PLANS,
1509            self::JETPACK_SOCIAL_V1_PLANS,
1510            self::JETPACK_CREATOR_PLANS,
1511            self::JETPACK_GROWTH_PLANS,
1512            self::EXCLUDE_PLANS => array(
1513                self::WPCOM_MIGRATION_TRIAL_PLANS,
1514                self::WPCOM_HOSTING_TRIAL_PLANS,
1515            ),
1516            // A4A Jetpack Stats plans
1517            self::A4A_JETPACK_STATS_MONTHLY,
1518            self::A4A_JETPACK_STATS_YEARLY,
1519        ),
1520
1521        self::SUBSCRIPTION_GIFTING              => array(
1522            self::WPCOM_PERSONAL_AND_HIGHER_PLANS,
1523            self::EXCLUDE_PLANS => array(
1524                self::WPCOM_MIGRATION_TRIAL_PLANS,
1525                self::WPCOM_HOSTING_TRIAL_PLANS,
1526                self::WPCOM_ECOMMERCE_TRIAL_PLANS,
1527            ),
1528        ),
1529
1530        // SUPPORT - Everybody needs somebody.
1531        self::SUPPORT                           => array(
1532            self::WPCOM_ALL_SITES,
1533            self::JETPACK_PERSONAL_AND_HIGHER,
1534            self::JETPACK_GOLDEN_TOKEN,
1535        ),
1536        self::TITAN_MAIL_1YEAR_TRIAL            => array(
1537            array(
1538                'required_sticker' => 'gating-business-q1',
1539                self::WPCOM_BUSINESS_PLANS,
1540                self::WPCOM_ECOMMERCE_PLANS,
1541            ),
1542        ),
1543        self::UPGRADED_UPLOAD_FILETYPES         => array(
1544            self::SPACE_1GB,
1545            self::SPACE_3GB,
1546            self::SPACE_10GB,
1547            self::SPACE_25GB,
1548            self::SPACE_50GB,
1549            self::SPACE_100GB,
1550            self::SPACE_200GB,
1551            self::WPCOM_BLOGGER_AND_HIGHER_PLANS,
1552            self::WP_P2_PLUS_MONTHLY,
1553        ),
1554        self::UPLOAD_AUDIO_FILES                => array(
1555            self::WPCOM_PREMIUM_AND_HIGHER_PLANS,
1556            self::JETPACK_ALL_SITES,
1557        ),
1558        self::UPLOAD_PLUGINS                    => array(
1559            self::WPCOM_PRO_PLANS,
1560            self::EXCLUDE_PLANS => array(
1561                self::WPCOM_ECOMMERCE_TRIAL_PLANS,
1562            ),
1563            self::WPCOM_PERSONAL_AND_HIGHER_PLANS,
1564            self::WPCOM_FLEX_CACHE_SITE_FREE_PLANS,
1565        ),
1566        self::UPLOAD_SPACE_1GB                  => array(
1567            self::SPACE_1GB,
1568        ),
1569        self::UPLOAD_SPACE_3GB                  => array(
1570            self::SPACE_3GB,
1571        ),
1572        self::UPLOAD_SPACE_10GB                 => array(
1573            self::SPACE_10GB,
1574        ),
1575        self::UPLOAD_SPACE_25GB                 => array(
1576            self::SPACE_25GB,
1577        ),
1578        self::UPLOAD_SPACE_50GB                 => array(
1579            self::SPACE_50GB,
1580        ),
1581        self::UPLOAD_SPACE_100GB                => array(
1582            self::SPACE_100GB,
1583        ),
1584        self::UPLOAD_SPACE_200GB                => array(
1585            self::SPACE_200GB,
1586            array(
1587                'before' => LEGACY_200GB_CUTOFF_DATE,
1588                self::WPCOM_BUSINESS_PLANS,
1589                self::WPCOM_ECOMMERCE_PLANS,
1590            ),
1591            array(
1592                'required_sticker' => 'legacy-200gb-storage',
1593                self::WPCOM_BUSINESS_PLANS,
1594                self::WPCOM_ECOMMERCE_PLANS,
1595            ),
1596        ),
1597        self::UPLOAD_SPACE_UNLIMITED            => array(
1598            array(
1599                'before' => '2019-08-01',
1600                self::WPCOM_BUSINESS_PLANS,
1601                self::WPCOM_ECOMMERCE_PLANS,
1602            ),
1603        ),
1604        self::UPLOAD_THEMES                     => array(
1605            self::WPCOM_PRO_PLANS,
1606            self::EXCLUDE_PLANS => array(
1607                self::WPCOM_ECOMMERCE_TRIAL_PLANS,
1608            ),
1609            self::WPCOM_PERSONAL_AND_HIGHER_PLANS,
1610            self::WPCOM_FLEX_CACHE_SITE_FREE_PLANS,
1611        ),
1612
1613        /*
1614         * UPLOAD_VIDEO_FILES - This feature is linked to the ability to upload video files to the website.
1615         *
1616         * Active for:
1617         * - Simple and Atomic sites with Premium or up plan.
1618         * - Jetpack sites with any plan.
1619         */
1620        self::UPLOAD_VIDEO_FILES                => array(
1621            self::WP_P2_PLUS_MONTHLY,
1622            self::WPCOM_PREMIUM_AND_HIGHER_PLANS,
1623            self::JETPACK_ALL_SITES,
1624        ),
1625
1626        self::VAULTPRESS_AUTOMATED_RESTORES     => array(
1627            self::JETPACK_PREMIUM_PLANS,
1628            self::JETPACK_BUSINESS_PLANS,
1629        ),
1630        self::VAULTPRESS_BACKUP_ARCHIVE         => array(
1631            self::JETPACK_PREMIUM_PLANS,
1632            self::JETPACK_BUSINESS_PLANS,
1633        ),
1634        self::VAULTPRESS_BACKUPS                => array(
1635            self::JETPACK_PERSONAL_AND_HIGHER,
1636        ),
1637        self::VAULTPRESS_SECURITY_SCANNING      => array(
1638            self::JETPACK_BUSINESS_PLANS,
1639        ),
1640        self::VAULTPRESS_STORAGE_SPACE          => array(
1641            self::JETPACK_PREMIUM_PLANS,
1642            self::JETPACK_BUSINESS_PLANS,
1643        ),
1644
1645        /*
1646         * VIDEO_HOSTING - Host video effortlessly and deliver it at high speeds to your viewers.
1647         * https://jetpack.com/features/design/video-hosting/
1648         *
1649         * Active for:
1650         * - Simple and Atomic sites with Premium or up plan.
1651         * - Jetpack sites with Premium or up plan.
1652         */
1653        self::VIDEO_HOSTING                     => array(
1654            array(
1655                'sticker_not_present' => 'gating-business-q1',
1656                self::WPCOM_PREMIUM_PLANS,
1657            ),
1658            self::WPCOM_PRO_PLANS,
1659            self::WPCOM_BUSINESS_AND_HIGHER_PLANS,
1660            self::JETPACK_PREMIUM_AND_HIGHER,
1661            self::EXCLUDE_PLANS => array(
1662                self::WPCOM_ECOMMERCE_TRIAL_PLANS,
1663            ),
1664        ),
1665        self::VIDEOPRESS                        => array(
1666            self::JETPACK_BUSINESS_PLANS,
1667            self::JETPACK_COMPLETE_PLANS,
1668            self::JETPACK_PERSONAL_PLANS,
1669            self::JETPACK_PREMIUM_PLANS,
1670            self::JETPACK_VIDEOPRESS_PLANS,
1671            array(
1672                'sticker_not_present' => 'gating-business-q1',
1673                self::WPCOM_PREMIUM_PLANS,
1674            ),
1675            self::WPCOM_PRO_PLANS,
1676            self::WPCOM_BUSINESS_AND_HIGHER_PLANS,
1677            self::WPCOM_VIDEOPRESS,
1678            self::WPCOM_VIDEOPRESS_PRO,
1679            self::WP_P2_PLUS_MONTHLY,
1680            array(
1681                'before' => '2021-10-07',
1682                self::JETPACK_SECURITY_DAILY_PLANS,
1683                self::JETPACK_SECURITY_REALTIME_PLANS,
1684                self::JETPACK_SECURITY_T0_PLANS,
1685                self::JETPACK_SECURITY_T1_PLANS,
1686                self::JETPACK_SECURITY_T2_PLANS,
1687            ),
1688        ),
1689
1690        /*
1691         * Note: VIDEOPRESS_1TB_STORAGE and VIDEOPRESS_UNLIMITED_STORAGE are
1692         * currently only checked on standalone Jetpack sites.
1693         * For example, adding VIDEOPRESS_UNLIMITED_STORAGE to a WP.com plan
1694         * will not provide it with unlimited VideoPress storage.
1695         *
1696         * All WoA VIDEOPRESS sites currently get 2TB storage on their cache
1697         * site for VideoPress.
1698         */
1699        self::VIDEOPRESS_1TB_STORAGE            => array(
1700            array(
1701                self::JETPACK_COMPLETE_PLANS,
1702                self::JETPACK_VIDEOPRESS_PLANS,
1703                self::JETPACK_PREMIUM_PLANS,
1704                self::JETPACK_BUSINESS_PLANS,
1705            ),
1706        ),
1707        // VIDEOPRESS_VIDEO - videopress/video requires a paid plan.
1708        self::VIDEOPRESS_VIDEO                  => array(
1709            self::WP_P2_PLUS_MONTHLY,
1710            array(
1711                'sticker_not_present' => 'gating-business-q1',
1712                self::WPCOM_PREMIUM_PLANS,
1713            ),
1714            self::WPCOM_PRO_PLANS,
1715            self::WPCOM_BUSINESS_AND_HIGHER_PLANS,
1716            self::JETPACK_BUSINESS_PLANS,
1717            self::JETPACK_PREMIUM_PLANS,
1718            self::EXCLUDE_PLANS => array(
1719                self::WPCOM_ECOMMERCE_TRIAL_PLANS,
1720            ),
1721        ),
1722        self::VIDEOPRESS_UNLIMITED_STORAGE      => array(
1723            array(
1724                'before' => '2021-10-07',
1725                self::JETPACK_COMPLETE_PLANS,
1726                self::JETPACK_SECURITY_DAILY_PLANS,
1727                self::JETPACK_SECURITY_REALTIME_PLANS,
1728                self::JETPACK_SECURITY_T0_PLANS,
1729                self::JETPACK_SECURITY_T1_PLANS,
1730                self::JETPACK_SECURITY_T2_PLANS,
1731                self::JETPACK_PREMIUM_PLANS,
1732                self::JETPACK_BUSINESS_PLANS,
1733            ),
1734        ),
1735        self::WHATSAPP_BUTTON                   => array(
1736            self::WPCOM_PREMIUM_AND_HIGHER_PLANS,
1737            self::JETPACK_ALL_SITES,
1738        ),
1739
1740        /*
1741         * WOOP - WooCommerce on all Plans is available to install.
1742         *
1743         * Active for:
1744         * - Simple and Atomic sites with Business or up plan.
1745         * - Not Jetpack sites
1746         */
1747        self::WOOP                              => array(
1748            self::WPCOM_PRO_PLANS,
1749            self::WPCOM_BUSINESS_AND_HIGHER_PLANS,
1750        ),
1751        self::WORDADS                           => array(
1752            self::JETPACK_STARTER_PLANS,
1753            self::WPCOM_PREMIUM_AND_HIGHER_PLANS,
1754            self::JETPACK_PREMIUM_AND_HIGHER,
1755            self::JETPACK_CREATOR_PLANS,
1756            self::JETPACK_GROWTH_PLANS,
1757        ),
1758
1759        /*
1760         * WORDADS_JETPACK - `wordads-jetpack` is maintained as a legacy alias of `wordads` which was used to gate
1761         * the feature in old versions of Jetpack.
1762         * @see https://github.com/Automattic/jetpack/blob/c4f8fe120e1286e85f49e20e0f7fe22e44641449/projects/plugins/jetpack/class.jetpack-plan.php#L330.
1763         */
1764        self::WORDADS_JETPACK                   => array(
1765            self::WPCOM_PREMIUM_AND_HIGHER_PLANS,
1766            self::JETPACK_PREMIUM_AND_HIGHER,
1767        ),
1768
1769        /*
1770         * WORDPRESS_LABS - unlocked purely by the `wordpress-labs` blog sticker, independent of any
1771         * purchase.
1772         */
1773        self::WORDPRESS_LABS                    => array(
1774            array(
1775                'required_sticker' => 'wordpress-labs',
1776                self::WPCOM_ALL_SITES,
1777                self::JETPACK_ALL_SITES,
1778            ),
1779        ),
1780    );
1781    /**
1782     * Some A8C owned sites have additional features enabled. e.g. Jetpack SEO.
1783     * This is an array of blog IDs where these features are enabled.
1784     */
1785    public const A8C_SITES_WITH_ADDITIONAL_SEO_FEATURES = array(
1786        1, // https://wordpress.com/
1787        69197545, // br.support.wordpress.com
1788        69197545, // br.support.wordpress.com
1789        12084301, // he.support.wordpress.com
1790        12358344, // pt.support.wordpress.com
1791        20614491, // de.support.wordpress.com
1792        110643074, // es.support.wordpress.com
1793        9619154, // en.support.wordpress.com
1794        9620355, // fr.support.wordpress.com
1795        22718864, // ru.support.wordpress.com
1796        26068228, // ja.support.wordpress.com
1797        151395884, // ko.support.wordpress.com
1798        151398260, // sv.support.wordpress.com
1799        151398564, // ar.support.wordpress.com
1800        150300509, // it.support.wordpress.com
1801        150381433, // nl.support.wordpress.com
1802        150645278, // id.support.wordpress.com
1803        150881074, // tr.support.wordpress.com
1804        151397720, // zh-cn.support.wordpress.com
1805        151397956, // zh-tw.support.wordpress.com
1806        3584907, // en.blog.wordpress.com
1807        7944537, // ja.blog.wordpress.com
1808        11241806, // es.blog.wordpress.com
1809        8181651, // pt.blog.wordpress.com
1810        8994420, // fr.blog.wordpress.com
1811        66243751, // br.blog.wordpress.com
1812        196931530, // enwpgo.wordpress.com
1813        173323553, // eswpgo.wordpress.com
1814        173331416, // dewpgo.wordpress.com
1815        162814143, // frwpgo.wordpress.com
1816        173328699, // itwpgo.wordpress.com
1817        163161552, // brwpgo.wordpress.com
1818        53424024, // discover.wordpress.com
1819        489937, // dailypost.wordpress.com
1820        33534099,  // developer.wordpress.com
1821        233643880, // eswpcomdeveloper.wordpress.com
1822        244311505, // jawpcomdeveloper.wordpress.com
1823        244447807, // frwpcomdeveloper.wordpress.com
1824        244448116, // dewpcomdeveloper.wordpress.com
1825        244448279, // ptbrwpcomdeveloper.wordpress.com
1826        244517526, // idwpcomdeveloper.wordpress.com
1827        244516213, // itwpcomdeveloper.wordpress.com
1828        244518337, // nlwpcomdeveloper.wordpress.com
1829        22994, // theme.wordpress.com
1830        16390, // learn.wordpress.com
1831        54117, // automattic.wordpress.com
1832    );
1833
1834    /**
1835     * Checks whether the given feature is declared in our map.
1836     *
1837     * @param string $feature The feature to check.
1838     *
1839     * @return bool Whether the given feature exists.
1840     */
1841    public static function feature_exists( $feature ) {
1842        return ! empty( self::FEATURES_MAP[ $feature ] );
1843    }
1844
1845    /**
1846     * Given a primitive type $needle, and an array $haystack, recursively
1847     * search $haystack for an instance of $needle. If arrays are encountered,
1848     * they will also be searched. Only strict comparisons are used.
1849     *
1850     * @param mixed $needle   What to look for.
1851     * @param array $haystack Array of items to check, may contain other arrays.
1852     *
1853     * @return bool Is the needle in the haystack somewhere?
1854     */
1855    public static function in_array_recursive( $needle, $haystack ) {
1856        foreach ( $haystack as $item ) {
1857            if ( is_array( $item ) ) {
1858                if ( self::in_array_recursive( $needle, $item ) ) {
1859                    return true;
1860                }
1861            } elseif ( $item === $needle ) {
1862                return true;
1863            }
1864        }
1865        return false;
1866    }
1867
1868    /**
1869     * Given an array of $purchases and a single feature name, consult the FEATURES_MAP to determine if the feature
1870     * is included in one of the $purchases.
1871     *
1872     * Use the function wpcom_site_has_feature( $feature ) to determine if a site has access to a certain feature.
1873     *
1874     * @param string $feature   A singular feature.
1875     * @param array  $purchases A collection of purchases.
1876     * @param string $site_type Site type to check. Can be 'wpcom' or 'jetpack'. Default empty string.
1877     * @param int    $blog_id   The blog ID to check. Default null.
1878     *
1879     * @return bool Is the feature included in one of the purchases.
1880     */
1881    public static function has_feature( $feature, $purchases, $site_type = '', $blog_id = null ) {
1882        if ( ! self::feature_exists( $feature ) ) {
1883            return false;
1884        }
1885
1886        $products_map = self::FEATURES_MAP[ $feature ];
1887
1888        // Automatically grant features that don't require any purchase.
1889        if (
1890            ( 'wpcom' === $site_type && in_array( self::WPCOM_ALL_SITES, $products_map, true ) ) ||
1891            ( 'jetpack' === $site_type && in_array( self::JETPACK_ALL_SITES, $products_map, true ) )
1892        ) {
1893            return true;
1894        }
1895
1896        foreach ( $purchases as $purchase ) {
1897            if ( self::purchase_in_products_map( $purchase, $products_map, $blog_id ) ) {
1898                return true;
1899            }
1900        }
1901        return false;
1902    }
1903
1904    /**
1905     * Treat free plan as a purchase so the logic for purchase_in_products_map are applied when checking for legacy features.
1906     * As the free plan isn't actually a purchase, there is no subscribed_date, so we use the blog_registered_date instead.
1907     *
1908     * @param array  $purchases Reference to an array of purchases, this function adds a free plan to the end of the array passed in.
1909     * @param string $site_type Site type to check. Can be 'wpcom' or 'jetpack'.
1910     * @param string $blog_registered_date The date the blog was registered.
1911     */
1912    public static function add_free_plan_purchase( &$purchases, $site_type, $blog_registered_date ) {
1913        $free_purchase_object                  = new stdClass();
1914        $free_purchase_object->product_slug    = "{$site_type}-all-sites";
1915        $free_purchase_object->subscribed_date = $blog_registered_date;
1916
1917        $purchases[] = $free_purchase_object;
1918    }
1919
1920    /**
1921     * The products definition array ($products_map) may contain 1st-level sub-arrays with 'before' and/or 'after' keys
1922     * used to restrict access to a feature based on when the purchase was made. If the $purchase is included in
1923     * $products_map, and it was purchased within the defined date range (if a date range is defined), return true.
1924     *
1925     * Additionally, the 1st level of the array may contain the key 'excluded_plans' which is an array of plans that
1926     * should be excluded from the feature. This is useful for when there are very specific exceptions that would
1927     * otherwise require a lot of configuration to be added. If a plan is excluded, no further checks will be done.
1928     *
1929     * @param object $purchase A single purchase.
1930     * @param array  $products_map A feature map definition array.
1931     * @param int    $blog_id The blog ID to check. Default null.
1932     *
1933     * @return bool If the purchase is included in $products_map and meets any purchase date-range rules.
1934     */
1935    public static function purchase_in_products_map( $purchase, $products_map, $blog_id = null ) {
1936
1937        // First check if the current purchase is excluded in the product definition.
1938        if ( isset( $products_map[ self::EXCLUDE_PLANS ] ) ) {
1939            $excluded_plans = $products_map[ self::EXCLUDE_PLANS ] ?? array();
1940            if ( ! empty( $excluded_plans ) && self::in_array_recursive( $purchase->product_slug, array( $excluded_plans ) ) ) {
1941                return false;
1942            }
1943            unset( $products_map[ self::EXCLUDE_PLANS ] );
1944        }
1945
1946        // Loop through the first level of the $products_map array to identify potential legacy feature date ranges.
1947        foreach ( $products_map as $product_definition ) {
1948
1949            if ( ! empty( $product_definition['product_type'] ) ) {
1950                if ( ! empty( $purchase->product_type ) && in_array( $purchase->product_type, $product_definition['product_type'], true ) ) {
1951                    return true;
1952                }
1953                continue;
1954            }
1955
1956            $purchase_eligible_by_date    = false;
1957            $purchase_eligible_by_sticker = false;
1958
1959            // Check if sticker requirement exists.
1960            $required_sticker = $product_definition['required_sticker'] ?? null;
1961            if ( $required_sticker ) {
1962                if ( defined( 'IS_ATOMIC' ) && IS_ATOMIC && function_exists( 'wpcomsh_is_site_sticker_active' ) ) {
1963                    // Fallback for Atomic sites
1964                    $purchase_eligible_by_sticker = wpcomsh_is_site_sticker_active( $required_sticker );
1965                } elseif ( function_exists( 'has_blog_sticker' ) ) {
1966                    $blog_id                    ??= get_current_blog_id();
1967                    $purchase_eligible_by_sticker = has_blog_sticker( $required_sticker, $blog_id );
1968                }
1969                // Remove the sticker key so $product_definition is clean for in_array_recursive search.
1970                unset( $product_definition['required_sticker'] );
1971            } else {
1972                $purchase_eligible_by_sticker = true; // No sticker requirement, so eligible by default.
1973            }
1974
1975            // Check if sticker_not_present requirement exists (feature only available when sticker is NOT present).
1976            $sticker_not_present = $product_definition['sticker_not_present'] ?? null;
1977            if ( $sticker_not_present ) {
1978                $has_sticker = false;
1979                if ( defined( 'IS_ATOMIC' ) && IS_ATOMIC && function_exists( 'wpcomsh_is_site_sticker_active' ) ) {
1980                    // Fallback for Atomic sites
1981                    $has_sticker = wpcomsh_is_site_sticker_active( $sticker_not_present );
1982                } elseif ( function_exists( 'has_blog_sticker' ) ) {
1983                    $blog_id   ??= get_current_blog_id();
1984                    $has_sticker = has_blog_sticker( $sticker_not_present, $blog_id );
1985                }
1986                // Only eligible if the sticker is NOT present.
1987                $purchase_eligible_by_sticker = $purchase_eligible_by_sticker && ! $has_sticker;
1988                // Remove the sticker key so $product_definition is clean for in_array_recursive search.
1989                unset( $product_definition['sticker_not_present'] );
1990            }
1991
1992            // If 'before' & 'after' are empty, this is not a legacy feature.
1993            if ( empty( $product_definition['before'] ) && empty( $product_definition['after'] ) ) {
1994                $purchase_eligible_by_date = true;
1995            } else {
1996                // If the date key is defined, set its variable to its Unix timestamp, else set invalid or undefined dates to false.
1997                $before          = isset( $product_definition['before'] ) ? strtotime( $product_definition['before'] ) : false;
1998                $after           = isset( $product_definition['after'] ) ? strtotime( $product_definition['after'] ) : false;
1999                $subscribed_date = isset( $purchase->subscribed_date ) ? strtotime( $purchase->subscribed_date ) : false;
2000
2001                // Remove the date keys so $product_definition is clean for in_array_recursive search.
2002                unset( $product_definition['before'], $product_definition['after'] );
2003
2004                // If 'before' or 'after', & the subscribed_date are valid, check if the legacy feature is available.
2005                if ( ( false !== $before || false !== $after ) && false !== $subscribed_date ) {
2006                    if ( false !== $before && false !== $after ) {
2007                        if (
2008                            $subscribed_date >= $after &&
2009                            $subscribed_date <= $before ) {
2010                            $purchase_eligible_by_date = true;
2011                        }
2012                    } elseif ( false !== $before ) {
2013                        if ( $subscribed_date <= $before ) {
2014                            $purchase_eligible_by_date = true;
2015                        }
2016                    } elseif ( false !== $after ) {
2017                        if ( $subscribed_date >= $after ) {
2018                            $purchase_eligible_by_date = true;
2019                        }
2020                    }
2021                }
2022            }
2023
2024            // If the date range and sticker requirements are cleared, check if the purchase is included in the $product_definition.
2025            if ( $purchase_eligible_by_date && $purchase_eligible_by_sticker ) {
2026                if ( self::in_array_recursive( $purchase->product_slug ?? null, array( $product_definition ) ) ) {
2027                    return true;
2028                }
2029            }
2030        }
2031
2032        return false;
2033    }
2034
2035    /**
2036     * Return a list of all possible feature slugs.
2037     *
2038     * @return array An array of strings like 'premium-themes', one for each possible feature slug.
2039     */
2040    public static function get_feature_slugs() {
2041        return array_keys( self::FEATURES_MAP );
2042    }
2043}