Make WordPress Core

Opened 14 years ago

Closed 14 years ago

Last modified 7 years ago

#14359 closed enhancement (wontfix)

Support loading mu_plugins from subdirectories

Reported by: benward's profile benward Owned by: benward's profile benward
Milestone: Priority: normal
Severity: normal Version: 3.0
Component: Plugins Keywords:
Focuses: Cc:


Aim: Enhance the load_mu_plugins mechanism to support loading plugins from inside subdirectories in WPMU_PLUGIN_DIR, in both initialization and plugins administration interface.

Why: We (Yahoo, hello) are making substantial use of the mu-plugins mechanism to extend WordPress functionality at a deployment level, adding core product/instance functionality to a as part of the code deployment, rather than features that are enabled through the GUI. (e.g. Authentication, custom input filtering, integration with low level options configuration systems we have.) Each such enhancement is modular, and some wrap additional libraries, so all of our ‘must-use’ plugins are packaged in separate directories. WordPress, as of now, does not load must-use plugins from subdirectories.

Thus, we have one root must-use plugin that recursively loads plugins from subdirectories. This has the disadvantage that those sub-directory plugins then aren't listed in the Plugins UI, and it's all a bit of a hack.

I'm working on a patch to improve the mu-plugin loading to support single-subdirectory loading, _similar_ to regular plugins. The components of this are:

  1. Patch wp-admin/includes/plugin.php:get_plugins() to accept $plugin_root as a parameter—either WP_PLUGIN_DIR or WPMU_PLUGIN_DIR—and build a cache key using that path rather than fixed plugins key.
  2. Patch wp-admin/includes/plugin.php:get_mu_plugins() to call get_plugins() specifying WPMU_PLUGIN_DIR as the $plugin_root. This loads subdirectory plugins with details into the admin UI.
  3. From wp-admin/includes/plugin.php:get_plugins() refactor the recursive directory listing code into a non-admin get_plugins() method in wp-includes/load.php, since it is needed to load the mu-plugins.
  4. Patch load.php:wp_get_mu_plugins() to grab plugin files from WPMU_PLUGINS_DIR and subdirectories, using refactoring file-listing function from \#3.

In writing this I quickly hit on why WordPress treats mu-plugins so simply already: Regular plugins are examined for metadata to check their validity, regardless of filename, and then active plugins are stored as an option and cached. Since must-use plugins are not stored in an option, and since caching is not a default feature of WordPress, mu-plugin loading cannot require calling /wp-admin/includes/plugin.php:get_plugin_data() on every load. As such, I'm currently working with a new, but I think more reasonable structure limitation for mu-plugins: That the main file for a subdirectory-based mu-plugin must be named the same as its containing directory: That is, the ./yahoo_example plugin must be initialized by ./yahoo_example/yahoo_example.php. This pattern seems to match how many plugins already package themselves anyway.

That said, I am interested to hear other suggestions on how to load from mu_plugins without introducing a performance hit.

I'm posting this bug to describe my fix. I'm testing the patch at present and will attach it for review/comment after a couple of immediate kinks are ironed out.

Change History (8)

#1 @nacin
14 years ago

The issue I see is that many use it like so: a directory of scripts, with files at the root including what must be loaded that happens to be below the top level. This is how any multi-file mu plugin must work currently.

Changing that without it being an opt-in would obviously break quite a bit.

The ability for files in mu-plugins to be visible in the admin is quite new. I wrote the code for it for 3.0; the functionality itself was introduced in 2.8 in core, and in MU years before that. Enabling it to scan plugin headers is a complete afterthought in the general sense.

My point is, even if we scanned subdirectories, files not containing headers would need to be moved down an additional directory anyway (no different from moving a single file up a directory, as it is now) or we would need to store valid plugins in the DB, something we've never done for these -- mu-plugins are completely stateless. Not only do we make headers optional, but they were useless until 3.0.

Simple solution I see is that you simply move up yahoo_example.php to be on the same level as yahoo_example and make sure the php file includes what it needs out of the folder. More complex solution, well, I'm not sure -- it involves a significant rework of a section that, I think, is best kept light and simple so plugins, networks, and Yahoo can build whatever their heart desires on top of it.

#2 @benward
14 years ago

Thanks for the expanded explanation & history, Andrew. I agree with your assessment. We've changed out deployment method, and whilst it makes the packaging a bit messier, I take your point about not breaking existing plugin structures, and the complexity that introduces.


#3 @scribu
14 years ago

  • Milestone Awaiting Review deleted
  • Resolution set to wontfix
  • Status changed from new to closed

What nacin said.

#4 @SergeyBiryukov
11 years ago

#23403 was marked as a duplicate.

#5 follow-up: @lavoiesl
11 years ago

  • Keywords changed from plugins, mu_plugins, subdirectory to plugins mu_plugins, subdirectory

I personally think mu-plugins are useless, we need plugin dependency instead. Plugins that require plugins and themes that require plugins. That way, mu-plugins would just be normal plugins that are always active.

Anyway, for those who still want subdirectory support for mu-plugins, I made a small mu-plugin that does just that:

#6 @SergeyBiryukov
11 years ago

  • Keywords plugins mu_plugins subdirectory removed

#7 in reply to: ↑ 5 @SergeyBiryukov
11 years ago

Replying to lavoiesl:

I personally think mu-plugins are useless, we need plugin dependency instead.

Related: #22316

#8 @SergeyBiryukov
7 years ago

#41481 was marked as a duplicate.

Note: See TracTickets for help on using tickets.