3 * Formatter for block log entries.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * http://www.gnu.org/copyleft/gpl.html
21 * @license GPL-2.0-or-later
26 * This class formats block log entries.
30 class BlockLogFormatter
extends LogFormatter
{
31 protected function getMessageParameters() {
32 $params = parent
::getMessageParameters();
34 $title = $this->entry
->getTarget();
35 if ( substr( $title->getText(), 0, 1 ) === '#' ) {
36 // autoblock - no user link possible
37 $params[2] = $title->getText();
38 $params[3] = ''; // no user name for gender use
40 // Create a user link for the blocked
41 $username = $title->getText();
42 // @todo Store the user identifier in the parameters
43 // to make this faster for future log entries
44 $targetUser = User
::newFromName( $username, false );
45 $params[2] = Message
::rawParam( $this->makeUserLink( $targetUser, Linker
::TOOL_LINKS_NOBLOCK
) );
46 $params[3] = $username; // plain user name for gender use
49 $subtype = $this->entry
->getSubtype();
50 if ( $subtype === 'block' ||
$subtype === 'reblock' ) {
51 if ( !isset( $params[4] ) ) {
52 // Very old log entry without duration: means infinite
53 $params[4] = 'infinite';
55 // Localize the duration, and add a tooltip
56 // in English to help visitors from other wikis.
57 // The lrm is needed to make sure that the number
58 // is shown on the correct side of the tooltip text.
59 $durationTooltip = '‎' . htmlspecialchars( $params[4] );
60 $params[4] = Message
::rawParam(
61 "<span class=\"blockExpiry\" title=\"$durationTooltip\">" .
62 $this->context
->getLanguage()->translateBlockExpiry(
64 $this->context
->getUser(),
65 wfTimestamp( TS_UNIX
, $this->entry
->getTimestamp() )
69 $params[5] = isset( $params[5] ) ?
70 self
::formatBlockFlags( $params[5], $this->context
->getLanguage() ) : '';
73 if ( isset( $params[6] ) ) {
74 $pages = $params[6]['pages'] ??
[];
75 $pages = array_map( function ( $page ){
76 return $this->makePageLink( Title
::newFromText( ( $page ) ) );
79 $params[6] = Message
::rawParam( $this->context
->getLanguage()->listToText( $pages ) );
80 $params[7] = count( $pages );
87 protected function extractParameters() {
88 $params = parent
::extractParameters();
89 // Legacy log params returning the params in index 3 and 4, moved to 4 and 5
90 if ( $this->entry
->isLegacy() && isset( $params[3] ) ) {
91 if ( isset( $params[4] ) ) {
92 $params[5] = $params[4];
94 $params[4] = $params[3];
100 public function getPreloadTitles() {
101 $title = $this->entry
->getTarget();
102 // Preload user page for non-autoblocks
103 if ( substr( $title->getText(), 0, 1 ) !== '#' ) {
104 return [ $title->getTalkPage() ];
109 public function getActionLinks() {
110 $subtype = $this->entry
->getSubtype();
111 $linkRenderer = $this->getLinkRenderer();
112 if ( $this->entry
->isDeleted( LogPage
::DELETED_ACTION
) // Action is hidden
113 ||
!( $subtype === 'block' ||
$subtype === 'reblock' )
114 ||
!$this->context
->getUser()->isAllowed( 'block' )
119 // Show unblock/change block link
120 $title = $this->entry
->getTarget();
122 $linkRenderer->makeKnownLink(
123 SpecialPage
::getTitleFor( 'Unblock', $title->getDBkey() ),
124 $this->msg( 'unblocklink' )->text()
126 $linkRenderer->makeKnownLink(
127 SpecialPage
::getTitleFor( 'Block', $title->getDBkey() ),
128 $this->msg( 'change-blocklink' )->text()
132 return $this->msg( 'parentheses' )->rawParams(
133 $this->context
->getLanguage()->pipeList( $links ) )->escaped();
137 * Convert a comma-delimited list of block log flags
138 * into a more readable (and translated) form
140 * @param string $flags Flags to format
141 * @param Language $lang
144 public static function formatBlockFlags( $flags, Language
$lang ) {
145 $flags = trim( $flags );
146 if ( $flags === '' ) {
147 return ''; // nothing to do
149 $flags = explode( ',', $flags );
150 $flagsCount = count( $flags );
152 for ( $i = 0; $i < $flagsCount; $i++
) {
153 $flags[$i] = self
::formatBlockFlag( $flags[$i], $lang );
156 return wfMessage( 'parentheses' )->inLanguage( $lang )
157 ->rawParams( $lang->commaList( $flags ) )->escaped();
161 * Translate a block log flag if possible
163 * @param int $flag Flag to translate
164 * @param Language $lang Language object to use
167 public static function formatBlockFlag( $flag, Language
$lang ) {
168 static $messages = [];
170 if ( !isset( $messages[$flag] ) ) {
171 $messages[$flag] = htmlspecialchars( $flag ); // Fallback
173 // For grepping. The following core messages can be used here:
174 // * block-log-flags-angry-autoblock
175 // * block-log-flags-anononly
176 // * block-log-flags-hiddenname
177 // * block-log-flags-noautoblock
178 // * block-log-flags-nocreate
179 // * block-log-flags-noemail
180 // * block-log-flags-nousertalk
181 $msg = wfMessage( 'block-log-flags-' . $flag )->inLanguage( $lang );
183 if ( $msg->exists() ) {
184 $messages[$flag] = $msg->escaped();
188 return $messages[$flag];
191 protected function getParametersForApi() {
192 $entry = $this->entry
;
193 $params = $entry->getParameters();
196 // While this looks wrong to be starting at 5 rather than 4, it's
197 // because getMessageParameters uses $4 for its own purposes.
200 '6::flags' => '6:array:flags',
203 foreach ( $map as $index => $key ) {
204 if ( isset( $params[$index] ) ) {
205 $params[$key] = $params[$index];
206 unset( $params[$index] );
212 $subtype = $entry->getSubtype();
213 if ( $subtype === 'block' ||
$subtype === 'reblock' ) {
214 // Defaults for old log entries missing some fields
216 '5::duration' => 'infinite',
217 '6:array:flags' => [],
220 if ( !is_array( $params['6:array:flags'] ) ) {
221 $params['6:array:flags'] = $params['6:array:flags'] === ''
223 : explode( ',', $params['6:array:flags'] );
226 if ( !wfIsInfinity( $params['5::duration'] ) ) {
227 $ts = wfTimestamp( TS_UNIX
, $entry->getTimestamp() );
228 $expiry = strtotime( $params['5::duration'], $ts );
229 if ( $expiry !== false && $expiry > 0 ) {
230 $params[':timestamp:expiry'] = $expiry;
238 public function formatParametersForApi() {
239 $ret = parent
::formatParametersForApi();
240 if ( isset( $ret['flags'] ) ) {
241 ApiResult
::setIndexedTagName( $ret['flags'], 'f' );
244 if ( isset( $ret['restrictions']['pages'] ) ) {
245 $ret['restrictions']['pages'] = array_map( function ( $title ) {
246 return $this->formatParameterValueForApi( 'page', 'title-link', $title );
247 }, $ret['restrictions']['pages'] );
248 ApiResult
::setIndexedTagName( $ret['restrictions']['pages'], 'p' );
254 protected function getMessageKey() {
255 $type = $this->entry
->getType();
256 $subtype = $this->entry
->getSubtype();
257 $sitewide = $this->entry
->getParameters()['sitewide'] ??
true;
259 $key = "logentry-$type-$subtype";
260 if ( ( $subtype === 'block' ||
$subtype === 'reblock' ) && !$sitewide ) {
261 // $this->getMessageParameters is doing too much. We just need
262 // to check the presence of restrictions ($param[6]) and calling
263 // on parent gives us that
264 $params = parent
::getMessageParameters();
266 // message changes depending on whether there are editing restrictions or not
267 if ( isset( $params[6] ) ) {
268 $key = "logentry-partial$type-$subtype";
270 $key = "logentry-non-editing-$type-$subtype";