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