Add a button to request a new fancy captcha

This adds HTML, CSS, and JS to FancyCaptcha output to refresh the image,
which requests it via a new fancycaptchareload API.
It also cleans up the Asirra class a little.

Bug: 14230
Change-Id: I4e476f32de199534c9798fc78e8490b3ef91dd45
This commit is contained in:
lalei 2013-01-16 18:00:09 -08:00 committed by Matthew Flaschen
parent 6dca978e4e
commit 12361c5f31
11 changed files with 194 additions and 27 deletions

34
ApiFancyCaptchaReload.php Normal file
View file

@ -0,0 +1,34 @@
<?
/**
* Api module to reload FancyCaptcha
*
* @ingroup API
* @ingroup Extensions
*/
class ApiFancyCaptchaReload extends ApiBase {
public function execute() {
# Get a new FancyCaptcha form data
$captcha = new FancyCaptcha();
$captchaIndex = $captcha->getCaptchaIndex();
$result = $this->getResult();
$result->addValue( null, $this->getModuleName(), array ( 'index' => $captchaIndex ) );
return true;
}
public function getDescription() {
return 'Get a new FancyCaptcha.';
}
public function getAllowedParams() {
return array();
}
public function getParamDescription() {
return array();
}
public function getExamples() {
return array( 'api.php?action=fancycaptchareload&format=xml' );
}
}

View file

@ -17,7 +17,7 @@ class Asirra extends SimpleCaptcha {
function getForm() {
global $wgOut;
$wgOut->addModules( 'ext.confirmedit.asirra' );
$wgOut->addModules( 'ext.confirmEdit.asirra' );
$js = Html::linkedScript( $this->asirra_clientscript );
$message = Xml::encodeJsVar( wfMessage( 'asirra-createaccount-fail' )->plain() );

View file

@ -24,17 +24,17 @@ if ( !defined( 'MEDIAWIKI' ) ) {
exit;
}
$dir = __DIR__ . '/';
require_once( "$dir/ConfirmEdit.php" );
$dir = __DIR__;
require_once( $dir . '/ConfirmEdit.php' );
$wgCaptchaClass = 'Asirra';
$wgExtensionMessagesFiles['Asirra'] = "$dir/Asirra.i18n.php";
$wgAutoloadClasses['Asirra'] = "$dir/Asirra.class.php";
$wgExtensionMessagesFiles['Asirra'] = $dir . '/Asirra.i18n.php';
$wgAutoloadClasses['Asirra'] = $dir . '/Asirra.class.php';
$wgResourceModules['ext.confirmedit.asirra'] = array(
'localBasePath' => $dir,
'remoteExtPath' => 'ConfirmEdit',
'scripts' => 'ext.confirmedit.asirra.js',
$wgResourceModules['ext.confirmEdit.asirra'] = array(
'localBasePath' => $dir . '/resources',
'remoteExtPath' => 'ConfirmEdit/resources',
'scripts' => 'ext.confirmEdit.asirra.js',
'messages' => array(
'asirra-failed',
),

View file

@ -89,30 +89,40 @@ class FancyCaptcha extends SimpleCaptcha {
* Insert the captcha prompt into the edit form.
*/
function getForm() {
$info = $this->pickImage();
if ( !$info ) {
throw new MWException( "Ran out of captcha images" );
}
global $wgOut, $wgExtensionAssetsPath, $wgEnableAPI;
// Generate a random key for use of this captcha image in this session.
// This is needed so multiple edits in separate tabs or windows can
// go through without extra pain.
$index = $this->storeCaptcha( $info );
wfDebug( "Captcha id $index using hash ${info['hash']}, salt ${info['salt']}.\n" );
// Uses addModuleStyles so it is loaded when JS is disabled.
$wgOut->addModuleStyles( 'ext.confirmEdit.fancyCaptcha.styles' );
$title = SpecialPage::getTitleFor( 'Captcha', 'image' );
$index = $this->getCaptchaIndex();
return "<p>" .
if ( $wgEnableAPI ) {
$reloadText = wfMessage( 'fancycaptcha-reload-text' )->text();
// Loaded only if JS is enabled
$wgOut->addModules( 'ext.confirmEdit.fancyCaptcha' );
$captchaReload = "<span class='confirmedit-captcha-reload fancycaptcha-reload'>" .
Html::element( 'img', array(
'class' => 'fancycaptcha-reload-button',
'src' => $wgExtensionAssetsPath . '/ConfirmEdit/images/fancycaptcha-reload-icon.png',
'alt' => wfMessage( 'fancycaptcha-reload-button' )->text(),
'title' => $reloadText ) ) .
Html::rawElement( 'small', array(
'class' => 'fancycaptcha-reload-text' ),
$reloadText ) .
"</span>\n";
} else {
$captchaReload = '';
}
return "<div class='fancycaptcha-wrapper'><div class='fancycaptcha-image-container'>" .
Html::element( 'img', array(
'class' => 'fancycaptcha-image',
'src' => $title->getLocalUrl( 'wpCaptchaId=' . urlencode( $index ) ),
'alt' => '' ) ) .
"</p>\n" .
Html::element( 'input', array(
'type' => 'hidden',
'name' => 'wpCaptchaId',
'id' => 'wpCaptchaId',
'value' => $index ) ) .
"</div>\n" .
'<p>' .
Html::element( 'label', array(
'for' => 'wpCaptchaWord',
@ -125,7 +135,32 @@ class FancyCaptcha extends SimpleCaptcha {
'autocapitalize' => 'off',
'required' => 'required',
'tabindex' => 1 ) ) . // tab in before the edit textarea
"</p>\n";
$captchaReload .
Html::element( 'input', array(
'type' => 'hidden',
'name' => 'wpCaptchaId',
'id' => 'wpCaptchaId',
'value' => $index ) ) .
"</p>\n" .
"</div>\n";;
}
/**
* Get captcha index key
* @return string captcha ID key
*/
function getCaptchaIndex() {
$info = $this->pickImage();
if ( !$info ) {
throw new MWException( "Ran out of captcha images" );
}
// Generate a random key for use of this captcha image in this session.
// This is needed so multiple edits in separate tabs or windows can
// go through without extra pain.
$index = $this->storeCaptcha( $info );
return $index;
}
/**

View file

@ -19,6 +19,8 @@ To help protect against automated spam, please enter the words that appear below
'fancycaptcha-create' => 'To create the page, please enter the words that appear below in the box ([[Special:Captcha/help|more info]]):',
'fancycaptcha-edit' => 'To edit this page, please enter the words that appear below in the box ([[Special:Captcha/help|more info]]):',
'fancycaptcha-sendemail' => 'To help protect against automated spamming, please enter the words that appear below in the box ([[Special:Captcha/help|more info]]):',
'fancycaptcha-reload-button' => 'Refresh',
'fancycaptcha-reload-text' => 'Refresh',
);
/** Message documentation (Message documentation)
@ -36,6 +38,8 @@ $messages['qqq'] = array(
'fancycaptcha-create' => '{{Related|ConfirmEdit-create}}',
'fancycaptcha-edit' => '{{Related|ConfirmEdit-edit}}',
'fancycaptcha-sendemail' => '{{Related|ConfirmEdit-sendemail}}',
'fancycaptcha-reload-button' => 'Alternative (alt) text for reload button to get a new FancyCaptcha image.',
'fancycaptcha-reload-text' => 'Prompts a click to get a new FancyCaptcha image. Used as regular element text and title text of button',
);
/** Gheg Albanian (Gegë)

View file

@ -58,3 +58,19 @@ $wgCaptchaDeleteOnSolve = false;
$wgExtensionMessagesFiles['FancyCaptcha'] = $dir . '/FancyCaptcha.i18n.php';
$wgAutoloadClasses['FancyCaptcha'] = $dir . '/FancyCaptcha.class.php';
$wgResourceModules['ext.confirmEdit.fancyCaptcha.styles'] = array(
'localBasePath' => $dir . '/resources',
'remoteExtPath' => 'ConfirmEdit/resources',
'styles' => 'ext.confirmEdit.fancyCaptcha.css',
);
$wgResourceModules['ext.confirmEdit.fancyCaptcha'] = array(
'localBasePath' => $dir . '/resources',
'remoteExtPath' => 'ConfirmEdit/resources',
'scripts' => 'ext.confirmEdit.fancyCaptcha.js',
'dependencies' => 'mediawiki.api',
);
$wgAutoloadClasses['ApiFancyCaptchaReload'] = $dir . '/ApiFancyCaptchaReload.php';
$wgAPIModules['fancycaptchareload'] = 'ApiFancyCaptchaReload';

Binary file not shown.

After

Width:  |  Height:  |  Size: 6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 307 B

View file

@ -0,0 +1,38 @@
.fancycaptcha-wrapper {
display: table;
background-color: #FFF;
}
/* Prevents the size of the container from changing, affecting page
layout, for normal CAPTCHA sizes. */
.fancycaptcha-image-container {
min-height: 95px;
}
.fancycaptcha-reload {
padding: 0 5px;
}
.client-nojs .fancycaptcha-reload {
display: none;
}
.fancycaptcha-reload-button {
padding: 5px;
}
.fancycaptcha-reload-button:hover {
cursor: pointer;
cursor: hand;
}
.fancycaptcha-reload-text {
color: #0645AD;
display: inline !important;
}
.fancycaptcha-reload-text:hover {
text-decoration: underline;
cursor: pointer;
cursor: hand;
}

View file

@ -0,0 +1,40 @@
( function ( $, mw ) {
var api = new mw.Api();
$( document ).on( 'click', '.fancycaptcha-reload', function () {
var staticImageDirectory = mw.config.get( 'wgExtensionAssetsPath' ) + '/ConfirmEdit/images/',
$this = $( this ), reloadButtonImage, captchaImage;
reloadButtonImage = $this
.find( '.fancycaptcha-reload-button' )
.attr( 'src', staticImageDirectory + 'ajax-loader-10x10.gif' );
captchaImage = $( '.fancycaptcha-image' );
// AJAX request to get captcha index key
api.post( {
action: 'fancycaptchareload',
format: 'xml'
}, {
dataType: 'xml'
} )
.done( function ( xmldata ) {
var imgSrc, captchaIndex;
captchaIndex = $( xmldata ).find( 'fancycaptchareload' ).attr( 'index' );
if ( typeof captchaIndex === 'string' ) {
// replace index key with a new one for captcha image
imgSrc = captchaImage.attr( 'src' )
.replace( /(wpCaptchaId=)\w+/, '$1' + captchaIndex );
captchaImage.attr( 'src', imgSrc );
// replace index key with a new one for hidden tag
$( '#wpCaptchaId' ).val( captchaIndex );
$( '#wpCaptchaWord' ).val( '' ).focus();
}
} )
.always( function () {
reloadButtonImage.attr( 'src', staticImageDirectory + 'fancycaptcha-reload-icon.png' );
} );
return false;
} );
} )( jQuery, mediaWiki );