Umherirrender has uploaded a new change for review.
https://gerrit.wikimedia.org/r/101233
Change subject: Expand CleanupPreferences script to handle unused preferences
......................................................................
Expand CleanupPreferences script to handle unused preferences
Also added a check for preferences which are equal to the default value.
Adds a --delete param to avoid write actions on first run.
Script does a batched full table select to check each row against the
criteria (unused or removed preferences; hidden [optional]; equal to
default preference) and than deletes the found rows from the database
This can help by cleaning up user_properties table as single or montly
run, see bug 52777.
This is not equals to calling User::saveSettings on a full loaded user
object, but should be nearly the same.
Using the user object sounds expensiver, because the whole user object
is loaded for each user.
Must add 3 preferences to $wgDefaultUserOptions, because otherwise there
are not recognize as such and the rows where deleted.
Change-Id: Ia5d8d1a344a6846777ffda980f884cfc5cdd55e7
---
M includes/DefaultSettings.php
M maintenance/cleanupPreferences.php
2 files changed, 159 insertions(+), 9 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/mediawiki/core
refs/changes/33/101233/1
diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php
index 40f943f..54cb797 100644
--- a/includes/DefaultSettings.php
+++ b/includes/DefaultSettings.php
@@ -4012,6 +4012,7 @@
'math' => 1,
'minordefault' => 0,
'newpageshidepatrolled' => 0,
+ 'nickname' => '',
'noconvertlink' => 0,
'norollbackdiff' => 0,
'numberheadings' => 0,
@@ -4028,6 +4029,7 @@
'showtoolbar' => 1,
'skin' => false,
'stubthreshold' => 0,
+ 'timecorrection' => '',
'thumbsize' => 2,
'underline' => 2,
'uselivepreview' => 0,
@@ -4043,6 +4045,7 @@
'watchlisthideminor' => 0,
'watchlisthideown' => 0,
'watchlisthidepatrolled' => 0,
+ 'watchlisttoken' => '',
'watchmoves' => 0,
'wllimit' => 250,
'useeditwarning' => 1,
diff --git a/maintenance/cleanupPreferences.php
b/maintenance/cleanupPreferences.php
index 06ae17f..8345717 100644
--- a/maintenance/cleanupPreferences.php
+++ b/maintenance/cleanupPreferences.php
@@ -1,6 +1,6 @@
<?php
/**
- * Remove hidden preferences from the database.
+ * Remove hidden, unused or default preferences from the database.
*
* 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
@@ -31,20 +31,167 @@
* @ingroup Maintenance
*/
class CleanupPreferences extends Maintenance {
+ public function __construct() {
+ parent::__construct();
+ $this->mDescription = 'Delete hidden, unused or default
preferences from database';
+ $this->addOption( 'delete', 'Perform the deletion' );
+ $this->addOption( 'start',
+ 'Key to start the script from in format "user" or
"user,property"', false, true );
+ $this->addOption( 'hidden', 'Remove also hidden prefs (from
$wgHiddenPrefs)' );
+ $this->setBatchSize( 150 );
+ }
+
public function execute() {
global $wgHiddenPrefs;
$dbw = wfGetDB( DB_MASTER );
- $dbw->begin( __METHOD__ );
- foreach ( $wgHiddenPrefs as $item ) {
- $dbw->delete(
+ $delete = $this->hasOption( 'delete' );
+ $hidden = $this->hasOption( 'hidden' );
+
+ $defaultOptions = User::getDefaultOptions();
+
+ $cond = array();
+ if ( $this->hasOption( 'start' ) ) {
+ $start = $this->getOption( 'start' );
+ $startArray = explode( ',', $start, 2 );
+ $cond = $this->buildSelectCond( $dbw, $startArray[0],
+ count( $startArray ) >= 2 ? $startArray[1] :
null );
+ $this->output( "Start by > " . $start . "\n" );
+ }
+
+ $countAll = 0;
+ $count = 0;
+ $deletedAll = 0;
+ $deleted = 0;
+ $statsDeletedProperty = array();
+ do {
+ // select next batch
+ $res = $dbw->select(
'user_properties',
- array( 'up_property' => $item ),
- __METHOD__
+ array( 'up_user', 'up_property', 'up_value' ),
+ $cond,
+ __METHOD__,
+ array( 'LIMIT' => $this->mBatchSize, 'ORDER BY'
=> array( 'up_user', 'up_property' ) )
);
- };
- $dbw->commit( __METHOD__ );
- $this->output( "Finished!\n" );
+ $count = $res->numRows();
+ $countAll += $count;
+
+ $lastRow = null;
+ $deleteRows = array();
+ foreach ( $res as $row ) {
+ $deleteTask = false;
+ $user = $row->up_user;
+ $property = $row->up_property;
+ $value = $row->up_value;
+
+ //Check the row
+ if ( !isset( $defaultOptions[$property] ) ) {
+ // unused or old preference -> delete
+ $deleteTask = 'unused';
+ } elseif ( $hidden && isset(
$wgHiddenPrefs[$property] ) ) {
+ // marked as hidden
+ $deleteTask = 'hidden';
+ } else {
+ // default property, check value
+ $defaultValue =
$defaultOptions[$row->up_property];
+ if ( $defaultValue === $row->up_value )
{
+ // row has same value as
default -> delete
+ $deleteTask = 'default';
+ }
+ }
+
+ // a common wrong situation (from bug 52777)
+ if ( $property === 'skin' && $value === '' ) {
+ // Skin::newFromKey will return default
skin
+ $deleteTask = 'default';
+ }
+
+ if ( $deleteTask !== false ) {
+ if ( !isset(
$statsDeletedProperty[$deleteTask] ) ) {
+
$statsDeletedProperty[$deleteTask] = array();
+ }
+ if ( !isset(
$statsDeletedProperty[$deleteTask][$property] ) ) {
+
$statsDeletedProperty[$deleteTask][$property] = 0;
+ }
+
$statsDeletedProperty[$deleteTask][$property]++;
+
+ $deleteRows[] = $row;
+ }
+
+ $lastRow = $row;
+ }
+
+ // Delete unused rows
+ $toDelete = count( $deleteRows );
+ $deletedAll += $toDelete;
+ if ( $delete && $toDelete ) {
+ $dbw->begin( __METHOD__ );
+ $dbw->delete(
+ 'user_properties',
+ $this->buildDeleteCond( $dbw,
$deleteRows ),
+ __METHOD__
+ );
+ $dbw->commit( __METHOD__ );
+
+ $this->output( "Deleted " . $toDelete . "
rows\n" );
+
+ wfWaitForSlaves();
+ }
+
+ // build condition to get the next batch
+ if ( $lastRow !== null && $count === $this->mBatchSize
) {
+ $cond = $this->buildSelectCond( $dbw,
$lastRow->up_user, $lastRow->up_property );
+ $this->output( "Last batch ends by " .
$lastRow->up_user . "," . $lastRow->up_property . "\n" );
+ }
+ } while ( $count === $this->mBatchSize );
+
+ $this->output( "\n" );
+
+ if ( $deletedAll > 0 ) {
+ if ( $delete ) {
+ $this->output( "Deleted the following
properties:\n" );
+ $this->printStats( $statsDeletedProperty );
+ $this->output( 'Deleted ' . $deletedAll . '
rows out of ' . $countAll . ' rows' );
+ } else {
+ $this->output( "Would delete the following
properties:\n" );
+ $this->printStats( $statsDeletedProperty );
+ $this->output( 'Would delete ' . $deletedAll .
' rows out of ' . $countAll . ' rows' );
+ }
+ } else {
+ $this->output( 'Nothing to do!' );
+ }
+ }
+
+ private function buildSelectCond( $db, $user, $property ) {
+ if ( $property === null ) {
+ return 'up_user > ' . $db->addQuotes( $user );
+ }
+
+ return 'up_user > ' . $db->addQuotes( $user ) . ' OR ' .
+ '(up_user = ' . $db->addQuotes( $user ) . ' AND ' .
+ 'up_property > ' . $db->addQuotes( $property ) . ')';
+ }
+
+ private function buildDeleteCond( $db, $rows ) {
+ $conds = array();
+ foreach ( $rows as $row ) {
+ $conds[] = $db->makeList(
+ // the unique index of the table
+ array( 'up_user' => $row->up_user,
'up_property' => $row->up_property ),
+ LIST_AND
+ );
+ }
+
+ return $db->makeList( $conds, LIST_OR );
+ }
+
+ private function printStats( $statsDeletedProperty ) {
+ foreach ( $statsDeletedProperty as $type => $stats ) {
+ $this->output( $type . ":\n" );
+ foreach ( $stats as $property => $count ) {
+ $this->output( ' "' . $property . '" (' .
$count . ")\n" );
+ }
+ }
}
}
--
To view, visit https://gerrit.wikimedia.org/r/101233
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ia5d8d1a344a6846777ffda980f884cfc5cdd55e7
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/core
Gerrit-Branch: master
Gerrit-Owner: Umherirrender <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits