88 $this->
addDeprecation(
'apiwarn-deprecation-deletedrevs',
'action=query&list=deletedrevs' );
93 $prop = array_fill_keys( $params[
'prop'],
true );
94 $fld_parentid = isset( $prop[
'parentid'] );
95 $fld_revid = isset( $prop[
'revid'] );
96 $fld_user = isset( $prop[
'user'] );
97 $fld_userid = isset( $prop[
'userid'] );
98 $fld_comment = isset( $prop[
'comment'] );
99 $fld_parsedcomment = isset( $prop[
'parsedcomment'] );
100 $fld_minor = isset( $prop[
'minor'] );
101 $fld_len = isset( $prop[
'len'] );
102 $fld_sha1 = isset( $prop[
'sha1'] );
103 $fld_content = isset( $prop[
'content'] );
104 $fld_token = isset( $prop[
'token'] );
105 $fld_tags = isset( $prop[
'tags'] );
114 if ( !$this->
getAuthority()->isAllowed(
'undelete' ) ) {
120 $titles = $pageSet->getPages();
127 if ( count( $titles ) > 0 ) {
129 } elseif ( $params[
'user'] !==
null ) {
133 if ( $mode ==
'revs' || $mode ==
'user' ) {
135 foreach ( [
'from',
'to',
'prefix', ] as $p ) {
136 if ( $params[$p] !==
null ) {
137 $this->
dieWithError( [
'apierror-deletedrevs-param-not-1-2', $p ],
'badparams' );
141 foreach ( [
'start',
'end' ] as $p ) {
142 if ( $params[$p] !==
null ) {
143 $this->
dieWithError( [
'apierror-deletedrevs-param-not-3', $p ],
'badparams' );
148 if ( $params[
'user'] !==
null && $params[
'excludeuser'] !==
null ) {
149 $this->
dieWithError(
'user and excludeuser cannot be used together',
'badparams' );
152 $arQuery = $this->revisionStore->getArchiveQueryInfo();
156 $this->
addFields( [
'ar_title',
'ar_namespace' ] );
162 if ( $params[
'tag'] !==
null ) {
165 [
'change_tag' => [
'JOIN', [
'ar_rev_id=ct_rev_id' ] ] ]
168 $this->
addWhereFld(
'ct_tag_id', $this->changeTagDefStore->getId( $params[
'tag'] ) );
176 if ( $fld_content ) {
183 $limit = $params[
'limit'];
185 if ( $limit ==
'max' ) {
186 $limit = $this->
getMain()->canApiHighLimits() ? $botMax : $userMax;
190 $limit = $this->
getMain()->getParamValidator()->validateValue(
191 $this,
'limit', $limit, [
192 ParamValidator::PARAM_TYPE =>
'limit',
193 IntegerDef::PARAM_MIN => 1,
194 IntegerDef::PARAM_MAX => $userMax,
195 IntegerDef::PARAM_MAX2 => $botMax,
196 IntegerDef::PARAM_IGNORE_RANGE =>
true,
205 $dir = $params[
'dir'];
208 if ( $mode ==
'revs' ) {
209 $lb = $this->linkBatchFactory->newLinkBatch( $titles );
210 $where = $lb->constructSet(
'ar', $db );
212 } elseif ( $mode ==
'all' ) {
213 $this->
addWhereFld(
'ar_namespace', $params[
'namespace'] );
215 $from = $params[
'from'] ===
null
218 $to = $params[
'to'] ===
null
223 if ( isset( $params[
'prefix'] ) ) {
224 $this->
addWhere(
'ar_title' . $db->buildLike(
225 $this->titlePartToKey( $params[
'prefix'], $params[
'namespace'] ),
226 $db->anyString() ) );
230 if ( $params[
'user'] !==
null ) {
232 $this->
addWhereFld(
'actor_name', $params[
'user'] );
233 } elseif ( $params[
'excludeuser'] !==
null ) {
234 $this->
addWhere(
'actor_name<>' . $db->addQuotes( $params[
'excludeuser'] ) );
237 if ( $params[
'user'] !==
null || $params[
'excludeuser'] !==
null ) {
241 if ( !$this->
getAuthority()->isAllowed(
'deletedhistory' ) ) {
242 $bitmask = RevisionRecord::DELETED_USER;
243 } elseif ( !$this->
getAuthority()->isAllowedAny(
'suppressrevision',
'viewsuppressed' ) ) {
244 $bitmask = RevisionRecord::DELETED_USER | RevisionRecord::DELETED_RESTRICTED;
249 $this->
addWhere( $db->bitAnd(
'ar_deleted', $bitmask ) .
" != $bitmask" );
253 if ( $params[
'continue'] !==
null ) {
254 $cont = explode(
'|', $params[
'continue'] );
255 $op = ( $dir ==
'newer' ?
'>' :
'<' );
256 if ( $mode ==
'all' || $mode ==
'revs' ) {
260 $title = $db->addQuotes( $cont[1] );
261 $ts = $db->addQuotes( $db->timestamp( $cont[2] ) );
262 $ar_id = (int)$cont[3];
264 $this->
addWhere(
"ar_namespace $op $ns OR " .
265 "(ar_namespace = $ns AND " .
266 "(ar_title $op $title OR " .
267 "(ar_title = $title AND " .
268 "(ar_timestamp $op $ts OR " .
269 "(ar_timestamp = $ts AND " .
270 "ar_id $op= $ar_id)))))" );
273 $ts = $db->addQuotes( $db->timestamp( $cont[0] ) );
274 $ar_id = (int)$cont[1];
276 $this->
addWhere(
"ar_timestamp $op $ts OR " .
277 "(ar_timestamp = $ts AND " .
278 "ar_id $op= $ar_id)" );
283 if ( $mode ==
'all' ) {
284 if ( $params[
'unique'] ) {
286 $this->
addOption(
'GROUP BY',
'ar_title' );
288 $sort = ( $dir ==
'newer' ?
'' :
' DESC' );
291 'ar_timestamp' . $sort,
296 if ( $mode ==
'revs' ) {
307 $formattedComments = [];
308 if ( $fld_parsedcomment ) {
309 $formattedComments = $this->commentFormatter->formatItems(
310 $this->commentFormatter->rows(
$res )
311 ->indexField(
'ar_id' )
312 ->commentKey(
'ar_comment' )
313 ->namespaceField(
'ar_namespace' )
314 ->titleField(
'ar_title' )
321 foreach (
$res as $row ) {
322 if ( ++$count > $limit ) {
324 if ( $mode ==
'all' || $mode ==
'revs' ) {
326 "$row->ar_namespace|$row->ar_title|$row->ar_timestamp|$row->ar_id"
337 $rev[
'timestamp'] =
wfTimestamp( TS_ISO_8601, $row->ar_timestamp );
339 $rev[
'revid'] = (int)$row->ar_rev_id;
341 if ( $fld_parentid && $row->ar_parent_id !==
null ) {
342 $rev[
'parentid'] = (int)$row->ar_parent_id;
344 if ( $fld_user || $fld_userid ) {
345 if ( $row->ar_deleted & RevisionRecord::DELETED_USER ) {
346 $rev[
'userhidden'] =
true;
349 if ( RevisionRecord::userCanBitfield(
351 RevisionRecord::DELETED_USER,
355 $rev[
'user'] = $row->ar_user_text;
358 $rev[
'userid'] = (int)$row->ar_user;
363 if ( $fld_comment || $fld_parsedcomment ) {
364 if ( $row->ar_deleted & RevisionRecord::DELETED_COMMENT ) {
365 $rev[
'commenthidden'] =
true;
368 if ( RevisionRecord::userCanBitfield(
370 RevisionRecord::DELETED_COMMENT,
373 $comment = $this->commentStore->getComment(
'ar_comment', $row )->text;
374 if ( $fld_comment ) {
375 $rev[
'comment'] = $comment;
377 if ( $fld_parsedcomment ) {
378 $rev[
'parsedcomment'] = $formattedComments[$row->ar_id];
384 $rev[
'minor'] = $row->ar_minor_edit == 1;
387 $rev[
'len'] = $row->ar_len;
390 if ( $row->ar_deleted & RevisionRecord::DELETED_TEXT ) {
391 $rev[
'sha1hidden'] =
true;
394 if ( RevisionRecord::userCanBitfield(
396 RevisionRecord::DELETED_TEXT,
399 if ( $row->ar_sha1 !=
'' ) {
400 $rev[
'sha1'] = Wikimedia\base_convert( $row->ar_sha1, 36, 16, 40 );
406 if ( $fld_content ) {
407 if ( $row->ar_deleted & RevisionRecord::DELETED_TEXT ) {
408 $rev[
'texthidden'] =
true;
411 if ( RevisionRecord::userCanBitfield(
413 RevisionRecord::DELETED_TEXT,
416 ApiResult::setContentValue( $rev,
'text',
417 $this->revisionStore->newRevisionFromArchiveRow( $row )
418 ->getContent( SlotRecord::MAIN )->serialize() );
423 if ( $row->ts_tags ) {
424 $tags = explode(
',', $row->ts_tags );
425 ApiResult::setIndexedTagName( $tags,
'tag' );
426 $rev[
'tags'] = $tags;
432 if ( $anyHidden && ( $row->ar_deleted & RevisionRecord::DELETED_RESTRICTED ) ) {
433 $rev[
'suppressed'] =
true;
436 if ( !isset( $pageMap[$row->ar_namespace][$row->ar_title] ) ) {
437 $pageID = $newPageID++;
438 $pageMap[$row->ar_namespace][$row->ar_title] = $pageID;
439 $a = [
'revisions' => [ $rev ] ];
440 ApiResult::setIndexedTagName( $a[
'revisions'],
'rev' );
441 $title = Title::makeTitle( $row->ar_namespace, $row->ar_title );
445 $a[
'token'] = $token;
447 $fit = $result->addValue( [
'query', $this->
getModuleName() ], $pageID, $a );
449 $pageID = $pageMap[$row->ar_namespace][$row->ar_title];
450 $fit = $result->addValue(
455 if ( $mode ==
'all' || $mode ==
'revs' ) {
457 "$row->ar_namespace|$row->ar_title|$row->ar_timestamp|$row->ar_id"
465 $result->addIndexedTagName( [
'query', $this->
getModuleName() ],
'page' );
475 ParamValidator::PARAM_TYPE =>
'timestamp',
479 ParamValidator::PARAM_TYPE =>
'timestamp',
483 ParamValidator::PARAM_TYPE => [
487 ParamValidator::PARAM_DEFAULT =>
'older',
490 'newer' =>
'api-help-paramvalue-direction-newer',
491 'older' =>
'api-help-paramvalue-direction-older',
505 ParamValidator::PARAM_DEFAULT =>
false,
509 ParamValidator::PARAM_TYPE =>
'namespace',
510 ParamValidator::PARAM_DEFAULT =>
NS_MAIN,
515 ParamValidator::PARAM_TYPE =>
'user',
516 UserDef::PARAM_ALLOWED_USER_TYPES => [
'name',
'ip',
'id',
'interwiki' ],
519 ParamValidator::PARAM_TYPE =>
'user',
520 UserDef::PARAM_ALLOWED_USER_TYPES => [
'name',
'ip',
'id',
'interwiki' ],
523 ParamValidator::PARAM_DEFAULT =>
'user|comment',
524 ParamValidator::PARAM_TYPE => [
538 ParamValidator::PARAM_ISMULTI =>
true,
540 EnumDef::PARAM_DEPRECATED_VALUES => [
545 ParamValidator::PARAM_DEFAULT => 10,
546 ParamValidator::PARAM_TYPE =>
'limit',
547 IntegerDef::PARAM_MIN => 1,