MediaWiki master
purgeUserOptions.php
Go to the documentation of this file.
1<?php
12
13// @codeCoverageIgnoreStart
14require_once __DIR__ . '/Maintenance.php';
15// @codeCoverageIgnoreEnd
16
21
22 public function __construct() {
23 parent::__construct();
24
25 $this->addDescription( 'Pass through all users and purge options for
26 users that have not logged in for certain time and have below certain edits' );
27
28 $this->addOption( 'login-age', 'How many years since last login. Default: 5', false, true );
29 $this->addOption( 'max-editcount', 'How many edit or more to skip deletion. Default: 100', false, true );
30 $this->addOption( 'dry', 'Do not carry out the deletion' );
31 $this->addArg( 'option name', 'Only delete this option', false );
32 $this->setBatchSize( 1000 );
33 }
34
35 public function execute() {
36 $option = $this->getArg( 0 );
37 $dbr = $this->getServiceContainer()->getConnectionProvider()->getReplicaDatabase();
38 $dbw = $this->getServiceContainer()->getConnectionProvider()->getPrimaryDatabase();
39 $maxUserId = $dbr->newSelectQueryBuilder()
40 ->select( 'MAX(user_id)' )
41 ->from( 'user' )
42 ->caller( __METHOD__ )
43 ->fetchField();
44 $cleaned = 0;
45 $duration = 'P' . (int)$this->getOption( 'login-age', 5 ) . 'Y';
46 $cutoff = $dbr->timestamp( ( new DateTime() )->sub( new DateInterval( $duration ) )->getTimestamp() );
47 for ( $min = 0; $min <= $maxUserId; $min += $this->getBatchSize() ) {
48 $userIdsToClean = $dbr->newSelectQueryBuilder()
49 ->select( 'user_id' )
50 ->from( 'user' )
51 ->where( $dbr->expr( 'user_id', '>=', $min ) )
52 ->where( $dbr->expr( 'user_id', '<', $min + $this->getBatchSize() ) )
53 ->where( $dbr->expr( 'user_touched', '<', $cutoff ) )
54 ->where( $dbr->expr( 'user_editcount', '<', (int)$this->getOption( 'max-editcount', 100 ) ) )
55 ->caller( __METHOD__ )->fetchFieldValues();
56 if ( $userIdsToClean === [] ) {
57 continue;
58 }
59
60 if ( $this->getOption( 'dry' ) ) {
61 $this->output( 'The script will clean up user_properties for the following users ' .
62 json_encode( $userIdsToClean ) . "\n" );
63 continue;
64 }
65
66 $deleteQueryBuilder = $dbw->newDeleteQueryBuilder()
67 ->deleteFrom( 'user_properties' )
68 ->where( [ 'up_user' => $userIdsToClean ] );
69 if ( $option ) {
70 $deleteQueryBuilder->where( [ 'up_property' => $option ] );
71 }
72 $deleteQueryBuilder->caller( __METHOD__ )->execute();
73 $this->waitForReplication();
74
75 $cleaned += count( $userIdsToClean );
76 $this->output( 'Cleaned up user_properties for users up to ' . ( $min + $this->getBatchSize() ) .
77 ' and ' . $cleaned . " users have been cleared.\n" );
78
79 }
80 }
81}
82
83// @codeCoverageIgnoreStart
84$maintClass = PurgeUserOptions::class;
85require_once RUN_MAINTENANCE_IF_MAIN;
86// @codeCoverageIgnoreEnd
Abstract maintenance class for quickly writing and churning out maintenance scripts with minimal effo...
addArg( $arg, $description, $required=true, $multi=false)
Add some args that are needed.
getArg( $argId=0, $default=null)
Get an argument.
getBatchSize()
Returns batch size.
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.
getOption( $name, $default=null)
Get an option, or return the default.
getServiceContainer()
Returns the main service container.
addDescription( $text)
Set the description text.
execute()
Do the actual work.
__construct()
Default constructor.