Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
46.67% |
21 / 45 |
|
22.22% |
2 / 9 |
CRAP | |
0.00% |
0 / 1 |
Hooks | |
46.67% |
21 / 45 |
|
22.22% |
2 / 9 |
60.84 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
onSetup | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
20 | |||
onBeforePageDisplay | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
12 | |||
getSchemas | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
getEventLoggingConfig | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
1 | |||
getModuleData | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
onGetPreferences | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
2 | |||
onCanonicalNamespaces | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
loadEventStreamConfigs | |
84.62% |
11 / 13 |
|
0.00% |
0 / 1 |
3.03 |
1 | <?php |
2 | /** |
3 | * Hooks for EventLogging extension. |
4 | * |
5 | * @file |
6 | * |
7 | * @ingroup Extensions |
8 | * @ingroup EventLogging |
9 | * |
10 | * @author Ori Livneh <ori@wikimedia.org> |
11 | */ |
12 | |
13 | namespace MediaWiki\Extension\EventLogging; |
14 | |
15 | use MediaWiki\Config\Config; |
16 | use MediaWiki\Hook\CanonicalNamespacesHook; |
17 | use MediaWiki\MediaWikiServices; |
18 | use MediaWiki\Output\Hook\BeforePageDisplayHook; |
19 | use MediaWiki\Output\OutputPage; |
20 | use MediaWiki\Preferences\Hook\GetPreferencesHook; |
21 | use MediaWiki\Registration\ExtensionRegistry; |
22 | use MediaWiki\ResourceLoader as RL; |
23 | use MediaWiki\User\Options\UserOptionsLookup; |
24 | use MediaWiki\User\User; |
25 | use Skin; |
26 | |
27 | class Hooks implements |
28 | CanonicalNamespacesHook, |
29 | BeforePageDisplayHook, |
30 | GetPreferencesHook |
31 | { |
32 | |
33 | /** |
34 | * The list of stream config settings that should be sent to the client as part of the |
35 | * ext.eventLogging RL module. |
36 | * |
37 | * @var string[] |
38 | */ |
39 | private const STREAM_CONFIG_SETTINGS_ALLOWLIST = [ |
40 | 'sample', |
41 | 'producers', |
42 | ]; |
43 | |
44 | private UserOptionsLookup $userOptionsLookup; |
45 | |
46 | public function __construct( |
47 | UserOptionsLookup $userOptionsLookup |
48 | ) { |
49 | $this->userOptionsLookup = $userOptionsLookup; |
50 | } |
51 | |
52 | /** |
53 | * Emit a debug log message for each invalid or unset |
54 | * configuration variable (if any). |
55 | */ |
56 | public static function onSetup(): void { |
57 | global $wgEventLoggingBaseUri, $wgEventLoggingStreamNames; |
58 | |
59 | if ( $wgEventLoggingBaseUri === false ) { |
60 | EventLogging::getLogger()->debug( 'wgEventLoggingBaseUri has not been configured.' ); |
61 | } |
62 | |
63 | if ( $wgEventLoggingStreamNames !== false && !is_array( $wgEventLoggingStreamNames ) ) { |
64 | EventLogging::getLogger()->debug( |
65 | 'wgEventLoggingStreamNames is configured but is not a list of stream names' |
66 | ); |
67 | |
68 | $wgEventLoggingStreamNames = []; |
69 | } |
70 | } |
71 | |
72 | /** |
73 | * @param OutputPage $out |
74 | * @param Skin $skin |
75 | */ |
76 | public function onBeforePageDisplay( $out, $skin ): void { |
77 | $out->addModules( [ 'ext.eventLogging' ] ); |
78 | |
79 | if ( $this->userOptionsLookup->getIntOption( $out->getUser(), 'eventlogging-display-web' ) |
80 | || $this->userOptionsLookup->getIntOption( $out->getUser(), 'eventlogging-display-console' ) |
81 | ) { |
82 | $out->addModules( 'ext.eventLogging.debug' ); |
83 | } |
84 | } |
85 | |
86 | /** |
87 | * Return all schemas registered in extension.json EventLoggingSchemas and |
88 | * PHP $wgEventLoggingSchemas. The returned array will map from schema name |
89 | * to either MediaWiki (metawiki) revision id, or to a relative schema URI |
90 | * for forward compatibility with Event Platform. |
91 | * TODO: what happens when two extensions register the same schema with a different revision? |
92 | * |
93 | * @return array |
94 | */ |
95 | private static function getSchemas() { |
96 | global $wgEventLoggingSchemas; |
97 | |
98 | $extRegistry = ExtensionRegistry::getInstance(); |
99 | $schemas = $wgEventLoggingSchemas + $extRegistry->getAttribute( 'EventLoggingSchemas' ); |
100 | |
101 | return $schemas; |
102 | } |
103 | |
104 | /** |
105 | * Returns an object with EventLogging specific configuration extracted from |
106 | * MW Config and from extension attributes. |
107 | * |
108 | * @param Config $config |
109 | * @return array |
110 | */ |
111 | public static function getEventLoggingConfig( Config $config ) { |
112 | return [ |
113 | 'baseUrl' => $config->get( 'EventLoggingBaseUri' ), |
114 | 'schemasInfo' => self::getSchemas(), |
115 | 'serviceUri' => $config->get( 'EventLoggingServiceUri' ), |
116 | 'queueLingerSeconds' => $config->get( 'EventLoggingQueueLingerSeconds' ), |
117 | // If this is false, EventLogging will not use stream config. |
118 | 'streamConfigs' => self::loadEventStreamConfigs() |
119 | ]; |
120 | } |
121 | |
122 | /** |
123 | * Wraps getEventLoggingConfig for use with ResourceLoader. |
124 | * |
125 | * @param RL\Context $context |
126 | * @param Config $config |
127 | * @return array |
128 | */ |
129 | public static function getModuleData( RL\Context $context, Config $config ) { |
130 | return self::getEventLoggingConfig( $config ); |
131 | } |
132 | |
133 | /** |
134 | * @param User $user |
135 | * @param array &$preferences |
136 | */ |
137 | public function onGetPreferences( $user, &$preferences ): void { |
138 | // See 'ext.eventLogging.debug' module. |
139 | $preferences['eventlogging-display-web'] = [ |
140 | 'type' => 'api', |
141 | ]; |
142 | $preferences['eventlogging-display-console'] = [ |
143 | 'type' => 'api', |
144 | ]; |
145 | } |
146 | |
147 | /** @inheritDoc */ |
148 | public function onCanonicalNamespaces( &$namespaces ): void { |
149 | if ( JsonSchemaHooks::isSchemaNamespaceEnabled() ) { |
150 | $namespaces[ NS_SCHEMA ] = 'Schema'; |
151 | $namespaces[ NS_SCHEMA_TALK ] = 'Schema_talk'; |
152 | } |
153 | } |
154 | |
155 | /** |
156 | * Uses the EventStreamConfig extension to return a stream configs map |
157 | * (stream name -> config). The target stream configs to export are |
158 | * selected using the $wgEventLoggingStreamNames MW config variable. |
159 | * This is expected to be a list of stream names that are defined |
160 | * in $wgEventStreams. |
161 | * |
162 | * EventLogging uses this within the ./data.json data file |
163 | * from which it loads and configures all of the streams and stream |
164 | * configs to which it is allowed to submit events. |
165 | * |
166 | * This function returns an array mapping explicit stream names |
167 | * to their configurations. |
168 | * |
169 | * NOTE: We need a list of target streams to get configs for. |
170 | * $wgEventStreams may not explicitly define all stream names; |
171 | * it supports matching stream names by regexes. We need to |
172 | * give the EventStreamConfig StreamConfigs->get function |
173 | * a list of streams to search for in $wgEventStreams. |
174 | * $wgEventLoggingStreamNames is that list. |
175 | * |
176 | * @return array|bool Selected stream name -> stream configs |
177 | */ |
178 | private static function loadEventStreamConfigs() { |
179 | // FIXME: Does the following need to be logged? |
180 | if ( !ExtensionRegistry::getInstance()->isLoaded( 'EventStreamConfig' ) ) { |
181 | EventLogging::getLogger()->debug( 'EventStreamConfig is not installed' ); |
182 | return false; |
183 | } |
184 | |
185 | $streamConfigs = MediaWikiServices::getInstance()->getService( 'EventLogging.StreamConfigs' ); |
186 | |
187 | if ( $streamConfigs === false ) { |
188 | return false; |
189 | } |
190 | |
191 | // Only send stream config settings that should be sent to the client as part of the |
192 | // ext.eventLogging RL module. |
193 | $settingsAllowList = array_flip( self::STREAM_CONFIG_SETTINGS_ALLOWLIST ); |
194 | |
195 | return array_map( |
196 | static function ( $streamConfig ) use ( $settingsAllowList ) { |
197 | return array_intersect_key( $streamConfig, $settingsAllowList ); |
198 | }, |
199 | $streamConfigs |
200 | ); |
201 | } |
202 | } |