Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 147 |
|
0.00% |
0 / 6 |
CRAP | |
0.00% |
0 / 1 |
ApiQueryAllMessages | |
0.00% |
0 / 146 |
|
0.00% |
0 / 6 |
1892 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
2 | |||
execute | |
0.00% |
0 / 95 |
|
0.00% |
0 / 1 |
1332 | |||
getCacheMode | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
12 | |||
getAllowedParams | |
0.00% |
0 / 33 |
|
0.00% |
0 / 1 |
2 | |||
getExamplesMessages | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
2 | |||
getHelpUrls | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | /** |
3 | * Copyright © 2006 Yuri Astrakhan "<Firstname><Lastname>@gmail.com" |
4 | * |
5 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License as published by |
7 | * the Free Software Foundation; either version 2 of the License, or |
8 | * (at your option) any later version. |
9 | * |
10 | * This program is distributed in the hope that it will be useful, |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | * GNU General Public License for more details. |
14 | * |
15 | * You should have received a copy of the GNU General Public License along |
16 | * with this program; if not, write to the Free Software Foundation, Inc., |
17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
18 | * http://www.gnu.org/copyleft/gpl.html |
19 | * |
20 | * @file |
21 | */ |
22 | |
23 | namespace MediaWiki\Api; |
24 | |
25 | use LocalisationCache; |
26 | use MediaWiki\Language\Language; |
27 | use MediaWiki\Languages\LanguageFactory; |
28 | use MediaWiki\Languages\LanguageNameUtils; |
29 | use MediaWiki\Pager\AllMessagesTablePager; |
30 | use MediaWiki\Title\Title; |
31 | use MessageCache; |
32 | use Wikimedia\ParamValidator\ParamValidator; |
33 | |
34 | /** |
35 | * A query action to return messages from site message cache |
36 | * |
37 | * @ingroup API |
38 | */ |
39 | class ApiQueryAllMessages extends ApiQueryBase { |
40 | |
41 | private Language $contentLanguage; |
42 | private LanguageFactory $languageFactory; |
43 | private LanguageNameUtils $languageNameUtils; |
44 | private LocalisationCache $localisationCache; |
45 | private MessageCache $messageCache; |
46 | |
47 | public function __construct( |
48 | ApiQuery $query, |
49 | string $moduleName, |
50 | Language $contentLanguage, |
51 | LanguageFactory $languageFactory, |
52 | LanguageNameUtils $languageNameUtils, |
53 | LocalisationCache $localisationCache, |
54 | MessageCache $messageCache |
55 | ) { |
56 | parent::__construct( $query, $moduleName, 'am' ); |
57 | $this->contentLanguage = $contentLanguage; |
58 | $this->languageFactory = $languageFactory; |
59 | $this->languageNameUtils = $languageNameUtils; |
60 | $this->localisationCache = $localisationCache; |
61 | $this->messageCache = $messageCache; |
62 | } |
63 | |
64 | public function execute() { |
65 | $params = $this->extractRequestParams(); |
66 | if ( $params['lang'] === null ) { |
67 | $langObj = $this->getLanguage(); |
68 | } elseif ( !$this->languageNameUtils->isValidCode( $params['lang'] ) ) { |
69 | $this->dieWithError( |
70 | [ 'apierror-invalidlang', $this->encodeParamName( 'lang' ) ], 'invalidlang' |
71 | ); |
72 | } else { |
73 | $langObj = $this->languageFactory->getLanguage( $params['lang'] ); |
74 | } |
75 | |
76 | if ( $params['enableparser'] ) { |
77 | if ( $params['title'] !== null ) { |
78 | $title = Title::newFromText( $params['title'] ); |
79 | if ( !$title || $title->isExternal() ) { |
80 | $this->dieWithError( [ 'apierror-invalidtitle', wfEscapeWikiText( $params['title'] ) ] ); |
81 | } |
82 | } else { |
83 | $title = Title::newFromText( 'API' ); |
84 | } |
85 | } |
86 | |
87 | $prop = array_fill_keys( (array)$params['prop'], true ); |
88 | |
89 | // Determine which messages should we print |
90 | if ( in_array( '*', $params['messages'] ) ) { |
91 | $message_names = $this->localisationCache->getSubitemList( $langObj->getCode(), 'messages' ) ?? []; |
92 | if ( $params['includelocal'] ) { |
93 | $message_names = array_unique( array_merge( |
94 | $message_names, |
95 | // Pass in the content language code so we get local messages that have a |
96 | // MediaWiki:msgkey page. We might theoretically miss messages that have no |
97 | // MediaWiki:msgkey page but do have a MediaWiki:msgkey/lang page, but that's |
98 | // just a stupid case. |
99 | $this->messageCache->getAllMessageKeys( $this->contentLanguage->getCode() ) |
100 | ) ); |
101 | } |
102 | sort( $message_names ); |
103 | $messages_target = $message_names; |
104 | } else { |
105 | $messages_target = $params['messages']; |
106 | } |
107 | |
108 | // Filter messages that have the specified prefix |
109 | // Because we sorted the message array earlier, they will appear in a clump: |
110 | if ( isset( $params['prefix'] ) ) { |
111 | $skip = false; |
112 | $messages_filtered = []; |
113 | foreach ( $messages_target as $message ) { |
114 | if ( str_starts_with( $message, $params['prefix'] ) ) { |
115 | if ( !$skip ) { |
116 | $skip = true; |
117 | } |
118 | $messages_filtered[] = $message; |
119 | } elseif ( $skip ) { |
120 | break; |
121 | } |
122 | } |
123 | $messages_target = $messages_filtered; |
124 | } |
125 | |
126 | // Filter messages that contain specified string |
127 | if ( isset( $params['filter'] ) ) { |
128 | $messages_filtered = []; |
129 | foreach ( $messages_target as $message ) { |
130 | if ( str_contains( $message, $params['filter'] ) ) { |
131 | $messages_filtered[] = $message; |
132 | } |
133 | } |
134 | $messages_target = $messages_filtered; |
135 | } |
136 | |
137 | // Whether we have any sort of message customisation filtering |
138 | $customiseFilterEnabled = $params['customised'] !== 'all'; |
139 | if ( $customiseFilterEnabled ) { |
140 | $customisedMessages = AllMessagesTablePager::getCustomisedStatuses( |
141 | array_map( |
142 | [ $langObj, 'ucfirst' ], |
143 | $messages_target |
144 | ), |
145 | $langObj->getCode(), |
146 | !$langObj->equals( $this->contentLanguage ), |
147 | $this->getDB() |
148 | ); |
149 | |
150 | $customised = $params['customised'] === 'modified'; |
151 | } |
152 | |
153 | // Get all requested messages and print the result |
154 | $skip = $params['from'] !== null; |
155 | $useto = $params['to'] !== null; |
156 | $result = $this->getResult(); |
157 | foreach ( $messages_target as $message ) { |
158 | // Skip all messages up to $params['from'] |
159 | if ( $skip && $message === $params['from'] ) { |
160 | $skip = false; |
161 | } |
162 | |
163 | if ( $useto && $message > $params['to'] ) { |
164 | break; |
165 | } |
166 | |
167 | if ( !$skip ) { |
168 | $a = [ |
169 | 'name' => $message, |
170 | 'normalizedname' => MessageCache::normalizeKey( $message ), |
171 | ]; |
172 | |
173 | $args = []; |
174 | if ( isset( $params['args'] ) && count( $params['args'] ) != 0 ) { |
175 | $args = $params['args']; |
176 | } |
177 | |
178 | if ( $customiseFilterEnabled ) { |
179 | $messageIsCustomised = isset( $customisedMessages['pages'][$langObj->ucfirst( $message )] ); |
180 | // @phan-suppress-next-line PhanPossiblyUndeclaredVariable customised is set when used |
181 | if ( $customised === $messageIsCustomised ) { |
182 | // @phan-suppress-next-line PhanPossiblyUndeclaredVariable customised is set when used |
183 | if ( $customised ) { |
184 | $a['customised'] = true; |
185 | } |
186 | } else { |
187 | continue; |
188 | } |
189 | } |
190 | |
191 | $msg = $this->msg( $message, $args )->inLanguage( $langObj ); |
192 | |
193 | if ( !$msg->exists() ) { |
194 | $a['missing'] = true; |
195 | } else { |
196 | // Check if the parser is enabled: |
197 | if ( $params['enableparser'] ) { |
198 | // @phan-suppress-next-line PhanPossiblyUndeclaredVariable title is set when used |
199 | $msgString = $msg->page( $title )->text(); |
200 | } else { |
201 | $msgString = $msg->plain(); |
202 | } |
203 | if ( !$params['nocontent'] ) { |
204 | ApiResult::setContentValue( $a, 'content', $msgString ); |
205 | } |
206 | if ( isset( $prop['default'] ) ) { |
207 | $default = $this->msg( $message )->inLanguage( $langObj )->useDatabase( false ); |
208 | if ( !$default->exists() ) { |
209 | $a['defaultmissing'] = true; |
210 | } elseif ( $default->plain() != $msgString ) { |
211 | $a['default'] = $default->plain(); |
212 | } |
213 | } |
214 | } |
215 | $fit = $result->addValue( [ 'query', $this->getModuleName() ], null, $a ); |
216 | if ( !$fit ) { |
217 | $this->setContinueEnumParameter( 'from', $message ); |
218 | break; |
219 | } |
220 | } |
221 | } |
222 | $result->addIndexedTagName( [ 'query', $this->getModuleName() ], 'message' ); |
223 | } |
224 | |
225 | public function getCacheMode( $params ) { |
226 | if ( $params['lang'] === null ) { |
227 | // Language not specified, will be fetched from preferences |
228 | return 'anon-public-user-private'; |
229 | } elseif ( $params['enableparser'] ) { |
230 | // User-specific parser options will be used |
231 | return 'anon-public-user-private'; |
232 | } else { |
233 | // OK to cache |
234 | return 'public'; |
235 | } |
236 | } |
237 | |
238 | public function getAllowedParams() { |
239 | return [ |
240 | 'messages' => [ |
241 | ParamValidator::PARAM_DEFAULT => '*', |
242 | ParamValidator::PARAM_ISMULTI => true, |
243 | ], |
244 | 'prop' => [ |
245 | ParamValidator::PARAM_ISMULTI => true, |
246 | ParamValidator::PARAM_TYPE => [ |
247 | 'default' |
248 | ] |
249 | ], |
250 | 'enableparser' => false, |
251 | 'nocontent' => false, |
252 | 'includelocal' => false, |
253 | 'args' => [ |
254 | ParamValidator::PARAM_ISMULTI => true, |
255 | ParamValidator::PARAM_ALLOW_DUPLICATES => true, |
256 | ], |
257 | 'filter' => [], |
258 | 'customised' => [ |
259 | ParamValidator::PARAM_DEFAULT => 'all', |
260 | ParamValidator::PARAM_TYPE => [ |
261 | 'all', |
262 | 'modified', |
263 | 'unmodified' |
264 | ] |
265 | ], |
266 | 'lang' => null, |
267 | 'from' => null, |
268 | 'to' => null, |
269 | 'title' => null, |
270 | 'prefix' => null, |
271 | ]; |
272 | } |
273 | |
274 | protected function getExamplesMessages() { |
275 | return [ |
276 | 'action=query&meta=allmessages&refix=ipb-' |
277 | => 'apihelp-query+allmessages-example-ipb', |
278 | 'action=query&meta=allmessages&ammessages=august|mainpage&amlang=de' |
279 | => 'apihelp-query+allmessages-example-de', |
280 | ]; |
281 | } |
282 | |
283 | public function getHelpUrls() { |
284 | return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Allmessages'; |
285 | } |
286 | } |
287 | |
288 | /** @deprecated class alias since 1.43 */ |
289 | class_alias( ApiQueryAllMessages::class, 'ApiQueryAllMessages' ); |