Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
97.14% covered (success)
97.14%
34 / 35
50.00% covered (danger)
50.00%
1 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
CheckSignatures
97.14% covered (success)
97.14%
34 / 35
50.00% covered (danger)
50.00%
1 / 2
7
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 execute
96.88% covered (success)
96.88%
31 / 32
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2/**
3 * @license GPL-2.0-or-later
4 * @file
5 * @ingroup Maintenance
6 */
7
8use MediaWiki\Maintenance\Maintenance;
9use MediaWiki\Parser\ParserOptions;
10
11// @codeCoverageIgnoreStart
12require_once __DIR__ . '/Maintenance.php';
13// @codeCoverageIgnoreEnd
14
15/**
16 * Maintenance script to list users with invalid signatures.
17 *
18 * @ingroup Maintenance
19 */
20class CheckSignatures extends Maintenance {
21
22    public function __construct() {
23        parent::__construct();
24        $this->addDescription( 'List users with invalid signatures' );
25        $this->setBatchSize( 1000 );
26    }
27
28    public function execute() {
29        $dbr = $this->getReplicaDB();
30        $userFactory = $this->getServiceContainer()->getUserIdentityLookup();
31        $userOptions = $this->getServiceContainer()->getUserOptionsLookup();
32        $signatureValidatorFactory = $this->getServiceContainer()->getSignatureValidatorFactory();
33        $contentLanguage = $this->getServiceContainer()->getContentLanguage();
34
35        $count = 0;
36        $maxUserId = 0;
37        do {
38            // List users who may have a signature that needs validation
39            $res = $dbr->newSelectQueryBuilder()
40                ->from( 'user_properties' )
41                ->select( 'up_user' )
42                ->where( [ 'up_property' => 'fancysig' ] )
43                ->andWhere( $dbr->expr( 'up_user', '>', $maxUserId ) )
44                ->orderBy( [ 'up_property', 'up_user' ] )
45                ->limit( $this->getBatchSize() )
46                ->caller( __METHOD__ )
47                ->fetchResultSet();
48
49            foreach ( $res as $row ) {
50                // Double-check effective preferences and check validation
51                $user = $userFactory->getUserIdentityByUserId( $row->up_user );
52                if ( !$user ) {
53                    continue;
54                }
55                $signature = $userOptions->getOption( $user, 'nickname' );
56                $useFancySig = $userOptions->getBoolOption( $user, 'fancysig' );
57                if ( $useFancySig && $signature !== '' ) {
58                    $parserOpts = new ParserOptions( $user, $contentLanguage );
59                    $validator = $signatureValidatorFactory->newSignatureValidator( $user, null, $parserOpts );
60                    $signatureErrors = $validator->validateSignature( $signature );
61                    if ( $signatureErrors ) {
62                        $count++;
63                        $this->output( $user->getName() . "\n" );
64                    }
65                }
66
67                $maxUserId = $row->up_user;
68            }
69        } while ( $res->numRows() );
70
71        $this->output( "-- $count invalid signatures --\n" );
72    }
73}
74
75// @codeCoverageIgnoreStart
76$maintClass = CheckSignatures::class;
77require_once RUN_MAINTENANCE_IF_MAIN;
78// @codeCoverageIgnoreEnd