Add Special:Thanks as a non-JS fallback

If the user has JavaScript disabled, clicking
on "thank" will send the user to Special:Thanks
with the revision id already filled in. When
submitted, the form calls the API internally
and then shows the user an error or confirmation
message.

Special:Thanks is not a listed special page
since it's mainly intended as a fallback.

The API was modified to return the user name of the
editor who is being thanked if a new notification
was created.

Bug: 49161
Change-Id: I7ba4664b92bb0da425784350487ed0e7ca352b4e
This commit is contained in:
Kunal Mehta 2013-10-23 18:13:43 -07:00
parent 559f494b14
commit 06360b6d0d
6 changed files with 135 additions and 6 deletions

View file

@ -16,7 +16,7 @@ class ApiThank extends ApiBase {
$revision = $this->getRevisionFromParams( $params ); $revision = $this->getRevisionFromParams( $params );
if ( $this->userAlreadySentThanksForRevision( $user, $revision ) ) { if ( $this->userAlreadySentThanksForRevision( $user, $revision ) ) {
$this->markResultSuccess(); $this->markResultSuccess( $revision );
} else { } else {
$recipient = $this->getUserFromRevision( $revision ); $recipient = $this->getUserFromRevision( $revision );
$this->dieOnBadRecipient( $user, $recipient ); $this->dieOnBadRecipient( $user, $recipient );
@ -86,8 +86,11 @@ class ApiThank extends ApiBase {
return User::newFromId( $recipient ); return User::newFromId( $recipient );
} }
private function markResultSuccess(){ private function markResultSuccess( Revision $revision ) {
$this->getResult()->addValue( null, 'result', array( 'success' => 1 ) ); $this->getResult()->addValue( null, 'result', array(
'success' => 1,
'recipient' => $revision->getUserText( Revision::FOR_PUBLIC )
) );
} }
private function dieOnBadRecipient( User $agent, User $recipient ) { private function dieOnBadRecipient( User $agent, User $recipient ) {
@ -119,7 +122,7 @@ class ApiThank extends ApiBase {
// Mark the thank in session to prevent duplicates (Bug 46690) // Mark the thank in session to prevent duplicates (Bug 46690)
$user->getRequest()->setSessionData( "thanks-thanked-{$revision->getId()}", true ); $user->getRequest()->setSessionData( "thanks-thanked-{$revision->getId()}", true );
// Set success message // Set success message
$this->markResultSuccess(); $this->markResultSuccess( $revision );
// Log it if we're supposed to log it // Log it if we're supposed to log it
if ( $wgThanksLogging ) { if ( $wgThanksLogging ) {
$logEntry = new ManualLogEntry( 'thanks', 'thank' ); $logEntry = new ManualLogEntry( 'thanks', 'thank' );

111
SpecialThanks.php Normal file
View file

@ -0,0 +1,111 @@
<?php
class SpecialThanks extends FormSpecialPage {
/** @var array $result */
protected $result;
public function __construct() {
parent::__construct( 'Thanks' );
}
/**
* HTMLForm fields
* @return Array
*/
protected function getFormFields() {
return array(
'revid' => array(
'id' => 'mw-thanks-form-revid',
'name' => 'revid',
'type' => 'int',
'label-message' => 'thanks-form-revid',
'default' => $this->getRequest()->getInt( 'revid', $this->par ) ?: '',
)
);
}
/**
* Make it look pretty
* @param HTMLForm $form
*/
protected function alterForm( HTMLForm $form ) {
$form->setDisplayFormat( 'vform' );
$form->setWrapperLegend( false );
}
/**
* Calls the API internally
* @param array $data
* @return Status
*/
public function onSubmit( array $data ) {
if ( !isset( $data['revid'] ) ) {
return Status::newFatal( 'thanks-error-invalidrevision' );
}
$request = new DerivativeRequest(
$this->getRequest(),
array(
'action' => 'thank',
'rev' => (int)$data['revid'],
'source' => 'specialpage',
'token' => $this->getUser()->getEditToken(),
),
true // posted
);
$api = new ApiMain(
$request,
true // enable write mode
);
try {
$api->execute();
} catch ( UsageException $e ) {
return $this->handleErrorCodes( $e->getCodeString() );
}
$result = $api->getResult()->getData();
$this->result = $result['result'];
return Status::newGood();
}
/**
* Handles error codes returned by the API
* @param $code
* @return Status
*/
protected function handleErrorCodes( $code ) {
$status = new Status;
switch ( $code ) {
case 'invalidrevision':
case 'ratelimited':
$status->fatal( "thanks-error-$code" );
break;
case 'notloggedin':
case 'blockedtext':
$status->fatal( $code );
break;
default:
$status->fatal( 'thanks-error-undefined' );
}
return $status;
}
/**
* Display a message to the user
*/
public function onSuccess() {
$recipient = User::newFromName( $this->result['recipient'] );
$link = Linker::userLink( $recipient->getId(), $recipient->getName() );
$this->getOutput()->addHTML( $this->msg( 'thanks-thanked-notice' )
->rawParams( $link )
->params( $recipient->getName() )->parse()
);
}
public function isListed() {
return false;
}
}

View file

@ -66,7 +66,7 @@ class ThanksHooks {
'a', 'a',
array( array(
'class' => 'mw-thanks-thank-link', 'class' => 'mw-thanks-thank-link',
'href' => '#', 'href' => SpecialPage::getTitleFor( 'Thanks', $rev->getId() )->getFullURL(),
'title' => $tooltip, 'title' => $tooltip,
'data-revision-id' => $rev->getId(), 'data-revision-id' => $rev->getId(),
), ),

View file

@ -23,6 +23,9 @@ $messages['en'] = array(
'thanks-thank-tooltip' => '{{GENDER:$1|Send}} a thank you notification to this {{GENDER:$2|user}}', 'thanks-thank-tooltip' => '{{GENDER:$1|Send}} a thank you notification to this {{GENDER:$2|user}}',
'thanks-confirmation' => 'Do you want to {{GENDER:$1|thank}} $2 for this edit?', 'thanks-confirmation' => 'Do you want to {{GENDER:$1|thank}} $2 for this edit?',
'thanks-thanked-notice' => '$1 was notified that you liked {{GENDER:$2|his|her|their}} edit.', 'thanks-thanked-notice' => '$1 was notified that you liked {{GENDER:$2|his|her|their}} edit.',
'thanks' => 'Send thanks',
'thanks-form-revid' => 'Revision ID for edit',
'thanks-already-thanked' => '{{GENDER:$1|You}} have already sent thanks for this edit.',
'echo-pref-subscription-edit-thank' => 'Thanks me for my edit', 'echo-pref-subscription-edit-thank' => 'Thanks me for my edit',
'echo-pref-tooltip-edit-thank' => 'Notify me when someone thanks me for an edit I made.', 'echo-pref-tooltip-edit-thank' => 'Notify me when someone thanks me for an edit I made.',
'echo-category-title-edit-thank' => 'Thanks', 'echo-category-title-edit-thank' => 'Thanks',
@ -86,6 +89,9 @@ Pop-up message that is displayed after a user has thanked another user for their
Parameters: Parameters:
* $1 - the username of the user that was thanked * $1 - the username of the user that was thanked
* $2 - the gender of the user that was thanked', * $2 - the gender of the user that was thanked',
'thanks' => '{{doc-special|Thanks}}',
'thanks-form-revid' => 'Label for form field where the user inputs the revision id',
'thanks-already-thanked' => 'Message shown to user if they have already sent thanks for this edit. $1 is the user\'s username.',
'echo-pref-subscription-edit-thank' => 'Option for getting notifications when someone thanks the user for their edit. 'echo-pref-subscription-edit-thank' => 'Option for getting notifications when someone thanks the user for their edit.
This is the conclusion of the sentence begun by the header: {{msg-mw|Prefs-echosubscriptions}}.', This is the conclusion of the sentence begun by the header: {{msg-mw|Prefs-echosubscriptions}}.',

View file

@ -45,11 +45,15 @@ $wgAutoloadClasses['ThanksHooks'] = $dir . '/Thanks.hooks.php';
$wgAutoloadClasses['EchoThanksFormatter'] = $dir . '/ThanksFormatter.php'; $wgAutoloadClasses['EchoThanksFormatter'] = $dir . '/ThanksFormatter.php';
$wgAutoloadClasses['ApiThank'] = $dir . '/ApiThank.php'; $wgAutoloadClasses['ApiThank'] = $dir . '/ApiThank.php';
$wgAutoloadClasses['ThanksLogFormatter'] = $dir . '/ThanksLogFormatter.php'; $wgAutoloadClasses['ThanksLogFormatter'] = $dir . '/ThanksLogFormatter.php';
$wgAutoloadClasses['SpecialThanks'] = $dir . '/SpecialThanks.php';
$wgExtensionMessagesFiles['Thanks'] = $dir . '/Thanks.i18n.php'; $wgExtensionMessagesFiles['Thanks'] = $dir . '/Thanks.i18n.php';
// Register APIs // Register APIs
$wgAPIModules['thank'] = 'ApiThank'; $wgAPIModules['thank'] = 'ApiThank';
// Register special page
$wgSpecialPages['Thanks'] = 'SpecialThanks';
// Register hooks // Register hooks
$wgHooks['HistoryRevisionTools'][] = 'ThanksHooks::insertThankLink'; $wgHooks['HistoryRevisionTools'][] = 'ThanksHooks::insertThankLink';
$wgHooks['DiffRevisionTools'][] = 'ThanksHooks::insertThankLink'; $wgHooks['DiffRevisionTools'][] = 'ThanksHooks::insertThankLink';

View file

@ -59,7 +59,12 @@ class ApiThankTest extends \ApiTestCase {
} }
protected function assertSuccess( $result ){ protected function assertSuccess( $result ){
$this->assertEquals( array( 'result' => array( 'success' => 1 ) ), $result ); $this->assertEquals( array(
'result' => array(
'success' => 1,
'recipient' => self::$users['uploader']->username,
),
), $result );
} }
public function testInvalidRequest(){ public function testInvalidRequest(){