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