MediaWiki master
DeleteLogFormatter.php
Go to the documentation of this file.
1<?php
26namespace MediaWiki\Logging;
27
32
40 private $parsedParametersDeleteLog;
41
45 protected function getMessageKey() {
46 $key = parent::getMessageKey();
47 if ( in_array( $this->entry->getSubtype(), [ 'event', 'revision' ] ) ) {
48 if ( count( $this->getMessageParameters() ) < 5 ) {
49 // Messages: logentry-delete-event-legacy, logentry-delete-revision-legacy,
50 // logentry-suppress-event-legacy, logentry-suppress-revision-legacy
51 return "$key-legacy";
52 }
53 } elseif ( $this->entry->getSubtype() === 'restore' ) {
54 $rawParams = $this->entry->getParameters();
55 if ( !isset( $rawParams[':assoc:count'] ) ) {
56 // Message: logentry-delete-restore-nocount
57 return $key . '-nocount';
58 }
59 }
60
61 return $key;
62 }
63
67 protected function getMessageParameters() {
68 if ( $this->parsedParametersDeleteLog !== null ) {
69 return $this->parsedParametersDeleteLog;
70 }
71
72 $params = parent::getMessageParameters();
73 $subtype = $this->entry->getSubtype();
74 if ( in_array( $subtype, [ 'event', 'revision' ] ) ) {
75 // $params[3] here is 'revision' or 'archive' for page revisions, 'oldimage' or
76 // 'filearchive' for file versions, or a comma-separated list of log_ids for log
77 // entries. $subtype here is 'revision' for page revisions and file
78 // versions, or 'event' for log entries.
79 if (
80 ( $subtype === 'event' && count( $params ) === 6 )
81 || (
82 $subtype === 'revision' && isset( $params[3] ) && count( $params ) === 7
83 && in_array( $params[3], [ 'revision', 'archive', 'oldimage', 'filearchive' ] )
84 )
85 ) {
86 // See RevDelList::getLogParams()/RevDelLogList::getLogParams()
87 $paramStart = $subtype === 'revision' ? 4 : 3;
88
89 $old = $this->parseBitField( $params[$paramStart + 1] );
90 $new = $this->parseBitField( $params[$paramStart + 2] );
91 [ $hid, $unhid, $extra ] = RevisionDeleter::getChanges( $new, $old );
92 $changes = [];
93 // messages used: revdelete-content-hid, revdelete-summary-hid, revdelete-uname-hid
94 foreach ( $hid as $v ) {
95 $changes[] = $this->msg( "$v-hid" )->plain();
96 }
97 // messages used: revdelete-content-unhid, revdelete-summary-unhid,
98 // revdelete-uname-unhid
99 foreach ( $unhid as $v ) {
100 $changes[] = $this->msg( "$v-unhid" )->plain();
101 }
102 foreach ( $extra as $v ) {
103 $changes[] = $this->msg( $v )->plain();
104 }
105 $changeText = $this->context->getLanguage()->listToText( $changes );
106
107 $newParams = array_slice( $params, 0, 3 );
108 $newParams[3] = $changeText;
109 $ids = is_array( $params[$paramStart] )
110 ? $params[$paramStart]
111 : explode( ',', $params[$paramStart] );
112 $newParams[4] = $this->context->getLanguage()->formatNum( count( $ids ) );
113
114 $this->parsedParametersDeleteLog = $newParams;
115 return $this->parsedParametersDeleteLog;
116 } else {
117 $this->parsedParametersDeleteLog = array_slice( $params, 0, 3 );
118 return $this->parsedParametersDeleteLog;
119 }
120 } elseif ( $subtype === 'restore' ) {
121 $rawParams = $this->entry->getParameters();
122 if ( isset( $rawParams[':assoc:count'] ) ) {
123 $countList = [];
124 foreach ( $rawParams[':assoc:count'] as $type => $count ) {
125 if ( $count ) {
126 // Messages: restore-count-revisions, restore-count-files
127 $countList[] = $this->context->msg( 'restore-count-' . $type )
128 ->numParams( $count )->plain();
129 }
130 }
131 $params[3] = $this->context->getLanguage()->listToText( $countList );
132 }
133 }
134
135 $this->parsedParametersDeleteLog = $params;
136 return $this->parsedParametersDeleteLog;
137 }
138
139 protected function parseBitField( $string ) {
140 // Input is like ofield=2134 or just the number
141 if ( strpos( $string, 'field=' ) === 1 ) {
142 [ , $field ] = explode( '=', $string );
143
144 return (int)$field;
145 } else {
146 return (int)$string;
147 }
148 }
149
150 public function getActionLinks() {
151 $linkRenderer = $this->getLinkRenderer();
152 if ( !$this->context->getAuthority()->isAllowed( 'deletedhistory' )
153 || $this->entry->isDeleted( LogPage::DELETED_ACTION )
154 ) {
155 return '';
156 }
157
158 switch ( $this->entry->getSubtype() ) {
159 case 'delete': // Show undelete link
160 case 'delete_redir':
161 case 'delete_redir2':
162 if ( $this->context->getAuthority()->isAllowed( 'undelete' ) ) {
163 $message = 'undeletelink';
164 } else {
165 $message = 'undeleteviewlink';
166 }
167 $revert = $linkRenderer->makeKnownLink(
168 SpecialPage::getTitleFor( 'Undelete' ),
169 $this->msg( $message )->text(),
170 [],
171 [ 'target' => $this->entry->getTarget()->getPrefixedDBkey() ]
172 );
173
174 return $this->msg( 'parentheses' )->rawParams( $revert )->escaped();
175
176 case 'revision': // If an edit was hidden from a page give a review link to the history
177 $params = $this->extractParameters();
178 if ( !isset( $params[3] ) || !isset( $params[4] ) ) {
179 return '';
180 }
181
182 // Different revision types use different URL params...
183 $key = $params[3];
184 // This is a array or CSV of the IDs
185 $ids = is_array( $params[4] )
186 ? $params[4]
187 : explode( ',', $params[4] );
188
189 $links = [];
190
191 // If there's only one item, we can show a diff link
192 if ( count( $ids ) == 1 ) {
193 // Live revision diffs...
194 if ( $key == 'oldid' || $key == 'revision' ) {
195 $links[] = $linkRenderer->makeKnownLink(
196 $this->entry->getTarget(),
197 $this->msg( 'diff' )->text(),
198 [],
199 [
200 'diff' => intval( $ids[0] ),
201 'unhide' => 1
202 ]
203 );
204 // Deleted revision diffs...
205 } elseif ( $key == 'artimestamp' || $key == 'archive' ) {
206 $links[] = $linkRenderer->makeKnownLink(
207 SpecialPage::getTitleFor( 'Undelete' ),
208 $this->msg( 'diff' )->text(),
209 [],
210 [
211 'target' => $this->entry->getTarget()->getPrefixedDBkey(),
212 'diff' => 'prev',
213 'timestamp' => $ids[0]
214 ]
215 );
216 }
217 }
218
219 // View/modify link...
220 $links[] = $linkRenderer->makeKnownLink(
221 SpecialPage::getTitleFor( 'Revisiondelete' ),
222 $this->msg( 'revdel-restore' )->text(),
223 [],
224 [
225 'target' => $this->entry->getTarget()->getPrefixedText(),
226 'type' => $key,
227 'ids' => implode( ',', $ids ),
228 ]
229 );
230
231 return $this->msg( 'parentheses' )->rawParams(
232 $this->context->getLanguage()->pipeList( $links ) )->escaped();
233
234 case 'event': // Hidden log items, give review link
235 $params = $this->extractParameters();
236 if ( !isset( $params[3] ) ) {
237 return '';
238 }
239 // This is a CSV of the IDs
240 $query = $params[3];
241 if ( is_array( $query ) ) {
242 $query = implode( ',', $query );
243 }
244 // Link to each hidden object ID, $params[1] is the url param
245 $revert = $linkRenderer->makeKnownLink(
246 SpecialPage::getTitleFor( 'Revisiondelete' ),
247 $this->msg( 'revdel-restore' )->text(),
248 [],
249 [
250 'target' => $this->entry->getTarget()->getPrefixedText(),
251 'type' => 'logging',
252 'ids' => $query
253 ]
254 );
255
256 return $this->msg( 'parentheses' )->rawParams( $revert )->escaped();
257 default:
258 return '';
259 }
260 }
261
262 protected function getParametersForApi() {
264 $params = [];
265
266 $subtype = $this->entry->getSubtype();
267 if ( in_array( $subtype, [ 'event', 'revision' ] ) ) {
268 $rawParams = $entry->getParameters();
269 if ( $subtype === 'event' ) {
270 array_unshift( $rawParams, 'logging' );
271 }
272
273 static $map = [
274 '4::type',
275 '5::ids',
276 '6::ofield',
277 '7::nfield',
278 '4::ids' => '5::ids',
279 '5::ofield' => '6::ofield',
280 '6::nfield' => '7::nfield',
281 ];
282 foreach ( $map as $index => $key ) {
283 if ( isset( $rawParams[$index] ) ) {
284 $rawParams[$key] = $rawParams[$index];
285 unset( $rawParams[$index] );
286 }
287 }
288
289 if ( !is_array( $rawParams['5::ids'] ) ) {
290 $rawParams['5::ids'] = explode( ',', $rawParams['5::ids'] );
291 }
292
293 $params = [
294 '::type' => $rawParams['4::type'],
295 ':array:ids' => $rawParams['5::ids'],
296 ];
297
298 static $fields = [
299 RevisionRecord::DELETED_TEXT => 'content',
300 RevisionRecord::DELETED_COMMENT => 'comment',
301 RevisionRecord::DELETED_USER => 'user',
302 RevisionRecord::DELETED_RESTRICTED => 'restricted',
303 ];
304
305 if ( isset( $rawParams['6::ofield'] ) ) {
306 $old = $this->parseBitField( $rawParams['6::ofield'] );
307 $params[':assoc:old'] = [ 'bitmask' => $old ];
308 foreach ( $fields as $bit => $key ) {
309 $params[':assoc:old'][$key] = (bool)( $old & $bit );
310 }
311 }
312 if ( isset( $rawParams['7::nfield'] ) ) {
313 $new = $this->parseBitField( $rawParams['7::nfield'] );
314 $params[':assoc:new'] = [ 'bitmask' => $new ];
315 foreach ( $fields as $bit => $key ) {
316 $params[':assoc:new'][$key] = (bool)( $new & $bit );
317 }
318 }
319 } elseif ( $subtype === 'restore' ) {
320 $rawParams = $entry->getParameters();
321 if ( isset( $rawParams[':assoc:count'] ) ) {
322 $params[':assoc:count'] = $rawParams[':assoc:count'];
323 }
324 }
325
326 return $params;
327 }
328
329 public function formatParametersForApi() {
330 $ret = parent::formatParametersForApi();
331 if ( isset( $ret['ids'] ) ) {
332 ApiResult::setIndexedTagName( $ret['ids'], 'id' );
333 }
334 return $ret;
335 }
336}
337
339class_alias( DeleteLogFormatter::class, 'DeleteLogFormatter' );
This class represents the result of the API operations.
Definition ApiResult.php:45
This class formats delete log entries.
getMessageParameters()
Formats parameters intended for action message from array of all parameters.There are three hardcoded...
getMessageKey()
Returns a key to be used for formatting the action sentence.Default is logentry-TYPE-SUBTYPE for mode...
getParametersForApi()
Get the array of parameters, converted from legacy format if necessary.
getActionLinks()
Returns extra links that comes after the action text, like "revert", etc.
formatParametersForApi()
Format parameters for API output.
Implements the default log formatting.
extractParameters()
Extracts the optional extra parameters for use in action messages.
msg( $key,... $params)
Shortcut for wfMessage which honors local context.
Page revision base class.
Parent class for all special pages.
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,...
General controller for RevDel, used by both SpecialRevisiondelete and ApiRevisionDelete.
getParameters()
Get the extra parameters stored for this message.
This program is free software; you can redistribute it and/or modify it under the terms of the GNU Ge...