Completed
Push — feature/update_autoloader ( e03353...5a6eeb )
by
unknown
22:10 queued 15:28
created

functions.php ➔ get_current_plugin()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 0
dl 0
loc 9
rs 9.9666
c 0
b 0
f 0
1
<?php
2
/* HEADER */ // phpcs:ignore
3
4
global $jetpack_packages_classmap;
5
global $jetpack_packages_filemap;
6
7
if ( ! is_array( $jetpack_packages_classmap ) ) {
8
	$jetpack_packages_classmap = array();
9
}
10
11
if ( ! is_array( $jetpack_packages_filemap ) ) {
12
	$jetpack_packages_filemap = array();
13
}
14
15
/**
16
 * Adds the version of a package to the $jetpack_packages global array so that
17
 * the autoloader is able to find it.
18
 *
19
 * @param string $class_name Name of the class that you want to autoload.
20
 * @param string $version Version of the class.
21
 * @param string $path Absolute path to the class so that we can load it.
22
 */
23 View Code Duplication
function enqueue_package_class( $class_name, $version, $path ) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
24
	global $jetpack_packages_classmap;
25
26
	if ( ! isset( $jetpack_packages_classmap[ $class_name ] ) ) {
27
		$jetpack_packages_classmap[ $class_name ] = array(
28
			'version' => $version,
29
			'path'    => $path,
30
		);
31
32
		return;
33
	}
34
	// If we have a @dev version set always use that one!
35
	if ( 'dev-' === substr( $jetpack_packages_classmap[ $class_name ]['version'], 0, 4 ) ) {
36
		return;
37
	}
38
39
	// Always favour the @dev version. Since that version is the same as bleeding edge.
40
	// We need to make sure that we don't do this in production!
41
	if ( 'dev-' === substr( $version, 0, 4 ) ) {
42
		$jetpack_packages_classmap[ $class_name ] = array(
43
			'version' => $version,
44
			'path'    => $path,
45
		);
46
47
		return;
48
	}
49
	// Set the latest version!
50
	if ( version_compare( $jetpack_packages_classmap[ $class_name ]['version'], $version, '<' ) ) {
51
		$jetpack_packages_classmap[ $class_name ] = array(
52
			'version' => $version,
53
			'path'    => $path,
54
		);
55
	}
56
}
57
58
/**
59
 * Adds the version of a package file to the $jetpack_packages_filemap global array so that
60
 * we can load the most recent version after 'plugins_loaded'.
61
 *
62
 * @param string $file_identifier Unique id to file assigned by composer based on package name and filename.
63
 * @param string $version Version of the file.
64
 * @param string $path Absolute path to the file so that we can load it.
65
 */
66 View Code Duplication
function enqueue_package_file( $file_identifier, $version, $path ) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
67
	global $jetpack_packages_filemap;
68
69
	if ( ! isset( $jetpack_packages_filemap[ $file_identifier ] ) ) {
70
		$jetpack_packages_filemap[ $file_identifier ] = array(
71
			'version' => $version,
72
			'path'    => $path,
73
		);
74
75
		return;
76
	}
77
	// If we have a @dev version set always use that one!
78
	if ( 'dev-' === substr( $jetpack_packages_filemap[ $file_identifier ]['version'], 0, 4 ) ) {
79
		return;
80
	}
81
82
	// Always favour the @dev version. Since that version is the same as bleeding edge.
83
	// We need to make sure that we don't do this in production!
84
	if ( 'dev-' === substr( $version, 0, 4 ) ) {
85
		$jetpack_packages_filemap[ $file_identifier ] = array(
86
			'version' => $version,
87
			'path'    => $path,
88
		);
89
90
		return;
91
	}
92
	// Set the latest version!
93
	if ( version_compare( $jetpack_packages_filemap[ $file_identifier ]['version'], $version, '<' ) ) {
94
		$jetpack_packages_filemap[ $file_identifier ] = array(
95
			'version' => $version,
96
			'path'    => $path,
97
		);
98
	}
99
}
100
101
/**
102
 * Include latest version of all enqueued files. Should be called after all plugins are loaded.
103
 */
104
function file_loader() {
105
	global $jetpack_packages_filemap;
106
	foreach ( $jetpack_packages_filemap as $file_identifier => $file_data ) {
107
		if ( empty( $GLOBALS['__composer_autoload_files'][ $file_identifier ] ) ) {
108
			require_once $file_data['path'];
109
110
			$GLOBALS['__composer_autoload_files'][ $file_identifier ] = true;
111
		}
112
	}
113
}
114
115
/**
116
 * Used for autoloading jetpack packages.
117
 *
118
 * @param string $class_name Class Name to load.
119
 */
120
function autoloader( $class_name ) {
121
	global $jetpack_packages_classmap;
122
123
	if ( isset( $jetpack_packages_classmap[ $class_name ] ) ) {
124
		if ( file_exists( $jetpack_packages_classmap[ $class_name ]['path'] ) ) {
125
			require_once $jetpack_packages_classmap[ $class_name ]['path'];
126
			return true;
127
		}
128
	}
129
130
	return false;
131
}
132
133
/**
134
 * Used for running the code that initializes class and file maps.
135
 */
136
function enqueue_files() {
137
	$active_plugins = get_active_plugins();
138
	$paths          = array_map( __NAMESPACE__ . '\create_map_path_array', $active_plugins );
139
140
	foreach ( $paths as $path ) {
141
		if ( is_readable( $path['class'] ) ) {
142
			$class_map = require $path['class'];
143
144
			if ( is_array( $class_map ) ) {
145
				foreach ( $class_map as $class_name => $class_info ) {
146
					enqueue_package_class( $class_name, $class_info['version'], $class_info['path'] );
147
				}
148
			}
149
		}
150
151
		if ( is_readable( $path['file'] ) ) {
152
			$file_map = require $path['file'];
153
154
			if ( is_array( $file_map ) ) {
155
				foreach ( $file_map as $file_identifier => $file_data ) {
156
					enqueue_package_file( $file_identifier, $file_data['version'], $file_data['path'] );
157
				}
158
			}
159
		}
160
	}
161
162
	file_loader();
163
}
164
165
/**
166
 * Returns an array containing the active plugins. If plugin is activating, it
167
 * is included in the array.
168
 *
169
 * @return Array An array of plugin names as strings.
170
 */
171
function get_active_plugins() {
172
	$active_plugins = array_merge(
173
		is_multisite()
174
			? array_keys( get_site_option( 'active_sitewide_plugins', array() ) )
175
			: array(),
176
		(array) get_option( 'active_plugins', array() )
177
	);
178
	$current_plugin = get_current_plugin();
179
180
	if ( ! in_array( $current_plugin, $active_plugins, true ) ) {
181
		// The current plugin isn't active, so it must be activating. Add it to the list.
182
		$active_plugins[] = $current_plugin;
183
	}
184
185
	// If the activating plugin is not the only activating plugin, we need to add others too.
186
	$active_plugins = array_unique( array_merge( $active_plugins, get_activating_plugins() ) );
187
188
	return $active_plugins;
189
}
190
191
/**
192
 * Creates an array containing the paths to the classmap and filemap for the given plugin.
193
 * The filenames are the names of the files generated by the Jetpack Autoloader version >2.0.
194
 *
195
 * @param String $plugin The plugin string.
196
 * @return Array An array containing the paths to the plugin's classmap and filemap.
197
 */
198
function create_map_path_array( $plugin ) {
199
	$plugin_path = plugin_dir_path( trailingslashit( WP_PLUGIN_DIR ) . $plugin );
200
201
	return array(
202
		'class' => trailingslashit( $plugin_path ) . 'vendor/composer/jetpack_autoload_classmap.php',
203
		'file'  => trailingslashit( $plugin_path ) . 'vendor/composer/jetpack_autoload_filemap.php',
204
	);
205
}
206
207
/**
208
 * Checks whether the current plugin is active.
209
 *
210
 * @return Boolean True if the current plugin is active, else false.
211
 */
212
function is_current_plugin_active() {
213
	$active_plugins = (array) get_option( 'active_plugins', array() );
214
	$current_plugin = get_current_plugin();
215
216
	return in_array( $current_plugin, $active_plugins, true );
217
}
218
219
/**
220
 * Returns the name of activating plugin if a plugin is activating via a request.
221
 *
222
 * @return Array The array of the activating plugins or empty array.
223
 */
224
function get_activating_plugins() {
225
226
	// phpcs:disable WordPress.Security.NonceVerification.Recommended
227
228
	$action = isset( $_REQUEST['action'] ) ? $_REQUEST['action'] : false;
229
	$plugin = isset( $_REQUEST['plugin'] ) ? $_REQUEST['plugin'] : false;
230
	$nonce  = isset( $_REQUEST['_wpnonce'] ) ? $_REQUEST['_wpnonce'] : false;
231
232
	/**
233
	 * Note: we're not actually checking the nonce here becase it's too early
234
	 * in the execution. The pluggable functions are not yet loaded to give
235
	 * plugins a chance to plug their versions. Therefore we're doing the bare
236
	 * minimum: checking whether the nonce exists and it's in the right place.
237
	 * The request will fail later if the nonce doesn't pass the check.
238
	 */
239
240
	// In case of a single plugin activation there will be a plugin slug.
241
	if ( 'activate' === $action && ! empty( $nonce ) ) {
242
		return array( wp_unslash( $plugin ) );
243
	}
244
245
	$plugins = isset( $_REQUEST['checked'] ) ? $_REQUEST['checked'] : array();
246
247
	// In case of bulk activation there will be an array of plugins.
248
	if ( 'activate-selected' === $action && ! empty( $nonce ) ) {
249
		return array_map( 'wp_unslash', $plugins );
250
	}
251
252
	// phpcs:enable WordPress.Security.NonceVerification.Recommended
253
254
	return array();
255
}
256
257
/**
258
 * Returns the name of the current plugin.
259
 *
260
 * @return String The name of the current plugin.
261
 */
262
function get_current_plugin() {
263
	if ( ! function_exists( 'get_plugins' ) ) {
264
		require_once ABSPATH . 'wp-admin/includes/plugin.php';
265
	}
266
267
	$dir  = explode( '/', plugin_basename( __FILE__ ) )[0];
268
	$file = array_keys( get_plugins( "/$dir" ) )[0];
269
	return "$dir/$file";
270
}
271
272
/**
273
 * Find the latest installed autoloader and set up the classmap and filemap.
274
 */
275
function set_up_autoloader() {
276
	global $latest_autoloader_version;
277
	global $jetpack_packages_classmap;
278
279
	if ( ! is_current_plugin_active() ) {
280
		// The current plugin is activating, so reset the autoloader.
281
		$latest_autoloader_version = null;
282
		$jetpack_packages_classmap = array();
283
	}
284
285
	$classmap_file       = trailingslashit( dirname( __FILE__ ) ) . 'composer/jetpack_autoload_classmap.php';
286
	$autoloader_packages = require $classmap_file;
287
288
	$current_autoloader_version = $autoloader_packages['Automattic\\Jetpack\\Autoloader\\AutoloadGenerator']['version'];
289
	$current_autoloader_path    = trailingslashit( dirname( __FILE__ ) ) . 'autoload_packages.php';
290
291
	// Find the latest autoloader.
292
	if ( ! $latest_autoloader_version ) {
293
		$autoloader_version = $current_autoloader_version;
294
		$autoloader_path    = $current_autoloader_path;
295
		$current_plugin     = get_current_plugin();
296
297
		$active_plugins = get_active_plugins();
298
299
		foreach ( $active_plugins as $plugin ) {
300
			if ( $current_plugin === $plugin ) {
301
				continue;
302
			}
303
304
			$plugin_path   = plugin_dir_path( trailingslashit( WP_PLUGIN_DIR ) . $plugin );
305
			$classmap_path = trailingslashit( $plugin_path ) . 'vendor/composer/jetpack_autoload_classmap.php';
306
			if ( file_exists( $classmap_path ) ) {
307
				$packages = require $classmap_path;
308
309
				$current_version = $packages['Automattic\\Jetpack\\Autoloader\\AutoloadGenerator']['version'];
310
311
				// TODO: This comparison needs to properly handle dev versions.
312
				if ( version_compare( $autoloader_version, $current_version, '<' ) ) {
313
					$autoloader_version = $current_version;
314
					$autoloader_path    = trailingslashit( $plugin_path ) . 'vendor/autoload_packages.php';
315
				}
316
			}
317
		}
318
319
		$latest_autoloader_version = $autoloader_version;
320
		if ( $current_autoloader_path !== $autoloader_path ) {
321
			require $autoloader_path;
322
		}
323
	}
324
325
	// This is the latest autoloader, so generate the classmap and filemap and register the autoloader function.
326
	if ( empty( $jetpack_packages_classmap ) && $current_autoloader_version === $latest_autoloader_version ) {
327
		enqueue_files();
328
329
		spl_autoload_register( __NAMESPACE__ . '\autoloader' );
330
331
		$autoload_chain = spl_autoload_functions();
332
		if ( in_array( 'Automattic\Jetpack\Autoloader\autoloader', $autoload_chain, true ) ) {
333
			// Move the old autoloader function to the end of the spl autoloader chaain.
334
			spl_autoload_unregister( 'Automattic\Jetpack\Autoloader\autoloader' );
335
			spl_autoload_register( 'Automattic\Jetpack\Autoloader\autoloader' );
336
		}
337
	}
338
}
339