Observer Endpoints
Observer endpoints let plugins dispatch named events that any active module can subscribe to, without creating a direct dependency between them.
1. Define a Listener Interface
Create the interface in the dispatching plugin's domain/listener/ (or domain/event/) folder:
namespace plugin\TestPlugin\domain\event;
use plugin\TestPlugin\domain\model\TestValuesObject;
interface ITestListener
{
public function onTestHandler(TestValuesObject $testValuesObject): void;
}
2. Dispatch the Event
Call dispatchObserverEndpoint() with the interface and a closure, or use dispatchObserverEndpointByMethodName() as a shorthand:
use plugin\Modules\ModulesManager;
use plugin\TestPlugin\domain\event\ITestListener;
// Explicit closure — use when you need to control argument passing
ModulesManager::getInstance()->dispatchObserverEndpoint(
ITestListener::class,
function (ITestListener $instance, ...$args) {
$instance->onTestHandler(...$args);
},
$testValuesObject
);
// Shorthand — use when the method signature maps directly to the extra args
ModulesManager::getInstance()->dispatchObserverEndpointByMethodName(
ITestListener::class,
'onTestHandler',
$testValuesObject
);
All extra arguments beyond the closure are passed by reference. Mutating them inside the closure affects the original data.
3. Subscribe in a Module
Implement the listener interface in any module that needs to handle the event:
use DisplayPlugin;
use plugin\Modules\IModule;
use plugin\TestPlugin\domain\event\ITestListener;
use plugin\TestPlugin\domain\model\TestValuesObject;
class TestModulePlugin extends DisplayPlugin implements IModule, ITestListener
{
public function onTestHandler(TestValuesObject $testValuesObject): void
{
// Handle the event
}
}
New listener interfaces belong in domain/listener/ of the plugin that owns the event.