MediaWiki master
BlockLogFormatter.php
Go to the documentation of this file.
1<?php
30
37 protected function getMessageParameters() {
38 $params = parent::getMessageParameters();
39
40 $title = $this->entry->getTarget();
41 if ( substr( $title->getText(), 0, 1 ) === '#' ) {
42 // autoblock - no user link possible
43 $params[2] = $title->getText();
44 $params[3] = ''; // no user name for gender use
45 } else {
46 // Create a user link for the blocked
47 $username = $title->getText();
48 // @todo Store the user identifier in the parameters
49 // to make this faster for future log entries
50 $targetUser = User::newFromName( $username, false );
51 $params[2] = Message::rawParam( $this->makeUserLink( $targetUser, Linker::TOOL_LINKS_NOBLOCK ) );
52 $params[3] = $username; // plain user name for gender use
53 }
54
55 $subtype = $this->entry->getSubtype();
56 if ( $subtype === 'block' || $subtype === 'reblock' ) {
57 if ( !isset( $params[4] ) ) {
58 // Very old log entry without duration: means infinity
59 $params[4] = 'infinity';
60 }
61 // Localize the duration, and add a tooltip
62 // in English to help visitors from other wikis.
63 // The lrm is needed to make sure that the number
64 // is shown on the correct side of the tooltip text.
65 // @phan-suppress-next-line SecurityCheck-DoubleEscaped
66 $durationTooltip = '&lrm;' . htmlspecialchars( $params[4] );
67 $blockExpiry = $this->context->getLanguage()->translateBlockExpiry(
68 $params[4],
69 $this->context->getUser(),
70 (int)wfTimestamp( TS_UNIX, $this->entry->getTimestamp() )
71 );
72 if ( $this->plaintext ) {
73 // @phan-suppress-next-line SecurityCheck-XSS Unlikely positive, only if language format is bad
74 $params[4] = Message::rawParam( $blockExpiry );
75 } else {
76 $params[4] = Message::rawParam(
77 "<span class=\"blockExpiry\" title=\"$durationTooltip\">" .
78 // @phan-suppress-next-line SecurityCheck-DoubleEscaped language class does not escape
79 htmlspecialchars( $blockExpiry ) .
80 '</span>'
81 );
82 }
83 $params[5] = isset( $params[5] ) ?
84 self::formatBlockFlags( $params[5], $this->context->getLanguage() ) : '';
85
86 // block restrictions
87 if ( isset( $params[6] ) ) {
88 $pages = $params[6]['pages'] ?? [];
89 $pageLinks = [];
90 foreach ( $pages as $page ) {
91 $pageLinks[] = $this->makePageLink( Title::newFromText( $page ) );
92 }
93
94 $rawNamespaces = $params[6]['namespaces'] ?? [];
95 $namespaces = [];
96 foreach ( $rawNamespaces as $ns ) {
97 $text = (int)$ns === NS_MAIN
98 ? $this->msg( 'blanknamespace' )->escaped()
99 : htmlspecialchars( $this->context->getLanguage()->getFormattedNsText( $ns ) );
100 if ( $this->plaintext ) {
101 // Because the plaintext cannot link to the Special:AllPages
102 // link that is linked to in non-plaintext mode, just return
103 // the name of the namespace.
104 $namespaces[] = $text;
105 } else {
106 $namespaces[] = $this->makePageLink(
107 SpecialPage::getTitleFor( 'Allpages' ),
108 [ 'namespace' => $ns ],
109 $text
110 );
111 }
112 }
113
114 $rawActions = $params[6]['actions'] ?? [];
115 $actions = [];
116 foreach ( $rawActions as $action ) {
117 $actions[] = $this->msg( 'ipb-action-' . $action )->escaped();
118 }
119
120 $restrictions = [];
121 if ( $pageLinks ) {
122 $restrictions[] = $this->msg( 'logentry-partialblock-block-page' )
123 ->numParams( count( $pageLinks ) )
124 ->rawParams( $this->context->getLanguage()->listToText( $pageLinks ) )->escaped();
125 }
126
127 if ( $namespaces ) {
128 $restrictions[] = $this->msg( 'logentry-partialblock-block-ns' )
129 ->numParams( count( $namespaces ) )
130 ->rawParams( $this->context->getLanguage()->listToText( $namespaces ) )->escaped();
131 }
132 $enablePartialActionBlocks = $this->context->getConfig()
133 ->get( MainConfigNames::EnablePartialActionBlocks );
134 if ( $actions && $enablePartialActionBlocks ) {
135 $restrictions[] = $this->msg( 'logentry-partialblock-block-action' )
136 ->numParams( count( $actions ) )
137 ->rawParams( $this->context->getLanguage()->listToText( $actions ) )->escaped();
138 }
139
140 $params[6] = Message::rawParam( $this->context->getLanguage()->listToText( $restrictions ) );
141 }
142 }
143
144 return $params;
145 }
146
147 protected function extractParameters() {
148 $params = parent::extractParameters();
149 // Legacy log params returning the params in index 3 and 4, moved to 4 and 5
150 if ( $this->entry->isLegacy() && isset( $params[3] ) ) {
151 if ( isset( $params[4] ) ) {
152 $params[5] = $params[4];
153 }
154 $params[4] = $params[3];
155 $params[3] = '';
156 }
157 return $params;
158 }
159
160 public function getPreloadTitles() {
161 $title = $this->entry->getTarget();
162 $preload = [];
163 // Preload user page for non-autoblocks
164 if ( substr( $title->getText(), 0, 1 ) !== '#' && $title->canExist() ) {
165 $preload[] = $title->getTalkPage();
166 }
167 // Preload page restriction
168 $params = $this->extractParameters();
169 if ( isset( $params[6]['pages'] ) ) {
170 foreach ( $params[6]['pages'] as $page ) {
171 $preload[] = Title::newFromText( $page );
172 }
173 }
174 return $preload;
175 }
176
177 public function getActionLinks() {
178 $subtype = $this->entry->getSubtype();
179 $linkRenderer = $this->getLinkRenderer();
180 if ( $this->entry->isDeleted( LogPage::DELETED_ACTION ) // Action is hidden
181 || !( $subtype === 'block' || $subtype === 'reblock' )
182 || !$this->context->getAuthority()->isAllowed( 'block' )
183 ) {
184 return '';
185 }
186
187 // Show unblock/change block link
188 $title = $this->entry->getTarget();
189 $links = [
190 $linkRenderer->makeKnownLink(
191 SpecialPage::getTitleFor( 'Unblock', $title->getDBkey() ),
192 $this->msg( 'unblocklink' )->text()
193 ),
194 $linkRenderer->makeKnownLink(
195 SpecialPage::getTitleFor( 'Block', $title->getDBkey() ),
196 $this->msg( 'change-blocklink' )->text()
197 )
198 ];
199
200 return $this->msg( 'parentheses' )->rawParams(
201 $this->context->getLanguage()->pipeList( $links ) )->escaped();
202 }
203
212 public static function formatBlockFlags( $flags, Language $lang ) {
213 $flags = trim( $flags );
214 if ( $flags === '' ) {
215 return ''; // nothing to do
216 }
217 $flags = explode( ',', $flags );
218 $flagsCount = count( $flags );
219
220 for ( $i = 0; $i < $flagsCount; $i++ ) {
221 $flags[$i] = self::formatBlockFlag( $flags[$i], $lang );
222 }
223
224 return wfMessage( 'parentheses' )->inLanguage( $lang )
225 ->rawParams( $lang->commaList( $flags ) )->escaped();
226 }
227
235 public static function formatBlockFlag( $flag, Language $lang ) {
236 static $messages = [];
237
238 if ( !isset( $messages[$flag] ) ) {
239 $messages[$flag] = htmlspecialchars( $flag ); // Fallback
240
241 // For grepping. The following core messages can be used here:
242 // * block-log-flags-angry-autoblock
243 // * block-log-flags-anononly
244 // * block-log-flags-hiddenname
245 // * block-log-flags-noautoblock
246 // * block-log-flags-nocreate
247 // * block-log-flags-noemail
248 // * block-log-flags-nousertalk
249 $msg = wfMessage( 'block-log-flags-' . $flag )->inLanguage( $lang );
250
251 if ( $msg->exists() ) {
252 $messages[$flag] = $msg->escaped();
253 }
254 }
255
256 return $messages[$flag];
257 }
258
259 protected function getParametersForApi() {
260 $entry = $this->entry;
262
263 static $map = [
264 // While this looks wrong to be starting at 5 rather than 4, it's
265 // because getMessageParameters uses $4 for its own purposes.
266 '5::duration',
267 '6:array:flags',
268 '6::flags' => '6:array:flags',
269 ];
270
271 foreach ( $map as $index => $key ) {
272 if ( isset( $params[$index] ) ) {
273 $params[$key] = $params[$index];
274 unset( $params[$index] );
275 }
276 }
277
278 ksort( $params );
279
280 $subtype = $entry->getSubtype();
281 if ( $subtype === 'block' || $subtype === 'reblock' ) {
282 // Defaults for old log entries missing some fields
283 $params += [
284 '5::duration' => 'infinity',
285 '6:array:flags' => [],
286 ];
287
288 if ( !is_array( $params['6:array:flags'] ) ) {
289 // @phan-suppress-next-line PhanSuspiciousValueComparison
290 $params['6:array:flags'] = $params['6:array:flags'] === ''
291 ? []
292 : explode( ',', $params['6:array:flags'] );
293 }
294
295 if ( wfIsInfinity( $params['5::duration'] ) ) {
296 // Normalize all possible values to one for pre-T241709 rows
297 $params['5::duration'] = 'infinity';
298 } else {
299 $ts = (int)wfTimestamp( TS_UNIX, $entry->getTimestamp() );
300 $expiry = strtotime( $params['5::duration'], $ts );
301 if ( $expiry !== false && $expiry > 0 ) {
302 $params[':timestamp:expiry'] = $expiry;
303 }
304 }
305 }
306
307 return $params;
308 }
309
314 public function formatParametersForApi() {
315 $ret = parent::formatParametersForApi();
316 if ( isset( $ret['flags'] ) ) {
317 ApiResult::setIndexedTagName( $ret['flags'], 'f' );
318 }
319
320 if ( isset( $ret['restrictions']['pages'] ) ) {
321 $ret['restrictions']['pages'] = array_map( function ( $title ) {
322 return $this->formatParameterValueForApi( 'page', 'title-link', $title );
323 }, $ret['restrictions']['pages'] );
324 ApiResult::setIndexedTagName( $ret['restrictions']['pages'], 'p' );
325 }
326
327 if ( isset( $ret['restrictions']['namespaces'] ) ) {
328 // @phan-suppress-next-line PhanTypeMismatchArgument False positive
329 ApiResult::setIndexedTagName( $ret['restrictions']['namespaces'], 'ns' );
330 }
331
332 return $ret;
333 }
334
335 protected function getMessageKey() {
336 $type = $this->entry->getType();
337 $subtype = $this->entry->getSubtype();
338 $sitewide = $this->entry->getParameters()['sitewide'] ?? true;
339
340 $key = "logentry-$type-$subtype";
341 if ( ( $subtype === 'block' || $subtype === 'reblock' ) && !$sitewide ) {
342 // $this->getMessageParameters is doing too much. We just need
343 // to check the presence of restrictions ($param[6]) and calling
344 // on parent gives us that
345 $params = parent::getMessageParameters();
346
347 // message changes depending on whether there are editing restrictions or not
348 if ( isset( $params[6] ) ) {
349 $key = "logentry-partial$type-$subtype";
350 } else {
351 $key = "logentry-non-editing-$type-$subtype";
352 }
353 }
354
355 return $key;
356 }
357}
const NS_MAIN
Definition Defines.php:64
wfIsInfinity( $str)
Determine input string is represents as infinity.
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
array $params
The job parameters.
This class formats block log entries.
getMessageKey()
Returns a key to be used for formatting the action sentence.
getMessageParameters()
Formats parameters intended for action message from array of all parameters.
static formatBlockFlags( $flags, Language $lang)
Convert a comma-delimited list of block log flags into a more readable (and translated) form.
static formatBlockFlag( $flag, Language $lang)
Translate a block log flag if possible.
getActionLinks()
Returns extra links that comes after the action text, like "revert", etc.
getParametersForApi()
Get the array of parameters, converted from legacy format if necessary.
formatParametersForApi()
Format parameters for API output.The result array should generally map named keys to values....
extractParameters()
Extracts the optional extra parameters for use in action messages.
Base class for language-specific code.
Definition Language.php:63
commaList(array $list)
Take a list of strings and build a locale-friendly comma-separated list, using the local comma-separa...
Implements the default log formatting.
LogEntryBase $entry
msg( $key,... $params)
Shortcut for wfMessage which honors local context.
formatParameterValueForApi( $name, $type, $value)
Format a single parameter value for API output.
makePageLink(Title $title=null, $parameters=[], $html=null)
Helper to make a link to the page, taking the plaintext value in consideration.
makeUserLink(UserIdentity $user, $toolFlags=0)
Some internal bits split of from Skin.php.
Definition Linker.php:65
A class containing constants representing the names of configuration variables.
Parent class for all special pages.
Represents a title within MediaWiki.
Definition Title.php:78
internal since 1.36
Definition User.php:93
getParameters()
Get the extra parameters stored for this message.
getTimestamp()
Get the timestamp when the action was executed.
getSubtype()
The log subtype.