Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
CRAP
100.00% covered (success)
100.00%
1 / 1
Protected_Options
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
5
100.00% covered (success)
100.00%
1 / 1
 is_protected
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
5
1<?php
2/**
3 * Option names the Protect dashboard never deletes.
4 *
5 * @package automattic/jetpack-protect
6 */
7
8namespace Automattic\Jetpack\Protect;
9
10/**
11 * WordPress core's and Jetpack's options, which stay even when Scan flags them, because the site or Jetpack needs them.
12 *
13 * @since 0.4.0
14 */
15class Protected_Options {
16
17    /**
18     * Core's options: the defaults from populate_options() in wp-admin/includes/schema.php, then those core adds later, such as wp_salt()'s keys.
19     *
20     * @var string[]
21     */
22    const CORE = array(
23        'active_plugins',
24        'admin_email',
25        'admin_email_lifespan',
26        'auto_plugin_theme_update_emails',
27        'auto_update_core_dev',
28        'auto_update_core_major',
29        'auto_update_core_minor',
30        'avatar_default',
31        'avatar_rating',
32        'blog_charset',
33        'blog_public',
34        'blogdescription',
35        'blogname',
36        'category_base',
37        'close_comments_days_old',
38        'close_comments_for_old_posts',
39        'comment_max_links',
40        'comment_moderation',
41        'comment_order',
42        'comment_previously_approved',
43        'comment_registration',
44        'comments_notify',
45        'comments_per_page',
46        'date_format',
47        'db_version',
48        'default_category',
49        'default_comment_status',
50        'default_comments_page',
51        'default_email_category',
52        'default_link_category',
53        'default_ping_status',
54        'default_pingback_flag',
55        'default_post_format',
56        'default_role',
57        'disallowed_keys',
58        'finished_splitting_shared_terms',
59        'gmt_offset',
60        'hack_file',
61        'home',
62        'html_type',
63        'image_default_align',
64        'image_default_link_type',
65        'image_default_size',
66        'large_size_h',
67        'large_size_w',
68        'link_manager_enabled',
69        'links_updated_date_format',
70        'mailserver_login',
71        'mailserver_pass',
72        'mailserver_port',
73        'mailserver_url',
74        'medium_large_size_h',
75        'medium_large_size_w',
76        'medium_size_h',
77        'medium_size_w',
78        'moderation_keys',
79        'moderation_notify',
80        'page_comments',
81        'page_for_posts',
82        'page_on_front',
83        'permalink_structure',
84        'ping_sites',
85        'posts_per_page',
86        'posts_per_rss',
87        'recently_edited',
88        'require_name_email',
89        'rewrite_rules',
90        'rss_use_excerpt',
91        'show_avatars',
92        'show_comments_cookies_opt_in',
93        'show_on_front',
94        'site_icon',
95        'siteurl',
96        'start_of_week',
97        'sticky_posts',
98        'stylesheet',
99        'tag_base',
100        'template',
101        'thread_comments',
102        'thread_comments_depth',
103        'thumbnail_crop',
104        'thumbnail_size_h',
105        'thumbnail_size_w',
106        'time_format',
107        'timezone_string',
108        'uninstall_plugins',
109        'upload_path',
110        'upload_url_path',
111        'uploads_use_yearmonth_folders',
112        'use_balanceTags',
113        'use_smilies',
114        'use_trackback',
115        'users_can_register',
116        'wp_attachment_pages_enabled',
117        'wp_force_deactivated_plugins',
118        'wp_notes_notify',
119        'wp_page_for_privacy_policy',
120        'adminhash',
121        'auth_key',
122        'auth_salt',
123        'auto_core_update_notified',
124        'auto_update_plugins',
125        'auto_update_themes',
126        'can_compress_scripts',
127        'category_children',
128        'cron',
129        'current_theme',
130        'customize_stashed_theme_mods',
131        'dashboard_widget_options',
132        'db_upgraded',
133        'finished_updating_comment_type',
134        'fresh_site',
135        'https_detection_errors',
136        'initial_db_version',
137        'logged_in_key',
138        'logged_in_salt',
139        'nav_menu_options',
140        'new_admin_email',
141        'nonce_key',
142        'nonce_salt',
143        'recently_activated',
144        'recovery_keys',
145        'recovery_mode_email_last_sent',
146        'secret_key',
147        'secure_auth_key',
148        'secure_auth_salt',
149        'sidebars_widgets',
150        'site_logo',
151        'stylesheet_root',
152        'template_root',
153        'theme_switched',
154        'theme_switched_via_customizer',
155        'user_count',
156        'wp_calendar_block_has_published_posts',
157        'WPLANG',
158    );
159
160    /**
161     * Jetpack's options that no prefix in PREFIXES covers.
162     *
163     * @var string[]
164     */
165    const JETPACK = array(
166        'carousel_enable_it',
167        'disabled_likes',
168        'disabled_reblogs',
169        'do_activate',
170        'enable_odyssey_stats',
171        'gravatar_disable_hovercards',
172        'highlander_comment_form_prompt',
173        'site_icon_id',
174        'sm_enabled',
175        'stb_enabled',
176        'stc_enabled',
177        'subscription_options',
178        'tiled_galleries',
179        'trusted_ip_header',
180        'verification_services_codes',
181        'wpcc_options',
182    );
183
184    /**
185     * Prefixes of core's per-widget, per-theme and per-site options, and of Jetpack's.
186     *
187     * @var string[]
188     */
189    const PREFIXES = array(
190        'widget_',
191        'theme_mods_',
192        'jetpack',
193        'jp_',
194        'jpsq_',
195        'monitor_receive_notifications',
196        'odyssey_stats',
197        'post_by_email_',
198        'sharing-',
199        'sharedaddy',
200        'social_notifications_',
201        'stats_',
202        'videopress',
203        'wordads_',
204        'wp_mobile_',
205        'wpcom_',
206    );
207
208    /**
209     * Whether an option belongs to WordPress core or Jetpack.
210     *
211     * @param string $name The option name.
212     * @return bool
213     */
214    public static function is_protected( $name ) {
215        // MySQL matches option names case-insensitively, and core trims them, so " SiteURL" is the siteurl row.
216        $name = strtolower( trim( $name ) );
217        if ( in_array( $name, array_map( 'strtolower', array_merge( self::CORE, self::JETPACK ) ), true ) ) {
218            return true;
219        }
220        // Roles are stored per site, as "{prefix}user_roles".
221        if ( str_ends_with( $name, 'user_roles' ) ) {
222            return true;
223        }
224        foreach ( self::PREFIXES as $prefix ) {
225            if ( str_starts_with( $name, $prefix ) ) {
226                return true;
227            }
228        }
229        return false;
230    }
231}