* @author Kunal Mehta */ require_once __DIR__ . '/Maintenance.php'; use MediaWiki\MediaWikiServices; /** * Maintenance script that deletes revisions which refer to a nonexisting page. * * @ingroup Maintenance */ class PurgeOrphanedLinks extends Maintenance { public function __construct() { parent::__construct(); $this->addDescription( 'Maintenance script to delete links entries which refer to a nonexisting page' ); $this->addOption( 'dry-run', 'Dry-run' ); $this->setBatchSize( 500 ); } public function execute() { $dbw = $this->getDB( DB_PRIMARY ); do { list( $page, $links ) = $dbw->tableNamesN( 'page', 'categorylinks' ); $sql = "SELECT cl_from FROM {$links} LEFT JOIN {$page} ON cl_from = page_id " . "WHERE page_id IS NULL LIMIT {$this->mBatchSize}"; # Find all the orphaned links $res = $dbw->query( $sql, 'purgeOrphanedLinks' ); # Stash 'em all up for deletion (if needed) $toDelete = []; foreach ( $res as $row ) { $toDelete[] = $row->cl_from; } if ( !$toDelete ) { break; } $count = count( $toDelete ); $this->output( "deleting {$count}..." ); if ( !$this->hasOption('dry-run' ) ) { $dbw->delete( 'categorylinks', [ 'cl_from' => $toDelete ], __METHOD__ ); } $this->output( "done. Sleeping\n" ); MediaWikiServices::getInstance()->getDBLoadBalancerFactory()->waitForReplication() } while ( $dbw->affectedRows() ); $this->output("Done done!\n" ); } } $maintClass = PurgeOrphanedLinks::class; require_once RUN_MAINTENANCE_IF_MAIN;