MediaWiki master
initEditCount.php
Go to the documentation of this file.
1<?php
11// @codeCoverageIgnoreStart
12require_once __DIR__ . '/Maintenance.php';
13// @codeCoverageIgnoreEnd
14
19
21 public function __construct() {
22 parent::__construct();
23 $this->addOption( 'quick', 'Force the update to be done in a single query' );
24 $this->addOption( 'background', 'Force replication-friendly mode; may be inefficient but avoids'
25 . 'locking tables or lagging replica DBs with large updates; calculates counts on a replica DB'
26 . 'if possible. Background mode will be automatically used if multiple servers are listed in the'
27 . 'load balancer, usually indicating a replication environment.' );
28 $this->addDescription( 'Batch-recalculate user_editcount fields from the revision table' );
29 }
30
31 public function execute() {
32 $dbw = $this->getPrimaryDB();
33
34 // Autodetect mode...
35 if ( $this->hasOption( 'background' ) ) {
36 $backgroundMode = true;
37 } elseif ( $this->hasOption( 'quick' ) ) {
38 $backgroundMode = false;
39 } else {
40 $lb = $this->getServiceContainer()->getDBLoadBalancer();
41 $backgroundMode = $lb->hasReplicaServers();
42 }
43
44 if ( $backgroundMode ) {
45 $this->output( "Using replication-friendly background mode...\n" );
46
47 $dbr = $this->getReplicaDB();
48 $chunkSize = 100;
49 $lastUser = $dbr->newSelectQueryBuilder()
50 ->select( 'MAX(user_id)' )
51 ->from( 'user' )
52 ->caller( __METHOD__ )->fetchField();
53
54 $start = microtime( true );
55 $migrated = 0;
56 for ( $min = 0; $min <= $lastUser; $min += $chunkSize ) {
57 $max = $min + $chunkSize;
58
59 $result = $dbr->newSelectQueryBuilder()
60 ->select( [ 'user_id', 'user_editcount' => 'COUNT(rev_actor)' ] )
61 ->from( 'user' )
62 ->join( 'actor', 'actor_rev_user', 'user_id = actor_rev_user.actor_user' )
63 ->leftJoin( 'revision', 'rev', 'actor_rev_user.actor_id = rev.rev_actor' )
64 ->where( $dbr->expr( 'user_id', '>', $min )->and( 'user_id', '<=', $max ) )
65 ->groupBy( 'user_id' )
66 ->caller( __METHOD__ )->fetchResultSet();
67
68 foreach ( $result as $row ) {
69 $dbw->newUpdateQueryBuilder()
70 ->update( 'user' )
71 ->set( [ 'user_editcount' => $row->user_editcount ] )
72 ->where( [ 'user_id' => $row->user_id ] )
73 ->caller( __METHOD__ )->execute();
74 ++$migrated;
75 }
76
77 $delta = microtime( true ) - $start;
78 $rate = ( $delta == 0.0 ) ? 0.0 : $migrated / $delta;
79 $this->output( sprintf( "%s %d (%0.1f%%) done in %0.1f secs (%0.3f accounts/sec).\n",
80 WikiMap::getCurrentWikiDbDomain()->getId(),
81 $migrated,
82 min( $max, $lastUser ) / $lastUser * 100.0,
83 $delta,
84 $rate ) );
85
86 $this->waitForReplication();
87 }
88 } else {
89 $this->output( "Using single-query mode...\n" );
90
91 $subquery = $dbw->newSelectQueryBuilder()
92 ->select( 'COUNT(*)' )
93 ->from( 'revision' )
94 ->join( 'actor', 'actor_rev_user', 'actor_rev_user.actor_id = rev_actor' )
95 ->where( 'user_id = actor_rev_user.actor_user' )
96 ->caller( __METHOD__ )->getSQL();
97
98 $dbw->newUpdateQueryBuilder()
99 ->table( 'user' )
100 ->set( [ 'user_editcount' => new RawSQLValue( "($subquery)" ) ] )
101 ->where( IDatabase::ALL_ROWS )
102 ->caller( __METHOD__ )
103 ->execute();
104 }
105
106 $this->output( "Done!\n" );
107 }
108}
109
110// @codeCoverageIgnoreStart
111$maintClass = InitEditCount::class;
112require_once RUN_MAINTENANCE_IF_MAIN;
113// @codeCoverageIgnoreEnd
__construct()
Default constructor.
execute()
Do the actual work.
Abstract maintenance class for quickly writing and churning out maintenance scripts with minimal effo...
output( $out, $channel=null)
Throw some output to the user.
addOption( $name, $description, $required=false, $withArg=false, $shortName=false, $multiOccurrence=false)
Add a parameter to the script.
waitForReplication()
Wait for replica DB servers to catch up.
hasOption( $name)
Checks to see if a particular option was set.
getReplicaDB(string|false $virtualDomain=false)
getServiceContainer()
Returns the main service container.
getPrimaryDB(string|false $virtualDomain=false)
addDescription( $text)
Set the description text.
Tools for dealing with other locally-hosted wikis.
Definition WikiMap.php:19
Raw SQL value to be used in query builders.
$maintClass
Interface to a relational database.
Definition IDatabase.php:31