Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
10.61% |
14 / 132 |
|
50.00% |
1 / 2 |
CRAP | |
0.00% |
0 / 1 |
CheckRevision | |
11.11% |
14 / 126 |
|
50.00% |
1 / 2 |
131.69 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
1 | |||
execute | |
5.88% |
7 / 119 |
|
0.00% |
0 / 1 |
132.05 |
1 | <?php |
2 | |
3 | namespace AutoModerator\Maintenance; |
4 | |
5 | use AutoModerator\AutoModeratorServices; |
6 | use AutoModerator\RevisionCheck; |
7 | use AutoModerator\Services\AutoModeratorRollback; |
8 | use AutoModerator\Util; |
9 | use MediaWiki\Config\ServiceOptions; |
10 | use MediaWiki\Logger\LoggerFactory; |
11 | use MediaWiki\MainConfigNames; |
12 | use MediaWiki\Maintenance\Maintenance; |
13 | use MediaWiki\MediaWikiServices; |
14 | use MediaWiki\Revision\RevisionRecord; |
15 | use MediaWiki\Revision\SlotRecord; |
16 | |
17 | $IP = getenv( 'MW_INSTALL_PATH' ); |
18 | if ( $IP === false ) { |
19 | $IP = __DIR__ . '/../../..'; |
20 | } |
21 | require_once "$IP/maintenance/Maintenance.php"; |
22 | |
23 | /** |
24 | * Check a revision to see if it would be reverted |
25 | */ |
26 | class CheckRevision extends Maintenance { |
27 | |
28 | public function __construct() { |
29 | parent::__construct(); |
30 | $this->requireExtension( 'AutoModerator' ); |
31 | $this->addDescription( |
32 | 'Check a revision and report if it would be reverted based on scoring from a machine learning model.' |
33 | ); |
34 | $this->addOption( 'revid', 'Revision ID', true, true ); |
35 | $this->addOption( 'client', 'Client for score fetching', false, true ); |
36 | } |
37 | |
38 | public function execute() { |
39 | if ( !ctype_digit( $this->getoption( 'revid' ) ) ) { |
40 | $this->output( "'revid' must be an integer\n" ); |
41 | return; |
42 | } |
43 | $revId = (int)$this->getOption( 'revid' ); |
44 | if ( $revId === 0 ) { |
45 | $this->output( "'revid' must be greater than zero\n" ); |
46 | return; |
47 | } |
48 | |
49 | // setup dependencies that we get for free when running in a hook. |
50 | $services = MediaWikiServices::getInstance(); |
51 | $autoModeratorServices = AutoModeratorServices::wrap( $services ); |
52 | |
53 | $changeTagsStore = $services->getChangeTagsStore(); |
54 | $config = $services->getMainConfig(); |
55 | $wikiConfig = $autoModeratorServices->getAutoModeratorWikiConfig(); |
56 | $contentHandlerFactory = $services->getContentHandlerFactory(); |
57 | $revisionLookup = $services->getRevisionLookup(); |
58 | $revisionStore = $services->getRevisionStoreFactory()->getRevisionStore(); |
59 | $userGroupManager = $services->getUserGroupManager(); |
60 | $wikiPageFactory = $services->getWikiPageFactory(); |
61 | $restrictionStore = $services->getRestrictionStore(); |
62 | $permissionManager = $services->getPermissionManager(); |
63 | $autoModeratorUser = Util::getAutoModeratorUser( $config, $userGroupManager ); |
64 | $wikiId = Util::getWikiID( $config ); |
65 | $dbr = $this->getReplicaDB(); |
66 | $tags = $changeTagsStore->getTags( $dbr, null, $revId ); |
67 | $rev = $revisionLookup->getRevisionById( $revId ); |
68 | // Check if revision or the revision user is not null |
69 | $userIdentity = $rev->getUser(); |
70 | if ( !$rev || !$userIdentity ) { |
71 | return; |
72 | } |
73 | $wikiPageId = $rev->getPageId(); |
74 | $undoSummaryMessageKey = ( !$userIdentity->isRegistered() && $config->get( MainConfigNames::DisableAnonTalk ) ) |
75 | ? 'automoderator-wiki-undo-summary-anon' : 'automoderator-wiki-undo-summary'; |
76 | $contentHandler = $contentHandlerFactory->getContentHandler( $rev->getSlot( |
77 | SlotRecord::MAIN, |
78 | RevisionRecord::RAW |
79 | )->getModel() ); |
80 | $logger = LoggerFactory::getInstance( 'AutoModerator' ); |
81 | if ( !RevisionCheck::revertPreCheck( |
82 | $userIdentity, |
83 | $autoModeratorUser, |
84 | $logger, |
85 | $revisionStore, |
86 | $tags, |
87 | $restrictionStore, |
88 | $wikiPageFactory, |
89 | $wikiConfig, |
90 | $revId, |
91 | $wikiPageId, |
92 | $permissionManager |
93 | ) ) { |
94 | $this->output( "precheck skipped rev:\t$revId\n" ); |
95 | return; |
96 | } |
97 | |
98 | $revisionCheck = new RevisionCheck( |
99 | $wikiPageId, |
100 | $wikiPageFactory, |
101 | $rev->getId(), |
102 | $autoModeratorUser, |
103 | $revisionStore, |
104 | $wikiConfig, |
105 | $config, |
106 | $contentHandler, |
107 | wfMessage( $undoSummaryMessageKey )->rawParams( $revId, $userIdentity->getName() )->plain(), |
108 | new AutoModeratorRollback( |
109 | new ServiceOptions( AutoModeratorRollback::CONSTRUCTOR_OPTIONS, $config ), |
110 | $services->getDBLoadBalancerFactory(), |
111 | $revisionStore, |
112 | $services->getTitleFormatter(), |
113 | $services->getHookContainer(), |
114 | $wikiPageFactory, |
115 | $services->getActorMigration(), |
116 | $services->getActorNormalization(), |
117 | $wikiPageFactory->newFromID( $wikiPageId ), |
118 | $autoModeratorUser->getUser(), |
119 | $rev->getUser(), |
120 | $config, |
121 | $wikiConfig |
122 | ) |
123 | ); |
124 | |
125 | // Get a real score or optionally set a fake score |
126 | $score = []; |
127 | switch ( $this->getOption( 'client', 'liftwing' ) ) { |
128 | case 'liftwing': |
129 | $liftWingClient = Util::initializeLiftWingClient( $config ); |
130 | $score = $liftWingClient->get( $rev->getId() ); |
131 | break; |
132 | case 'testfail': |
133 | $score = [ |
134 | 'model_name' => 'revertrisk-language-agnostic', |
135 | 'model_version' => '3', |
136 | 'wiki_db' => 'enwiki', |
137 | 'revision_id' => $revId, |
138 | 'output' => [ |
139 | 'prediction' => true, |
140 | 'probabilities' => [ |
141 | 'true' => 1.000000000000000, |
142 | 'false' => 0.000000000000000, |
143 | ], |
144 | ], |
145 | ]; |
146 | break; |
147 | case 'testpass': |
148 | $score = [ |
149 | 'model_name' => 'revertrisk-language-agnostic', |
150 | 'model_version' => '3', |
151 | 'wiki_db' => 'enwiki', |
152 | 'revision_id' => $revId, |
153 | 'output' => [ |
154 | 'prediction' => false, |
155 | 'probabilities' => [ |
156 | 'true' => 0.000000000000000, |
157 | 'false' => 1.000000000000000, |
158 | ], |
159 | ], |
160 | ]; |
161 | break; |
162 | default: |
163 | break; |
164 | } |
165 | $revertRiskModelName = Util::getRevertRiskModel( $config ); |
166 | $reverted = json_encode( $revisionCheck->maybeRollback( $score, $revertRiskModelName ), |
167 | JSON_FORCE_OBJECT, |
168 | JSON_PRETTY_PRINT ); |
169 | $scoreStr = json_encode( $score, JSON_PRETTY_PRINT ); |
170 | $this->output( "Revision ID:\t$revId\nWould revert?\t$reverted\nScore:\t$scoreStr\n" ); |
171 | } |
172 | } |
173 | |
174 | $maintClass = CheckRevision::class; |
175 | require_once RUN_MAINTENANCE_IF_MAIN; |