Extension:EnhancedAutopromote

From mediawiki.org
MediaWiki extensions manual
EnhancedAutopromote
Release status: unmaintained
Implementation Page action
Description Provides some additional autopromotion criteria possibilities
Author(s) (Leucostictetalk)
Latest version 1.0.0
MediaWiki 1.19+
Database changes Yes
Tables enh_autopromote
License GNU General Public License 2.0 or later
Download No link
$wgEnhancedAutopromoteCount, $wgEnhancedAutopromoteAgeSinceCount, $wgEnhancedAutopromoteCaptchaCount, $wgEnhancedAutopromoteAgeSinceCaptchaCount, $wgEnhancedAutopromoteGrandfather

The EnhancedAutopromote extension provides some additional autopromotion criteria possibilities.

Rationale[edit]

$wgAutoConfirmAge, $wgAutoConfirmCount and so on may not provide all the functionality you might want for screening users before they become autoconfirmed. For example, suppose you autoconfirm all users who have made 6 edits and been around 24 hours since their first edit. A user could make 1 good edit, wait 24 hours, and then make another 5 junk edits in rapid succession to become autoconfirmed. This extension allows you to put up additional barriers by, for instance, requiring that a user wait 24 hours after passing his 6th CAPTCHA before becoming autoconfirmed.

Hack[edit]

To get this to work, you need to hack the appropriate Extension:ConfirmEdit file to add the necessary CaptchaPassed hook to the passCaptcha() function.

Installation[edit]

  • Create a folder in the extensions folder named EnhancedAutopromote
  • Move the files to the extensions/EnhancedAutopromote/ folder
  • Edit LocalSettings.php in the root of your MediaWiki installation, and add the following line near the bottom:
require_once("$IP/extensions/EnhancedAutopromote/EnhancedAutopromote.php");

Configuration[edit]

Add the desired configuration settings below the require_once line in LocalSettings.php:

Configuration settings[edit]

$wgEnhancedAutopromoteCount[edit]

// Number of edits an account requires before it is autopromoted (similar to $wgAutoConfirmCount)
$wgEnhancedAutopromoteCount = 12; // 12 edits

$wgEnhancedAutopromoteAgeSinceCount[edit]

// Required seconds since $wgEnhancedAutopromoteCount reached
$wgEnhancedAutopromoteAgeSinceCount = 3600 * 24; // 24 hours

$wgEnhancedAutopromoteCaptchaCount[edit]

// Number of Captchas that need to be passed to autoconfirm
$wgEnhancedAutopromoteCaptchaCount = 6; // 6 CAPTCHAs

$wgEnhancedAutopromoteAgeSinceCaptchaCount[edit]

// Required seconds since $wgEnhancedAutopromoteCaptchaCount reached
$wgEnhancedAutopromoteAgeSinceCaptchaCount = 3600 * 24; // 24 hours

$wgEnhancedAutopromoteGrandfather[edit]

// Autopromote those who made their first edit before a certain timestamp. This takes precedence
// over the other EnhancedAutopromote configuration settings.
$wgEnhancedAutopromoteGrandfather = 20120304050607; // 5:06:07 AM UDC on 4 March 2012

Autopromote options[edit]

Condition Description Argument(s)
APCOND_AGE_FROM_CAPTCHACOUNT Number of seconds since the user finished passing the required number of CAPTCHAs N/A; use $wgEnhancedAutopromoteCaptchaCount and $wgEnhancedAutopromoteAgeSinceCaptchaCount
APCOND_AGE_FROM_EDITCOUNT Number of seconds since the user finished making the required number of edits N/A; use $wgEnhancedAutopromoteCount and $wgEnhancedAutopromoteAgeSinceCount
APCOND_CAPTCHACOUNT Number of CAPTCHAs that the user must pass to be enhanced-autoconfirmed N/A; use $wgEnhancedAutopromoteCaptchaCount

Default enhancedautoconfirmed group[edit]

// Default enhancedautoconfirmed group
$wgAutopromote[ "enhancedautoconfirmed" ] = array( "&",
    APCOND_CAPTCHACOUNT,
    APCOND_AGE_FROM_CAPTCHACOUNT,
    APCOND_AGE_FROM_EDITCOUNT,
);


Example[edit]

To put into the "enhancedautoconfirmed" group users who have passed the required number of CAPTCHAs a sufficient amount of time ago and who have made the required number of edits a sufficient amount of time ago, you might use the following:

$wgAutopromote[ "enhancedautoconfirmed" ] = array( "&",
    APCOND_AGE_FROM_CAPTCHACOUNT,
    APCOND_AGE_FROM_EDITCOUNT,
);

You may then wish to exempt those users from further CAPTCHAs:

$wgGroupPermissions['enhancedautoconfirmed']['skipcaptcha'] = true;

Files[edit]

EnhancedAutopromote.php[edit]

<?php
/**
 * EnhancedAutopromote MediaWiki extension.
 *
 * This extension provides some additional autopromotion criteria possibilities.
 *
 * Written by Leucosticte
 * http://www.mediawiki.org/wiki/User:Leucosticte
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 * http://www.gnu.org/copyleft/gpl.html
 *
 * @file
 * @ingroup Extensions
 */

if ( !defined( 'MEDIAWIKI' ) ) {
        die( 'This file is a MediaWiki extension. It is not a valid entry point' );
}
$wgExtensionCredits['antispam'][] = array(
    'path' => __FILE__,
    'name' => 'EnhancedAutopromote',
    'descriptionmsg' => 'enhancedautopromote-desc',
    'version' => '1.0.0',
    'author' => '[http://www.mediawiki.org/wiki/User:Leucosticte Leucosticte]',
    'url' => 'https://www.mediawiki.org/wiki/Extension:EnhancedAutopromote',
);

$wgAutoloadClasses['EnhancedAutopromoteHooks'] = dirname( __FILE__ ) .
    '/EnhancedAutopromoteHooks.php';
$wgExtensionMessagesFiles['EnhancedAutopromote'] = dirname( __FILE__ ) .
    '/EnhancedAutopromote.i18n.php';

define( 'APCOND_AGE_FROM_EDITCOUNT', 30 );
define( 'APCOND_CAPTCHACOUNT', 31 );
define( 'APCOND_AGE_FROM_CAPTCHACOUNT', 32 );

// Number of edits an account requires before it is autopromoted (similar to $wgAutoConfirmCount)
$wgEnhancedAutopromoteCount = 0;
// Required seconds since $wgEnhancedAutopromoteCount reached
$wgEnhancedAutopromoteAgeSinceCount = 0;
// Number of Captchas that need to be passed to autoconfirm
$wgEnhancedAutopromoteCaptchaCount = 0;
// Required seconds since $wgEnhancedAutopromoteCaptchaCount reached
$wgEnhancedAutopromoteAgeSinceCaptchaCount = 0;
// Autopromote those who made their first edit before a certain timestamp. This takes precedence
// over the other EnhancedAutopromote configuration settings.
$wgEnhancedAutopromoteGrandfather = 0;
// Namespaces that count toward the required edit count
$wgEnhancedAutopromoteNamespaces = array();
// Default enhancedautoconfirmed group
$wgAutopromote[ "enhancedautoconfirmed" ] = array( "&",
    APCOND_CAPTCHACOUNT,
    APCOND_AGE_FROM_CAPTCHACOUNT,
    APCOND_AGE_FROM_EDITCOUNT,
);

$wgHooks['AutopromoteCondition'][] = 'EnhancedAutopromoteHooks::moreCriteria';
$wgHooks['CaptchaPassed'][] = 'EnhancedAutopromoteHooks::captchaPassed';
$wgHooks['LoadExtensionSchemaUpdates'][] = 'EnhancedAutopromoteHooks::enhAutopromoteTable';

EnhancedAutopromote.hooks.php[edit]

<?php
if ( !defined( 'MEDIAWIKI' ) ) {
        die( 'This file is a MediaWiki extension. It is not a valid entry point' );
}

class EnhancedAutopromoteHooks {
    
    // Main entry point
    public static function moreCriteria( $type, $args, $user, &$result ) {
        global $wgEnhancedAutopromoteCount, $wgEnhancedAutopromoteAgeSinceCount,
            $wgEnhancedAutopromoteCaptchaCount, $wgEnhancedAutopromoteAgeSinceCaptchaCount,
            $wgEnhancedAutopromoteGrandfather;
        // If none of these enhanced features are being used, abort
        if ( $type != APCOND_AGE_FROM_EDITCOUNT
            && $type != APCOND_CAPTCHACOUNT
            && $type != APCOND_AGE_FROM_CAPTCHACOUNT ) {
            $result = null;
            return true;
        }
        
        // Those who made their first edit before a certain timestamp are exempt from CAPTCHA
        if ( $wgEnhancedAutopromoteGrandfather ) {
            $firstEdit = $user->getFirstEditTimestamp();
            if ( $firstEdit ) {
                if ( $firstEdit < $wgEnhancedAutopromoteGrandfather ) {
                    $result = true;
                    return true;
                }
            }
        }

        // If the globals are set so that anyone would pass, don't bother checking anything else
        switch ( $type ) {
                case APCOND_CAPTCHACOUNT:
                        if ( !$wgEnhancedAutopromoteCaptchaCount ) {
                                $result = true;
                                return true;
                        }
                        break;
                case APCOND_AGE_FROM_EDITCOUNT:
                        if ( !$wgEnhancedAutopromoteCount
                                || !$wgEnhancedAutopromoteAgeSinceCount ) {
                                $result = true;
                                return true;
                        }
                        break;
                case APCOND_AGE_FROM_CAPTCHACOUNT:
                        if ( !$wgEnhancedAutopromoteCaptchaCount
                                || !$wgEnhancedAutopromoteAgeSinceCaptchaCount ) {
                                $result = true;
                                return true;
                        }
        }
        $dbw = wfGetDB( DB_MASTER );
        $dbr = wfGetDB( DB_REPLICA );
        $row = EnhancedAutopromoteHooks::getEnhRow ( $user );
        if ( !$row ) {
            $row = EnhancedAutopromoteHooks::addEnhRow( $user );
        }
        
        switch ( $type ) {
            case APCOND_CAPTCHACOUNT:
                // Once the user has reached the required number of CAPTCHAs, he will never have to
                // pass another CAPTCHA, even if the required number is later increased
                $enhCaptchaReached = $row['eha_captcha_count_reached'];
                if ( $enhCaptchaReached ) {
                    $result = true;
                    return true;
                }
                $result = false;
                return true;
            case APCOND_AGE_FROM_EDITCOUNT:
                // Get the count from the enh_autopromote table if possible; it's probably less
                // expensive.
                $enhCountReached = $row['eha_count_reached'];
                // If it's not recorded in enh_autopromote, check the user's edit count and query the
                // revision table to get that timestamp
                if ( $enhCountReached ) {
                    $countReached = $enhCountReached;
                } else {
                    $countReached = EnhancedAutopromoteHooks::whenReachedCount ( $user );
                    // Record that timestamp in the table for the next time
                    if ( $countReached ) {
                        $dbw->update ( 'enh_autopromote', array (
                            'eha_count_reached' => $countReached ),
                            array ( 'eha_user' => $row['eha_user'] ) );
                    }
                }
                // If the user has reached the required edit count, then compare the timestamp of
                // when it was reached to the timestamp of now
                if ( $countReached ) {
                    if ( wfTimestampNow() - $row['eha_count_reached']
                        < $wgEnhancedAutopromoteAgeSinceCount ) {
                        // The user has reached the required edit count, but it's too recently to
                        // autopromote yet
                        $result = false;
                        return true;
                    } else {
                        // Yes, autopromote
                        $result = true;
                        return true;
                    }
                }
                // No, the required edit count has not been reached
                $result = false;
                return true;
            case APCOND_AGE_FROM_CAPTCHACOUNT:
                // If the user has reached the required captcha count, then compare the timestamp of
                // when it was reached to the timestamp of now.
                if ( $row['eha_captcha_count_reached'] ) {
                    if ( wfTimestampNow() - $row['eha_captcha_count_reached']
                        < $wgEnhancedAutopromoteAgeSinceCaptchaCount ) {
                        // The user has reached the required captcha count, but it's too recently to
                        // autopromote yet
                        $result = false;
                        return true;
                    } else {
                        // Yes, autopromote
                        $result = true;
                        return true;
                    }
                }
                // No, the required captcha count has not been reached
                $result = false;
                return true;
        }
    }
    
    // Get the user's row from the enh_autopromote table
    public static function getEnhRow ( $user ) {
        $dbr = wfGetDB( DB_REPLICA );
        $res = $dbr->selectRow ( 'enh_autopromote',
            array ( 'eha_id', 'eha_user', 'eha_count_reached', 'eha_captchas_thus_far',
                'eha_captcha_count_reached',
            ),
            array ( 'eha_user' => $user->getId() )
        );
        $row = null;
        if ( $res ) {
            $row = array (
                'eha_user' => $user->getId(),
                'eha_count_reached' => $res->eha_count_reached,
                'eha_captchas_thus_far' => $res->eha_captchas_thus_far,
                'eha_captcha_count_reached' => $res->eha_captcha_count_reached,
            );
        }
        return $row;
    }
    
    // Add a new row to the table
    public static function addEnhRow ( $user, $captchasThusFar = 0 ) {
        global $wgEnhancedAutopromoteCount, $wgEnhancedAutopromoteAgeSinceCount,
            $wgEnhancedAutopromoteCaptchaCount;
        $countReached = null;
        $captchaCountReached = null;
        // Get the info needed to populate the eha_count_reached field
        if ( $wgEnhancedAutopromoteCount > 0
            && $user->getEditCount() >= $wgEnhancedAutopromoteCount ) {
            $countReached = EnhancedAutopromoteHooks::whenReachedCount ( $user );
        }
        // Get the info needed to populate the eha_captcha_count_reached field
        if ( $wgEnhancedAutopromoteCaptchaCount > 0
            && $captchasThusFar >= $wgEnhancedAutopromoteCaptchaCount ) {
            $captchaCountReached = wfTimestampNow();
        }
        $row = array (
            'eha_user' => $user->getId(),
            'eha_count_reached' => $countReached,
            'eha_captchas_thus_far' => $captchasThusFar,
            'eha_captcha_count_reached' => $captchaCountReached,
        );
        $dbw = wfGetDB( DB_MASTER );
        $dbw->insert ( 'enh_autopromote', $row );
        return $row;
    }
    
    // Check to see when the user's edit count became sufficient. Return null if it hasn't yet
    public static function whenReachedCount ( $user ) {
        global $wgEnhancedAutopromoteCount, $wgEnhancedAutopromoteNamespaces;
        // If the user hasn't reached the required number of edits, don't bother checking the table
        if ( $user->getEditCount() < $wgEnhancedAutopromoteCount ) {
            return null;
        }
        $dbr = wfGetDB( DB_REPLICA );
        $table = array ( 'revision' );
        $cond = array (
                'rev_user' => $user->getId(),
        );
        // FIXME: This namespace feature doesn't work; there's something wrong with the way this
        // query is set up.
        /*
        if ( $wgEnhancedAutopromoteNamespaces ) {
                $table[] = 'page';
                $cond[ 'revision.rev_page' ] = 'page.page_id';
                $cond[ 'page.page_namespace' ] = $wgEnhancedAutopromoteNamespaces;
        }
        */
        $revisionRow = $dbr->selectRow (
            $table,
            array (
                'rev_user',
                'rev_timestamp',
            ),
            $cond,
            __METHOD__,
            "OFFSET $wgEnhancedAutopromoteCount"
        );
        $result = null;
        if ( $revisionRow ) {
            $result = $revisionRow->rev_timestamp;
        }
        return $result;
    }
    
    // Upon passing a CAPTCHA, increment the eha_captchas_thus_far field
    public static function captchaPassed () {
        global $wgUser,
            $wgEnhancedAutopromoteCaptchaCount, $wgEnhancedAutopromoteAgeSinceCaptchaCount;
        $user = $wgUser;
        if ( !$user || !$user->getId() )
        {
            return true;
        }
        $dbw = wfGetDB( DB_MASTER );
        $dbr = wfGetDB( DB_REPLICA );
        $row = EnhancedAutopromoteHooks::getEnhRow ( $user );
        // Initialization check, since it's possible the sysadmin hasn't configured
        // the wiki to check before loading the CAPTCHA
        if ( !$row ) {
            $row = EnhancedAutopromoteHooks::addEnhRow( $user, 1 );
            return true;
        }
        $captchasThusFar = $row[ 'eha_captchas_thus_far' ] + 1;
        $captchaCountReached = $row[ 'eha_captcha_count_reached' ];
        // If we've reached the necessary number of CAPTCHAs, record the timestamp
        if ( !$captchaCountReached
            && $wgEnhancedAutopromoteCaptchaCount > 0
            && $captchasThusFar >= $wgEnhancedAutopromoteCaptchaCount ) {
            $captchaCountReached = wfTimestampNow();
        }
        $dbw->update( 'enh_autopromote',
            array (
                'eha_captchas_thus_far' => $captchasThusFar,
                'eha_captcha_count_reached' => $captchaCountReached,
            ),
            array ( 'eha_user' => $user->getId() ), __METHOD__ );
        return true;
    }
    
    // Create table
    public static function enhAutopromoteTable ( DatabaseUpdater $updater ) {
        $updater->addExtensionUpdate( array( 'addTable', 'enh_autopromote',
                dirname( __FILE__ ) . '/enh-autopromote.sql', true ) );
        return true;
    }
}

EnhancedAutopromote.i18n.php[edit]

<?php
/**
* Internationalisation file for the EnhancedAutopromote extension.
*
* @file
* @ingroup Extensions
*/

$messages = array();

$messages['en'] = array(
    'enhancedautopromote-desc' => 'Provides some additional autopromotion criteria possibilities',
);

enh-autopromote.sql[edit]

-- The enh_autopromote table contains data concerning how many CAPTCHAs a user has passed and when
-- the user finished making the required number of edits and passing the required number of
-- CAPTCHAS.
CREATE TABLE /*_*/enh_autopromote (
    -- Primary key
    eha_id int unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT,
    -- user.user_id of the user
    eha_user int unsigned NOT NULL,
    -- Timestamp of when the required number of edits was reached
    eha_count_reached binary(14),
    -- Number of captchas that the user has passed thus far
    eha_captchas_thus_far int,
    -- Timestamp of when the required number of captchas were passed
    eha_captcha_count_reached binary(14)
);