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