stellarwp / plugin-absorber
Safely load bundled WordPress plugins inside a host plugin, togglable or always-on, without fatal errors.
Requires
- php: >=7.4
- stellarwp/container-contract: ^1.1
Requires (Dev)
- codeception/module-asserts: ^1.0
- codeception/util-universalframework: ^1.0
- lucatume/di52: ^3.0
- lucatume/wp-browser: ^3.6.5
- php-stubs/wordpress-stubs: ~6.4.0
- phpstan/phpstan: ~1.12.0
- phpunit/phpunit: ^9.5
- szepeviktor/phpstan-wordpress: ~1.3.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-09-10 18:19:54 UTC
README
Safely load bundled WordPress plugins inside a host plugin — togglable or always-on — without re-declaration fatal errors.
Requires PHP 7.4+ and WordPress 6.4+.
Install
composer require stellarwp/plugin-absorber
Use Strauss — two plugins shipping different versions of this library will collide otherwise. Installing has the one prefixing rule you must not get wrong.
Quick start
use Nexcess\PluginAbsorber\Config; use Nexcess\PluginAbsorber\Absorber; add_action( 'plugins_loaded', function () { Config::set_hook_prefix( 'give' ); // required — keys the hooks and options Config::set_container( give()->container ); // required — every part of the library comes from it Absorber::register( [ 'slug' => 'give-recurring', 'bundled_plugin_file' => __DIR__ . '/sub-plugins/recurring/give-recurring.php', 'plugin_loaded_constant' => 'GIVE_RECURRING_VERSION', 'standalone_plugin_basename' => 'give-recurring/give-recurring.php', ] ); Absorber::boot(); }, 0 );
The container is required, and any StellarWP ContainerInterface implementation will do — the one
you already hand to Telemetry or Uplink.
If your plugin can run on multisite, add
Config::set_host_plugin_basename( plugin_basename( __FILE__ ) ). It is a no-op off a network, so set
it unconditionally: it stops the library deactivating a network-active standalone when your host
plugin is not itself network-activated, which would leave the network's other sites with no copy of
it at all.
Keep the , 0. Anything below plugins_loaded priority 5 wires cleanly; priority 0, in the
block that owns your container rather than a service provider, is the recommendation. Booting at 5
or later still works, with the whole sequence running inline and reported through
_doing_it_wrong(). Configuration explains both, and closes with a complete
bootstrap — two sub-plugins, every optional key.
Docs
- Installing — Composer, Strauss, and the constants Strauss must leave alone.
- Configuration — the hook prefix, the container, every sub-plugin key.
- Recipes — a settings toggle, a manifest of add-ons, and staging the absorption across releases.
- Git history — a script that brings the standalone's commits and blame across with its code.
- Conflict handling — the policies, when they run, and the guard's limits.
- Filters — the runtime overrides for policies and notice text.
- Actions — what the library reports as it loads and skips.
- Notices — where the queue lives, who may see it, and how to render it yourself.
- Extending — swapping out a piece of the library.
- Tests — running the suite, the fixtures and traits it offers, and every scenario it drives the library through.
docs/ and tests/ are both export-ignored, so neither ships in a vendored copy — these links
point at the repository rather than at paths that would be missing beside the installed source.
License
This program is free software; you can redistribute it and/or modify it under the terms of the
GNU General Public License as published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version. See LICENSE.