diff --git a/ApiFancyCaptchaReload.php b/ApiFancyCaptchaReload.php
new file mode 100644
index 000000000..1de1947da
--- /dev/null
+++ b/ApiFancyCaptchaReload.php
@@ -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' );
+ }
+}
diff --git a/Asirra.class.php b/Asirra.class.php
index cbe51e262..bd58eb3a0 100644
--- a/Asirra.class.php
+++ b/Asirra.class.php
@@ -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() );
diff --git a/Asirra.php b/Asirra.php
index ff4cee9a6..923b0b9e8 100644
--- a/Asirra.php
+++ b/Asirra.php
@@ -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',
),
diff --git a/FancyCaptcha.class.php b/FancyCaptcha.class.php
index 45c48d2aa..02ad777c5 100644
--- a/FancyCaptcha.class.php
+++ b/FancyCaptcha.class.php
@@ -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 "
" .
+ if ( $wgEnableAPI ) {
+ $reloadText = wfMessage( 'fancycaptcha-reload-text' )->text();
+
+ // Loaded only if JS is enabled
+ $wgOut->addModules( 'ext.confirmEdit.fancyCaptcha' );
+
+ $captchaReload = "" .
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 ) .
+ "\n";
+ } else {
+ $captchaReload = '';
+ }
+
+ return "
" .
+ Html::element( 'img', array(
+ 'class' => 'fancycaptcha-image',
'src' => $title->getLocalUrl( 'wpCaptchaId=' . urlencode( $index ) ),
'alt' => '' ) ) .
- "\n" .
- Html::element( 'input', array(
- 'type' => 'hidden',
- 'name' => 'wpCaptchaId',
- 'id' => 'wpCaptchaId',
- 'value' => $index ) ) .
+ "
\n" .
'
' .
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
- "
\n";
+ $captchaReload .
+ Html::element( 'input', array(
+ 'type' => 'hidden',
+ 'name' => 'wpCaptchaId',
+ 'id' => 'wpCaptchaId',
+ 'value' => $index ) ) .
+ "\n" .
+ "
\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;
}
/**
diff --git a/FancyCaptcha.i18n.php b/FancyCaptcha.i18n.php
index 66143f7a2..52a192260 100644
--- a/FancyCaptcha.i18n.php
+++ b/FancyCaptcha.i18n.php
@@ -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ë)
diff --git a/FancyCaptcha.php b/FancyCaptcha.php
index 69e3be012..46002e22e 100644
--- a/FancyCaptcha.php
+++ b/FancyCaptcha.php
@@ -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';
diff --git a/images/ajax-loader-10x10.gif b/images/ajax-loader-10x10.gif
new file mode 100644
index 000000000..772e9a555
Binary files /dev/null and b/images/ajax-loader-10x10.gif differ
diff --git a/images/fancycaptcha-reload-icon.png b/images/fancycaptcha-reload-icon.png
new file mode 100644
index 000000000..6cbde303c
Binary files /dev/null and b/images/fancycaptcha-reload-icon.png differ
diff --git a/ext.confirmedit.asirra.js b/resources/ext.confirmEdit.asirra.js
similarity index 100%
rename from ext.confirmedit.asirra.js
rename to resources/ext.confirmEdit.asirra.js
diff --git a/resources/ext.confirmEdit.fancyCaptcha.css b/resources/ext.confirmEdit.fancyCaptcha.css
new file mode 100644
index 000000000..5115957aa
--- /dev/null
+++ b/resources/ext.confirmEdit.fancyCaptcha.css
@@ -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;
+}
diff --git a/resources/ext.confirmEdit.fancyCaptcha.js b/resources/ext.confirmEdit.fancyCaptcha.js
new file mode 100644
index 000000000..7640df3e6
--- /dev/null
+++ b/resources/ext.confirmEdit.fancyCaptcha.js
@@ -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 );