Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 48
0.00% covered (danger)
0.00%
0 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
DeleteTag
0.00% covered (danger)
0.00%
0 / 45
0.00% covered (danger)
0.00%
0 / 2
30
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 execute
0.00% covered (danger)
0.00%
0 / 41
0.00% covered (danger)
0.00%
0 / 1
20
1<?php
2
3/**
4 * Remove a revision tag from edits and log entries it was applied to.
5 * @see bug T75181
6 */
7
8use MediaWiki\Storage\NameTableAccessException;
9
10require_once __DIR__ . '/Maintenance.php';
11
12class DeleteTag extends Maintenance {
13    public function __construct() {
14        parent::__construct();
15        $this->addDescription( 'Deletes a change tag' );
16        $this->addArg( 'tag name', 'Name of the tag to delete' );
17        $this->setBatchSize( 500 );
18    }
19
20    public function execute() {
21        $dbw = $this->getPrimaryDB();
22        $services = $this->getServiceContainer();
23        $defStore = $services->getChangeTagDefStore();
24
25        $tag = $this->getArg( 0 );
26        try {
27            $tagId = $defStore->getId( $tag );
28        } catch ( NameTableAccessException $ex ) {
29            $this->fatalError( "Tag '$tag' not found" );
30        }
31
32        $status = ChangeTags::canDeleteTag( $tag, null, ChangeTags::BYPASS_MAX_USAGE_CHECK );
33        if ( !$status->isOK() ) {
34            $this->fatalError( $status );
35        }
36
37        $this->output( "Deleting tag '$tag'...\n" );
38
39        // Make the tag impossible to add by users while we're deleting it and drop the
40        // usage counter to zero
41        $dbw->newUpdateQueryBuilder()
42            ->update( 'change_tag_def' )
43            ->set( [
44                'ctd_user_defined' => 0,
45                'ctd_count' => 0,
46            ] )
47            ->where( [ 'ctd_id' => $tagId ] )
48            ->caller( __METHOD__ )->execute();
49        ChangeTags::purgeTagCacheAll();
50
51        // Iterate over change_tag, deleting rows in batches
52        $count = 0;
53        do {
54            $ids = $dbw->newSelectQueryBuilder()
55                ->select( 'ct_id' )
56                ->from( 'change_tag' )
57                ->where( [ 'ct_tag_id' => $tagId ] )
58                ->limit( $this->getBatchSize() )
59                ->caller( __METHOD__ )
60                ->fetchFieldValues();
61
62            if ( !$ids ) {
63                break;
64            }
65            $dbw->newDeleteQueryBuilder()
66                ->deleteFrom( 'change_tag' )
67                ->where( [ 'ct_id' => $ids ] )
68                ->caller( __METHOD__ )->execute();
69            $count += $dbw->affectedRows();
70            $this->output( "$count\n" );
71            $this->waitForReplication();
72        } while ( true );
73        $this->output( "The tag has been removed from $count revisions, deleting the tag itself...\n" );
74
75        ChangeTags::deleteTagEverywhere( $tag );
76        $this->output( "Done.\n" );
77    }
78}
79
80$maintClass = DeleteTag::class;
81require_once RUN_MAINTENANCE_IF_MAIN;