addDescription( <<addOption( 'mode', '"add" empty categories with description pages, "remove" empty categories ' . 'without description pages, or "both"', false, true ); $this->addOption( 'begin', 'Only do categories whose names are alphabetically after the provided name', false, true ); $this->addOption( 'throttle', 'Wait this many milliseconds after each batch. Default: 0', false, true ); } protected function getUpdateKey() { return 'cleanup empty categories'; } protected function doDBUpdates() { $mode = $this->getOption( 'mode', 'both' ); $begin = $this->getOption( 'begin', '' ); $throttle = $this->getOption( 'throttle', 0 ); if ( !in_array( $mode, [ 'add', 'remove', 'both' ] ) ) { $this->output( "--mode must be 'add', 'remove', or 'both'.\n" ); return false; } $dbw = $this->getDB( DB_MASTER ); $throttle = intval( $throttle ); if ( $mode === 'add' || $mode === 'both' ) { if ( $begin !== '' ) { $where = [ 'page_title > ' . $dbw->addQuotes( $begin ) ]; } else { $where = []; } $this->output( "Adding empty categories with description pages...\n" ); while ( true ) { # Find which category to update $rows = $dbw->select( [ 'page', 'category' ], 'page_title', array_merge( $where, [ 'page_namespace' => NS_CATEGORY, 'cat_title' => null, ] ), __METHOD__, [ 'ORDER BY' => 'page_title', 'LIMIT' => $this->getBatchSize(), ], [ 'category' => [ 'LEFT JOIN', 'page_title = cat_title' ], ] ); if ( !$rows || $rows->numRows() <= 0 ) { break; } foreach ( $rows as $row ) { $name = $row->page_title; $where = [ 'page_title > ' . $dbw->addQuotes( $name ) ]; # Use the row to update the category count $cat = Category::newFromName( $name ); if ( !is_object( $cat ) ) { $this->output( "The category named $name is not valid?!\n" ); } else { $cat->refreshCounts(); } } $this->output( "--mode=$mode --begin=$name\n" ); wfWaitForSlaves(); usleep( $throttle * 1000 ); } $begin = ''; } if ( $mode === 'remove' || $mode === 'both' ) { if ( $begin !== '' ) { $where = [ 'cat_title > ' . $dbw->addQuotes( $begin ) ]; } else { $where = []; } $this->output( "Removing empty categories without description pages...\n" ); while ( true ) { # Find which category to update $rows = $dbw->select( [ 'category', 'page' ], 'cat_title', array_merge( $where, [ 'page_title' => null, 'cat_pages' => 0, ] ), __METHOD__, [ 'ORDER BY' => 'cat_title', 'LIMIT' => $this->getBatchSize(), ], [ 'page' => [ 'LEFT JOIN', [ 'page_namespace' => NS_CATEGORY, 'page_title = cat_title' ] ], ] ); if ( !$rows || $rows->numRows() <= 0 ) { break; } foreach ( $rows as $row ) { $name = $row->cat_title; $where = [ 'cat_title > ' . $dbw->addQuotes( $name ) ]; # Use the row to update the category count $cat = Category::newFromName( $name ); if ( !is_object( $cat ) ) { $this->output( "The category named $name is not valid?!\n" ); } else { $cat->refreshCounts(); } } $this->output( "--mode=remove --begin=$name\n" ); wfWaitForSlaves(); usleep( $throttle * 1000 ); } } $this->output( "Category cleanup complete.\n" ); return true; } } $maintClass = CleanupEmptyCategories::class; require_once RUN_MAINTENANCE_IF_MAIN;