Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
43.48% covered (danger)
43.48%
10 / 23
25.00% covered (danger)
25.00%
1 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
EventSubscriberBase
43.48% covered (danger)
43.48%
10 / 23
25.00% covered (danger)
25.00%
1 / 4
28.06
0.00% covered (danger)
0.00%
0 / 1
 initEvents
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 initSubscriber
37.50% covered (danger)
37.50%
3 / 8
0.00% covered (danger)
0.00%
0 / 1
7.91
 registerListenerMethod
50.00% covered (danger)
50.00%
3 / 6
0.00% covered (danger)
0.00%
0 / 1
2.50
 registerListeners
37.50% covered (danger)
37.50%
3 / 8
0.00% covered (danger)
0.00%
0 / 1
5.20
1<?php
2
3namespace MediaWiki\DomainEvent;
4
5use InvalidArgumentException;
6use LogicException;
7
8/**
9 * Base class for classes that implement DomainEventSubscriber.
10 *
11 * This class provides a default implementation of registerListeners() that will
12 * attempt to find listener methods for the events defined in the constructor.
13 * Listener methods must have a name based on the event type, following the
14 * pattern "handle{$eventType}EventAfterCommit". The "AfterCommit" suffix
15 * specifies the dispatch mode. More dispatch modes will be defined in the
16 * future.
17 *
18 * Subclasses can either override registerListeners() and register listeners
19 * directly with the given DomainEventSource, or they can rely on the default
20 * implementation of registerListeners() which will automatically register
21 * method for each event passed to the constructor based on a naming convention.
22 *
23 * @since 1.44
24 * @unstable until 1.45, should become stable to extend
25 */
26abstract class EventSubscriberBase implements InitializableDomainEventSubscriber {
27
28    /**
29     * @var string[]
30     */
31    private array $eventTypes = [];
32
33    /**
34     * May be called from the constructor of subclasses that want to
35     * directly specify the list of events.
36     *
37     * @param string[] $events
38     */
39    protected function initEvents( array $events ): void {
40        $this->initSubscriber( [ 'events' => $events ] );
41    }
42
43    /**
44     * Called by DomainEventDispatcher to provide access to the list of events to
45     * subscribe to and any other relevant information from the extension.json.
46     *
47     * @param array $options the object spec describing the subscriber, typically
48     *        from extension.json.
49     */
50    public function initSubscriber( array $options ): void {
51        if ( !isset( $options['events'] ) ) {
52            throw new InvalidArgumentException( '$options must contain the "events" key' );
53        }
54
55        if ( $this->eventTypes && $options['events'] != $this->eventTypes ) {
56            throw new InvalidArgumentException(
57                'A different set of events was provided previously, ' .
58                'probably by a call to initEvents().'
59            );
60        }
61
62        $this->eventTypes = $options['events'];
63    }
64
65    protected function registerListenerMethod(
66        DomainEventSource $eventSource,
67        string $eventType,
68        ?string $method = null
69    ) {
70        // TODO: use a different prefix, dispatch on dispatch mode
71        $method ??= "handle{$eventType}EventAfterCommit";
72
73        if ( !method_exists( $this, $method ) ) {
74            throw new LogicException(
75                "Missing listener method $method on " . get_class( $this )
76            );
77        }
78
79        $eventSource->registerListener( $eventType, [ $this, $method ] );
80    }
81
82    /**
83     * This default implementation of registerListeners() will automatically
84     * register a listener method for each event passed to initEvents() or
85     * initSubscriber(). The methods have to start with "handler" followed
86     * by the name of the event followed by "Event" followed by an appropriate
87     * suffix, e.g. handlePageUpdatedEventAfterCommit().
88     *
89     * @stable to override
90     */
91    public function registerListeners( DomainEventSource $eventSource ): void {
92        if ( !$this->eventTypes ) {
93            throw new LogicException(
94                'Subclassed of EventSubscriberBase must either override ' .
95                'registerListeners or provide a list of event types via ' .
96                'initSubscriber() or initEvents().'
97            );
98        }
99
100        foreach ( $this->eventTypes as $type ) {
101            $this->registerListenerMethod( $eventSource, $type );
102        }
103    }
104
105}