Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
93.33% covered (success)
93.33%
28 / 30
66.67% covered (warning)
66.67%
4 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
Jetpack_Modules_Overrides
93.33% covered (success)
93.33%
28 / 30
66.67% covered (warning)
66.67%
4 / 6
15.07
0.00% covered (danger)
0.00%
0 / 1
 clear_cache
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 do_overrides_exist
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
3
 get_module_override
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 get_overrides
100.00% covered (success)
100.00%
18 / 18
100.00% covered (success)
100.00%
1 / 1
6
 instance
66.67% covered (warning)
66.67%
2 / 3
0.00% covered (danger)
0.00%
0 / 1
2.15
 __construct
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2/**
3 * Special cases for overriding modules.
4 *
5 * @package automattic/jetpack
6 */
7
8use Automattic\Jetpack\Feature_Policy;
9
10/**
11 * Provides methods for dealing with module overrides.
12 *
13 * @since 5.9.0
14 */
15class Jetpack_Modules_Overrides {
16    /**
17     * Used to cache module overrides so that we minimize how many times we apply the
18     * option_jetpack_active_modules filter.
19     *
20     * @var null|array
21     */
22    private $overrides = null;
23
24    /**
25     * Clears the $overrides member used for caching.
26     *
27     * Since get_overrides() can be passed a falsey value to skip caching, this is probably
28     * most useful for clearing cache between tests.
29     *
30     * @return void
31     */
32    public function clear_cache() {
33        $this->overrides = null;
34    }
35
36    /**
37     * Returns true if there is a filter on the jetpack_active_modules option.
38     *
39     * @return bool Whether there is a filter on the jetpack_active_modules option.
40     */
41    public function do_overrides_exist() {
42        if ( method_exists( Feature_Policy::class, 'ensure_hooks' ) ) {
43            Feature_Policy::ensure_hooks();
44        }
45
46        return ( has_filter( 'option_jetpack_active_modules' ) || has_filter( 'jetpack_active_modules' ) );
47    }
48
49    /**
50     * Gets the override for a given module.
51     *
52     * @param string  $module_slug The module's slug.
53     * @param boolean $use_cache   Whether or not cached overrides should be used.
54     *
55     * @return bool|string False if no override for module. 'active' or 'inactive' if there is an override.
56     */
57    public function get_module_override( $module_slug, $use_cache = true ) {
58        $overrides = $this->get_overrides( $use_cache );
59
60        if ( ! isset( $overrides[ $module_slug ] ) ) {
61            return false;
62        }
63
64        return $overrides[ $module_slug ];
65    }
66
67    /**
68     * Returns an array of module overrides where the key is the module slug and the value
69     * is true if the module is forced on and false if the module is forced off.
70     *
71     * @param bool $use_cache Whether or not cached overrides should be used.
72     *
73     * @return array The array of module overrides.
74     */
75    public function get_overrides( $use_cache = true ) {
76        if ( $use_cache && $this->overrides !== null ) {
77            return $this->overrides;
78        }
79
80        if ( ! $this->do_overrides_exist() ) {
81            return array();
82        }
83
84        $available_modules = Jetpack::get_available_modules();
85
86        /**
87         * First, let's get all modules that have been forced on.
88         */
89
90        /** This filter is documented in wp-includes/option.php */
91        $filtered = apply_filters( 'option_jetpack_active_modules', array() );
92
93        /** This filter is documented in class.jetpack.php */
94        $filtered = apply_filters( 'jetpack_active_modules', $filtered );
95
96        $forced_on = array_diff( $filtered, array() );
97
98        /**
99         * Second, let's get all modules forced off.
100         */
101
102        /** This filter is documented in wp-includes/option.php */
103        $filtered = apply_filters( 'option_jetpack_active_modules', $available_modules );
104
105        /** This filter is documented in class.jetpack.php */
106        $filtered = apply_filters( 'jetpack_active_modules', $filtered );
107
108        $forced_off = array_diff( $available_modules, $filtered );
109
110        /**
111         * Last, build the return value.
112         */
113        $return_value = array();
114        foreach ( $forced_on as $on ) {
115            $return_value[ $on ] = 'active';
116        }
117
118        foreach ( $forced_off as $off ) {
119            $return_value[ $off ] = 'inactive';
120        }
121
122        $this->overrides = $return_value;
123
124        return $return_value;
125    }
126
127    /**
128     * A reference to an instance of this class.
129     *
130     * @var Jetpack_Modules_Overrides
131     */
132    private static $instance = null;
133
134    /**
135     * Returns the singleton instance of Jetpack_Modules_Overrides
136     *
137     * @return Jetpack_Modules_Overrides
138     */
139    public static function instance() {
140        if ( self::$instance === null ) {
141            self::$instance = new Jetpack_Modules_Overrides();
142        }
143
144        return self::$instance;
145    }
146
147    /**
148     * Private construct to enforce singleton.
149     */
150    private function __construct() {
151    }
152}