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  $params = [ 'namespace' => $ns ];
94 
95  return $this->makePageLink( SpecialPage::getTitleFor( 'Allpages' ), $params, $text );
96  }, $namespaces );
97 
98  $actions = $params[6]['actions'] ?? [];
99  $actions = array_map( function ( $actions ) {
100  return $this->msg( 'ipb-action-' . $actions )->text();
101  }, $actions );
102 
103  $restrictions = [];
104  if ( $pages ) {
105  $restrictions[] = $this->msg( 'logentry-partialblock-block-page' )
106  ->numParams( count( $pages ) )
107  ->rawParams( $this->context->getLanguage()->listToText( $pages ) )->text();
108  }
109 
110  if ( $namespaces ) {
111  $restrictions[] = $this->msg( 'logentry-partialblock-block-ns' )
112  ->numParams( count( $namespaces ) )
113  ->rawParams( $this->context->getLanguage()->listToText( $namespaces ) )->text();
114  }
115  $enablePartialActionBlocks = $this->context->getConfig()
116  ->get( MainConfigNames::EnablePartialActionBlocks );
117  if ( $actions && $enablePartialActionBlocks ) {
118  $restrictions[] = $this->msg( 'logentry-partialblock-block-action' )
119  ->numParams( count( $actions ) )
120  ->rawParams( $this->context->getLanguage()->listToText( $actions ) )->text();
121  }
122 
123  $params[6] = Message::rawParam( $this->context->getLanguage()->listToText( $restrictions ) );
124  }
125  }
126 
127  return $params;
128  }
129 
130  protected function extractParameters() {
131  $params = parent::extractParameters();
132  // Legacy log params returning the params in index 3 and 4, moved to 4 and 5
133  if ( $this->entry->isLegacy() && isset( $params[3] ) ) {
134  if ( isset( $params[4] ) ) {
135  $params[5] = $params[4];
136  }
137  $params[4] = $params[3];
138  $params[3] = '';
139  }
140  return $params;
141  }
142 
143  public function getPreloadTitles() {
144  $title = $this->entry->getTarget();
145  $preload = [];
146  // Preload user page for non-autoblocks
147  if ( substr( $title->getText(), 0, 1 ) !== '#' && $title->canExist() ) {
148  $preload[] = $title->getTalkPage();
149  }
150  // Preload page restriction
151  $params = $this->extractParameters();
152  if ( isset( $params[6]['pages'] ) ) {
153  foreach ( $params[6]['pages'] as $page ) {
154  $preload[] = Title::newFromText( $page );
155  }
156  }
157  return $preload;
158  }
159 
160  public function getActionLinks() {
161  $subtype = $this->entry->getSubtype();
162  $linkRenderer = $this->getLinkRenderer();
163  if ( $this->entry->isDeleted( LogPage::DELETED_ACTION ) // Action is hidden
164  || !( $subtype === 'block' || $subtype === 'reblock' )
165  || !$this->context->getAuthority()->isAllowed( 'block' )
166  ) {
167  return '';
168  }
169 
170  // Show unblock/change block link
171  $title = $this->entry->getTarget();
172  $links = [
173  $linkRenderer->makeKnownLink(
174  SpecialPage::getTitleFor( 'Unblock', $title->getDBkey() ),
175  $this->msg( 'unblocklink' )->text()
176  ),
177  $linkRenderer->makeKnownLink(
178  SpecialPage::getTitleFor( 'Block', $title->getDBkey() ),
179  $this->msg( 'change-blocklink' )->text()
180  )
181  ];
182 
183  return $this->msg( 'parentheses' )->rawParams(
184  $this->context->getLanguage()->pipeList( $links ) )->escaped();
185  }
186 
195  public static function formatBlockFlags( $flags, Language $lang ) {
196  $flags = trim( $flags );
197  if ( $flags === '' ) {
198  return ''; // nothing to do
199  }
200  $flags = explode( ',', $flags );
201  $flagsCount = count( $flags );
202 
203  for ( $i = 0; $i < $flagsCount; $i++ ) {
204  $flags[$i] = self::formatBlockFlag( $flags[$i], $lang );
205  }
206 
207  return wfMessage( 'parentheses' )->inLanguage( $lang )
208  ->rawParams( $lang->commaList( $flags ) )->escaped();
209  }
210 
218  public static function formatBlockFlag( $flag, Language $lang ) {
219  static $messages = [];
220 
221  if ( !isset( $messages[$flag] ) ) {
222  $messages[$flag] = htmlspecialchars( $flag ); // Fallback
223 
224  // For grepping. The following core messages can be used here:
225  // * block-log-flags-angry-autoblock
226  // * block-log-flags-anononly
227  // * block-log-flags-hiddenname
228  // * block-log-flags-noautoblock
229  // * block-log-flags-nocreate
230  // * block-log-flags-noemail
231  // * block-log-flags-nousertalk
232  $msg = wfMessage( 'block-log-flags-' . $flag )->inLanguage( $lang );
233 
234  if ( $msg->exists() ) {
235  $messages[$flag] = $msg->escaped();
236  }
237  }
238 
239  return $messages[$flag];
240  }
241 
242  protected function getParametersForApi() {
244  $params = $entry->getParameters();
245 
246  static $map = [
247  // While this looks wrong to be starting at 5 rather than 4, it's
248  // because getMessageParameters uses $4 for its own purposes.
249  '5::duration',
250  '6:array:flags',
251  '6::flags' => '6:array:flags',
252  ];
253 
254  foreach ( $map as $index => $key ) {
255  if ( isset( $params[$index] ) ) {
256  $params[$key] = $params[$index];
257  unset( $params[$index] );
258  }
259  }
260 
261  ksort( $params );
262 
263  $subtype = $entry->getSubtype();
264  if ( $subtype === 'block' || $subtype === 'reblock' ) {
265  // Defaults for old log entries missing some fields
266  $params += [
267  '5::duration' => 'infinity',
268  '6:array:flags' => [],
269  ];
270 
271  if ( !is_array( $params['6:array:flags'] ) ) {
272  // @phan-suppress-next-line PhanSuspiciousValueComparison
273  $params['6:array:flags'] = $params['6:array:flags'] === ''
274  ? []
275  : explode( ',', $params['6:array:flags'] );
276  }
277 
278  if ( wfIsInfinity( $params['5::duration'] ) ) {
279  // Normalize all possible values to one for pre-T241709 rows
280  $params['5::duration'] = 'infinity';
281  } else {
282  $ts = (int)wfTimestamp( TS_UNIX, $entry->getTimestamp() );
283  $expiry = strtotime( $params['5::duration'], $ts );
284  if ( $expiry !== false && $expiry > 0 ) {
285  $params[':timestamp:expiry'] = $expiry;
286  }
287  }
288  }
289 
290  return $params;
291  }
292 
297  public function formatParametersForApi() {
298  $ret = parent::formatParametersForApi();
299  if ( isset( $ret['flags'] ) ) {
300  ApiResult::setIndexedTagName( $ret['flags'], 'f' );
301  }
302 
303  if ( isset( $ret['restrictions']['pages'] ) ) {
304  $ret['restrictions']['pages'] = array_map( function ( $title ) {
305  return $this->formatParameterValueForApi( 'page', 'title-link', $title );
306  }, $ret['restrictions']['pages'] );
307  ApiResult::setIndexedTagName( $ret['restrictions']['pages'], 'p' );
308  }
309 
310  if ( isset( $ret['restrictions']['namespaces'] ) ) {
311  // @phan-suppress-next-line PhanTypeMismatchArgument False positive
312  ApiResult::setIndexedTagName( $ret['restrictions']['namespaces'], 'ns' );
313  }
314 
315  return $ret;
316  }
317 
318  protected function getMessageKey() {
319  $type = $this->entry->getType();
320  $subtype = $this->entry->getSubtype();
321  $sitewide = $this->entry->getParameters()['sitewide'] ?? true;
322 
323  $key = "logentry-$type-$subtype";
324  if ( ( $subtype === 'block' || $subtype === 'reblock' ) && !$sitewide ) {
325  // $this->getMessageParameters is doing too much. We just need
326  // to check the presence of restrictions ($param[6]) and calling
327  // on parent gives us that
328  $params = parent::getMessageParameters();
329 
330  // message changes depending on whether there are editing restrictions or not
331  if ( isset( $params[6] ) ) {
332  $key = "logentry-partial$type-$subtype";
333  } else {
334  $key = "logentry-non-editing-$type-$subtype";
335  }
336  }
337 
338  return $key;
339  }
340 }
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.
Internationalisation code See https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation for more...
Definition: Language.php:45
const TOOL_LINKS_NOBLOCK
Flags for userToolLinks()
Definition: Linker.php:44
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.
LinkRenderer null $linkRenderer
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:597
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