Completed
Push — add/going-backwards ( 3440c3 )
by
unknown
448:15 queued 439:43
created

Config::ensure_options_back()   A

Complexity

Conditions 5
Paths 4

Size

Total Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
nc 4
nop 0
dl 0
loc 15
rs 9.4555
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
/*
11
 * The Config package does not require the composer packages that
12
 * contain the package classes shown below. The consumer plugin
13
 * must require the corresponding packages to use these features.
14
 */
15
16
use Automattic\Jetpack\Back\Compatibility;
17
use Automattic\Jetpack\Connection\Manager;
18
use Automattic\Jetpack\Connection\Plugin;
19
use Automattic\Jetpack\JITM as JITM;
20
use Automattic\Jetpack\JITMS\JITM as JITMS_JITM;
21
use Automattic\Jetpack\Sync\Main as Sync_Main;
22
23
/**
24
 * The configuration class.
25
 */
26
class Config {
27
28
	const FEATURE_ENSURED         = 1;
29
	const FEATURE_NOT_AVAILABLE   = 0;
30
	const FEATURE_ALREADY_ENSURED = -1;
31
32
	/**
33
	 * The initial setting values.
34
	 *
35
	 * @var Array
36
	 */
37
	protected $config = array(
38
		'jitm'       => false,
39
		'connection' => false,
40
		'sync'       => false,
41
		'back'       => false,
42
	);
43
44
	/**
45
	 * Initialization options stored here.
46
	 *
47
	 * @var array
48
	 */
49
	protected $feature_options = array();
50
51
	/**
52
	 * Creates the configuration class instance.
53
	 */
54
	public function __construct() {
55
		/**
56
		 * Adding the config handler to run on priority 2 because the class itself is
57
		 * being constructed on priority 1.
58
		 */
59
		add_action( 'plugins_loaded', array( $this, 'on_plugins_loaded' ), 2 );
60
61
	}
62
63
	/**
64
	 * Require a feature to be initialized. It's up to the package consumer to actually add
65
	 * the package to their composer project. Declaring a requirement using this method
66
	 * instructs the class to initialize it.
67
	 *
68
	 * @param String $feature the feature slug.
69
	 * @param array  $options Additional options, optional.
70
	 */
71
	public function ensure( $feature, array $options = array() ) {
72
		$this->config[ $feature ] = true;
73
74
		$this->set_feature_options( $feature, $options );
75
	}
76
77
	/**
78
	 * Runs on plugins_loaded hook priority with priority 2.
79
	 *
80
	 * @action plugins_loaded
81
	 */
82
	public function on_plugins_loaded() {
83
		if ( $this->config['connection'] ) {
84
			$this->ensure_class( 'Automattic\Jetpack\Connection\Manager' )
85
				&& $this->ensure_feature( 'connection' );
86
		}
87
88
		if ( $this->config['sync'] ) {
89
			$this->ensure_class( 'Automattic\Jetpack\Sync\Main' )
90
				&& $this->ensure_feature( 'sync' );
91
		}
92
93
		if ( $this->config['jitm'] ) {
94
			// Check for the JITM class in both namespaces. The namespace was changed in jetpack-jitm v1.6.
95
			( $this->ensure_class( 'Automattic\Jetpack\JITMS\JITM', false )
96
				|| $this->ensure_class( 'Automattic\Jetpack\JITM' ) )
97
			&& $this->ensure_feature( 'jitm' );
98
		}
99
100
		if ( $this->config['back'] ) {
101
			$this->ensure_class( 'Automattic\Jetpack\Back\Compatibility' )
102
				&& $this->ensure_feature( 'back' );
103
		}
104
	}
105
106
	/**
107
	 * Returns true if the required class is available and alerts the user if it's not available
108
	 * in case the site is in debug mode.
109
	 *
110
	 * @param String  $classname a fully qualified class name.
111
	 * @param Boolean $log_notice whether the E_USER_NOTICE should be generated if the class is not found.
112
	 *
113
	 * @return Boolean whether the class is available.
114
	 */
115
	protected function ensure_class( $classname, $log_notice = true ) {
116
		$available = class_exists( $classname );
117
118
		if ( $log_notice && ! $available && defined( 'WP_DEBUG' ) && WP_DEBUG ) {
119
			trigger_error( // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error
120
				sprintf(
121
					/* translators: %1$s is a PHP class name. */
122
					esc_html__(
123
						'Unable to load class %1$s. Please add the package that contains it using composer and make sure you are requiring the Jetpack autoloader',
124
						'jetpack'
125
					),
126
					esc_html( $classname )
127
				),
128
				E_USER_NOTICE
129
			);
130
		}
131
132
		return $available;
133
	}
134
135
	/**
136
	 * Ensures a feature is enabled, sets it up if it hasn't already been set up.
137
	 * Run the options method (if exists) every time the method is called.
138
	 *
139
	 * @param String $feature slug of the feature.
140
	 * @return Integer either FEATURE_ENSURED, FEATURE_ALREADY_ENSURED or FEATURE_NOT_AVAILABLE constants.
141
	 */
142
	protected function ensure_feature( $feature ) {
143
		$method = 'enable_' . $feature;
144
		if ( ! method_exists( $this, $method ) ) {
145
			return self::FEATURE_NOT_AVAILABLE;
146
		}
147
148
		$method_options = 'ensure_options_' . $feature;
149
		if ( method_exists( $this, $method_options ) ) {
150
			$this->{ $method_options }();
151
		}
152
153
		if ( did_action( 'jetpack_feature_' . $feature . '_enabled' ) ) {
154
			return self::FEATURE_ALREADY_ENSURED;
155
		}
156
157
		$this->{ $method }();
158
159
		/**
160
		 * Fires when a specific Jetpack package feature is initalized using the Config package.
161
		 *
162
		 * @since 8.2.0
163
		 */
164
		do_action( 'jetpack_feature_' . $feature . '_enabled' );
165
166
		return self::FEATURE_ENSURED;
167
	}
168
169
	/**
170
	 * Enables the JITM feature.
171
	 */
172
	protected function enable_jitm() {
173
		if ( class_exists( 'Automattic\Jetpack\JITMS\JITM' ) ) {
174
			JITMS_JITM::configure();
175
		} else {
176
			// Provides compatibility with jetpack-jitm <v1.6.
177
			JITM::configure();
178
		}
179
180
		return true;
181
	}
182
183
	/**
184
	 * Enables the Sync feature.
185
	 */
186
	protected function enable_sync() {
187
		Sync_Main::configure();
188
189
		return true;
190
	}
191
192
	/**
193
	 * Enable the backward compatibility package.
194
	 */
195
	protected function enable_back() {
196
		// Nothing to do here.
197
	}
198
199
	/**
200
	 * Setup the backward compatibility features.
201
	 */
202
	protected function ensure_options_back() {
203
		$options = $this->get_feature_options( 'back' );
204
205
		if ( empty( $options['slug'] ) ) {
206
			return;
207
		}
208
209
		Compatibility::add_plugin( $options['slug'] );
210
211
		if ( ! empty( $options['features'] ) && is_array( $options['features'] ) ) {
212
			foreach ( $options['features'] as $feature ) {
213
				Compatibility::add_feature( $options['slug'], $feature );
214
			}
215
		}
216
	}
217
218
	/**
219
	 * Enables the Connection feature.
220
	 */
221
	protected function enable_connection() {
222
		Manager::configure();
223
224
		return true;
225
	}
226
227
	/**
228
	 * Setup the Connection options.
229
	 */
230
	protected function ensure_options_connection() {
231
		$options = $this->get_feature_options( 'connection' );
232
233
		if ( ! empty( $options['slug'] ) ) {
234
			// The `slug` and `name` are removed from the options because they need to be passed as arguments.
235
			$slug = $options['slug'];
236
			unset( $options['slug'] );
237
238
			$name = $slug;
239
			if ( ! empty( $options['name'] ) ) {
240
				$name = $options['name'];
241
				unset( $options['name'] );
242
			}
243
244
			( new Plugin( $slug ) )->add( $name, $options );
245
246
			// Providing backward compatibility for the backward compatibility package.
247
			Compatibility::add_plugin( $slug );
248
		}
249
250
		return true;
251
	}
252
253
	/**
254
	 * Temporary save initialization options for a feature.
255
	 *
256
	 * @param string $feature The feature slug.
257
	 * @param array  $options The options.
258
	 *
259
	 * @return bool
260
	 */
261
	protected function set_feature_options( $feature, array $options ) {
262
		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...
263
			$this->feature_options[ $feature ] = $options;
264
		}
265
266
		return true;
267
	}
268
269
	/**
270
	 * Get initialization options for a feature from the temporary storage.
271
	 *
272
	 * @param string $feature The feature slug.
273
	 *
274
	 * @return array
275
	 */
276
	protected function get_feature_options( $feature ) {
277
		return empty( $this->feature_options[ $feature ] ) ? array() : $this->feature_options[ $feature ];
278
	}
279
280
}
281