Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 67 |
|
0.00% |
0 / 12 |
CRAP | |
0.00% |
0 / 1 |
MassMessageHooks | |
0.00% |
0 / 67 |
|
0.00% |
0 / 12 |
1406 | |
0.00% |
0 / 1 |
onParserFirstCallInit | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
outputParserFunction | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
12 | |||
storeDataParserFunction | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
12 | |||
onUserGetReservedNames | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
onAPIQuerySiteInfoStatisticsInfo | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
onSkinTemplateNavigation__Universal | |
0.00% |
0 / 27 |
|
0.00% |
0 / 1 |
240 | |||
onBeforePageDisplay | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
30 | |||
onRejectParserCacheValue | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
12 | |||
onEmailConfirmed | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
onListDefinedTags | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
onChangeTagsListActive | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
addRegisterTags | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | |
3 | // phpcs:disable MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName |
4 | |
5 | namespace MediaWiki\MassMessage; |
6 | |
7 | use MediaWiki\Api\Hook\APIQuerySiteInfoStatisticsInfoHook; |
8 | use MediaWiki\ChangeTags\Hook\ChangeTagsListActiveHook; |
9 | use MediaWiki\ChangeTags\Hook\ListDefinedTagsHook; |
10 | use MediaWiki\Hook\ParserFirstCallInitHook; |
11 | use MediaWiki\Hook\RejectParserCacheValueHook; |
12 | use MediaWiki\Hook\SkinTemplateNavigation__UniversalHook; |
13 | use MediaWiki\MainConfigNames; |
14 | use MediaWiki\MediaWikiServices; |
15 | use MediaWiki\Output\Hook\BeforePageDisplayHook; |
16 | use MediaWiki\Output\OutputPage; |
17 | use MediaWiki\Parser\Parser; |
18 | use MediaWiki\Parser\ParserOptions; |
19 | use MediaWiki\Parser\ParserOutput; |
20 | use MediaWiki\SpecialPage\SpecialPage; |
21 | use MediaWiki\User\Hook\UserGetReservedNamesHook; |
22 | use MediaWiki\User\User; |
23 | use Skin; |
24 | use WikiPage; |
25 | |
26 | /** |
27 | * Hooks! |
28 | */ |
29 | |
30 | class MassMessageHooks implements |
31 | ParserFirstCallInitHook, |
32 | APIQuerySiteInfoStatisticsInfoHook, |
33 | UserGetReservedNamesHook, |
34 | SkinTemplateNavigation__UniversalHook, |
35 | BeforePageDisplayHook, |
36 | ListDefinedTagsHook, |
37 | ChangeTagsListActiveHook, |
38 | RejectParserCacheValueHook |
39 | { |
40 | |
41 | /** |
42 | * Hook to load our parser function. |
43 | * |
44 | * @param Parser $parser |
45 | */ |
46 | public function onParserFirstCallInit( $parser ) { |
47 | $parser->setFunctionHook( 'target', [ __CLASS__, 'outputParserFunction' ] ); |
48 | } |
49 | |
50 | /** |
51 | * Main parser function for {{#target:User talk:Example|en.wikipedia.org}}. |
52 | * Prepares the human facing output. |
53 | * Hostname is optional for local delivery. |
54 | * |
55 | * @param Parser $parser |
56 | * @param string $page |
57 | * @param string $site |
58 | * @return array |
59 | */ |
60 | public static function outputParserFunction( Parser $parser, $page, $site = '' ) { |
61 | $config = MediaWikiServices::getInstance()->getMainConfig(); |
62 | |
63 | $parser->addTrackingCategory( 'massmessage-list-category' ); |
64 | |
65 | $data = MassMessage::processPFData( $page, $site ); |
66 | if ( isset( $data['error'] ) ) { |
67 | return $data; |
68 | } |
69 | |
70 | // Use a message so wikis can customize the output. |
71 | if ( $config->get( 'AllowGlobalMessaging' ) ) { |
72 | $msg = wfMessage( 'massmessage-target' ) |
73 | ->params( $data['site'], $config->get( MainConfigNames::Script ), $data['title'] )->plain(); |
74 | } else { |
75 | $msg = wfMessage( 'massmessage-target-local' )->params( $data['title'] )->plain(); |
76 | } |
77 | |
78 | return [ $msg, 'noparse' => false ]; |
79 | } |
80 | |
81 | /** |
82 | * Reads the parser function and extracts the data from it. |
83 | * |
84 | * @param Parser $parser |
85 | * @param string $page |
86 | * @param string $site |
87 | * @return string |
88 | */ |
89 | public static function storeDataParserFunction( Parser $parser, $page, $site = '' ) { |
90 | $data = MassMessage::processPFData( $page, $site ); |
91 | if ( isset( $data['error'] ) ) { |
92 | // Output doesn't matter |
93 | return ''; |
94 | } |
95 | $output = $parser->getOutput(); |
96 | $current = $output->getExtensionData( 'massmessage-targets' ); |
97 | if ( !$current ) { |
98 | $output->setExtensionData( 'massmessage-targets', [ $data ] ); |
99 | } else { |
100 | $output->setExtensionData( 'massmessage-targets', |
101 | array_merge( $current, [ $data ] ) ); |
102 | } |
103 | return ''; |
104 | } |
105 | |
106 | /** |
107 | * Add our username to the list of reserved ones |
108 | * |
109 | * @param array &$reservedUsernames |
110 | */ |
111 | public function onUserGetReservedNames( &$reservedUsernames ) { |
112 | $reservedUsernames[] = MediaWikiServices::getInstance()->getMainConfig()->get( 'MassMessageAccountUsername' ); |
113 | } |
114 | |
115 | /** |
116 | * Add the number of queued messages to &meta=siteinfo&siprop=statistics. |
117 | * |
118 | * @param array &$result |
119 | */ |
120 | public function onAPIQuerySiteInfoStatisticsInfo( &$result ) { |
121 | $result['queued-massmessages'] = MassMessage::getQueuedCount(); |
122 | } |
123 | |
124 | /** |
125 | * Override the Edit tab for delivery lists. |
126 | * |
127 | * @param \SkinTemplate $sktemplate |
128 | * @param array &$links |
129 | */ |
130 | public function onSkinTemplateNavigation__Universal( $sktemplate, &$links ): void { |
131 | $title = $sktemplate->getTitle(); |
132 | if ( $title->hasContentModel( 'MassMessageListContent' ) |
133 | && array_key_exists( 'edit', $links['views'] ) |
134 | ) { |
135 | // Get the revision being viewed, if applicable |
136 | $request = $sktemplate->getRequest(); |
137 | $direction = $request->getVal( 'direction' ); |
138 | $diff = $request->getVal( 'diff' ); |
139 | // getInt is guaranteed to return an integer, 0 if invalid |
140 | $oldid = $request->getInt( 'oldid' ); |
141 | $revisionLookup = MediaWikiServices::getInstance()->getRevisionLookup(); |
142 | $oldRev = $revisionLookup->getRevisionById( $oldid ); |
143 | if ( $direction === 'next' && $oldRev ) { |
144 | $next = $revisionLookup->getNextRevision( $oldRev ); |
145 | $revId = $next ? $next->getId() : $oldid; |
146 | } elseif ( $direction === 'prev' && $oldRev ) { |
147 | $prev = $revisionLookup->getPreviousRevision( $oldRev ); |
148 | $revId = $prev ? $prev->getId() : $oldid; |
149 | } elseif ( $diff !== null ) { |
150 | if ( ctype_digit( $diff ) ) { |
151 | $revId = (int)$diff; |
152 | } elseif ( $diff === 'next' && $oldRev ) { |
153 | $next = $revisionLookup->getNextRevision( $oldRev ); |
154 | $revId = $next ? $next->getId() : $oldid; |
155 | } else { |
156 | // diff is 'prev' or gibberish |
157 | $revId = $oldid; |
158 | } |
159 | } else { |
160 | $revId = $oldid; |
161 | } |
162 | |
163 | $query = ( $revId > 0 ) ? 'oldid=' . $revId : ''; |
164 | $links['views']['edit']['href'] = SpecialPage::getTitleFor( |
165 | 'EditMassMessageList', $title |
166 | )->getFullUrl( $query ); |
167 | } |
168 | } |
169 | |
170 | /** |
171 | * Add scripts and styles. |
172 | * |
173 | * @param OutputPage $out |
174 | * @param Skin $skin |
175 | */ |
176 | public function onBeforePageDisplay( $out, $skin ): void { |
177 | $title = $out->getTitle(); |
178 | if ( $title->exists() && $title->hasContentModel( 'MassMessageListContent' ) ) { |
179 | $permManager = MediaWikiServices::getInstance()->getPermissionManager(); |
180 | if ( $out->getRevisionId() === $title->getLatestRevId() |
181 | && $permManager->quickUserCan( 'edit', $out->getUser(), $title ) |
182 | ) { |
183 | $out->addBodyClasses( 'mw-massmessage-editable' ); |
184 | } |
185 | } |
186 | } |
187 | |
188 | /** |
189 | * Hook: RejectParserCacheValue |
190 | * |
191 | * Reject old cache entries that don't contain our "ext.MassMessage.content" |
192 | * module. |
193 | * |
194 | * @param ParserOutput $parserOutput |
195 | * @param WikiPage $wikiPage |
196 | * @param ParserOptions $parserOptions |
197 | * @return bool |
198 | */ |
199 | public function onRejectParserCacheValue( $parserOutput, $wikiPage, |
200 | $parserOptions |
201 | ): bool { |
202 | if ( $wikiPage->getTitle()->hasContentModel( 'MassMessageListContent' ) && |
203 | !in_array( 'ext.MassMessage.content', $parserOutput->getModules() ) |
204 | ) { |
205 | return false; |
206 | } |
207 | |
208 | return true; |
209 | } |
210 | |
211 | /** |
212 | * Mark the messenger account's email as confirmed in job runs (T75061). |
213 | * |
214 | * @param User $user |
215 | * @param bool &$confirmed |
216 | * @return bool |
217 | */ |
218 | public static function onEmailConfirmed( User $user, &$confirmed ) { |
219 | if ( $user->getId() === MassMessage::getMessengerUser()->getId() ) { |
220 | $confirmed = true; |
221 | // Skip further checks |
222 | return false; |
223 | } |
224 | return true; |
225 | } |
226 | |
227 | /** |
228 | * Register the change tag for MassMessage delivery |
229 | * |
230 | * @param array &$tags |
231 | */ |
232 | public function onListDefinedTags( &$tags ) { |
233 | $this->addRegisterTags( $tags ); |
234 | } |
235 | |
236 | /** |
237 | * Register the change tag for MassMessage delivery |
238 | * |
239 | * @param array &$tags |
240 | */ |
241 | public function onChangeTagsListActive( &$tags ) { |
242 | $this->addRegisterTags( $tags ); |
243 | } |
244 | |
245 | /** |
246 | * @param array &$tags |
247 | */ |
248 | private function addRegisterTags( &$tags ) { |
249 | $tags[] = 'massmessage-delivery'; |
250 | } |
251 | } |