Completed
Push — add/setup-wizard-site-income-q... ( 458557...1155d5 )
by
unknown
17:17 queued 10:10
created

Config::ensure_options_connection()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
nc 3
nop 0
dl 0
loc 19
rs 9.6333
c 0
b 0
f 0
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 ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $options of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

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.

Loading history...
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