Support rate limiting backlink purges, including null edits
authorAaron Schulz <aschulz@wikimedia.org>
Fri, 20 Sep 2013 22:26:08 +0000 (15:26 -0700)
committerTim Starling <tstarling@wikimedia.org>
Fri, 27 Sep 2013 05:37:39 +0000 (05:37 +0000)
Change-Id: I86e45b7d0eba7d87f65150b34e190e04d8342b3e

docs/hooks.txt
includes/DefaultSettings.php
includes/EditPage.php
includes/User.php
includes/api/ApiPurge.php

index 5d6a6e4..377a669 100644 (file)
@@ -1879,6 +1879,7 @@ $action : Action being performed
 &$result : Whether or not the action should be prevented
 Change $result and return false to give a definitive answer, otherwise
 the built-in rate limiting checks are used, if enabled.
+$incrBy: Amount to increment counter by
 
 'PlaceNewSection': Override placement of new sections. Return false and put the
 merged text into $text to override the default behavior.
index 4d8c032..5b1d4b3 100644 (file)
@@ -4653,6 +4653,13 @@ $wgRateLimits = array(
        'emailuser' => array(
                'user' => null,
        ),
+       'linkpurge' => array(
+               'anon' => null,
+               'user' => null,
+               'newbie' => null,
+               'ip' => null,
+               'subnet' => null,
+       ),
 );
 
 /**
index 63e3e66..12cd4b3 100644 (file)
@@ -1493,7 +1493,7 @@ class EditPage {
                        wfProfileOut( __METHOD__ );
                        return $status;
                }
-               if ( $wgUser->pingLimiter() ) {
+               if ( $wgUser->pingLimiter() || $wgUser->pingLimiter( 'linkpurge', 0 ) ) {
                        $status->fatal( 'actionthrottledtext' );
                        $status->value = self::AS_RATE_LIMITED;
                        wfProfileOut( __METHOD__ . '-checks' );
@@ -1771,6 +1771,10 @@ class EditPage {
                }
 
                $result['nullEdit'] = $doEditStatus->hasMessage( 'edit-no-change' );
+               if ( $result['nullEdit'] ) {
+                       // We don't know if it was a null edit until now, so increment here
+                       $wgUser->pingLimiter( 'linkpurge' );
+               }
                $result['redirect'] = $content->isRedirect();
                $this->updateWatchlist();
                wfProfileOut( __METHOD__ );
index 60efc9d..12912e1 100644 (file)
@@ -1489,12 +1489,13 @@ class User {
         * last-hit counters will be shared across wikis.
         *
         * @param string $action Action to enforce; 'edit' if unspecified
+        * @param integer $incrBy Positive amount to increment counter by [defaults to 1]
         * @return bool True if a rate limiter was tripped
         */
-       public function pingLimiter( $action = 'edit' ) {
+       public function pingLimiter( $action = 'edit', $incrBy = 1 ) {
                // Call the 'PingLimiter' hook
                $result = false;
-               if ( !wfRunHooks( 'PingLimiter', array( &$this, $action, &$result ) ) ) {
+               if ( !wfRunHooks( 'PingLimiter', array( &$this, $action, &$result, $incrBy ) ) ) {
                        return $result;
                }
 
@@ -1583,9 +1584,13 @@ class User {
                                }
                        } else {
                                wfDebug( __METHOD__ . ": adding record for $key $summary\n" );
-                               $wgMemc->add( $key, 0, intval( $period ) ); // first ping
+                               if ( $incrBy > 0 ) {
+                                       $wgMemc->add( $key, 0, intval( $period ) ); // first ping
+                               }
+                       }
+                       if ( $incrBy > 0 ) {
+                               $wgMemc->incr( $key, $incrBy );
                        }
-                       $wgMemc->incr( $key );
                }
 
                wfProfileOut( __METHOD__ );
index e2eae61..0812ba5 100644 (file)
@@ -84,7 +84,7 @@ class ApiPurge extends ApiBase {
                        $r['purged'] = '';
 
                        if ( $forceLinkUpdate || $forceRecursiveLinkUpdate ) {
-                               if ( !$this->getUser()->pingLimiter() ) {
+                               if ( !$this->getUser()->pingLimiter( 'linkpurge' ) ) {
                                        global $wgEnableParserCache;
 
                                        $popts = $page->makeParserOptions( 'canonical' );