MediaWiki master
applyChangeTag.php
Go to the documentation of this file.
1<?php
2
12
14
15// @codeCoverageIgnoreStart
16require_once __DIR__ . '/Maintenance.php';
17// @codeCoverageIgnoreEnd
18
28
29 public function __construct() {
30 parent::__construct();
31 $this->addDescription( 'Applies an existing change tag to revisions and/or log entries.' );
32
33 $this->addOption( 'tag', 'Tag to apply. Must already be defined.', true, true );
34 $this->addOption( 'revisions', 'A list of revision IDs to tag, separated by comma.', false, true );
35 $this->addOption( 'logs', 'A list of log entry IDs to tag, separated by comma.', false, true );
36 $this->setBatchSize( 100 );
37 }
38
39 public function execute() {
40 $changeTagsStore = $this->getServiceContainer()->getChangeTagsStore();
41
42 $tag = $this->getOption( 'tag' );
43 if ( !in_array( $tag, $changeTagsStore->listDefinedTags(), true ) ) {
44 $this->fatalError( "Tag '$tag' is not defined; define it before applying it." );
45 }
46
47 $revIds = $this->parseIntList( $this->getOption( 'revisions', '' ) );
48 $logIds = $this->parseIntList( $this->getOption( 'logs', '' ) );
49 if ( !$revIds && !$logIds ) {
50 $this->fatalError( 'Specify at least one of --revisions or --logs.' );
51 }
52
53 $applied = 0;
54 $applied += $this->tagTargets( $changeTagsStore, $tag, $revIds, 'revision' );
55 $applied += $this->tagTargets( $changeTagsStore, $tag, $logIds, 'logging' );
56
57 $this->output( "Applied '$tag' to $applied target(s).\n" );
58 }
59
70 private function tagTargets( ChangeTagsStore $changeTagsStore, string $tag, array $ids, string $table ): int {
71 if ( !$ids ) {
72 return 0;
73 }
74
75 $isLog = $table === 'logging';
76 $idField = $isLog ? 'log_id' : 'rev_id';
77 $existing = array_map(
78 'intval',
79 $this->getReplicaDB()->newSelectQueryBuilder()
80 ->select( $idField )
81 ->from( $table )
82 ->where( [ $idField => $ids ] )
83 ->caller( __METHOD__ )
84 ->fetchFieldValues()
85 );
86
87 $missing = array_diff( $ids, $existing );
88 if ( $missing ) {
89 $this->output( "Skipping $table IDs that do not exist: " . implode( ', ', $missing ) . "\n" );
90 }
91
92 $applied = 0;
93 foreach ( array_chunk( $existing, $this->getBatchSize() ) as $batch ) {
94 $this->beginTransactionRound( __METHOD__ );
95 foreach ( $batch as $id ) {
96 if ( $changeTagsStore->addTags( $tag, null, $isLog ? null : $id, $isLog ? $id : null ) ) {
97 $applied++;
98 }
99 }
100 $this->commitTransactionRound( __METHOD__ );
101 }
102 return $applied;
103 }
104}
105
106// @codeCoverageIgnoreStart
107$maintClass = ApplyChangeTag::class;
108require_once RUN_MAINTENANCE_IF_MAIN;
109// @codeCoverageIgnoreEnd
if(!defined('MW_SETUP_CALLBACK'))
Definition WebStart.php:71
$maintClass
Read-write access to the change_tags table.
Applies an existing change tag to revisions and/or log entries.
Abstract maintenance class for quickly writing and churning out maintenance scripts with minimal effo...
getBatchSize()
Returns batch size.
output( $out, $channel=null)
Throw some output to the user.
fatalError( $msg, $exitCode=1)
Output a message and terminate the current script.
addOption( $name, $description, $required=false, $withArg=false, $shortName=false, $multiOccurrence=false)
Add a parameter to the script.
getOption( $name, $default=null)
Get an option, or return the default.
commitTransactionRound( $fname)
Commit a transactional batch of DB operations and wait for replica DB servers to catch up.
getReplicaDB(string|false $virtualDomain=false)
parseIntList( $text)
Utility function to parse a string (perhaps from a command line option) into a list of integers (perh...
beginTransactionRound( $fname)
Start a transactional batch of DB operations.
getServiceContainer()
Returns the main service container.
addDescription( $text)
Set the description text.
Update the CREDITS list by merging in the list of git commit authors.