PluginProbe
Performance Lab / 4.0.0
Performance Lab v4.0.0
trunk 1.0.0 1.0.0-beta.1 1.0.0-beta.2 1.0.0-beta.3 1.0.0-rc.1 1.1.0 1.2.0 1.3.0 1.4.0 1.5.0 1.6.0 1.7.0 1.8.0 1.9.0 2.0.0 2.1.0 2.2.0 2.3.0 2.4.0 2.5.0 2.6.0 2.6.1 2.7.0 2.8.0 All 44 releases
performance-lab / load.php

load.php in Performance Lab 4.0.0, at load.php

363 lines 12.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Plugin Name: Performance Lab
4 * Plugin URI: https://github.com/WordPress/performance
5 * Description: Performance plugin from the WordPress Performance Team, which is a collection of standalone performance features.
6 * Requires at least: 6.6
7 * Requires PHP: 7.2
8 * Version: 4.0.0
9 * Author: WordPress Performance Team
10 * Author URI: https://make.wordpress.org/performance/
11 * License: GPLv2 or later
12 * License URI: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
13 * Text Domain: performance-lab
14 *
15 * @package performance-lab
16 */
17
18 // @codeCoverageIgnoreStart
19 if ( ! defined( 'ABSPATH' ) ) {
20 exit; // Exit if accessed directly.
21 }
22 // @codeCoverageIgnoreEnd
23
24 define( 'PERFLAB_VERSION', '4.0.0' );
25 define( 'PERFLAB_MAIN_FILE', __FILE__ );
26 define( 'PERFLAB_PLUGIN_DIR_PATH', plugin_dir_path( PERFLAB_MAIN_FILE ) );
27 define( 'PERFLAB_SCREEN', 'performance-lab' );
28
29 // If the constant isn't defined yet, it means the Performance Lab object cache file is not loaded.
30 if ( ! defined( 'PERFLAB_OBJECT_CACHE_DROPIN_VERSION' ) ) {
31 define( 'PERFLAB_OBJECT_CACHE_DROPIN_VERSION', false );
32 }
33 define( 'PERFLAB_OBJECT_CACHE_DROPIN_LATEST_VERSION', 3 );
34
35 // Load server-timing API.
36 require_once PERFLAB_PLUGIN_DIR_PATH . 'includes/server-timing/class-perflab-server-timing-metric.php';
37 require_once PERFLAB_PLUGIN_DIR_PATH . 'includes/server-timing/class-perflab-server-timing.php';
38 require_once PERFLAB_PLUGIN_DIR_PATH . 'includes/server-timing/load.php';
39 require_once PERFLAB_PLUGIN_DIR_PATH . 'includes/server-timing/defaults.php';
40
41 // Load site health checks.
42 require_once PERFLAB_PLUGIN_DIR_PATH . 'includes/site-health/load.php';
43
44 /**
45 * Gets the content attribute for the generator tag for the Performance Lab plugin.
46 *
47 * This attribute is then used in {@see perflab_render_generator()}.
48 *
49 * @since 1.1.0
50 * @since 2.9.0 The generator tag now includes the active standalone plugin slugs.
51 * @since 3.0.0 The generator tag no longer includes module slugs.
52 */
53 function perflab_get_generator_content(): string {
54 $active_plugins = array();
55 foreach ( perflab_get_standalone_plugin_version_constants() as $plugin_slug => $constant_name ) {
56 if ( defined( $constant_name ) && ! str_starts_with( constant( $constant_name ), 'Performance Lab ' ) ) {
57 $active_plugins[] = $plugin_slug;
58 }
59 }
60
61 return sprintf(
62 // Use the plugin slug as it is immutable.
63 'performance-lab %1$s; plugins: %2$s',
64 PERFLAB_VERSION,
65 implode( ', ', $active_plugins )
66 );
67 }
68
69 /**
70 * Displays the HTML generator tag for the Performance Lab plugin.
71 *
72 * See {@see 'wp_head'}.
73 *
74 * @since 1.1.0
75 */
76 function perflab_render_generator(): void {
77 $content = perflab_get_generator_content();
78
79 echo '<meta name="generator" content="' . esc_attr( $content ) . '">' . "\n";
80 }
81 add_action( 'wp_head', 'perflab_render_generator' );
82
83 /**
84 * Gets the standalone plugins and their data.
85 *
86 * @since 3.0.0
87 *
88 * @return array<string, array{'constant': string, 'experimental'?: bool}> Associative array of $plugin_slug => $plugin_data pairs.
89 */
90 function perflab_get_standalone_plugin_data(): array {
91 /*
92 * Alphabetically sorted list of plugin slugs and their data.
93 * Supported keys per plugin are:
94 * - 'constant' (string, required)
95 * - 'experimental' (boolean, optional)
96 */
97 return array(
98 'auto-sizes' => array(
99 'constant' => 'IMAGE_AUTO_SIZES_VERSION',
100 'experimental' => false,
101 ),
102 'dominant-color-images' => array(
103 'constant' => 'DOMINANT_COLOR_IMAGES_VERSION',
104 ),
105 'embed-optimizer' => array(
106 'constant' => 'EMBED_OPTIMIZER_VERSION',
107 'experimental' => false,
108 ),
109 'image-prioritizer' => array(
110 'constant' => 'IMAGE_PRIORITIZER_VERSION',
111 'experimental' => false,
112 ),
113 'performant-translations' => array(
114 'constant' => 'PERFORMANT_TRANSLATIONS_VERSION',
115 ),
116 'nocache-bfcache' => array(
117 'constant' => 'WestonRuter\NocacheBFCache\VERSION',
118 ),
119 'speculation-rules' => array(
120 'constant' => 'SPECULATION_RULES_VERSION',
121 ),
122 'view-transitions' => array(
123 'constant' => 'VIEW_TRANSITIONS_VERSION',
124 'experimental' => true,
125 ),
126 'web-worker-offloading' => array(
127 'constant' => 'WEB_WORKER_OFFLOADING_VERSION',
128 'experimental' => true,
129 ),
130 'webp-uploads' => array(
131 'constant' => 'WEBP_UPLOADS_VERSION',
132 ),
133 );
134 }
135
136 /**
137 * Gets the standalone plugin constants used for each available standalone plugin.
138 *
139 * @since 2.9.0
140 * @since 3.0.0 The $source parameter was removed.
141 *
142 * @return array<string, string> Map of plugin slug and the version constant used.
143 */
144 function perflab_get_standalone_plugin_version_constants(): array {
145 return wp_list_pluck( perflab_get_standalone_plugin_data(), 'constant' );
146 }
147
148 /**
149 * Places the Performance Lab's object cache drop-in in the drop-ins folder.
150 *
151 * This only runs in WP Admin to not have any potential performance impact on
152 * the frontend.
153 *
154 * This function will short-circuit if at least one of the constants
155 * 'PERFLAB_DISABLE_SERVER_TIMING' or
156 * 'PERFLAB_DISABLE_OBJECT_CACHE_DROPIN' is set as true or if the
157 * 'PERFLAB_PLACE_OBJECT_CACHE_DROPIN' constant is not set to a truthy value.
158 *
159 * @since 1.8.0
160 * @since 2.1.0 No longer attempts to use two of the drop-ins together.
161 * @since 4.0.0 No longer places the drop-in on new sites by default, unless the `PERFLAB_PLACE_OBJECT_CACHE_DROPIN` constant is set to true.
162 *
163 * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
164 */
165 function perflab_maybe_set_object_cache_dropin(): void {
166 global $wp_filesystem;
167
168 // Bail if Server-Timing is disabled entirely.
169 if ( defined( 'PERFLAB_DISABLE_SERVER_TIMING' ) && PERFLAB_DISABLE_SERVER_TIMING ) {
170 return;
171 }
172
173 // Bail if the drop-in is not enabled.
174 if ( ! defined( 'PERFLAB_PLACE_OBJECT_CACHE_DROPIN' ) || ! PERFLAB_PLACE_OBJECT_CACHE_DROPIN ) {
175 return;
176 }
177
178 // Bail if disabled via constant.
179 // This constant is maintained only for backward compatibility and should not be relied upon in new implementations.
180 // Use the 'PERFLAB_PLACE_OBJECT_CACHE_DROPIN' constant instead to control drop-in placement.
181 if ( defined( 'PERFLAB_DISABLE_OBJECT_CACHE_DROPIN' ) && PERFLAB_DISABLE_OBJECT_CACHE_DROPIN ) {
182 return;
183 }
184
185 /**
186 * Filters whether the Perflab server timing drop-in should be set.
187 *
188 * @since 2.0.0
189 *
190 * @param bool $disabled Whether to disable the server timing drop-in. Default false.
191 */
192 if ( apply_filters( 'perflab_disable_object_cache_dropin', false ) ) {
193 return;
194 }
195
196 /**
197 * Filters the value of the `object-cache.php` drop-in constant.
198 *
199 * This filter should not be used outside of tests.
200 *
201 * @since 3.0.0
202 * @internal
203 *
204 * @param int|bool $current_dropin_version The drop-in version as defined by the
205 * `PERFLAB_OBJECT_CACHE_DROPIN_VERSION` constant.
206 */
207 $current_dropin_version = apply_filters( 'perflab_object_cache_dropin_version', PERFLAB_OBJECT_CACHE_DROPIN_VERSION );
208
209 // Bail if already placed in the latest version or newer.
210 if ( null !== $current_dropin_version && $current_dropin_version >= PERFLAB_OBJECT_CACHE_DROPIN_LATEST_VERSION ) {
211 return;
212 }
213
214 // Bail if already attempted before timeout has been completed.
215 // This is present in case placing the file fails for some reason, to avoid
216 // excessively retrying to place it on every request.
217 $timeout = get_transient( 'perflab_set_object_cache_dropin' );
218 if ( false !== $timeout ) {
219 return;
220 }
221
222 if ( $wp_filesystem instanceof WP_Filesystem_Base || true === WP_Filesystem() ) {
223 $dropin_path = WP_CONTENT_DIR . '/object-cache.php';
224
225 /*
226 * If there is an actual object-cache.php file, it is most likely from
227 * a third party, or it may be an older version of the Performance Lab
228 * object-cache.php. If it's from a third party, do not replace it.
229 *
230 * Previous versions of the Performance Lab plugin were renaming the
231 * original object-cache.php file and then loading both. However, due
232 * to other plugins eagerly checking file headers, this caused too many
233 * problems across sites, so it was decided to remove this layer.
234 * Only placing the drop-in file if no other one exists yet is the
235 * safest solution.
236 */
237 if ( $wp_filesystem->exists( $dropin_path ) ) {
238 // If this constant evaluates to `false`, the existing file is for sure from a third party.
239 if ( false === $current_dropin_version ) {
240 // Set timeout of 1 day before retrying again (only in case the file already exists).
241 set_transient( 'perflab_set_object_cache_dropin', true, DAY_IN_SECONDS );
242 return;
243 }
244
245 // Otherwise, verify that it's actually the Performance Lab drop-in.
246 $test_content = "<?php\n/**\n * Plugin Name: Performance Lab Server Timing Object Cache Drop-In\n";
247 if ( ! str_starts_with( $wp_filesystem->get_contents( $dropin_path ), $test_content ) ) {
248 // Set timeout of 1 day before retrying again (only in case the file already exists).
249 set_transient( 'perflab_set_object_cache_dropin', true, DAY_IN_SECONDS );
250 return;
251 }
252
253 /*
254 * If this logic is reached, the existing file is an older version
255 * of the Performance Lab drop-in, so it can be safely deleted, and
256 * then be replaced below.
257 */
258 $wp_filesystem->delete( $dropin_path );
259 }
260
261 $wp_filesystem->copy( PERFLAB_PLUGIN_DIR_PATH . 'includes/server-timing/object-cache.copy.php', $dropin_path );
262 }
263
264 // Set timeout of 1 hour before retrying again (only relevant in case the above failed).
265 set_transient( 'perflab_set_object_cache_dropin', true, HOUR_IN_SECONDS );
266 }
267 add_action( 'admin_init', 'perflab_maybe_set_object_cache_dropin' );
268
269 /**
270 * Removes the Performance Lab's object cache drop-in from the drop-ins folder.
271 *
272 * This function should be run on plugin deactivation. For backward compatibility with
273 * an earlier implementation of `perflab_maybe_set_object_cache_dropin()`, this function
274 * checks whether there is an object-cache-plst-orig.php file, and if so restores it.
275 *
276 * This function will short-circuit if the constant
277 * 'PERFLAB_DISABLE_OBJECT_CACHE_DROPIN' is set as true.
278 *
279 * @since 1.8.0
280 *
281 * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
282 */
283 function perflab_maybe_remove_object_cache_dropin(): void {
284 global $wp_filesystem;
285
286 // Bail if disabled via constant.
287 if ( defined( 'PERFLAB_DISABLE_OBJECT_CACHE_DROPIN' ) && PERFLAB_DISABLE_OBJECT_CACHE_DROPIN ) {
288 return;
289 }
290
291 // Bail if custom drop-in not present anyway.
292 if ( ! PERFLAB_OBJECT_CACHE_DROPIN_VERSION ) {
293 return;
294 }
295
296 if ( $wp_filesystem instanceof WP_Filesystem_Base || true === WP_Filesystem() ) {
297 $dropin_path = WP_CONTENT_DIR . '/object-cache.php';
298 $dropin_backup_path = WP_CONTENT_DIR . '/object-cache-plst-orig.php';
299
300 /**
301 * If there is an object-cache-plst-orig.php file, restore it and
302 * override the Performance Lab file. This is only relevant for
303 * backward-compatibility with previous Performance Lab versions
304 * which were backing up the file and then loading both.
305 * Otherwise, just delete the Performance Lab file.
306 */
307 if ( $wp_filesystem->exists( $dropin_backup_path ) ) {
308 $wp_filesystem->move( $dropin_backup_path, $dropin_path, true );
309 } else {
310 $wp_filesystem->delete( $dropin_path );
311 }
312 }
313
314 // Delete transient for drop-in check in case the plugin is reactivated shortly after.
315 delete_transient( 'perflab_set_object_cache_dropin' );
316 }
317 register_deactivation_hook( __FILE__, 'perflab_maybe_remove_object_cache_dropin' );
318
319 /**
320 * Redirects legacy module page to the performance feature page.
321 *
322 * @since 3.0.0
323 *
324 * @global $plugin_page
325 */
326 function perflab_no_access_redirect_module_to_performance_feature_page(): void {
327 global $plugin_page;
328
329 if ( 'perflab-modules' !== $plugin_page ) {
330 return;
331 }
332
333 if (
334 current_user_can( 'manage_options' ) &&
335 wp_safe_redirect( add_query_arg( 'page', PERFLAB_SCREEN ) )
336 ) {
337 exit;
338 }
339 }
340 add_action( 'admin_page_access_denied', 'perflab_no_access_redirect_module_to_performance_feature_page' );
341
342 /**
343 * Cleanup function to delete legacy 'perflab_modules_settings' option if present.
344 *
345 * @since 3.0.0
346 */
347 function perflab_cleanup_option(): void {
348 if ( current_user_can( 'manage_options' ) ) {
349 delete_option( 'perflab_modules_settings' );
350 }
351 }
352 add_action( 'admin_init', 'perflab_cleanup_option' );
353
354 // Only load admin integration when in admin.
355 if ( is_admin() ) {
356 require_once PERFLAB_PLUGIN_DIR_PATH . 'includes/admin/load.php';
357 require_once PERFLAB_PLUGIN_DIR_PATH . 'includes/admin/server-timing.php';
358 require_once PERFLAB_PLUGIN_DIR_PATH . 'includes/admin/plugins.php';
359 }
360
361 // Load REST API.
362 require_once PERFLAB_PLUGIN_DIR_PATH . 'includes/admin/rest-api.php';
363