Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
5.88% covered (danger)
5.88%
4 / 68
16.67% covered (danger)
16.67%
3 / 18
CRAP
0.00% covered (danger)
0.00%
0 / 1
Constants
4.55% covered (danger)
4.55%
3 / 66
16.67% covered (danger)
16.67%
3 / 18
1100.43
0.00% covered (danger)
0.00%
0 / 1
 name
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 init_listeners
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 init_full_sync_listeners
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 init_before_send
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 reset_data
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 set_constants_whitelist
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 get_constants_whitelist
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 enqueue_full_sync_actions
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 send_full_sync_actions
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
6
 estimate_full_sync_actions
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 get_full_sync_actions
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 maybe_sync_constants
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
42
 get_all_constants
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
2
 get_constant
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 expand_constants
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
12
 total
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 get_objects_by_id
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
42
 get_object_by_id
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
20
1<?php
2/**
3 * Constants sync module.
4 *
5 * @package automattic/jetpack-sync
6 */
7
8namespace Automattic\Jetpack\Sync\Modules;
9
10use Automattic\Jetpack\Sync\Defaults;
11
12if ( ! defined( 'ABSPATH' ) ) {
13    exit( 0 );
14}
15
16/**
17 * Class to handle sync for constants.
18 */
19class Constants extends Module {
20    /**
21     * Name of the constants checksum option.
22     *
23     * @var string
24     */
25    const CONSTANTS_CHECKSUM_OPTION_NAME = 'jetpack_constants_sync_checksum';
26
27    /**
28     * Name of the transient for locking constants.
29     *
30     * @var string
31     */
32    const CONSTANTS_AWAIT_TRANSIENT_NAME = 'jetpack_sync_constants_await';
33
34    /**
35     * Constants whitelist array.
36     *
37     * @var array
38     */
39    public $constants_whitelist;
40
41    /**
42     * Sync module name.
43     *
44     * @access public
45     *
46     * @return string
47     */
48    public function name() {
49        return 'constants';
50    }
51
52    /**
53     * Initialize constants action listeners.
54     *
55     * @access public
56     *
57     * @param callable $callable Action handler callable.
58     */
59    public function init_listeners( $callable ) {
60        add_action( 'jetpack_sync_constant', $callable, 10, 2 );
61    }
62
63    /**
64     * Initialize constants action listeners for full sync.
65     *
66     * @access public
67     *
68     * @param callable $callable Action handler callable.
69     */
70    public function init_full_sync_listeners( $callable ) {
71        add_action( 'jetpack_full_sync_constants', $callable );
72    }
73
74    /**
75     * Initialize the module in the sender.
76     *
77     * @access public
78     */
79    public function init_before_send() {
80        add_action( 'jetpack_sync_before_send_queue_sync', array( $this, 'maybe_sync_constants' ) );
81
82        // Full sync.
83        add_filter( 'jetpack_sync_before_send_jetpack_full_sync_constants', array( $this, 'expand_constants' ) );
84    }
85
86    /**
87     * Perform module cleanup.
88     * Deletes any transients and options that this module uses.
89     * Usually triggered when uninstalling the plugin.
90     *
91     * @access public
92     */
93    public function reset_data() {
94        delete_option( self::CONSTANTS_CHECKSUM_OPTION_NAME );
95        delete_transient( self::CONSTANTS_AWAIT_TRANSIENT_NAME );
96    }
97
98    /**
99     * Set the constants whitelist.
100     *
101     * @access public
102     * @todo We don't seem to use this one. Should we remove it?
103     *
104     * @param array $constants The new constants whitelist.
105     */
106    public function set_constants_whitelist( $constants ) {
107        $this->constants_whitelist = $constants;
108    }
109
110    /**
111     * Get the constants whitelist.
112     *
113     * @access public
114     *
115     * @return array The constants whitelist.
116     */
117    public function get_constants_whitelist() {
118        return Defaults::get_constants_whitelist();
119    }
120
121    /**
122     * Enqueue the constants actions for full sync.
123     *
124     * @access public
125     *
126     * @param array   $config Full sync configuration for this sync module.
127     * @param int     $max_items_to_enqueue Maximum number of items to enqueue.
128     * @param boolean $state True if full sync has finished enqueueing this module, false otherwise.
129     *
130     * @return array Number of actions enqueued, and next module state.
131     */
132    public function enqueue_full_sync_actions( $config, $max_items_to_enqueue, $state ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
133        /**
134         * Tells the client to sync all constants to the server
135         *
136         * @param boolean Whether to expand constants (should always be true)
137         *
138         * @since 1.6.3
139         * @since-jetpack 4.2.0
140         */
141        do_action( 'jetpack_full_sync_constants', true );
142
143        // The number of actions enqueued, and next module state (true == done).
144        return array( 1, true );
145    }
146
147    /**
148     * Send the constants actions for full sync.
149     *
150     * @access public
151     *
152     * @param array $config Full sync configuration for this sync module.
153     * @param array $status This module Full Sync status.
154     * @param int   $send_until The timestamp until the current request can send.
155     * @param int   $started The timestamp when the full sync started.
156     *
157     * @return array This module Full Sync status.
158     */
159    public function send_full_sync_actions( $config, $status, $send_until, $started ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
160        // we call this instead of do_action when sending immediately.
161        $result = $this->send_action( 'jetpack_full_sync_constants', array( true ) );
162
163        if ( is_wp_error( $result ) ) {
164            $status['error'] = true;
165            return $status;
166        }
167        $status['finished'] = true;
168        $status['sent']     = $status['total'];
169        return $status;
170    }
171
172    /**
173     * Retrieve an estimated number of actions that will be enqueued.
174     *
175     * @access public
176     *
177     * @param array $config Full sync configuration for this sync module.
178     *
179     * @return int Number of items yet to be enqueued.
180     */
181    public function estimate_full_sync_actions( $config ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
182        return 1;
183    }
184
185    /**
186     * Retrieve the actions that will be sent for this module during a full sync.
187     *
188     * @access public
189     *
190     * @return array Full sync actions of this module.
191     */
192    public function get_full_sync_actions() {
193        return array( 'jetpack_full_sync_constants' );
194    }
195
196    /**
197     * Sync the constants if we're supposed to.
198     *
199     * @access public
200     */
201    public function maybe_sync_constants() {
202        if ( get_transient( self::CONSTANTS_AWAIT_TRANSIENT_NAME ) ) {
203            return;
204        }
205
206        set_transient( self::CONSTANTS_AWAIT_TRANSIENT_NAME, microtime( true ), Defaults::$default_sync_constants_wait_time );
207
208        $constants = $this->get_all_constants();
209        if ( empty( $constants ) ) {
210            return;
211        }
212
213        $constants_checksums = (array) get_option( self::CONSTANTS_CHECKSUM_OPTION_NAME, array() );
214
215        foreach ( $constants as $name => $value ) {
216            $checksum = $this->get_check_sum( $value );
217            // Explicitly not using Identical comparison as get_option returns a string.
218            if ( ! $this->still_valid_checksum( $constants_checksums, $name, $checksum ) && $value !== null ) {
219                /**
220                 * Tells the client to sync a constant to the server
221                 *
222                 * @param string The name of the constant
223                 * @param mixed The value of the constant
224                 *
225                 * @since 1.6.3
226                 * @since-jetpack 4.2.0
227                 */
228                do_action( 'jetpack_sync_constant', $name, $value );
229                $constants_checksums[ $name ] = $checksum;
230            } else {
231                $constants_checksums[ $name ] = $checksum;
232            }
233        }
234        update_option( self::CONSTANTS_CHECKSUM_OPTION_NAME, $constants_checksums );
235    }
236
237    /**
238     * Retrieve all constants as per the current constants whitelist.
239     * Public so that we don't have to store an option for each constant.
240     *
241     * @access public
242     *
243     * @return array All constants.
244     */
245    public function get_all_constants() {
246        $constants_whitelist = $this->get_constants_whitelist();
247
248        return array_combine(
249            $constants_whitelist,
250            array_map( array( $this, 'get_constant' ), $constants_whitelist )
251        );
252    }
253
254    /**
255     * Retrieve the value of a constant.
256     * Used as a wrapper to standartize access to constants.
257     *
258     * @access private
259     *
260     * @param string $constant Constant name.
261     *
262     * @return mixed Return value of the constant.
263     */
264    private function get_constant( $constant ) {
265        return ( defined( $constant ) ) ?
266            constant( $constant )
267            : null;
268    }
269
270    /**
271     * Expand the constants within a hook before they are serialized and sent to the server.
272     *
273     * @access public
274     *
275     * @param array $args The hook parameters.
276     *
277     * @return array $args The hook parameters.
278     */
279    public function expand_constants( $args ) {
280        if ( $args[0] ) {
281            $constants           = $this->get_all_constants();
282            $constants_checksums = array();
283            foreach ( $constants as $name => $value ) {
284                $constants_checksums[ $name ] = $this->get_check_sum( $value );
285            }
286            update_option( self::CONSTANTS_CHECKSUM_OPTION_NAME, $constants_checksums );
287
288            return $constants;
289        }
290
291        return $args;
292    }
293
294    /**
295     * Return Total number of objects.
296     *
297     * @param array $config Full Sync config.
298     *
299     * @return int total
300     */
301    public function total( $config ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
302        return count( $this->get_constants_whitelist() );
303    }
304
305    /**
306     * Retrieve a set of constants by their IDs.
307     *
308     * @access public
309     *
310     * @param string $object_type Object type.
311     * @param array  $ids         Object IDs.
312     * @return array Array of objects.
313     */
314    public function get_objects_by_id( $object_type, $ids ) {
315        if ( empty( $ids ) || empty( $object_type ) || 'constant' !== $object_type ) {
316            return array();
317        }
318
319        $objects = array();
320        foreach ( (array) $ids as $id ) {
321            $object = $this->get_object_by_id( $object_type, $id );
322
323            if ( 'all' === $id ) {
324                // If all was requested it contains all options and can simply be returned.
325                return $object;
326            }
327            $objects[ $id ] = $object;
328        }
329
330        return $objects;
331    }
332
333    /**
334     * Retrieve a constant by its name.
335     *
336     * @access public
337     *
338     * @param string $object_type Type of the sync object.
339     * @param string $id          ID of the sync object.
340     * @return mixed              Value of Constant.
341     */
342    public function get_object_by_id( $object_type, $id ) {
343        if ( 'constant' === $object_type ) {
344
345            // Only whitelisted constants can be returned.
346            if ( in_array( $id, $this->get_constants_whitelist(), true ) ) {
347                return $this->get_constant( $id );
348            } elseif ( 'all' === $id ) {
349                return $this->get_all_constants();
350            }
351        }
352
353        return false;
354    }
355}