2024-02-02 16:06:30 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace MediaWiki\Extension\DiscussionTools\Maintenance;
|
|
|
|
|
|
|
|
use LoggedUpdateMaintenance;
|
2024-06-24 17:18:02 +00:00
|
|
|
use Wikimedia\Rdbms\DBQueryError;
|
2024-02-02 16:06:30 +00:00
|
|
|
use Wikimedia\Rdbms\IExpression;
|
|
|
|
use Wikimedia\Rdbms\LikeValue;
|
|
|
|
|
|
|
|
$IP = getenv( 'MW_INSTALL_PATH' );
|
|
|
|
if ( $IP === false ) {
|
|
|
|
$IP = __DIR__ . '/../../..';
|
|
|
|
}
|
|
|
|
require_once "$IP/maintenance/Maintenance.php";
|
|
|
|
|
|
|
|
class FixTrailingWhitespaceIds extends LoggedUpdateMaintenance {
|
|
|
|
|
|
|
|
public function __construct() {
|
|
|
|
parent::__construct();
|
|
|
|
$this->addDescription( 'Fix comment IDs with trailing whitespace' );
|
|
|
|
$this->setBatchSize( 1000 );
|
|
|
|
$this->requireExtension( 'DiscussionTools' );
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @inheritDoc
|
|
|
|
*/
|
|
|
|
public function doDBUpdates() {
|
|
|
|
$dbw = $this->getDB( DB_PRIMARY );
|
|
|
|
|
|
|
|
$this->output( "Fixing DiscussionTools IDs with trailing whitespace..\n" );
|
|
|
|
$total = 0;
|
|
|
|
|
|
|
|
$skippedIds = [];
|
|
|
|
|
|
|
|
do {
|
|
|
|
// Match things that are possibly heading IDs with trailing underscores,
|
|
|
|
// possibly followed by a timestamp.
|
|
|
|
// As we are using LIKE there's a small chance of false positives, but
|
|
|
|
// this will become no-ops as we use a stricter RegExp later.
|
|
|
|
|
|
|
|
// Trailing underscore
|
|
|
|
// _-%\_
|
|
|
|
$like1 = new LikeValue( $dbw->anyChar(), '-', $dbw->anyString(), '_' );
|
|
|
|
// Trailing underscore followed by short timestamp
|
|
|
|
// _-%\_-2%00
|
|
|
|
$like2 = new LikeValue( $dbw->anyChar(), '-', $dbw->anyString(), '_-2', $dbw->anyString(), '00' );
|
|
|
|
// Trailing underscore followed by long timestamp
|
|
|
|
// _-%\_-2%00.000Z
|
|
|
|
$like3 = new LikeValue( $dbw->anyChar(), '-', $dbw->anyString(), '_-2', $dbw->anyString(), '00.000Z' );
|
|
|
|
|
|
|
|
$itemIdQueryBuilder = $dbw->newSelectQueryBuilder()
|
|
|
|
->from( 'discussiontools_item_ids' )
|
|
|
|
->field( 'itid_itemid' )
|
|
|
|
->where(
|
2024-07-21 20:59:23 +00:00
|
|
|
$dbw->orExpr( [
|
2024-02-02 16:06:30 +00:00
|
|
|
$dbw->expr( 'itid_itemid', IExpression::LIKE, $like1 ),
|
|
|
|
$dbw->expr( 'itid_itemid', IExpression::LIKE, $like2 ),
|
|
|
|
$dbw->expr( 'itid_itemid', IExpression::LIKE, $like3 ),
|
2024-07-21 20:59:23 +00:00
|
|
|
] )
|
2024-02-02 16:06:30 +00:00
|
|
|
)
|
|
|
|
->caller( __METHOD__ )
|
|
|
|
->limit( $this->getBatchSize() );
|
|
|
|
|
|
|
|
if ( $skippedIds ) {
|
2024-07-21 20:59:23 +00:00
|
|
|
$itemIdQueryBuilder->where( $dbw->expr( 'itid_itemid', '!=', $skippedIds ) );
|
2024-02-02 16:06:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
$itemIds = $itemIdQueryBuilder->fetchFieldValues();
|
|
|
|
|
|
|
|
if ( !$itemIds ) {
|
|
|
|
break;
|
|
|
|
}
|
2024-06-24 17:18:02 +00:00
|
|
|
|
2024-02-02 16:06:30 +00:00
|
|
|
foreach ( $itemIds as $itemId ) {
|
|
|
|
$fixedItemId = preg_replace(
|
|
|
|
'/^([hc]\-.*)_(\-([0-9]{14}|[0-9-]{10}T[0-9:]{6}00.000Z))?$/',
|
|
|
|
'$1$2',
|
|
|
|
$itemId
|
|
|
|
);
|
|
|
|
if ( $fixedItemId === $itemId ) {
|
|
|
|
// In the rare case we got a false positive from the LIKE, add this to a list of skipped IDs
|
|
|
|
// so we don't keep selecting it, and end up in an infinite loop
|
|
|
|
$skippedIds[] = $itemId;
|
2024-06-24 17:18:02 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
$dbw->newUpdateQueryBuilder()
|
|
|
|
->update( 'discussiontools_item_ids' )
|
|
|
|
->set( [ 'itid_itemid' => $fixedItemId ] )
|
|
|
|
->where( [ 'itid_itemid' => $itemId ] )
|
|
|
|
->caller( __METHOD__ )->execute();
|
|
|
|
} catch ( DBQueryError $err ) {
|
|
|
|
// Give up on updating in case of complex conflicts (T356196#9913698)
|
|
|
|
$this->output( "Failed to update $itemId\n" );
|
|
|
|
$skippedIds[] = $itemId;
|
|
|
|
continue;
|
2024-02-02 16:06:30 +00:00
|
|
|
}
|
2024-06-24 17:18:02 +00:00
|
|
|
|
2024-02-02 16:06:30 +00:00
|
|
|
$total += $dbw->affectedRows();
|
|
|
|
}
|
2024-06-24 17:18:02 +00:00
|
|
|
|
|
|
|
$this->waitForReplication();
|
|
|
|
$this->output( "$total\n" );
|
2024-02-02 16:06:30 +00:00
|
|
|
} while ( true );
|
|
|
|
|
|
|
|
$this->output( "Fixing DiscussionTools IDs with trailing whitespace: done.\n" );
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @inheritDoc
|
|
|
|
*/
|
|
|
|
public function getUpdateKey() {
|
|
|
|
return 'DiscussionToolsFixTrailingWhitespaceIds';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$maintClass = FixTrailingWhitespaceIds::class;
|
|
|
|
require_once RUN_MAINTENANCE_IF_MAIN;
|