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