Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
94.12% covered (success)
94.12%
64 / 68
50.00% covered (danger)
50.00%
1 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
PruneCheckUserDataJob
94.12% covered (success)
94.12%
64 / 68
50.00% covered (danger)
50.00%
1 / 2
7.01
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 run
94.03% covered (success)
94.03%
63 / 67
0.00% covered (danger)
0.00%
0 / 1
6.01
1<?php
2
3namespace MediaWiki\CheckUser\Jobs;
4
5use Job;
6use MediaWiki\CheckUser\ClientHints\ClientHintsReferenceIds;
7use MediaWiki\CheckUser\Services\UserAgentClientHintsManager;
8use MediaWiki\MediaWikiServices;
9use Wikimedia\Rdbms\ILoadBalancer;
10use Wikimedia\Timestamp\ConvertibleTimestamp;
11
12/**
13 * Prune data from the three CheckUser tables (cu_changes, cu_log_event and cu_private_event)
14 * using a job to avoid doing this post send.
15 */
16class PruneCheckUserDataJob extends Job {
17    /** @inheritDoc */
18    public function __construct( $title, $params ) {
19        parent::__construct( 'checkuserPruneCheckUserDataJob', $params );
20    }
21
22    /** @return bool */
23    public function run() {
24        $services = MediaWikiServices::getInstance();
25        $fname = __METHOD__;
26
27        $lb = $services->getDBLoadBalancer();
28        $dbw = $lb->getMaintenanceConnectionRef( ILoadBalancer::DB_PRIMARY, $this->params['domainID'] );
29
30        // per-wiki
31        $key = "{$this->params['domainID']}:PruneCheckUserData";
32        $scopedLock = $dbw->getScopedLockAndFlush( $key, $fname, 1 );
33        if ( !$scopedLock ) {
34            return true;
35        }
36
37        $cutoff = $dbw->timestamp(
38            ConvertibleTimestamp::time() - $services->getMainConfig()->get( 'CUDMaxAge' )
39        );
40
41        $shouldDeleteAssociatedClientData = $services->getMainConfig()->get( 'CheckUserPurgeOldClientHintsData' );
42
43        $deleteOperation = static function (
44            $table, $idField, $timestampField, $clientHintMapTypeIdentifier
45        ) use ( $dbw, $cutoff, $fname, $shouldDeleteAssociatedClientData ) {
46            $ids = [];
47            $referenceIds = [];
48            $clientHintReferenceField =
49                UserAgentClientHintsManager::IDENTIFIER_TO_COLUMN_NAME_MAP[$clientHintMapTypeIdentifier];
50            $idQueryBuilder = $dbw->newSelectQueryBuilder()
51                ->table( $table )
52                ->conds( $dbw->expr( $timestampField, '<', $cutoff ) )
53                ->limit( 500 )
54                ->caller( $fname );
55            if ( $shouldDeleteAssociatedClientData ) {
56                $result = $idQueryBuilder->fields( [ $idField, $clientHintReferenceField ] )
57                    ->fetchResultSet();
58                foreach ( $result as $row ) {
59                    $ids[] = $row->$idField;
60                    $referenceIds[] = $row->$clientHintReferenceField;
61                }
62            } else {
63                $ids = $idQueryBuilder
64                    ->field( $idField )
65                    ->fetchFieldValues();
66            }
67            if ( $ids ) {
68                $dbw->newDeleteQueryBuilder()
69                    ->table( $table )
70                    ->where( [ $idField => $ids ] )
71                    ->caller( $fname )
72                    ->execute();
73            }
74            return $referenceIds;
75        };
76
77        $deletedReferenceIds = new ClientHintsReferenceIds();
78
79        $deletedReferenceIds->addReferenceIds(
80            $deleteOperation(
81                'cu_changes', 'cuc_id', 'cuc_timestamp',
82                UserAgentClientHintsManager::IDENTIFIER_CU_CHANGES
83            ),
84            UserAgentClientHintsManager::IDENTIFIER_CU_CHANGES
85        );
86
87        $deletedReferenceIds->addReferenceIds(
88            $deleteOperation(
89                'cu_private_event', 'cupe_id', 'cupe_timestamp',
90                UserAgentClientHintsManager::IDENTIFIER_CU_PRIVATE_EVENT
91            ),
92            UserAgentClientHintsManager::IDENTIFIER_CU_PRIVATE_EVENT
93        );
94
95        $deletedReferenceIds->addReferenceIds(
96            $deleteOperation(
97                'cu_log_event', 'cule_id', 'cule_timestamp',
98                UserAgentClientHintsManager::IDENTIFIER_CU_LOG_EVENT
99            ),
100            UserAgentClientHintsManager::IDENTIFIER_CU_LOG_EVENT
101        );
102
103        if ( $shouldDeleteAssociatedClientData ) {
104            /** @var UserAgentClientHintsManager $userAgentClientHintsManager */
105            $userAgentClientHintsManager = $services->get( 'UserAgentClientHintsManager' );
106            $userAgentClientHintsManager->deleteMappingRows( $deletedReferenceIds );
107        }
108
109        return true;
110    }
111}