This is my approach for solving plugin dependencies. A three pronged approach involving
- dependency checking
- shared libraries
- compatibility checking
I’ve developed a plugin, oik-lib: shared library management, that satisfies some of the requirements for sharing PHP logic between WordPress plugins and themes.
- Its job is not to solve plugin dependencies.
- Its job is to manage requests from plugins which have dependencies on other components.
- Version 0.0.2 is now available on github.com/bobbingwide/oik-lib.
- Documentation and WordPress installable versions are available from oik-lib.
I’m in the process of redeveloping my plugins to co-operate using the shared library management API. Two of them are already available.
- oik base plugin – the source of the functionality on which many other plugins currently depend
- oik-bwtrace – WordPress problem determination and tracing
Others are in the pipeline.
In this post I attempt to document the story so far for oik plugin dependency checking and the requirements I have for plugin dependency checking in general. My requirements take into account considerations for shared libraries of PHP code. Some solutions are offered, others are proposed, and some requirements are also stated.
This post was originally drafted in May 2015, as a partial response to Ryan McCue’s proposals.
It has now been updated to reflect the current solution, as of August 2015.
My current solution helps me to solve some of the problems. But it also introduces new ones I didn’t think I had, and continues to be plagued with problems associated with backward version incompatibility, which will need to be handled using conflict checking.
Background – dependency checking
Many moons ago the
oik-bwtrace plugin existed as part of the oik plugin, along with a few other separately activatable plugins. When I split the oik base plugin up into multiple plugins, with each plugin becoming separately installable and activatable, rather than duplicating common functionality, I made each plugin dependent upon the oik base plugin.
Each plugin used basically the same logic as that which I’d developed for the
oik-nivo-slider plugin (v1.2, April 2012) dependency upon the existence and activation status of the oik base plugin (v1.12).
There were three parts to the solution:
- During normal processing dependent plugins wait until notified that it’s safe to do something; e.g. oik_loaded action
- They implement dependency checking in response to admin_notices action.
- Each plugin uses the same library functions, which they load dynamically if oik is not already providing the logic. See oik_plugin_lazy_activation()
I’ve used this plugin dependency logic in many of my plugins, extending it to support checking of dependencies on multiple plugins and checking for minimum required versions.
Recently (June/July 2015)
When I was updating my
oik-bwtrace plugin recently I looked more closely at the relationship between
oik-bwtrace. I concluded that in their existing form they were partially symbiotic plugins.
oikwill work without
oik-bwtraceis dependent upon
oikfor bootstrap code
oik-bwtraceis dependent upon
oikfor its admin user interface
- They share common logic for implementing tracing functions
oik-bwtraceand other plugins are dependent upon
oikfor the trace functions
oiktrace functions are dependent upon
oik-bwtracefor the actual implementation
What I actually wanted was…
oik-bwtrace should be dependent upon some functionality that’s currently delivered by the oik base plugin but should not require the whole plugin to be activated
oikbase plugin to be delivered as a set of modules or libraries
oik-bwtraceto be able to operate independently of
- Peaceful coexistence between plugins requiring or delivering library functions
Introducing shared library management
I already had a solution where a plugin could indicate a hard dependency on another plugin, but I also needed a solution where a plugin could indicate a dependency on some functionality, without being too concerned about who provided it.
So I developed some requirements for a shared library manager.
- Ability to request a library
- Notification actions when dependencies satisfied
- Dependency checking
- Shared delivery of library functions
- Applicable to plugins and themes
- Fallback support for standalone plugins
- Version checking
- Compatibility checking
- Plugin download and activation
Recent challenges (July 2015)
In parallel with developing the
oik-lib: shared library manager I developed the standalone solution for
But there were some problems.
- The upgrade path required plugins to be deactivated and reactivated. See How do I upgrade to oik-bwtrace v2.0.0?
- When updating the
oikbase plugin it effectively becomes deactivated, which can lead to these problems
Fatal error: Call to undefined function ...
Since the implementing files for the bw_backtrace() or bw_trace2() functions have not been loaded, any plugins or themes which try to use these functions, before notification that it’s safe to do so, produce this error.
- Alternatively, and much less problematic, any plugin that’s dependent upon oik may determine that it’s not present. Each plugin will produce a message requesting oik be installed and activated.
- Updating shared libraries to new versions can also lead to
Fatal error: Cannot redeclareconflicts.
The second set of problems can be resolved by making the
oik-lib plugin a Must-Use (MU) plugin.
Outline solution for oik-lib: shared library management
- Dynamically loads the mandatory libraries delivered by the plugins
- Polls to find the libraries each plugin shares oik_query_libs filter
- Responds to requests from plugins to load libraries on demand. oik_require_lib()
- Attempts to satisfy dependencies
- Attempts to perform compatibility checking and detect conflicts
- When a library has been loaded it notifies plugins through an action hook, oik_lib_loaded action
- Plugins can respond by loading their own private libraries and/or requesting other shared libraries
- APIs to facilitate other shared library requirements: autoload, library file loading
While the oik-lib shared library manager does not perform plugin download and activation, it will provide information to enable a third party repository manager to attempt to satisfy unsatisfied dependencies and/or resolve conflicts.
Compatibility checking requirements
These are some of the requirements for compatibility checking.
- Compatibility checking will be invoked at run-time
- Libraries can indicate their library dependencies
- Libraries can indicate their library version dependencies
- Libraries can indicate known conflicts with library versions or plugin versions
- Version checking to support semantic versioning and comparison operators
- Dependency resolution is deferred until a library is required
- First come first served approach
- If there is a compatibility or dependency problem then the API will return a WP_Error
- The WP_Error may include data indicating the cause for the problem
- No attempt to resolve the problem will be performed by oik-lib
- The calling routine should respond accordingly
- The calling routine may opt to use a fallback method
Where do we go from here?
Work to do
The solution is not yet fully implemented…
- The version checking logic is still in its infancy
- There is no conflict checking
- It does not support multi-file shareable shared libraries
- There are some challenges regarding localization
Develop more real world examples
Here are more examples of oik base functionality that will be converted into shared libraries. This may enable plugins which are currently dependent to either become standalone or dependent upon a selection of alternative plugins.
- Shortcode APIs, shortcode help and shortcode UI integration
- Custom post type and custom field APIs
- Admin page / settings APIs
- Admin list table APIs
- User related APIs
- jQuery library APIs
- Plugin & theme upgrade APIs
Integration with Composer
You’ll also notice that I haven’t yet mentioned Composer. To be honest, I haven’t thought enough about Composer. I can see its benefits in helping to manage the build and deployment of the shared libraries that a plugin delivers. But I can also envisage using Git submodules to do something similar.
But there’s also the “where does that come from?” thing that Composer does quite well, and the automatic creation of autoloading. Suffice it to say, there’s still a lot of work to be done.
- How I would solve plugin dependencies, by Ryan McCue
- How I would solve plugin dependencies, lol I wouldn’t, by Gary Pendergast
- #22316 (Plugin Dependencies (Yet Another Plugin Dependencies Ticket)) – WordPress Trac
- Solving dependency management in WordPress plugins, by Coen Jacobs
- Composer in WordPress
|Plugin||APIs & hooks|
|oik-libs||oik-libs: Shared Library Repository files|
Other potential library sources
The following plugins contain functionality that could be offered as shared libraries.
- BuddyPress: xProfile
- Jetpack modules: publicize
- WooCommerce: countries and currencies
Other libraries that are often needed
- Custom meta boxes: field types
- Authentication: Basic, OAuth, OAuth2