Add minor edit count to available REST API history counts

Add "minor" as an allowed value for the count type parameter
in PageHistoryCountHandler.php

Bug: T235587
Change-Id: I31cf37a28c62efa98d719d386001e560ca5dd188
This commit is contained in:
Bill Pirkle 2019-10-23 10:06:12 -05:00
parent 8074fc63e8
commit f54b4a72be
3 changed files with 53 additions and 12 deletions

View file

@ -23,7 +23,7 @@ use Wikimedia\Rdbms\ILoadBalancer;
* Handler class for Core REST API endpoints that perform operations on revisions
*/
class PageHistoryCountHandler extends SimpleHandler {
const ALLOWED_COUNT_TYPES = [ 'anonymous', 'bot', 'editors', 'edits', 'reverted' ];
const ALLOWED_COUNT_TYPES = [ 'anonymous', 'bot', 'editors', 'edits', 'reverted', 'minor' ];
// These types work identically to their similarly-named synonyms, but will be removed in the
// next major version of the API. Callers should use the corresponding non-deprecated type.
@ -31,8 +31,15 @@ class PageHistoryCountHandler extends SimpleHandler {
'anonedits', 'botedits', 'revertededits'
];
// The query for minor counts is inefficient for the database for pages with many revisions.
// If the specified title contains more revisions than allowed, we will return an error.
// This may be fixed with a database index, per T235572. If so, this check can be removed.
const MINOR_QUERY_EDIT_COUNT_LIMIT = 1000;
const REVERTED_TAG_NAMES = [ 'mw-undo', 'mw-rollback' ];
const MINOR_LIMIT = 500;
/** @var NameTableStore */
private $changeTagDefStore;
@ -80,8 +87,8 @@ class PageHistoryCountHandler extends SimpleHandler {
);
}
$count = $this->getCount( $titleObj, $type );
$response = $this->getResponseFactory()->createJson( [ 'count' => $count ] );
$responseData = $this->getResponseData( $titleObj, $type );
$response = $this->getResponseFactory()->createJson( $responseData );
// Inform clients who use a deprecated "type" value, so they can adjust
if ( in_array( $type, self::DEPRECATED_COUNT_TYPES ) ) {
@ -97,28 +104,42 @@ class PageHistoryCountHandler extends SimpleHandler {
/**
* @param Title $titleObj title object identifying the page to load history for
* @param string $type the validated count type
* @return int the count
* @return array the response data
* @throws LocalizedHttpException
*/
protected function getCount( $titleObj, $type ) {
protected function getResponseData( $titleObj, $type ) {
switch ( $type ) {
case 'anonedits':
case 'anonymous':
return $this->getAnonCount( $titleObj );
return [ 'count' => $this->getAnonCount( $titleObj ) ];
case 'botedits':
case 'bot':
return $this->getBotCount( $titleObj );
return [ 'count' => $this->getBotCount( $titleObj ) ];
case 'editors':
return $this->getEditorsCount( $titleObj );
return [ 'count' => $this->getEditorsCount( $titleObj ) ];
case 'edits':
return $this->getEditsCount( $titleObj );
return [ 'count' => $this->getEditsCount( $titleObj ) ];
case 'revertededits':
case 'reverted':
return $this->getRevertedCount( $titleObj );
return [ 'count' => $this->getRevertedCount( $titleObj ) ];
case 'minor':
$editsCount = $this->getEditsCount( $titleObj );
if ( $editsCount > self::MINOR_QUERY_EDIT_COUNT_LIMIT ) {
throw new LocalizedHttpException(
new MessageValue( 'rest-pagehistorycount-too-many-revisions' ),
500
);
}
$count = $this->getMinorCount( $titleObj );
return [
'count' => $count > self::MINOR_LIMIT ? self::MINOR_LIMIT : $count,
'limit' => $count > self::MINOR_LIMIT
];
// Sanity check
default:
@ -312,6 +333,24 @@ class PageHistoryCountHandler extends SimpleHandler {
return $edits;
}
/**
* @param Title $titleObj title object identifying the page to load history for
* @return int the count
*/
protected function getMinorCount( $titleObj ) {
$dbr = $this->loadBalancer->getConnectionRef( DB_REPLICA );
$edits = $dbr->selectRowCount( 'revision', '1',
[
'rev_page' => $titleObj->getArticleID(),
'rev_minor_edit != 0'
],
__METHOD__,
[ 'LIMIT' => self::MINOR_LIMIT + 1 ] // extra to detect truncation
);
return $edits;
}
/**
* Helper function for rev_deleted/user rights query conditions
*

View file

@ -23,5 +23,6 @@
"rest-compare-nonexistent": "The revision specified by the $1 parameter does not exist.",
"rest-compare-inaccessible": "The revision specified by the $1 parameter is not publicly accessible.",
"rest-compare-wrong-content": "The $1 slot of the revision specified by the $2 parameter has a content type which cannot be converted to text.",
"rest-compare-wikidiff2": "This endpoint requires wikidiff2 1.9.0 or later."
"rest-compare-wikidiff2": "This endpoint requires wikidiff2 1.9.0 or later.",
"rest-pagehistorycount-too-many-revisions": "The specified title contains too many revisions to retrieve this count."
}

View file

@ -23,5 +23,6 @@
"rest-compare-nonexistent": "Error message for REST API debugging, shown when one of the revisions does not exist. Parameters:\n* $1: The parameter name, either \"from\" or \"to\".",
"rest-compare-inaccessible": "Error message for REST API debugging, shown when the text of one of the revisions has been deleted or suppressed so that only privileged users can view it. Parameters:\n* $1: The parameter name, either \"from\" or \"to\".",
"rest-compare-wrong-content": "Error message for REST API debugging, shown when Content::convert() fails to convert the revision to text. Parameters:\n* $1: The slot role name, usually \"main\".\n* $2: The parameter name, either \"from\" or \"to\".",
"rest-compare-wikidiff2": "Error message for REST API debugging."
"rest-compare-wikidiff2": "Error message for REST API debugging.",
"rest-pagehistorycount-too-many-revisions": "Error message for REST API debugging, shown when the page has too many revisions to retrieve the count."
}