1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* The base Jetpack configuration class file. |
4
|
|
|
* |
5
|
|
|
* @package automattic/jetpack-config |
6
|
|
|
*/ |
7
|
|
|
|
8
|
|
|
namespace Automattic\Jetpack; |
9
|
|
|
|
10
|
|
|
use Automattic\Jetpack\Connection\Manager; |
11
|
|
|
use Automattic\Jetpack\Connection\Plugin; |
12
|
|
|
use Automattic\Jetpack\Plugin\Tracking as Plugin_Tracking; |
13
|
|
|
use Automattic\Jetpack\Sync\Main as Sync_Main; |
14
|
|
|
|
15
|
|
|
/** |
16
|
|
|
* The configuration class. |
17
|
|
|
*/ |
18
|
|
|
class Config { |
19
|
|
|
|
20
|
|
|
const FEATURE_ENSURED = 1; |
21
|
|
|
const FEATURE_NOT_AVAILABLE = 0; |
22
|
|
|
const FEATURE_ALREADY_ENSURED = -1; |
23
|
|
|
|
24
|
|
|
/** |
25
|
|
|
* The initial setting values. |
26
|
|
|
* |
27
|
|
|
* @var Array |
28
|
|
|
*/ |
29
|
|
|
protected $config = array( |
30
|
|
|
'jitm' => false, |
31
|
|
|
'connection' => false, |
32
|
|
|
'sync' => false, |
33
|
|
|
'tracking' => false, |
34
|
|
|
'tos' => false, |
35
|
|
|
); |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* Initialization options stored here. |
39
|
|
|
* |
40
|
|
|
* @var array |
41
|
|
|
*/ |
42
|
|
|
protected $feature_options = array(); |
43
|
|
|
|
44
|
|
|
/** |
45
|
|
|
* Indicates if the configuration is needed. |
46
|
|
|
* If at least one `Config` object was created, the property is set to `true`. |
47
|
|
|
* If no objects were created, the value is `false`. |
48
|
|
|
* |
49
|
|
|
* @var bool |
50
|
|
|
*/ |
51
|
|
|
private static $is_configuration_needed = false; |
52
|
|
|
|
53
|
|
|
/** |
54
|
|
|
* Indicates whether the configuration process has completed. |
55
|
|
|
* |
56
|
|
|
* @var bool |
57
|
|
|
*/ |
58
|
|
|
private static $is_configured = false; |
59
|
|
|
|
60
|
|
|
/** |
61
|
|
|
* Creates the configuration class instance. |
62
|
|
|
*/ |
63
|
|
|
public function __construct() { |
64
|
|
|
/** |
65
|
|
|
* Adding the config handler to run on priority 2 because the class itself is |
66
|
|
|
* being constructed on priority 1. |
67
|
|
|
*/ |
68
|
|
|
add_action( 'plugins_loaded', array( $this, 'on_plugins_loaded' ), 2 ); |
69
|
|
|
|
70
|
|
|
if ( false === self::$is_configuration_needed ) { |
71
|
|
|
// This is the first instance of the class, add the `on_configured` action (we need it to run only once). |
72
|
|
|
add_action( 'plugins_loaded', array( $this, 'on_configured' ), 3 ); |
73
|
|
|
self::$is_configuration_needed = true; |
74
|
|
|
} |
75
|
|
|
} |
76
|
|
|
|
77
|
|
|
/** |
78
|
|
|
* Require a feature to be initialized. It's up to the package consumer to actually add |
79
|
|
|
* the package to their composer project. Declaring a requirement using this method |
80
|
|
|
* instructs the class to initialize it. |
81
|
|
|
* |
82
|
|
|
* @param String $feature the feature slug. |
83
|
|
|
* @param array $options Additional options, optional. |
84
|
|
|
*/ |
85
|
|
|
public function ensure( $feature, array $options = array() ) { |
86
|
|
|
$this->config[ $feature ] = true; |
87
|
|
|
|
88
|
|
|
$this->set_feature_options( $feature, $options ); |
89
|
|
|
} |
90
|
|
|
|
91
|
|
|
/** |
92
|
|
|
* Runs on plugins_loaded hook priority with priority 2. |
93
|
|
|
* |
94
|
|
|
* @action plugins_loaded |
95
|
|
|
*/ |
96
|
|
|
public function on_plugins_loaded() { |
97
|
|
|
if ( $this->config['connection'] ) { |
98
|
|
|
$this->ensure_class( 'Automattic\Jetpack\Connection\Manager' ) |
99
|
|
|
&& $this->ensure_feature( 'connection' ); |
100
|
|
|
} |
101
|
|
|
|
102
|
|
|
if ( $this->config['tracking'] ) { |
103
|
|
|
$this->ensure_class( 'Automattic\Jetpack\Terms_Of_Service' ) |
104
|
|
|
&& $this->ensure_class( 'Automattic\Jetpack\Tracking' ) |
105
|
|
|
&& $this->ensure_feature( 'tracking' ); |
106
|
|
|
} |
107
|
|
|
|
108
|
|
|
if ( $this->config['sync'] ) { |
109
|
|
|
$this->ensure_class( 'Automattic\Jetpack\Sync\Main' ) |
110
|
|
|
&& $this->ensure_feature( 'sync' ); |
111
|
|
|
} |
112
|
|
|
|
113
|
|
|
if ( $this->config['jitm'] ) { |
114
|
|
|
$this->ensure_class( 'Automattic\Jetpack\JITM' ) |
115
|
|
|
&& $this->ensure_feature( 'jitm' ); |
116
|
|
|
} |
117
|
|
|
} |
118
|
|
|
|
119
|
|
|
/** |
120
|
|
|
* The method is called when configuration is completed. |
121
|
|
|
* `Config` is done, so we set the flag.. |
122
|
|
|
*/ |
123
|
|
|
public static function on_configured() { |
124
|
|
|
self::$is_configured = true; |
125
|
|
|
} |
126
|
|
|
|
127
|
|
|
/** |
128
|
|
|
* The method can be used to check if the `Config` needs to be run. |
129
|
|
|
* |
130
|
|
|
* @return bool Returns `true` if configuration has completed, or not needed (no instances were created); `false` if configuration is pending. |
131
|
|
|
*/ |
132
|
|
|
public static function is_configured() { |
133
|
|
|
return ! self::$is_configuration_needed || self::$is_configured; |
134
|
|
|
} |
135
|
|
|
|
136
|
|
|
/** |
137
|
|
|
* Returns true if the required class is available and alerts the user if it's not available |
138
|
|
|
* in case the site is in debug mode. |
139
|
|
|
* |
140
|
|
|
* @param String $classname a fully qualified class name. |
141
|
|
|
* @return Boolean whether the class is available. |
142
|
|
|
*/ |
143
|
|
|
protected function ensure_class( $classname ) { |
144
|
|
|
$available = class_exists( $classname ); |
145
|
|
|
|
146
|
|
|
if ( ! $available && defined( 'WP_DEBUG' ) && WP_DEBUG ) { |
147
|
|
|
trigger_error( // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error |
148
|
|
|
sprintf( |
149
|
|
|
/* translators: %1$s is a PHP class name. */ |
150
|
|
|
esc_html__( |
151
|
|
|
'Unable to load class %1$s. Please add the package that contains it using composer and make sure you are requiring the Jetpack autoloader', |
152
|
|
|
'jetpack' |
153
|
|
|
), |
154
|
|
|
esc_html( $classname ) |
155
|
|
|
), |
156
|
|
|
E_USER_NOTICE |
157
|
|
|
); |
158
|
|
|
} |
159
|
|
|
|
160
|
|
|
return $available; |
161
|
|
|
} |
162
|
|
|
|
163
|
|
|
/** |
164
|
|
|
* Ensures a feature is enabled, sets it up if it hasn't already been set up. |
165
|
|
|
* Run the options method (if exists) every time the method is called. |
166
|
|
|
* |
167
|
|
|
* @param String $feature slug of the feature. |
168
|
|
|
* @return Integer either FEATURE_ENSURED, FEATURE_ALREADY_ENSURED or FEATURE_NOT_AVAILABLE constants. |
169
|
|
|
*/ |
170
|
|
|
protected function ensure_feature( $feature ) { |
171
|
|
|
$method = 'enable_' . $feature; |
172
|
|
|
if ( ! method_exists( $this, $method ) ) { |
173
|
|
|
return self::FEATURE_NOT_AVAILABLE; |
174
|
|
|
} |
175
|
|
|
|
176
|
|
|
$method_options = 'ensure_options_' . $feature; |
177
|
|
|
if ( method_exists( $this, $method_options ) ) { |
178
|
|
|
$this->{ $method_options }(); |
179
|
|
|
} |
180
|
|
|
|
181
|
|
|
if ( did_action( 'jetpack_feature_' . $feature . '_enabled' ) ) { |
182
|
|
|
return self::FEATURE_ALREADY_ENSURED; |
183
|
|
|
} |
184
|
|
|
|
185
|
|
|
$this->{ $method }(); |
186
|
|
|
|
187
|
|
|
/** |
188
|
|
|
* Fires when a specific Jetpack package feature is initalized using the Config package. |
189
|
|
|
* |
190
|
|
|
* @since 8.2.0 |
191
|
|
|
*/ |
192
|
|
|
do_action( 'jetpack_feature_' . $feature . '_enabled' ); |
193
|
|
|
|
194
|
|
|
return self::FEATURE_ENSURED; |
195
|
|
|
} |
196
|
|
|
|
197
|
|
|
/** |
198
|
|
|
* Dummy method to enable Terms of Service. |
199
|
|
|
*/ |
200
|
|
|
protected function enable_tos() { |
201
|
|
|
return true; |
202
|
|
|
} |
203
|
|
|
|
204
|
|
|
/** |
205
|
|
|
* Enables the tracking feature. Depends on the Terms of Service package, so enables it too. |
206
|
|
|
*/ |
207
|
|
|
protected function enable_tracking() { |
208
|
|
|
|
209
|
|
|
// Enabling dependencies. |
210
|
|
|
$this->ensure_feature( 'tos' ); |
211
|
|
|
|
212
|
|
|
$terms_of_service = new Terms_Of_Service(); |
213
|
|
|
$tracking = new Plugin_Tracking(); |
214
|
|
|
if ( $terms_of_service->has_agreed() ) { |
215
|
|
|
add_action( 'init', array( $tracking, 'init' ) ); |
216
|
|
|
} else { |
217
|
|
|
/** |
218
|
|
|
* Initialize tracking right after the user agrees to the terms of service. |
219
|
|
|
*/ |
220
|
|
|
add_action( 'jetpack_agreed_to_terms_of_service', array( $tracking, 'init' ) ); |
221
|
|
|
} |
222
|
|
|
|
223
|
|
|
return true; |
224
|
|
|
} |
225
|
|
|
|
226
|
|
|
/** |
227
|
|
|
* Enables the JITM feature. |
228
|
|
|
*/ |
229
|
|
|
protected function enable_jitm() { |
230
|
|
|
JITM::configure(); |
231
|
|
|
|
232
|
|
|
return true; |
233
|
|
|
} |
234
|
|
|
|
235
|
|
|
/** |
236
|
|
|
* Enables the Sync feature. |
237
|
|
|
*/ |
238
|
|
|
protected function enable_sync() { |
239
|
|
|
Sync_Main::configure(); |
240
|
|
|
|
241
|
|
|
return true; |
242
|
|
|
} |
243
|
|
|
|
244
|
|
|
/** |
245
|
|
|
* Enables the Connection feature. |
246
|
|
|
*/ |
247
|
|
|
protected function enable_connection() { |
248
|
|
|
Manager::configure(); |
249
|
|
|
|
250
|
|
|
return true; |
251
|
|
|
} |
252
|
|
|
|
253
|
|
|
/** |
254
|
|
|
* Setup the Connection options. |
255
|
|
|
*/ |
256
|
|
|
protected function ensure_options_connection() { |
257
|
|
|
$options = $this->get_feature_options( 'connection' ); |
258
|
|
|
|
259
|
|
|
if ( ! empty( $options['slug'] ) ) { |
260
|
|
|
// The `slug` and `name` are removed from the options because they need to be passed as arguments. |
261
|
|
|
$slug = $options['slug']; |
262
|
|
|
unset( $options['slug'] ); |
263
|
|
|
|
264
|
|
|
$name = $slug; |
265
|
|
|
if ( ! empty( $options['name'] ) ) { |
266
|
|
|
$name = $options['name']; |
267
|
|
|
unset( $options['name'] ); |
268
|
|
|
} |
269
|
|
|
|
270
|
|
|
( new Plugin( $slug ) )->add( $name, $options ); |
271
|
|
|
} |
272
|
|
|
|
273
|
|
|
return true; |
274
|
|
|
} |
275
|
|
|
|
276
|
|
|
/** |
277
|
|
|
* Temporary save initialization options for a feature. |
278
|
|
|
* |
279
|
|
|
* @param string $feature The feature slug. |
280
|
|
|
* @param array $options The options. |
281
|
|
|
* |
282
|
|
|
* @return bool |
283
|
|
|
*/ |
284
|
|
|
protected function set_feature_options( $feature, array $options ) { |
285
|
|
|
if ( $options ) { |
|
|
|
|
286
|
|
|
$this->feature_options[ $feature ] = $options; |
287
|
|
|
} |
288
|
|
|
|
289
|
|
|
return true; |
290
|
|
|
} |
291
|
|
|
|
292
|
|
|
/** |
293
|
|
|
* Get initialization options for a feature from the temporary storage. |
294
|
|
|
* |
295
|
|
|
* @param string $feature The feature slug. |
296
|
|
|
* |
297
|
|
|
* @return array |
298
|
|
|
*/ |
299
|
|
|
protected function get_feature_options( $feature ) { |
300
|
|
|
return empty( $this->feature_options[ $feature ] ) ? array() : $this->feature_options[ $feature ]; |
301
|
|
|
} |
302
|
|
|
|
303
|
|
|
} |
304
|
|
|
|
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.