Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 63 |
|
0.00% |
0 / 3 |
CRAP | |
0.00% |
0 / 1 |
RollbackEdits | |
0.00% |
0 / 60 |
|
0.00% |
0 / 3 |
182 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 12 |
|
0.00% |
0 / 1 |
2 | |||
execute | |
0.00% |
0 / 36 |
|
0.00% |
0 / 1 |
110 | |||
getRollbackTitles | |
0.00% |
0 / 12 |
|
0.00% |
0 / 1 |
6 |
1 | <?php |
2 | /** |
3 | * Rollback all edits by a given user or IP provided they're the most |
4 | * recent edit (just like real rollback) |
5 | * |
6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by |
8 | * the Free Software Foundation; either version 2 of the License, or |
9 | * (at your option) any later version. |
10 | * |
11 | * This program is distributed in the hope that it will be useful, |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | * GNU General Public License for more details. |
15 | * |
16 | * You should have received a copy of the GNU General Public License along |
17 | * with this program; if not, write to the Free Software Foundation, Inc., |
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
19 | * http://www.gnu.org/copyleft/gpl.html |
20 | * |
21 | * @file |
22 | * @ingroup Maintenance |
23 | */ |
24 | |
25 | use MediaWiki\Title\Title; |
26 | use MediaWiki\User\User; |
27 | |
28 | require_once __DIR__ . '/Maintenance.php'; |
29 | |
30 | /** |
31 | * Maintenance script to rollback all edits by a given user or IP provided |
32 | * they're the most recent edit. |
33 | * |
34 | * @ingroup Maintenance |
35 | */ |
36 | class RollbackEdits extends Maintenance { |
37 | public function __construct() { |
38 | parent::__construct(); |
39 | $this->addDescription( |
40 | "Rollback all edits by a given user or IP provided they're the most recent edit" ); |
41 | $this->addOption( |
42 | 'titles', |
43 | 'A list of titles, none means all titles where the given user is the most recent', |
44 | false, |
45 | true |
46 | ); |
47 | $this->addOption( 'user', 'A user or IP to rollback all edits for', true, true ); |
48 | $this->addOption( 'summary', 'Edit summary to use', false, true ); |
49 | $this->addOption( 'bot', 'Mark the edits as bot' ); |
50 | } |
51 | |
52 | public function execute() { |
53 | $user = $this->getOption( 'user' ); |
54 | $services = $this->getServiceContainer(); |
55 | $userNameUtils = $services->getUserNameUtils(); |
56 | $username = $userNameUtils->isIP( $user ) ? $user : $userNameUtils->getCanonical( $user ); |
57 | if ( !$username ) { |
58 | $this->fatalError( 'Invalid username' ); |
59 | } |
60 | |
61 | $bot = $this->hasOption( 'bot' ); |
62 | $summary = $this->getOption( 'summary', $this->mSelf . ' mass rollback' ); |
63 | $titles = []; |
64 | if ( $this->hasOption( 'titles' ) ) { |
65 | foreach ( explode( '|', $this->getOption( 'titles' ) ) as $title ) { |
66 | $t = Title::newFromText( $title ); |
67 | if ( !$t ) { |
68 | $this->error( 'Invalid title, ' . $title ); |
69 | } else { |
70 | $titles[] = $t; |
71 | } |
72 | } |
73 | } else { |
74 | $titles = $this->getRollbackTitles( $user ); |
75 | } |
76 | |
77 | if ( !$titles ) { |
78 | $this->output( 'No suitable titles to be rolled back.' ); |
79 | |
80 | return; |
81 | } |
82 | |
83 | $doer = User::newSystemUser( User::MAINTENANCE_SCRIPT_USER, [ 'steal' => true ] ); |
84 | $byUser = $services->getUserIdentityLookup()->getUserIdentityByName( $username ); |
85 | |
86 | if ( !$byUser ) { |
87 | $this->fatalError( 'Unknown user.' ); |
88 | } |
89 | |
90 | $wikiPageFactory = $services->getWikiPageFactory(); |
91 | $rollbackPageFactory = $services->getRollbackPageFactory(); |
92 | foreach ( $titles as $t ) { |
93 | $page = $wikiPageFactory->newFromTitle( $t ); |
94 | $this->output( 'Processing ' . $t->getPrefixedText() . '...' ); |
95 | $rollbackResult = $rollbackPageFactory |
96 | ->newRollbackPage( $page, $doer, $byUser ) |
97 | ->markAsBot( $bot ) |
98 | ->setSummary( $summary ) |
99 | ->rollback(); |
100 | if ( $rollbackResult->isGood() ) { |
101 | $this->output( "Done!\n" ); |
102 | } else { |
103 | $this->output( "Failed!\n" ); |
104 | } |
105 | } |
106 | } |
107 | |
108 | /** |
109 | * Get all pages that should be rolled back for a given user |
110 | * @param string $user A name to check against |
111 | * @return array |
112 | */ |
113 | private function getRollbackTitles( $user ) { |
114 | $dbr = $this->getReplicaDB(); |
115 | $titles = []; |
116 | |
117 | $results = $dbr->newSelectQueryBuilder() |
118 | ->select( [ 'page_namespace', 'page_title' ] ) |
119 | ->from( 'page' ) |
120 | ->join( 'revision', null, 'page_latest = rev_id' ) |
121 | ->join( 'actor', null, 'rev_actor = actor_id' ) |
122 | ->where( [ 'actor_name' => $user ] ) |
123 | ->caller( __METHOD__ )->fetchResultSet(); |
124 | foreach ( $results as $row ) { |
125 | $titles[] = Title::makeTitle( $row->page_namespace, $row->page_title ); |
126 | } |
127 | |
128 | return $titles; |
129 | } |
130 | } |
131 | |
132 | $maintClass = RollbackEdits::class; |
133 | require_once RUN_MAINTENANCE_IF_MAIN; |