Add support to the Thanks API for thanking log entries

Add a 'log' API parameter (for the log ID to thank), and add
a whitelist config variable for specifying which log types are
thankable.

Bug: T186855
Change-Id: I58ae90c9729c0066f952e90fca2cf99b029d0d9b
This commit is contained in:
Sam Wilson 2018-02-09 15:04:06 +08:00 committed by Max Semenik
parent e754b25c6a
commit b84eedc74e
7 changed files with 266 additions and 47 deletions

View file

@ -184,7 +184,18 @@
"config": {
"ThanksSendToBots": false,
"ThanksLogging": true,
"ThanksConfirmationRequired": true
"ThanksConfirmationRequired": true,
"ThanksLogTypeWhitelist": [
"contentmodel",
"delete",
"import",
"merge",
"patrol",
"protect",
"tag",
"managetags",
"rights"
]
},
"manifest_version": 1
}

View file

@ -10,6 +10,8 @@
"thanks-button-thank": "{{GENDER:$1|{{GENDER:$2|Thank}}}}",
"thanks-button-thanked": "{{GENDER:$1|{{GENDER:$2|Thanked}}}}",
"thanks-error-undefined": "Thank action failed (error code: $1). Please try again.",
"thanks-error-invalid-log-type": "Log type '$1' is not in the whitelist of permitted log types.",
"thanks-error-log-deleted": "The requested log entry has been deleted and thanks cannot be given for it.",
"thanks-error-invalidrevision": "Revision ID is not valid.",
"thanks-error-revdeleted": "Revision has been deleted",
"thanks-error-notitle": "Page title could not be retrieved",
@ -19,6 +21,7 @@
"thanks-error-echonotinstalled": "Echo is not installed on this wiki",
"thanks-error-notloggedin": "Anonymous users cannot send thanks",
"thanks-error-ratelimited": "{{GENDER:$1|You}}'ve exceeded your rate limit. Please wait some time and try again.",
"thanks-error-api-params": "Either the 'revid' or the 'logid' parameter must be provided",
"thanks-thank-tooltip": "{{GENDER:$1|Send}} a thank you notification to this {{GENDER:$2|user}}",
"thanks-thank-tooltip-no": "{{GENDER:$1|Cancel}} the thank you notification",
"thanks-thank-tooltip-yes": "{{GENDER:$1|Send}} the thank you notification",
@ -31,9 +34,11 @@
"echo-pref-tooltip-edit-thank": "Notify me when someone thanks me for an edit I made.",
"echo-category-title-edit-thank": "Thanks",
"notification-thanks-diff-link": "your edit",
"notification-header-edit-thank": "$1 {{GENDER:$2|thanked}} {{GENDER:$4|you}} for your edit on <strong>$3</strong>.",
"notification-header-rev-thank": "$1 {{GENDER:$2|thanked}} {{GENDER:$4|you}} for your edit on <strong>$3</strong>.",
"notification-header-log-thank": "$1 {{GENDER:$2|thanked}} {{GENDER:$4|you}} for your action relating to <strong>$3</strong>.",
"notification-compact-header-edit-thank": "$1 {{GENDER:$2|thanked}} {{GENDER:$3|you}}.",
"notification-bundle-header-edit-thank": "{{PLURAL:$1|One person|$1 people|100=99+ people}} thanked {{GENDER:$3|you}} for your edit on <strong>$2</strong>.",
"notification-bundle-header-rev-thank": "{{PLURAL:$1|One person|$1 people|100=99+ people}} thanked {{GENDER:$3|you}} for your edit on <strong>$2</strong>.",
"notification-bundle-header-log-thank": "{{PLURAL:$1|One person|$1 people|100=99+ people}} thanked {{GENDER:$3|you}} for your action relating to <strong>$2</strong>.",
"log-name-thanks": "Thanks log",
"log-description-thanks": "Below is a list of users thanked by other users.",
"logentry-thanks-thank": "$1 {{GENDER:$2|thanked}} {{GENDER:$4|$3}}",
@ -41,6 +46,7 @@
"thanks-error-no-id-specified": "You must specify a revision ID to send thanks.",
"thanks-confirmation-special": "Do you want to publicly send thanks for this edit?",
"notification-link-text-view-post": "View comment",
"notification-link-text-view-logentry": "View log entry",
"thanks-error-invalidpostid": "Post ID is not valid.",
"flow-thanks-confirmation-special": "Do you want to publicly send thanks for this comment?",
"flow-thanks-thanked-notice": "{{GENDER:$3|You}} thanked $1 for {{GENDER:$2|his|her|their}} comment.",
@ -54,7 +60,8 @@
"apihelp-flowthank-example-1": "Send thanks for the comment with <kbd>UUID xyz789</kbd>",
"apihelp-thank-description": "Send a thank-you notification to an editor.",
"apihelp-thank-summary": "Send a thank-you notification to an editor.",
"apihelp-thank-param-rev": "Revision ID to thank someone for.",
"apihelp-thank-param-rev": "Revision ID to thank someone for. This or 'log' must be provided.",
"apihelp-thank-param-log": "Log ID to thank someone for. This or 'rev' must be provided.",
"apihelp-thank-param-source": "A short string describing the source of the request, for example <kbd>diff</kbd> or <kbd>history</kbd>.",
"apihelp-thank-example-1": "Send thanks for revision <kbd>ID 456</kbd>, with the source being a diff page"
}

View file

@ -21,6 +21,8 @@
"thanks-button-thank": "Text of a button to thank another user. Same as {{msg-mw|Thanks-thank}}, but the context is in a button.\n\nFor languages that need it, the gender of each of the thanked and thanking users is available.\n\nParameters:\n* $1 - The user that is thanking\n* $2 - The user that is being thanked\n\n{{Identical|Thank}}",
"thanks-button-thanked": "This message immediately replaces the message {{msg-mw|Thanks-button-thank}} after it's pressed. It means that the thanking operation has been completed. Same as {{msg-mw|Thanks-thanked}}, but the context is in a button.\n\nFor languages that need it, the gender of each of the thanked and thanking users is available.\n\nParameters:\n* $1 - The user that is thanking\n* $2 - The user that has been thanked\n\n{{Identical|Thanked}}",
"thanks-error-undefined": "Error message that is displayed when the thank action fails. $1 is the error code returned by the API (an English string).",
"thanks-error-invalid-log-type": "Error message that is displayed when thanks is attempted for a log entry of a non-whitelisted type. $1 is the offending log type.",
"thanks-error-log-deleted": "Error message that is displayed when thanks is attempted for a deleted log entry.",
"thanks-error-invalidrevision": "Error message that is displayed when the revision ID is not valid",
"thanks-error-revdeleted": "Error message that is displayed when the revision has been deleted (RevDel)",
"thanks-error-notitle": "Error message that is displayed when the title of the page cannot be determined",
@ -30,6 +32,7 @@
"thanks-error-echonotinstalled": "Error message that is displayed when Echo is not installed",
"thanks-error-notloggedin": "Error message that is displayed when the user is not logged in",
"thanks-error-ratelimited": "Error message that is displayed when user exceeds rate limit.\n\nParameters:\n* $1 - The user sending the thanks. Can be used for GENDER support.",
"thanks-error-api-params": "Error message shown when both the 'rev' and 'log' API parameters are absent",
"thanks-thank-tooltip": "Tooltip that appears when a user hovers over the \"thank\" link.\n\nParameters:\n* $1 - The user sending the thanks. Can be used for GENDER support.\n* $2 - The user receiving the thanks. Can be used for GENDER support.",
"thanks-thank-tooltip-no": "Tooltip that appears when a user hovers over the {{msg-mw|confirmable-no}} link, which cancels the thank action.\n\nParameters:\n* $1 - The user sending the thanks. Can be used for GENDER support.",
"thanks-thank-tooltip-yes": "Tooltip that appears when a user hovers over the {{msg-mw|confirmable-yes}} link, which confirms the thank action.\n\nParameters:\n* $1 - The user sending the thanks. Can be used for GENDER support.",
@ -42,9 +45,11 @@
"echo-pref-tooltip-edit-thank": "{{doc-echo-pref-tooltip|title=Echo-category-title-edit-thank}}\nYou can use parameterless <code><nowiki>{{GENDER:}}</nowiki></code> here.",
"echo-category-title-edit-thank": "{{doc-echo-category-title|tooltip=Echo-pref-tooltip-edit-thank}}\n{{Identical|Thank}}",
"notification-thanks-diff-link": "The text of a link to the user's edit.\n\nUsed for <code>$2</code> in {{msg-mw|Notification-thanks}}. Should have capitalization appropriate for the middle of a sentence.\n\nThis is an object in a sentence so it should be in object case in languages where there is a special object form for words.",
"notification-header-edit-thank": "Header text for a notification when a user is thanked for their edit. Parameters:\n* $1 is the username of the user sending the thanks (not suitable for GENDER).\n* $2 is the thanking user's name for use in GENDER.\n* $3 is the title of the page the thanked user edited.\n* $4 is the username of the user being thanked, for use in GENDER.",
"notification-header-rev-thank": "Header text for a notification when a user is thanked for their edit. Parameters:\n* $1 is the username of the user sending the thanks (not suitable for GENDER).\n* $2 is the thanking user's name for use in GENDER.\n* $3 is the title of the page the thanked user edited.\n* $4 is the username of the user being thanked, for use in GENDER.",
"notification-header-log-thank": "Header text for a notification when a user is thanked for a log entry. Parameters:\n* $1 is the username of the user sending the thanks (not suitable for GENDER).\n* $2 is the thanking user's name for use in GENDER.\n* $3 is the title of the page that is the target of the log entry.\n* $4 is the username of the user being thanked, for use in GENDER.",
"notification-compact-header-edit-thank": "Compact header text for a notification when a user is thanked for their edit. Parameters:\n* $1 is the username of the user sending the thanks (not suitable for GENDER).\n* $2 is the thanking user's name for use in GENDER.\n* $3 is the username of the user being thanked, for use in GENDER.",
"notification-bundle-header-edit-thank": "Bundle header text for a notification when a user is thanked for their edit. Parameters:\n* $1 is the number of users who sent thanks for the same edit. When used with PLURAL, the value 100 represents more than 99.\n* $2 is the title of the page the thanked user edited.\n* $3 is the username of the user being thanked, for use in GENDER.\n{{Related|Notification-bundle}}",
"notification-bundle-header-rev-thank": "Bundle header text for a notification when a user is thanked for their edit. Parameters:\n* $1 is the number of users who sent thanks for the same edit. When used with PLURAL, the value 100 represents more than 99.\n* $2 is the title of the page the thanked user edited.\n* $3 is the username of the user being thanked, for use in GENDER.\n{{Related|Notification-bundle}}",
"notification-bundle-header-log-thank": "Bundle header text for a notification when a user is thanked for a log entry. Parameters:\n* $1 is the number of users who sent thanks for the same edit. When used with PLURAL, the value 100 represents more than 99.\n* $2 is the title of the page that is the target of the log entry.\n* $3 is the username of the user being thanked, for use in GENDER.\n{{Related|Notification-bundle}}",
"log-name-thanks": "Name of log that appears on [[Special:Log]].",
"log-description-thanks": "Description of thanks log",
"logentry-thanks-thank": "Log entry that is created when a user thanks another user for an edit. Parameters:\n* $1 is a user link, for example \"Jane Doe (Talk | contribs)\"\n* $2 is a username. Can be used for GENDER.\n* $3 is a user link, for example \"John Doe (Talk | contribs)\n* $4 is the username of the recipient. Can be used for GENDER.\n{{Identical|Thanked}}",
@ -52,6 +57,7 @@
"thanks-error-no-id-specified": "Error message shown to the user when they visit Special:Thanks without specifying a revision ID",
"thanks-confirmation-special": "A confirmation message shown on [[Special:Thanks]] to make sure the user wants to send thanks for an edit (publicly).\n\nSee also:\n* {{msg-mw|Flow-thanks-confirmation-special}}\n* {{msg-mw|Thanks-confirmation2}}",
"notification-link-text-view-post": "Label for button that links to a comment on a Flow board",
"notification-link-text-view-logentry": "Label for button that links to a log entry",
"thanks-error-invalidpostid": "Error message that is displayed when the Flow post UUID is not valid",
"flow-thanks-confirmation-special": "A confirmation message shown on [[Special:Thanks]] to make sure the user wants to send thanks for a comment (publicly).\n\nSee also:\n* {{msg-mw|Thanks-confirmation-special}}\n* {{msg-mw|Thanks-confirmation2}}",
"flow-thanks-thanked-notice": "{{doc-singularthey}}\nMessage displayed after a user has thanked another user for their comment.\n\nParameters:\n* $1 - The username of the user that was thanked.\n* $2 - The gender of the user that was thanked.\n* $3 - The user sending the thanks. Can be used for GENDER support.\n\nSee also:\n* {{msg-mw|Thanks-thanked-notice}}",
@ -66,6 +72,7 @@
"apihelp-thank-description": "{{doc-apihelp-description|thank}}",
"apihelp-thank-summary": "{{doc-apihelp-summary|thank}}",
"apihelp-thank-param-rev": "{{doc-apihelp-param|thank|rev}}",
"apihelp-thank-param-log": "{{doc-apihelp-param|thank|log}}",
"apihelp-thank-param-source": "{{doc-apihelp-param|thank|source}}",
"apihelp-thank-example-1": "{{doc-apihelp-example|thank}}"
}

View file

@ -1,41 +1,87 @@
<?php
/**
* API module to send thanks notifications for revisions
* API module to send thanks notifications for revisions and log entries.
*
* @ingroup API
* @ingroup Extensions
*/
class ApiCoreThank extends ApiThank {
public function execute() {
$this->dieIfEchoNotInstalled();
/**
* Perform the API request.
*/
public function execute() {
// Initial setup.
$this->dieIfEchoNotInstalled();
$user = $this->getUser();
$this->dieOnBadUser( $user );
$params = $this->extractRequestParams();
$revision = $this->getRevisionFromParams( $params );
if ( $this->userAlreadySentThanksForRevision( $user, $revision ) ) {
$this->markResultSuccess( $revision->getUserText() );
// Extract type and ID from the parameters.
if ( isset( $params['rev'] ) && !isset( $params['log'] ) ) {
$type = 'rev';
$id = $params['rev'];
} elseif ( !isset( $params['rev'] ) && isset( $params['log'] ) ) {
$type = 'log';
$id = $params['log'];
} else {
$this->dieWithError( 'thanks-error-api-params', 'thanks-error-api-params' );
}
// Determine thanks parameters.
if ( $type === 'log' ) {
$logEntry = $this->getLogEntryFromId( $id );
// If there's an associated revision, thank for that instead.
if ( $logEntry->getAssociatedRevId() ) {
$type = 'rev';
$id = $logEntry->getAssociatedRevId();
} else {
$formatter = LogFormatter::newFromEntry( $logEntry );
$excerpt = $formatter->getPlainActionText();
$title = $logEntry->getTarget();
$recipient = $this->getUserFromLog( $logEntry );
$recipientUsername = $recipient->getName();
}
}
if ( $type === 'rev' ) {
$revision = $this->getRevisionFromParams( $params );
$excerpt = EchoDiscussionParser::getEditExcerpt( $revision, $this->getLanguage() );
$title = $this->getTitleFromRevision( $revision );
$recipient = $this->getUserFromRevision( $revision );
$recipientUsername = $revision->getUserText();
}
// Send thanks.
if ( $this->userAlreadySentThanks( $user, $type, $id ) ) {
$this->markResultSuccess( $recipientUsername );
} else {
$this->dieOnBadRecipient( $user, $recipient );
$this->sendThanks(
$user,
$revision,
$type,
$id,
$excerpt,
$recipient,
$this->getSourceFromParams( $params )
$this->getSourceFromParams( $params ),
$title
);
}
}
protected function userAlreadySentThanksForRevision( User $user, Revision $revision ) {
return $user->getRequest()->getSessionData( "thanks-thanked-{$revision->getId()}" );
/**
* Check the session data for an indication of whether this user has already sent this thanks.
* @param User $user The user being thanked.
* @param string $type Either 'rev' or 'log'.
* @param int $id The revision or log ID.
* @return bool
*/
protected function userAlreadySentThanks( User $user, $type, $id ) {
return (bool)$user->getRequest()->getSessionData( "thanks-thanked-$type$id" );
}
private function getRevisionFromParams( $params ) {
$revision = Revision::newFromId( $params['rev'] );
// Revision ID 1 means an invalid argument was passed in.
if ( !$revision || $revision->getId() === 1 ) {
$this->dieWithError( 'thanks-error-invalidrevision', 'invalidrevision' );
@ -45,6 +91,40 @@ class ApiCoreThank extends ApiThank {
return $revision;
}
/**
* Get the log entry from the ID.
* @param int $logId The log entry ID.
* @return DatabaseLogEntry
*/
protected function getLogEntryFromId( $logId ) {
$queryInfo = DatabaseLogEntry::getSelectQueryData();
$queryInfo['conds'] += [ 'log_id' => $logId ];
$db = wfGetDB( DB_REPLICA );
$logEntryData = $db->select(
$queryInfo['tables'],
$queryInfo['fields'],
$queryInfo['conds'],
__METHOD__,
$queryInfo['options'],
$queryInfo['join_conds']
);
$logEntry = DatabaseLogEntry::newFromRow( $logEntryData->current() );
// Make sure this log type is whitelisted.
$logTypeWhitelist = $this->getConfig()->get( 'ThanksLogTypeWhitelist' );
if ( !in_array( $logEntry->getType(), $logTypeWhitelist ) ) {
$err = $this->msg( 'thanks-error-invalid-log-type', $logEntry->getType() );
$this->dieWithError( $err, 'thanks-error-invalid-log-type' );
}
// Don't permit thanks if any part of the log entry is deleted.
if ( $logEntry->getDeleted() ) {
$this->dieWithError( 'thanks-error-log-deleted', 'thanks-error-log-deleted' );
}
return $logEntry;
}
private function getTitleFromRevision( Revision $revision ) {
$title = Title::newFromID( $revision->getPage() );
if ( !$title instanceof Title ) {
@ -55,6 +135,8 @@ class ApiCoreThank extends ApiThank {
/**
* Set the source of the thanks, e.g. 'diff' or 'history'
* @param string[] $params Incoming API parameters, with a 'source' key.
* @return string The source, or 'undefined' if not provided.
*/
private function getSourceFromParams( $params ) {
if ( $params['source'] ) {
@ -72,8 +154,30 @@ class ApiCoreThank extends ApiThank {
return User::newFromId( $recipient );
}
private function sendThanks( User $user, Revision $revision, User $recipient, $source ) {
$uniqueId = "rev-{$revision->getId()}";
private function getUserFromLog( LogEntry $logEntry ) {
$recipient = $logEntry->getPerformer();
if ( !$recipient ) {
$this->dieWithError( 'thanks-error-invalidrecipient', 'invalidrecipient' );
}
return $recipient;
}
/**
* Create the thanks notification event, and log the thanks.
* @param User $user The thanks-sending user.
* @param string $type The thanks type ('rev' or 'log').
* @param int $id The log or revision ID.
* @param string $excerpt The excerpt to display as the thanks notification. This will only
* be used if it is not possible to retrieve the relevant excerpt at the time the
* notification is displayed (in order to account for changing visibility in the meantime).
* @param User $recipient The recipient of the thanks.
* @param string $source Where the thanks was given.
* @param Title $title The title of the page for which thanks is given.
*/
protected function sendThanks(
User $user, $type, $id, $excerpt, User $recipient, $source, Title $title
) {
$uniqueId = $type . '-' . $id;
// Do one last check to make sure we haven't sent Thanks before
if ( $this->haveAlreadyThanked( $user, $uniqueId ) ) {
// Pretend the thanks were sent
@ -81,22 +185,21 @@ class ApiCoreThank extends ApiThank {
return;
}
$title = $this->getTitleFromRevision( $revision );
// Create the notification via Echo extension
EchoEvent::create( [
'type' => 'edit-thank',
'title' => $title,
'extra' => [
'revid' => $revision->getId(),
$type . 'id' => $id,
'thanked-user-id' => $recipient->getId(),
'source' => $source,
'excerpt' => EchoDiscussionParser::getEditExcerpt( $revision, $this->getLanguage() ),
'excerpt' => $excerpt,
],
'agent' => $user,
] );
// And mark the thank in session for a cheaper check to prevent duplicates (Bug 46690).
$user->getRequest()->setSessionData( "thanks-thanked-{$revision->getId()}", true );
// And mark the thank in session for a cheaper check to prevent duplicates (Phab:T48690).
$user->getRequest()->setSessionData( "thanks-thanked-$type$id", true );
// Set success message
$this->markResultSuccess( $recipient->getName() );
$this->logThanks( $user, $recipient, $uniqueId );
@ -107,7 +210,12 @@ class ApiCoreThank extends ApiThank {
'rev' => [
ApiBase::PARAM_TYPE => 'integer',
ApiBase::PARAM_MIN => 1,
ApiBase::PARAM_REQUIRED => true,
ApiBase::PARAM_REQUIRED => false,
],
'log' => [
ApiBase::PARAM_TYPE => 'integer',
ApiBase::PARAM_MIN => 1,
ApiBase::PARAM_REQUIRED => false,
],
'token' => [
ApiBase::PARAM_TYPE => 'string',

View file

@ -9,14 +9,15 @@ class EchoCoreThanksPresentationModel extends EchoEventPresentationModel {
}
public function getHeaderMessage() {
$type = $this->event->getExtraParam( 'logid' ) ? 'log' : 'rev';
if ( $this->isBundled() ) {
$msg = $this->msg( 'notification-bundle-header-edit-thank' );
$msg = $this->msg( "notification-bundle-header-$type-thank" );
$msg->params( $this->getBundleCount() );
$msg->params( $this->getTruncatedTitleText( $this->event->getTitle(), true ) );
$msg->params( $this->getViewingUserForGender() );
return $msg;
} else {
$msg = $this->getMessageWithAgent( 'notification-header-edit-thank' );
$msg = $this->getMessageWithAgent( "notification-header-$type-thank" );
$msg->params( $this->getTruncatedTitleText( $this->event->getTitle(), true ) );
$msg->params( $this->getViewingUserForGender() );
return $msg;
@ -30,7 +31,7 @@ class EchoCoreThanksPresentationModel extends EchoEventPresentationModel {
}
public function getBodyMessage() {
$comment = $this->getEditComment();
$comment = $this->getRevOrLogComment();
if ( $comment ) {
$msg = new RawMessage( '$1' );
$msg->plaintextParams( $comment );
@ -57,26 +58,48 @@ class EchoCoreThanksPresentationModel extends EchoEventPresentationModel {
return $summary ?: false;
}
private function getEditComment() {
// try to get edit summary
/**
* Get the comment/summary/excerpt of the log entry or revision,
* for use in the notification body.
* @return string|bool The comment or false if it could not be retrieved.
*/
protected function getRevOrLogComment() {
if ( $this->event->getExtraParam( 'logid' ) ) {
// Use the saved log entry excerpt.
$excerpt = $this->event->getExtraParam( 'excerpt', false );
// Turn wikitext into plaintext
$excerpt = Linker::formatComment( $excerpt );
$excerpt = Sanitizer::stripAllTags( $excerpt );
return $excerpt;
} else {
// Try to get edit summary.
$summary = $this->getRevisionEditSummary();
if ( $summary ) {
return $summary;
}
// fallback on edit excerpt
// Fallback on edit excerpt.
if ( $this->userCan( Revision::DELETED_TEXT ) ) {
return $this->event->getExtraParam( 'excerpt', false );
}
}
}
public function getPrimaryLink() {
return [
'url' => $this->event->getTitle()->getLocalURL( [
if ( $this->event->getExtraParam( 'logid' ) ) {
$logId = $this->event->getExtraParam( 'logid' );
$url = Title::newFromText( "Special:Redirect/logid/$logId" )->getCanonicalURL();
$label = 'notification-link-text-view-logentry';
} else {
$url = $this->event->getTitle()->getLocalURL( [
'oldid' => 'prev',
'diff' => $this->event->getExtraParam( 'revid' )
] ),
'label' => $this->msg( 'notification-link-text-view-edit' )->text(),
] );
$label = 'notification-link-text-view-edit';
}
return [
'url' => $url,
// Label is only used for non-JS clients.
'label' => $this->msg( $label )->text(),
];
}

View file

@ -340,9 +340,13 @@ class ThanksHooks {
switch ( $event->getType() ) {
case 'edit-thank':
$bundleString = 'edit-thank';
$revId = $event->getExtraParam( 'revid' );
if ( $revId ) {
$bundleString .= $event->getExtraParam( 'revid' );
// Try to get either the revid (old name) or id (new name) parameter.
$revOrLogId = $event->getExtraParam( 'revid' );
if ( !$revOrLogId ) {
$revOrLogId = $event->getExtraParam( 'id' );
}
if ( $revOrLogId ) {
$bundleString .= $revOrLogId;
}
break;
case 'flow-thank':

View file

@ -19,6 +19,11 @@ class ApiCoreThankIntegrationTest extends ApiTestCase {
*/
private $revId;
/**
* @var int The ID of a deletion log entry.
*/
protected $logId;
public function setUp() {
parent::setUp();
@ -31,6 +36,13 @@ class ApiCoreThankIntegrationTest extends ApiTestCase {
$revision = $result['revision'];
$this->revId = $revision->getId();
// Create a 2nd page and delete it, so we can thank for the log entry.
$pageToDeleteTitle = Title::newFromText( 'Page to delete' );
$pageToDelete = WikiPage::factory( $pageToDeleteTitle );
$pageToDelete->doEditContent( ContentHandler::makeContent( '', $pageToDeleteTitle ), '' );
$deleteStatus = $pageToDelete->doDeleteArticleReal( '' );
$this->logId = $deleteStatus->getValue();
$this->doLogin( 'sysop' );
DeferredUpdates::clearPendingUpdates();
}
@ -44,7 +56,7 @@ class ApiCoreThankIntegrationTest extends ApiTestCase {
] );
}
public function testValidRequest() {
public function testValidRevRequest() {
list( $result,, ) = $this->doApiRequestWithToken( [
'action' => 'thank',
'rev' => $this->revId,
@ -52,6 +64,53 @@ class ApiCoreThankIntegrationTest extends ApiTestCase {
$this->assertSuccess( $result );
}
public function testValidLogRequest() {
list( $result,, ) = $this->doApiRequestWithToken( [
'action' => 'thank',
'log' => $this->logId,
] );
$this->assertSuccess( $result );
}
public function testLogRequestWithDisallowedLogType() {
// Empty the log-type whitelist.
$this->setMwGlobals( [ 'wgThanksLogTypeWhitelist' => [] ] );
$this->setExpectedException(
ApiUsageException::class,
"Log type 'delete' is not in the whitelist of permitted log types."
);
$this->doApiRequestWithToken( [
'action' => 'thank',
'log' => $this->logId,
] );
}
public function testLogThanksForADeletedLogEntry() {
global $wgUser;
// Mark our test log entry as deleted.
// To do this we briefly switch back to our 'uploader' test user.
$this->doLogin( 'uploader' );
$wgUser->mRights[] = 'deletelogentry';
$this->doApiRequestWithToken( [
'action' => 'revisiondelete',
'type' => 'logging',
'ids' => $this->logId,
'hide' => 'content',
] );
$this->doLogin( 'sysop' );
// Then try to thank for it, and we should get an exception.
$this->setExpectedException(
ApiUsageException::class,
"The requested log entry has been deleted and thanks cannot be given for it."
);
$this->doApiRequestWithToken( [
'action' => 'thank',
'log' => $this->logId,
] );
}
public function testValidRequestWithSource() {
list( $result,, ) = $this->doApiRequestWithToken( [
'action' => 'thank',