diff --git a/maintenance/resetWiki.php b/maintenance/resetWiki.php new file mode 100644 index 00000000..8efe0298 --- /dev/null +++ b/maintenance/resetWiki.php @@ -0,0 +1,144 @@ +addDescription( 'Resets a wiki database to what it is when it is first created.' ); + $this->addOption( 'dbname', 'The database name of the wiki to reset.', true, true ); + $this->addOption( 'requester', 'The user to assign initial rights for.', true, true ); + + $this->requireExtension( 'CreateWiki' ); + } + + public function execute(): void { + $databaseName = strtolower( $this->getOption( 'dbname' ) ); + $requester = $this->getOption( 'requester' ); + + if ( !$databaseName || !$requester ) { + $this->fatalError( 'Both --dbname and --requester are required.' ); + } + + $userFactory = $this->getServiceContainer()->getUserFactory(); + if ( !$userFactory->newFromName( $requester ) ) { + $this->fatalError( "Requester '$requester' is invalid." ); + } + + $this->output( "Resetting database: $databaseName\n" ); + + $dbr = $this->getServiceContainer()->getConnectionProvider() + ->getReplicaDatabase( $this->getConfig()->get( 'CreateWikiDatabase' ) ); + + // Fetch the original data + $row = $dbr->newSelectQueryBuilder() + ->from( 'cw_wikis' ) + ->field( '*' ) + ->where( [ 'wiki_dbname' => $databaseName ] ) + ->caller( __METHOD__ ) + ->fetchRow(); + + $cluster = $row->wiki_dbcluster; + $sitename = $row->wiki_sitename; + $language = $row->wiki_language; + $category = $row->wiki_category; + $isPrivate = (bool)$row->wiki_private; + + if ( !$cluster ) { + $this->fatalError( "Cluster for $databaseName not found in cw_wikis." ); + } + + // Get the load balancer for the specific cluster + $dbLoadBalancerFactory = $this->getServiceContainer()->getDBLoadBalancerFactory(); + $loadBalancer = $dbLoadBalancerFactory->getAllMainLBs()[$cluster]; + + // Get the connection to the specific cluster that the wiki's database exists on + $dbw = $loadBalancer->getConnection( DB_PRIMARY, [], ILoadBalancer::DOMAIN_ANY ); + + // Check if the database exists + $dbExists = $dbw->newSelectQueryBuilder() + ->from( 'information_schema.SCHEMATA' ) + ->field( 'SCHEMA_NAME' ) + ->where( [ 'SCHEMA_NAME' => $databaseName ] ) + ->caller( __METHOD__ ) + ->fetchField(); + + if ( !$dbExists ) { + $this->fatalError( "Database $databaseName does not exist on cluster $cluster." ); + } + + $databaseQuotes = $dbw->addIdentifierQuotes( $databaseName ); + + $dataFactory = $this->getServiceContainer()->get( 'CreateWikiDataFactory' ); + $wikiManagerFactory = $this->getServiceContainer()->get( 'WikiManagerFactory' ); + + // Delete the wiki from CreateWiki + $wikiManager = $wikiManagerFactory->newInstance( $databaseName ); + $wikiManager->delete( force: true ); + + // Drop the database + $dbw->query( "DROP DATABASE $databaseQuotes", __METHOD__ ); + + // Create a new WikiManagerFactory instance + $wikiManager = $wikiManagerFactory->newInstance( $databaseName ); + + // This runs checkDatabaseName and if it returns a + // non-null value it is returning an error. + $notCreated = $wikiManager->create( + sitename: $sitename, + language: $language, + private: $isPrivate, + category: $category, + requester: $requester, + extra: [], + actor: '', + reason: '' + ); + + if ( $notCreated ) { + $this->fatalError( $notCreated ); + } + + $data = $dataFactory->newInstance( $databaseName ); + $data->resetWikiData( isNewChanges: true ); + + $this->output( "Database recreated successfully.\n" ); + } +} + +$maintClass = ResetWiki::class; +require_once RUN_MAINTENANCE_IF_MAIN;