Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
5.88% covered (danger)
5.88%
2 / 34
33.33% covered (danger)
33.33%
1 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
Settings
6.25% covered (danger)
6.25%
2 / 32
33.33% covered (danger)
33.33%
1 / 3
47.37
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 settings_register
0.00% covered (danger)
0.00%
0 / 28
0.00% covered (danger)
0.00%
0 / 1
12
 sanitize_ai_answers_enabled
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
3
1<?php
2/**
3 * Jetpack Search Overlay Settings
4 *
5 * @package automattic/jetpack-search
6 */
7
8namespace Automattic\Jetpack\Search;
9
10// Exit if file is accessed directly.
11if ( ! defined( 'ABSPATH' ) ) {
12    exit( 0 );
13}
14
15/**
16 * Class to initialize search settings on the site.
17 *
18 * 1. Settings are synced to WPCOM according to `Automattic\Jetpack\Sync\Modules\Search::$options_to_sync`.
19 * 2. All synced options must also be explicitly whitelisted and sanitized on WPCOM; see `PCYsg-sBM-p2`.
20 *
21 * @phan-constructor-used-for-side-effects
22 */
23class Settings {
24
25    /**
26     * Class initialization.
27     */
28    public function __construct() {
29        add_action( 'admin_init', array( $this, 'settings_register' ) );
30        add_action( 'rest_api_init', array( $this, 'settings_register' ) );
31    }
32
33    /**
34     * Register requisite settings.
35     *
36     * @since 9.x.x
37     */
38    public function settings_register() {
39        // NOTE: This contains significant code overlap with class-jetpack-search-customize.
40        $setting_prefix         = Options::OPTION_PREFIX;
41        $settings               = array(
42            array( $setting_prefix . 'ai_prompt_override', 'string', '' ),
43            array( $setting_prefix . 'color_theme', 'string', 'light' ),
44            array( $setting_prefix . 'result_format', 'string', 'minimal' ),
45            array( $setting_prefix . 'default_sort', 'string', 'relevance' ),
46            array( $setting_prefix . 'overlay_trigger', 'string', Options::DEFAULT_OVERLAY_TRIGGER ),
47            array( $setting_prefix . 'excluded_post_types', 'string', '' ),
48            array( $setting_prefix . 'highlight_color', 'string', '#FFC' ),
49            array( $setting_prefix . 'enable_sort', 'boolean', true ),
50            array( $setting_prefix . 'inf_scroll', 'boolean', true ),
51            array( $setting_prefix . 'filtering_opens_overlay', 'boolean', true ),
52            array( $setting_prefix . 'show_post_date', 'boolean', true ),
53            array( $setting_prefix . 'show_product_price', 'boolean', true ),
54            array( $setting_prefix . 'show_powered_by', 'boolean', true ),
55            array( $setting_prefix . 'ai_answers_enabled', 'boolean', false ),
56            array( $setting_prefix . 'suggestions_enabled', 'boolean', false ),
57        );
58        $ai_answers_enabled_key = $setting_prefix . 'ai_answers_enabled';
59
60        foreach ( $settings as $value ) {
61            $args = array(
62                'default'      => $value[2],
63                'show_in_rest' => true,
64                'type'         => $value[1],
65            );
66
67            // Also reachable via WordPress core's generic /wp/v2/settings route,
68            // which the plan-aware write gates elsewhere (REST_Controller, the
69            // plugin's AI feature settings endpoint) don't cover.
70            if ( $ai_answers_enabled_key === $value[0] ) {
71                $args['sanitize_callback'] = array( __CLASS__, 'sanitize_ai_answers_enabled' );
72            }
73
74            register_setting( 'options', $value[0], $args );
75        }
76    }
77
78    /**
79     * Reject enabling AI Answers on a site whose plan doesn't support it.
80     *
81     * @param mixed $value Raw value being saved.
82     * @return bool
83     */
84    public static function sanitize_ai_answers_enabled( $value ) {
85        $value = rest_sanitize_boolean( $value );
86        return $value && ! Search_Blocks::supports_paid_search() ? false : $value;
87    }
88}