3 namespace Civi\Core\Event
;
6 * A ServiceListener is a `callable` (supporting "__invoke()") which references
7 * a method of a service-object.
9 * The following two callables are conceptually similar:
11 * (A) addListener('some.event', [Civi::service('foo'), 'doBar']);
12 * (B) addListener('some.event', new ServiceListener(['foo', 'doBar']));
14 * The difference is that (A) immediately instantiates the 'foo' service,
15 * whereas (B) instantiates `foo` lazily. (B) is more amenable to serialization,
16 * caching, etc. If you have a long-tail of many services/listeners/etc that
17 * are not required for every page-load, then (B) should perform better.
19 * @package Civi\Core\Event
21 class ServiceListener
{
25 * Ex: ['service_name', 'someMethod']
27 private $inertCb = NULL;
31 * Ex: [$svcObj, 'someMethod']
33 private $liveCb = NULL;
36 * @var \Symfony\Component\DependencyInjection\ContainerInterface
38 private $container = NULL;
41 * @param array $callback
42 * Ex: ['service_name', 'someMethod']
44 public function __construct($callback) {
45 $this->inertCb
= $callback;
48 public function __invoke(...$args) {
49 if ($this->liveCb
=== NULL) {
50 $c = $this->container ?
: \Civi
::container();
51 $this->liveCb
= [$c->get($this->inertCb
[0]), $this->inertCb
[1]];
53 return call_user_func_array($this->liveCb
, $args);
56 public function __toString() {
58 if (\Civi\Core\Container
::isContainerBooted()) {
60 $c = $this->container ?
: \Civi
::container();
61 $class = $c->findDefinition($this->inertCb
[0])->getClass();
63 catch (Throwable
$t) {
67 return sprintf('$(%s)->%s($e) [%s]', $this->inertCb
[0], $this->inertCb
[1], $class);
70 return sprintf('\$(%s)->%s($e)', $this->inertCb
[0], $this->inertCb
[1]);
74 public function __sleep() {
79 * @param \Symfony\Component\DependencyInjection\ContainerInterface $container
82 public function setContainer(\Symfony\Component\DependencyInjection\ContainerInterface
$container) {
83 $this->container
= $container;