MediaWiki  master
cleanupPreferences.php
Go to the documentation of this file.
1 <?php
27 require_once __DIR__ . '/Maintenance.php';
28 
35  public function __construct() {
36  parent::__construct();
37  $this->addDescription(
38  'Clean up hidden preferences, removed preferences, and normalizes values'
39  );
40  $this->setBatchSize( 50 );
41  $this->addOption( 'dry-run', 'Print debug info instead of actually deleting' );
42  $this->addOption( 'hidden', 'Drop hidden preferences ($wgHiddenPrefs)' );
43  $this->addOption( 'unknown',
44  'Drop unknown preferences (not in $wgDefaultUserOptions or prefixed with "userjs-")' );
45  // TODO: actually implement this
46  // $this->addOption( 'bogus', 'Drop preferences that have invalid/unaccepted values' );
47  }
48 
61  public function execute() {
62  $dbw = $this->getDB( DB_MASTER );
63  $hidden = $this->hasOption( 'hidden' );
64  $unknown = $this->hasOption( 'unknown' );
65  $bogus = $this->hasOption( 'bogus' );
66 
67  if ( !$hidden && !$unknown && !$bogus ) {
68  $this->output( "Did not select one of --hidden, --unknown or --bogus, exiting\n" );
69  return;
70  }
71 
72  // Remove hidden prefs. Iterate over them to avoid the IN on a large table
73  if ( $hidden ) {
74  $hiddenPrefs = $this->getConfig()->get( 'HiddenPrefs' );
75  if ( !$hiddenPrefs ) {
76  $this->output( "No hidden preferences, skipping\n" );
77  }
78  foreach ( $hiddenPrefs as $hiddenPref ) {
79  $this->deleteByWhere(
80  $dbw,
81  'Dropping hidden preferences',
82  [ 'up_property' => $hiddenPref ]
83  );
84  }
85  }
86 
87  // Remove unknown preferences. Special-case 'userjs-' as we can't control those names.
88  if ( $unknown ) {
89  $defaultUserOptions = $this->getConfig()->get( 'DefaultUserOptions' );
90  $where = [
91  'up_property NOT' . $dbw->buildLike( 'userjs-', $dbw->anyString() ),
92  'up_property NOT IN (' . $dbw->makeList( array_keys( $defaultUserOptions ) ) . ')',
93  ];
94  // Allow extensions to add to the where clause to prevent deletion of their own prefs.
95  Hooks::run( 'DeleteUnknownPreferences', [ &$where, $dbw ] );
96  $this->deleteByWhere( $dbw, 'Dropping unknown preferences', $where );
97  }
98 
99  // Something something phase 3
100  if ( $bogus ) {
101  }
102  }
103 
104  private function deleteByWhere( $dbw, $startMessage, $where ) {
105  $this->output( $startMessage . "...\n" );
106  $total = 0;
107  while ( true ) {
108  $res = $dbw->select(
109  'user_properties',
110  '*', // The table lacks a primary key, so select the whole row
111  $where,
112  __METHOD__,
113  [ 'LIMIT' => $this->mBatchSize ]
114  );
115 
116  $numRows = $res->numRows();
117  $total += $numRows;
118  if ( $res->numRows() <= 0 ) {
119  $this->output( "DONE! (handled $total entries)\n" );
120  break;
121  }
122 
123  // Progress or something
124  $this->output( "..doing $numRows entries\n" );
125 
126  // Delete our batch, then wait
127  foreach ( $res as $row ) {
128  if ( $this->hasOption( 'dry-run' ) ) {
129  $this->output(
130  " DRY RUN, would drop: " .
131  "[up_user] => '{$row->up_user}' " .
132  "[up_property] => '{$row->up_property}' " .
133  "[up_value] => '{$row->up_value}'\n"
134  );
135  continue;
136  }
137  $this->beginTransaction( $dbw, __METHOD__ );
138  $dbw->delete(
139  'user_properties',
140  [
141  'up_user' => $row->up_user,
142  'up_property' => $row->up_property,
143  'up_value' => $row->up_value,
144  ],
145  __METHOD__
146  );
147  $this->commitTransaction( $dbw, __METHOD__ );
148  }
149  }
150  }
151 }
152 
153 $maintClass = CleanupPreferences::class; // Tells it to run the class
154 require_once RUN_MAINTENANCE_IF_MAIN;
commitTransaction(IDatabase $dbw, $fname)
Commit the transcation on a DB handle and wait for replica DBs to catch up.
const RUN_MAINTENANCE_IF_MAIN
Definition: Maintenance.php:39
Abstract maintenance class for quickly writing and churning out maintenance scripts with minimal effo...
Definition: Maintenance.php:82
setBatchSize( $s=0)
Set the batch size.
hasOption( $name)
Checks to see if a particular option exists.
const DB_MASTER
Definition: defines.php:26
execute()
We will do this in three passes 1) The easiest is to drop the hidden preferences from the database...
addDescription( $text)
Set the description text.
deleteByWhere( $dbw, $startMessage, $where)
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.
Maintenance script that removes bogus preferences from the database.
getDB( $db, $groups=[], $dbDomain=false)
Returns a database to be used by current maintenance script.
static run( $event, array $args=[], $deprecatedVersion=null)
Call hook functions defined in Hooks::register and $wgHooks.
Definition: Hooks.php:200
beginTransaction(IDatabase $dbw, $fname)
Begin a transcation on a DB.