-
Notifications
You must be signed in to change notification settings - Fork 384
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Prefix Composer dependencies #1867
Comments
😕 |
It looks like Mailpoet has implemented prefixing for PHP-CSS-Parser already: mailpoet/mailpoet#1776 But instead of Mozart they are using PHP-Scoper: mailpoet/mailpoet#1655 Apparently PHP-Scoper is better maintained. |
Here's another one: /~https://github.com/TypistTech/imposter-plugin |
Article I just came across about PHP-Scoper: https://deliciousbrains.com/php-scoper-namespace-composer-depencies/ |
Coen Jacobs also just shared a post about the differences between PHP Scoper and Mozart: https://coenjacobs.me/2019/07/05/why-i-felt-there-was-a-need-for-mozart/ |
An alternative to prefixing is to consider something that @gravityrail has shared: Jetpack Autoloader. This will ensure the latest version of the package is used from among the plugins that incorporate this custom Composer autoloader. |
Jetpack's autoloader is still quite new and I am not sure if their approach would work in all cases, i.e. when two versions of a package are incompatible and another plugin relies on the older version. But I guess we can keep an eye on it. |
Jetpack's autoloader is not ideal but probably the best of a bunch of bad choices, until we get proper dependency management in WP Core. As @swissspidy points out, sometimes there is no good dependency choice (in which case we want to detect before enabling a plugin that will break another plugin), or in some cases the best dependency choice is something between two shipped versions (in which case WP should perhaps detect the "good" choice, download it, and enable it in preference to the shipped versions). The improvements I described above are only really possible if/when Core ships with explicit support for composer.json dependencies. Alternatively, plugins could declare dependencies on each other, but I dislike that approach for a couple of reasons:
|
Just to be clear here, the thing I dislike about the randomised namespacing of classes in composer dependencies is that you can potentially have multiple initialisation - e.g. if your package dependency hooks some actions (therefore runs multiple times, if you have multiple instances of the dependency) and/or fires actions (in which case they may be fired multiple times). There are all kinds of other edge cases I could imagine creeping in, and debugging becomes horrific. Better to have one instance of a class than multiple with different randomised names. |
Unfortunately we are far away from such a scenario, which at the moment I think is very unlikely.
If N plugins all use the same dependency, each with their own custom prefix, then you will get at most N instances of said dependency, without any conflicts between them. So I don't see a problem here. |
Hm. I think I was not clear before. Let me give some concrete examples. Imagine we have a package which offers an API, mounted at Imagine a package has singleton classes to prevent multiple instances of a class being instantiated, because there are side-effects. Those singletons no longer actually work, since now there can be one instance per plugin. Imagine a package which modifies post_content by appending I could go on and on. Basically, the approach of namespacing (or randomising classnames) breaks down as soon as the packages start to hook into WordPress itself, mounting APIs and hooking actions and filters. This is because the name (or namespace) of a class is only ONE dimension of MANY ways that a package must be "namespaced" before it can truly be considered free of conflicts with other instances of the same package. Any shared resource, whether it's a hook or a path or wp-options or anything else, suddenly also needs to be namespaced. It's a neverending rabbit hole. Resolving dependencies globally across plugins is actually a much easier problem to solve. One of the most useful things that becomes possible with a package management system is the possibility of plugins adopting shared functionality before it's available in core, e.g. the PWA plugin. Having multiple instances of the PWA plugin functionality, each competing to mount the service worker in the same context, would be unworkable. |
Yeah, prefixing only works reliably for pure PHP libraries that do not extend WordPress directly, for example PHP-CSS-Parser. |
Site Kit ended up using PHP-Scoper: google/site-kit-wp#696 |
We can eliminate the problem of PHP-CSS-Parser and other Composer dependencies conflicting with copies included on other plugins (e.g. Mailpoet) by using Mozart to prefix the namespaces: /~https://github.com/coenjacobs/mozart
The text was updated successfully, but these errors were encountered: