A colleague of mine migrated a shopper website in preparation for taking on their account and was surprised when, upon profitable migration, the location didn’t operate accurately. The problem was fairly irritating within the trade. The company constructed {custom} options inaccessible to the shopper – both through SFTP or WordPress administration. I’ll clarify how later… and the way I used to be in a position to work across the subject.
In WordPress, mu-plugins (must-use plugins) are particular varieties 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.
Once 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, however, are mechanically activated and don’t seem on this checklist. Listed here are some key factors about mu-plugins:
- Location: Mu-plugins are positioned 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 lively 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 will have any title, however the file extension have to be
.php
. For instance,my-custom-functions.php
could be 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 lively.
- Modifying core WordPress habits or overriding default performance.
- Implementing sure plugins to be lively 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 world 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 via the WordPress admin panel. They must be manually up to date by changing the respective information within the
mu-plugins
listing.
On this specific occasion, the company had an mu-plugin that included a mum or dad listing the place they’d {custom} plugins constructed out for the shopper. That mum or dad listing was on their internet hosting surroundings however not accessible by the shopper in any respect. That is actually sinister, for my part. Selling WordPress to your shoppers comes with an expectation of getting an open-source platform.
By hiding code out of your shoppers, you’re making it unattainable for them emigrate away from you or handle the occasion independently. You’re mainly holding them hostage except they construct a brand new website from scratch. I’m not alleging that the company did something unlawful… I’m sure they’d particulars of this of their MSA or SOW. It doesn’t make it proper, although.
WordPress Plugin: How To Determine and Obtain mu-plugins
When you can execute PHP code, you possibly can in the end 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 supplied me with the mu-plugin that the company put in.
Observe: The mu-plugin
listing is seen through SFTP, however they did one thing further 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 surroundings! 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 supplied 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 personalized plugins, which corrected all the problems on the location. On condition that I didn’t know if they’d a authorized settlement, I didn’t need 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 assume it must be unfold with out some accountability. Right here’s how you should utilize it for those who want it, although.
- Save: Save the whole 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 through 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
Writer: Douglas Karr
Writer 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><sturdy>' . esc_html( $merchandise ) . '/</sturdy>';
$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' );