Interfaces to use it can be added shortly.
* Add user_editcount field to provide data for heuristics on account use.
Incremented on edit, with lazy initialization from past revision data.
Can batch-initialize with maintenance/initEditCount.php (not yet friendly
to replication environments, this will do all accounts in one query).
* Allow raw SQL subsections in Database::update() SET portion as well as
for WHERE portion. Handy for increments and such.
creation, so people don't immediately go off to request a second one.
* Add a warning on Special:Confirmemail if a code was already sent and has
not yet expired.
+* Add user_editcount field to provide data for heuristics on account use.
+ Incremented on edit, with lazy initialization from past revision data.
+ Can batch-initialize with maintenance/initEditCount.php (not yet friendly
+ to replication environments, this will do all accounts in one query).
+* Allow raw SQL subsections in Database::update() SET portion as well as
+ for WHERE portion. Handy for increments and such.
== Languages updated ==
RecentChange::markPatrolled( $rcid );
}
}
+ $wgUser->incEditCount();
$dbw->commit();
}
} else {
RecentChange::markPatrolled( $rcid );
}
}
+ $wgUser->incEditCount();
$dbw->commit();
# Update links, etc.
}
if ( ($mode == LIST_AND || $mode == LIST_OR) && is_numeric( $field ) ) {
$list .= "($value)";
+ } elseif ( ($mode == LIST_SET) && is_numeric( $field ) ) {
+ $list .= "$value";
} elseif ( ($mode == LIST_AND || $mode == LIST_OR) && is_array ($value) ) {
$list .= $field." IN (".$this->makeList($value).") ";
} else {
return $text;
}
}
+
+ /**
+ * Increment the user's edit-count field.
+ * Will have no effect for anonymous users.
+ */
+ function incEditCount() {
+ if( !$this->isAnon() ) {
+ $dbw = wfGetDB( DB_MASTER );
+ $dbw->update( 'user',
+ array( 'user_editcount=user_editcount+1' ),
+ array( 'user_id' => $this->getId() ),
+ __METHOD__ );
+
+ // Lazy initialization check...
+ if( $dbw->affectedRows() == 0 ) {
+ // Pull from a slave to be less cruel to servers
+ // Accuracy isn't the point anyway here
+ $dbr = wfGetDB( DB_SLAVE );
+ $count = $dbr->selectField( 'revision',
+ 'COUNT(rev_user)',
+ array( 'rev_user' => $this->getId() ),
+ __METHOD__ );
+
+ // Now here's a goddamn hack...
+ if( $dbr !== $dbw ) {
+ // If we actually have a slave server, the count is
+ // at least one behind because the current transaction
+ // has not been committed and replicated.
+ $count++;
+ } else {
+ // But if DB_SLAVE is selecting the master, then the
+ // count we just read includes the revision that was
+ // just added in the working transaction.
+ }
+
+ $dbw->update( 'user',
+ array( 'user_editcount' => $count ),
+ array( 'user_id' => $this->getId() ),
+ __METHOD__ );
+ }
+ }
+ }
}
?>
--- /dev/null
+ALTER TABLE /*$wgDBprefix*/user
+ ADD COLUMN user_editcount int;
+
+-- Don't initialize values immediately... or should we?
+-- They will be lazy-evaluated, or batch-filled via maintenance/initEditCount.php
--- /dev/null
+<?php
+
+require_once "commandLine.inc";
+
+// @fixme: add replication-friendly batch mode
+
+$dbw = wfGetDB( DB_MASTER );
+$user = $dbw->tableName( 'user' );
+$revision = $dbw->tableName( 'revision' );
+
+$dbver = $dbw->getServerVersion();
+if( ($dbw instanceof DatabaseMySql && version_compare( $dbver, '4.1' ) < 0)
+ || isset( $options['force-mysql4'] ) ) {
+
+ echo "Warning: MySQL $dbver; using hacky MySQL 4.0 compatibility query...\n";
+ $sql = "CREATE TEMPORARY TABLE temp_editcount (
+ temp_user_id INT,
+ temp_user_editcount INT
+ )";
+ $dbw->query( $sql );
+
+ $sql = "INSERT INTO temp_editcount
+ (temp_user_id, temp_user_editcount)
+ SELECT rev_user, COUNT(rev_user)
+ FROM $revision GROUP BY rev_user";
+ $dbw->query( $sql );
+
+ $sql = "UPDATE $user
+ LEFT OUTER JOIN temp_editcount ON user_id=temp_user_id
+ SET user_editcount=IF(temp_user_editcount IS NULL,0,temp_user_editcount)";
+ $dbw->query( $sql );
+} else {
+ // Subselect should work on modern MySQLs etc
+ $sql = "UPDATE $user SET user_editcount=(SELECT COUNT(*) FROM $revision WHERE rev_user=user_id)";
+ $dbw->query( $sql );
+}
+
+echo "Done!\n";
+
+?>
-- Timestamp of account registration.
-- Accounts predating this schema addition may contain NULL.
user_registration char(14) binary,
+
+ -- Count of edits and edit-like actions.
+ --
+ -- *NOT* intended to be an accurate copy of COUNT(*) WHERE rev_user=user_id
+ -- May contain NULL for old accounts if batch-update scripts haven't been
+ -- run, as well as listing deleted edits and other myriad ways it could be
+ -- out of sync.
+ --
+ -- Meant primarily for heuristic checks to give an impression of whether
+ -- the account has been used much.
+ --
+ user_editcount int,
PRIMARY KEY user_id (user_id),
UNIQUE INDEX user_name (user_name),
-- Timestamp of account registration.
-- Accounts predating this schema addition may contain NULL.
user_registration char(14) binary,
+
+ -- Count of edits and edit-like actions.
+ --
+ -- *NOT* intended to be an accurate copy of COUNT(*) WHERE rev_user=user_id
+ -- May contain NULL for old accounts if batch-update scripts haven't been
+ -- run, as well as listing deleted edits and other myriad ways it could be
+ -- out of sync.
+ --
+ -- Meant primarily for heuristic checks to give an impression of whether
+ -- the account has been used much.
+ --
+ user_editcount int,
PRIMARY KEY user_id (user_id),
UNIQUE INDEX user_name (user_name),
user_email_authenticated TIMESTAMPTZ,
user_options TEXT,
user_touched TIMESTAMPTZ,
- user_registration TIMESTAMPTZ
+ user_registration TIMESTAMPTZ,
+ user_editcount INTEGER
);
CREATE INDEX user_email_token_idx ON mwuser (user_email_token);
-- Timestamp of account registration.
-- Accounts predating this schema addition may contain NULL.
user_registration char(14) binary,
+
+ -- Count of edits and edit-like actions.
+ --
+ -- *NOT* intended to be an accurate copy of COUNT(*) WHERE rev_user=user_id
+ -- May contain NULL for old accounts if batch-update scripts haven't been
+ -- run, as well as listing deleted edits and other myriad ways it could be
+ -- out of sync.
+ --
+ -- Meant primarily for heuristic checks to give an impression of whether
+ -- the account has been used much.
+ --
+ user_editcount int,
PRIMARY KEY user_id (user_id),
UNIQUE INDEX user_name (user_name),
array( 'site_stats', 'ss_images', 'patch-ss_images.sql' ),
array( 'ipblocks', 'ipb_anon_only', 'patch-ipb_anon_only.sql' ),
array( 'user', 'user_newpass_time','patch-user_newpass_time.sql' ),
+ array( 'user', 'user_editcount', 'patch-user_editcount.sql' ),
);
function rename_table( $from, $to, $patch ) {
-- New column for better password tracking:
ALTER TABLE mwuser ADD user_newpass_time TIMESTAMPTZ;
+ALTER TABLE mwuser ADD user_editcount INTEGER;
-- New column for autoblocking problem users
ALTER TABLE ipblocks ADD ipb_enable_autoblock CHAR NOT NULL DEFAULT '1';