Modifying ConfirmEdit extension to make it API-friendly:
authorRoan Kattouw <catrope@users.mediawiki.org>
Thu, 28 Feb 2008 17:42:23 +0000 (17:42 +0000)
committerRoan Kattouw <catrope@users.mediawiki.org>
Thu, 28 Feb 2008 17:42:23 +0000 (17:42 +0000)
* Hooking into the APIEditBeforeSave hook (which will appear in the ApiEdit_Vodafone branch in the next revision)
* Moved general CAPTCHA generation in SimpleCaptcha to getCaptcha()
* Moved general confirmEdit() functionality to doConfirmEdit() to facilitate differtiating between UI and API handling
* Adding SimpleCaptcha::addCaptchaAPI() method that adds CAPTCHA information to an API result array. Other CAPTCHA implementations should override this method with a function that does the same (did this for FancyCaptcha and MathCaptcha)

ConfirmEdit.php
ConfirmEdit_body.php
FancyCaptcha.class.php
MathCaptcha.class.php

index 722a3c7ed5ddb6f7e1fbcd79f72533c90afce9ee..2faac7f0395f83078049b265272beb9cf2318772 100644 (file)
@@ -166,7 +166,6 @@ $wgCaptchaWhitelist = false;
 $wgCaptchaRegexes = array();
 
 /** Register special page */
-global $wgSpecialPages;
 $wgSpecialPages['Captcha'] = array( /*class*/'CaptchaSpecialPage', /*name*/'Captcha' );
 
 $wgConfirmEditIP = dirname( __FILE__ );
@@ -182,6 +181,8 @@ $wgHooks['AbortNewAccount'][] = 'ConfirmEditHooks::confirmUserCreate';
 $wgHooks['LoginAuthenticateAudit'][] = 'ConfirmEditHooks::triggerUserLogin';
 $wgHooks['UserLoginForm'][] = 'ConfirmEditHooks::injectUserLogin';
 $wgHooks['AbortLogin'][] = 'ConfirmEditHooks::confirmUserLogin';
+# Register API hook
+$wgHooks['APIEditBeforeSave'][] = 'ConfirmEditHooks::confirmEditAPI';
 
 $wgAutoloadClasses['ConfirmEditHooks'] 
        = $wgAutoloadClasses['SimpleCaptcha'] 
index 1755183a14eaa3f7307133277c4574da9553390d..e905640cf23b8bafb119fecba564e462a397effc 100644 (file)
@@ -22,6 +22,10 @@ class ConfirmEditHooks {
        static function confirmEditMerged( &$editPage, $newtext ) {
                return self::getInstance()->confirmEditMerged( $editPage, $newtext );
        }
+       
+       static function confirmEditAPI( &$editPage, $newtext, &$resultArr ) {
+               return self::getInstance()->confirmEditAPI( $editPage, $newtext, $resultArr );
+       }
 
        static function injectUserCreate( &$template ) {
                return self::getInstance()->injectUserCreate( $template );
@@ -65,6 +69,24 @@ class SimpleCaptcha {
                $this->storage = new $wgCaptchaStorageClass;
        }
        
+       function getCaptcha() {
+               $a = mt_rand(0, 100);
+               $b = mt_rand(0, 10);
+               $op = mt_rand(0, 1) ? '+' : '-';
+
+               $test = "$a $op $b";
+               $answer = ($op == '+') ? ($a + $b) : ($a - $b);
+               return array('question' => $test, 'answer' => $answer);
+       }
+       
+       function addCaptchaAPI(&$resultArr) {
+               $captcha = $this->getCaptcha();
+               $index = $this->storeCaptcha( $captcha );
+               $resultArr['captcha']['type'] = 'simple';
+               $resultArr['captcha']['id'] = $index;
+               $resultArr['captcha']['question'] = $captcha['question'];
+       }
+       
        /**
         * Insert a captcha prompt into the edit form.
         * This sample implementation generates a simple arithmetic operation;
@@ -75,16 +97,10 @@ class SimpleCaptcha {
         * @return string HTML
         */
        function getForm() {
-               $a = mt_rand(0, 100);
-               $b = mt_rand(0, 10);
-               $op = mt_rand(0, 1) ? '+' : '-';
-
-               $test = "$a $op $b";
-               $answer = ($op == '+') ? ($a + $b) : ($a - $b);
+               $captcha = $this->getCaptcha();
+               $index = $this->storeCaptcha( $captcha );
 
-               $index = $this->storeCaptcha( array( 'answer' => $answer ) );
-
-               return "<p><label for=\"wpCaptchaWord\">$test</label> = " .
+               return "<p><label for=\"wpCaptchaWord\">{$captcha['question']}</label> = " .
                        wfElement( 'input', array(
                                'name' => 'wpCaptchaWord',
                                'id'   => 'wpCaptchaWord',
@@ -430,21 +446,17 @@ class SimpleCaptcha {
                        $links[] = $row->el_to;
                }
                return $links;
-       }               
-
+       }
+       
        /**
-        * The main callback run on edit attempts.
-        * @param EditPage $editPage
-        * @param string $newtext
-        * @param string $section
-        * @param bool true to continue saving, false to abort and show a captcha form
+        * Backend function for confirmEdit() and confirmEditAPI()
+        * @return bool false if the CAPTCHA is rejected, true otherwise
         */
-       function confirmEdit( &$editPage, $newtext, $section, $merged = false ) {
+       private function doConfirmEdit( &$editPage, $newtext, $section, $merged = false ) {
                if( $this->shouldCheck( $editPage, $newtext, $section, $merged ) ) {
                        if( $this->passCaptcha() ) {
                                return true;
                        } else {
-                               $editPage->showEditForm( array( &$this, 'editCallback' ) );
                                return false;
                        }
                } else {
@@ -453,6 +465,28 @@ class SimpleCaptcha {
                }
        }
 
+       /**
+        * The main callback run on edit attempts.
+        * @param EditPage $editPage
+        * @param string $newtext
+        * @param string $section
+        * @param bool $merged
+        * @return bool true to continue saving, false to abort and show a captcha form
+        */
+       function confirmEdit( &$editPage, $newtext, $section, $merged = false ) {
+               global $wgTitle;
+               if( is_null( $wgTitle ) ) {
+                       # API mode
+                       # The CAPTCHA was already checked and approved 
+                       return true;
+               }
+               if( !$this->doConfirmEdit( $editPage, $newtext, $section, $merged ) ) {
+                       $editPage->showEditForm( array( &$this, 'editCallback' ) );
+                       return false;
+               }
+               return true;
+       }
+
        /**
         * A more efficient edit filter callback based on the text after section merging
         * @param EditPage $editPage
@@ -461,6 +495,15 @@ class SimpleCaptcha {
        function confirmEditMerged( &$editPage, $newtext ) {
                return $this->confirmEdit( $editPage, $newtext, false, true );
        }
+       
+       
+       function confirmEditAPI( &$editPage, $newtext, &$resultArr) {
+               if( !$this->doConfirmEdit( $editPage, $newtext, false, false ) ) {
+                       $this->addCaptchaAPI($resultArr);
+                       return false;
+               }
+               return true;
+       }
 
        /**
         * Hook for user creation form submissions.
index abdb2f8842bfa2f25a3b5b3c972d3d563197e59a..b560e712e0685422dc856c3a4dbebd56c43a170b 100644 (file)
@@ -24,6 +24,19 @@ class FancyCaptcha extends SimpleCaptcha {
                }
        }
 
+       function addCaptchaAPI(&$resultArr) {
+               $info = $this->pickImage();
+               if( !$info ) {
+                       $resultArr['captcha']['error'] = 'Out of images';
+                       return;
+               }
+               $index = $this->storeCaptcha( $info );
+               $title = Title::makeTitle( NS_SPECIAL, 'Captcha/image' );
+               $resultArr['captcha']['type'] = 'image';
+               $resultArr['captcha']['id'] = $index;
+               $resultArr['captcha']['url'] = $title->getLocalUrl( 'wpCaptchaId=' . urlencode( $index ) );             
+       }
+
        /**
         * Insert the captcha prompt into the edit form.
         */
index adf1663b8de956b6c3e03df859f25e53206fc0ec..a51e7fae6b857ab4f987f2613eca0643a698b6dd 100644 (file)
@@ -6,6 +6,14 @@ class MathCaptcha extends SimpleCaptcha {
        function keyMatch( $answer, $info ) {
                return (int)$answer == (int)$info['answer'];
        }
+
+       function addCaptchaAPI(&$resultArr) {
+               list( $sum, $answer ) = $this->pickSum();
+               $index = $this->storeCaptcha( array('answer' => $answer ) );
+               $resultArr['captcha']['type'] = 'math';
+               $resultArr['captcha']['id'] = $index;
+               $resultArr['captcha']['sum'] = $sum;
+       }
        
        /** Produce a nice little form */
        function getForm() {