Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
13.08% covered (danger)
13.08%
14 / 107
50.00% covered (danger)
50.00%
1 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
CheckRevision
13.86% covered (danger)
13.86%
14 / 101
50.00% covered (danger)
50.00%
1 / 2
121.01
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
1
 execute
7.45% covered (danger)
7.45%
7 / 94
0.00% covered (danger)
0.00%
0 / 1
126.17
1<?php
2
3namespace AutoModerator\Maintenance;
4
5use AutoModerator\Config\AutoModeratorConfigLoaderStaticTrait;
6use AutoModerator\RevisionCheck;
7use AutoModerator\Util;
8use Maintenance;
9use MediaWiki\Logger\LoggerFactory;
10use MediaWiki\MainConfigNames;
11use MediaWiki\MediaWikiServices;
12use MediaWiki\Revision\RevisionRecord;
13use MediaWiki\Revision\SlotRecord;
14
15$IP = getenv( 'MW_INSTALL_PATH' );
16if ( $IP === false ) {
17    $IP = __DIR__ . '/../../..';
18}
19require_once "$IP/maintenance/Maintenance.php";
20
21/**
22 * Check a revision to see if it would be reverted
23 */
24class CheckRevision extends Maintenance {
25
26    use AutoModeratorConfigLoaderStaticTrait;
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        $changeTagsStore = $services->getChangeTagsStore();
52        $config = $services->getMainConfig();
53        $wikiConfig = $this->getAutoModeratorWikiConfig();
54        $contentHandlerFactory = $services->getContentHandlerFactory();
55        $revisionLookup = $services->getRevisionLookup();
56        $revisionStore = $services->getRevisionStoreFactory()->getRevisionStore();
57        $userGroupManager = $services->getUserGroupManager();
58        $wikiPageFactory = $services->getWikiPageFactory();
59        $restrictionStore = $services->getRestrictionStore();
60        $autoModeratorUser = Util::getAutoModeratorUser( $config, $userGroupManager );
61        $wikiId = Util::getWikiID( $config );
62        $dbr = $this->getReplicaDB();
63        $tags = $changeTagsStore->getTags( $dbr, null, $revId );
64        $rev = $revisionLookup->getRevisionById( $revId );
65        // Check if revision or the revision user is not null
66        $userIdentity = $rev->getUser();
67        if ( !$rev || !$userIdentity ) {
68            return;
69        }
70        $wikiPageId = $rev->getPageId();
71        $undoSummaryMessageKey = ( !$userIdentity->isRegistered() && $config->get( MainConfigNames::DisableAnonTalk ) )
72            ? 'automoderator-wiki-undo-summary-anon' : 'automoderator-wiki-undo-summary';
73        $contentHandler = $contentHandlerFactory->getContentHandler( $rev->getSlot(
74            SlotRecord::MAIN,
75            RevisionRecord::RAW
76        )->getModel() );
77        $logger = LoggerFactory::getInstance( 'AutoModerator' );
78        $revisionCheck = new RevisionCheck(
79            $wikiPageId,
80            $wikiPageFactory,
81            $rev->getId(),
82            // @fixme: we should actually check for
83            //  $originalRevId as defined in onRevisionFromEditComplete
84            false,
85            $userIdentity,
86            $tags,
87            $autoModeratorUser,
88            $revisionStore,
89            $config,
90            $wikiConfig,
91            $contentHandler,
92            $logger,
93            $userGroupManager,
94            $restrictionStore,
95            $wikiId,
96            wfMessage( $undoSummaryMessageKey )->rawParams( $revId, $userIdentity->getName() )->plain()
97        );
98        if ( !$revisionCheck->passedPreCheck ) {
99            $this->output( "precheck skipped rev:\t$revId\n" );
100            return;
101        }
102
103        // Get a real score or optionally set a fake score
104        $score = [];
105        switch ( $this->getOption( 'client', 'liftwing' ) ) {
106            case 'liftwing':
107                $liftWingClient = Util::initializeLiftWingClient( $config );
108                $score = $liftWingClient->get( $rev->getId() );
109                break;
110            case 'testfail':
111                $score = [
112                    'model_name' => 'revertrisk-language-agnostic',
113                    'model_version' => '3',
114                    'wiki_db' => 'enwiki',
115                    'revision_id' => $revId,
116                    'output' => [
117                        'prediction' => true,
118                        'probabilities' => [
119                            'true' => 1.000000000000000,
120                            'false' => 0.000000000000000,
121                        ],
122                    ],
123                ];
124                break;
125            case 'testpass':
126                $score = [
127                    'model_name' => 'revertrisk-language-agnostic',
128                    'model_version' => '3',
129                    'wiki_db' => 'enwiki',
130                    'revision_id' => $revId,
131                    'output' => [
132                        'prediction' => false,
133                        'probabilities' => [
134                            'true' => 0.000000000000000,
135                            'false' => 1.000000000000000,
136                        ],
137                    ],
138                ];
139                break;
140            default:
141                break;
142        }
143        $reverted = json_encode( $revisionCheck->maybeRevert( $score ), JSON_FORCE_OBJECT, JSON_PRETTY_PRINT );
144        $scoreStr = json_encode( $score, JSON_PRETTY_PRINT );
145        $this->output( "Revision ID:\t$revId\nWould revert?\t$reverted\nScore:\t$scoreStr\n" );
146    }
147}
148
149$maintClass = CheckRevision::class;
150require_once RUN_MAINTENANCE_IF_MAIN;