Skip to content

Commit c94033c

Browse files
committed
Refactoring to properly discover from client-mu-plugins
1 parent 10d3dea commit c94033c

File tree

2 files changed

+63
-31
lines changed

2 files changed

+63
-31
lines changed

src/class-wp-plugin-loader.php

Lines changed: 62 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -92,22 +92,40 @@ public function set_cache_prefix( ?string $prefix ): static {
9292
* Load the requested plugins.
9393
*/
9494
protected function load_plugins(): void {
95-
$client_mu_plugins = is_dir( WP_CONTENT_DIR . '/client-mu-plugins' );
95+
$folders = [
96+
WP_CONTENT_DIR . '/plugins',
97+
];
98+
99+
// Use the client mu-plugins directory if it exists and the constant
100+
// from VIP's mu-plugins is defined.
101+
if ( defined( WPCOM_VIP_CLIENT_MU_PLUGIN_DIR ) ) {
102+
$folders[] = WPCOM_VIP_CLIENT_MU_PLUGIN_DIR;
103+
} else {
104+
// Add the mu-plugins directory if the client mu-plugins directory
105+
// does not exist. We wouldn't want to attempt to load from VIP's
106+
// mu-plugins directory if the client mu-plugins directory exists.
107+
$folders[] = WP_CONTENT_DIR . '/mu-plugins';
108+
}
96109

110+
// Loop through each plugin and attempt to load it.
97111
foreach ( $this->plugins as $plugin ) {
98-
if ( file_exists( WP_PLUGIN_DIR . "/$plugin" ) && ! is_dir( WP_PLUGIN_DIR . "/$plugin" ) ) {
99-
require_once WP_PLUGIN_DIR . "/$plugin";
100-
101-
$this->loaded_plugins[] = trim( $plugin, '/' );
102-
103-
continue;
104-
} elseif ( $client_mu_plugins && file_exists( WP_CONTENT_DIR . "/client-mu-plugins/$plugin" ) && ! is_dir( WP_CONTENT_DIR . "/client-mu-plugins/$plugin" ) ) {
105-
$plugin = ltrim( $plugin, '/' );
112+
// Loop through each possible folder and attempt to load the plugin
113+
// from it.
114+
foreach ( $folders as $folder ) {
115+
if ( file_exists( $folder . "/$plugin" ) && ! is_dir( $folder . "/$plugin" ) ) {
116+
require_once $folder . "/$plugin";
117+
118+
// Mark the plugin as loaded if it is in the /plugins directory.
119+
if ( WP_CONTENT_DIR . '/plugins' === $folder ) {
120+
$this->loaded_plugins[] = trim( $plugin, '/' );
121+
}
106122

107-
require_once WP_CONTENT_DIR . "/client-mu-plugins/$plugin";
123+
continue 2;
124+
}
125+
}
108126

109-
continue;
110-
} elseif ( false === strpos( $plugin, '.php' ) ) {
127+
// Attempt to locate the plugin by name if it isn't a file.
128+
if ( false === strpos( $plugin, '.php' ) ) {
111129
// Check the APCu cache if we have a prefix set.
112130
if ( $this->cache_prefix ) {
113131
$cached_plugin_path = apcu_fetch( $this->cache_prefix . $plugin );
@@ -134,41 +152,54 @@ protected function load_plugins(): void {
134152
WP_PLUGIN_DIR . "/$sanitized_plugin.php",
135153
];
136154

137-
$match = null;
155+
// Include the client mu-plugins directory if it exists.
156+
if ( defined( WPCOM_VIP_CLIENT_MU_PLUGIN_DIR ) ) {
157+
$paths[] = WPCOM_VIP_CLIENT_MU_PLUGIN_DIR . "/$sanitized_plugin/$sanitized_plugin.php";
158+
$paths[] = WPCOM_VIP_CLIENT_MU_PLUGIN_DIR . "/$sanitized_plugin/plugin.php";
159+
$paths[] = WPCOM_VIP_CLIENT_MU_PLUGIN_DIR . "/$sanitized_plugin.php";
160+
}
138161

139162
foreach ( $paths as $path ) {
140163
if ( file_exists( $path ) ) {
141164
require_once $path; // phpcs:ignore WordPressVIPMinimum.Files.IncludingFile.UsingVariable
142165

143-
$match = true;
166+
// Cache the plugin path in APCu if we have a prefix set.
167+
if ( $this->cache_prefix ) {
168+
apcu_store( $this->cache_prefix . $plugin, $path );
169+
}
144170

171+
172+
// Mark the plugin as loaded if it is in the /plugins directory.
145173
$this->loaded_plugins[] = trim( substr( $path, strlen( WP_PLUGIN_DIR ) + 1 ), '/' );
146-
break;
147-
}
148-
}
149174

150-
// Bail if we found a match.
151-
if ( $match ) {
152-
// Cache the plugin path in APCu if we have a prefix set.
153-
if ( $this->cache_prefix ) {
154-
apcu_store( $this->cache_prefix . $plugin, $path );
175+
continue 2;
155176
}
156-
157-
continue;
158177
}
159178
}
160179

161-
$error_message = sprintf( 'WP Plugin Loader: Plugin %s not found.', $plugin );
180+
$this->handle_missing_plugin( $plugin );
181+
}
182+
}
162183

163-
trigger_error( esc_html( $error_message ), E_USER_WARNING ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error
184+
/**
185+
* Handle a missing plugin.
186+
*
187+
* @todo Change return type to never when 8.1 is required.
188+
*
189+
* @param string $plugin The plugin name passed to the loader.
190+
* @return void
191+
*/
192+
protected function handle_missing_plugin( string $plugin ): void {
193+
$error_message = sprintf( 'WP Plugin Loader: Plugin %s not found.', $plugin );
164194

165-
if ( extension_loaded( 'newrelic' ) && function_exists( 'newrelic_notice_error' ) ) {
166-
newrelic_notice_error( $error_message );
167-
}
195+
trigger_error( esc_html( $error_message ), E_USER_WARNING ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error
168196

169-
// Bye bye!
170-
die( esc_html( $error_message ) );
197+
if ( extension_loaded( 'newrelic' ) && function_exists( 'newrelic_notice_error' ) ) {
198+
newrelic_notice_error( $error_message );
171199
}
200+
201+
// Bye bye!
202+
die( esc_html( $error_message ) );
172203
}
173204

174205
/**

stubs/constants.stub

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
<?php
22
define( 'WP_CONTENT_DIR', 'wp-content' );
33
define( 'WP_PLUGIN_DIR', 'wp-content/plugins' );
4+
define( 'WPCOM_VIP_CLIENT_MU_PLUGIN_DIR', 'wp-content/client-mu-plugins' );

0 commit comments

Comments
 (0)