A colleague of mine migrated a shopper website in preparation for taking on their account and was shocked when, upon profitable migration, the location didn’t operate appropriately. The difficulty was fairly irritating within the trade. The company constructed {custom} options inaccessible to the shopper – both by way of SFTP or WordPress administration. I’ll clarify how later… and the way I used to be in a position to work across the problem.
In WordPress, mu-plugins (must-use plugins) are particular sorts of WordPress plugins which might be mechanically activated and can’t be deactivated from the WordPress admin panel. The mu in mu-plugins stands for must-use.
Whenever you go to the Plugins part within the WordPress admin panel, you’ll solely see the common plugins that may be activated, deactivated, and managed individually. Mu-plugins, then again, are mechanically activated and don’t seem on this checklist. Listed here are some key factors about mu-plugins:
- Location: Mu-plugins are situated in a separate listing named
mu-plugins
within thewp-content
listing of your WordPress set up. - Computerized Activation: In contrast to common plugins, mu-plugins are activated mechanically and can’t be deactivated from the WordPress admin panel. They’re all the time energetic so long as they’re current within the
mu-plugins
listing. - Precedence: Mu-plugins are loaded earlier than common plugins. Which means they’ve the power to override or modify the habits of standard plugins.
- Naming Conference: Mu-plugins don’t comply with the identical naming conference as common plugins. They’ll have any title, however the file extension have to be
.php
. For instance,my-custom-functions.php
generally is a legitimate mu-plugin file title. - Use Instances: Mu-plugins are generally used for:
- Implementing site-specific performance that ought to all the time be energetic.
- Modifying core WordPress habits or overriding default performance.
- Implementing sure plugins to be energetic on all websites in a multisite community.
- Making use of {custom} code or modifications that shouldn’t be accessible or deactivatable by website directors.
- Multisite: In a WordPress multisite community, mu-plugins are international and have an effect on all websites within the community. They’re loaded earlier than common plugins on every website.
- Updates: Mu-plugins are not updateable by way of the WordPress admin panel. They have to be manually up to date by changing the respective information within the
mu-plugins
listing.
On this explicit occasion, the company had an mu-plugin that included a father or mother listing the place that they had {custom} plugins constructed out for the shopper. That father or mother listing was on their internet hosting setting however not accessible by the shopper in any respect. That is actually sinister, for my part. Selling WordPress on your shoppers comes with an expectation of getting an open-source platform.
By hiding code out of your shoppers, you’re making it inconceivable for them emigrate away from you or handle the occasion independently. You’re principally holding them hostage until they construct a brand new website from scratch. I’m not alleging that the company did something unlawful… I’m sure that they had particulars of this of their MSA or SOW. It doesn’t make it proper, although.
WordPress Plugin: How To Establish and Obtain mu-plugins
When you can execute PHP code, you possibly can finally entry that code. So, I wrote a {custom} plugin that might be put in on the server and created a shortcode itemizing the mu-plugins within the listing. I created a draft web page with [listmuplugins]
within the content material and previewed it in a brand new window. That offered me with the mu-plugin that the company put in.
Be aware: The mu-plugin
listing is seen by way of SFTP, however they did one thing additional sneaky. Once I opened their plugin, I discovered that they’d written a operate to incorporate a listing that was inaccessible from the shopper’s internet hosting setting! So, I up to date my code to permit crawling they particular listing they included with [listmuplugins dir="/custom/path/"]
.
As soon as I up to date the shortcode to the trail they offered of their mu-plugin
, I may learn and obtain each plugin the location required to function. Right here’s a screenshot of the output (I deleted any of the company’s {custom} mu-plugins
).
I used to be then in a position to write custom-made plugins, which corrected all the problems on the location. On condition that I didn’t know if that they had a authorized settlement, I didn’t wish to simply copy the company’s code… although they didn’t have any copyright info within the supply.
How To Use This Plugin
I gained’t publish this within the WordPress repository as I don’t suppose it ought to be unfold with out some duty. Right here’s how you need to use it if you happen to want it, although.
- Save: Save the complete code as
listmuplugins.php
inside a brand new folder namedlistmuplugins
inside your WordPress/wp-content/plugins/
listing. Or you possibly can zip the listing and PHP file and add it by way of the WordPress plugin administrative panel. - Activate: Activate the plugin titled Listing MU Plugins with Obtain and Listing Construction in your WordPress plugins dashboard.
- Shortcode Utilization:
[listmuplugins]
: Lists MU Plugins out of your website’s defaultwp-content/mu-plugins/
listing.[listmuplugins dir="/custom/path/"]
: Lists MU Plugins from a specified listing.
<?php
/*
Plugin Title: Listing MU Plugins with Obtain and Listing Construction
Description: Lists Should-Use Plugins with the power to obtain their supply code, and shows the listing construction. Listing will be specified within the shortcode.
Model: 2.0
Creator: Douglas Karr
Creator URI: https://dknewmedia.com
*/
operate list_mu_plugins_shortcode( $atts ) {
$atts = shortcode_atts( array(
'dir' => WPMU_PLUGIN_DIR // Default to website's MU Plugins listing
), $atts );
$dir = $atts['dir'];
// Validate the listing path
if ( ! is_dir( $dir ) || ! is_readable( $dir ) ) {
return "<p>MU Plugins listing not discovered or not readable.</p>n";
}
$output = "<h2>Listing of Included MU Plugins:</h2>n";
$output .= list_directory_contents( $dir );
return $output;
}
add_shortcode( 'listmuplugins', 'list_mu_plugins_shortcode' );
operate list_directory_contents( $dir ) {
$output = "<ul>n";
$objects = scandir( $dir );
foreach ( $objects as $merchandise ) {
if ( $merchandise === '.' || $merchandise === '..' ) {
proceed;
}
$path = $dir . '/' . $merchandise;
if ( is_dir( $path ) ) {
$output .= '<li><robust>' . esc_html( $merchandise ) . '/</robust>';
$output .= list_directory_contents( $path );
$output .= '</li>';
} else {
$output .= '<li>' . esc_html( $merchandise );
if ( current_user_can( 'manage_options' ) ) {
$download_link = add_query_arg( ['mu_plugin_download' => $item] );
$output .= ' <a href="' . esc_url( $download_link ) . '">Obtain</a>';
}
$output .= '</li>';
}
}
$output .= "</ul>n";
return $output;
}
// Deal with the obtain request
operate handle_mu_plugin_download() {
if ( isset( $_GET['mu_plugin_download'] ) && current_user_can( 'manage_options' ) ) {
$filename = sanitize_file_name( $_GET['mu_plugin_download'] );
$filepath = WPMU_PLUGIN_DIR . '/' . $filename;
if ( file_exists( $filepath ) && is_readable( $filepath ) ) {
header( 'Content material-Description: File Switch' );
header( 'Content material-Sort: software/octet-stream' );
header( 'Content material-Disposition: attachment; filename="' . $filename . '"' );
header( 'Expires: 0' );
header( 'Cache-Management: must-revalidate' );
header( 'Pragma: public' );
header( 'Content material-Size: ' . filesize( $filepath ) );
readfile( $filepath );
exit;
} else {
wp_die( 'File not discovered or not readable.' );
}
}
}
add_action( 'init', 'handle_mu_plugin_download' );