Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
96.30% covered (success)
96.30%
52 / 54
66.67% covered (warning)
66.67%
2 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
UpdateUserMetadata
96.30% covered (success)
96.30%
52 / 54
66.67% covered (warning)
66.67%
2 / 3
10
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 init
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 execute
95.92% covered (success)
95.92%
47 / 49
0.00% covered (danger)
0.00%
0 / 1
8
1<?php
2namespace MediaWiki\Extension\PageTriage\Maintenance;
3
4use Maintenance;
5use MediaWiki\Extension\PageTriage\ArticleCompile\ArticleCompileProcessor;
6use MediaWiki\Extension\PageTriage\PageTriageUtil;
7use Wikimedia\Rdbms\IDatabase;
8use Wikimedia\Rdbms\SelectQueryBuilder;
9
10/**
11 * A maintenance script that updates expired user metadata
12 */
13class UpdateUserMetadata extends Maintenance {
14
15    /**
16     * @var IDatabase|null
17     */
18    protected $dbr;
19    /**
20     * @var IDatabase|null
21     */
22    protected $dbw;
23
24    public function __construct() {
25        parent::__construct();
26        $this->addDescription( "Update the user metadata in pagetriage_page_tags table" );
27        $this->requireExtension( 'PageTriage' );
28        $this->setBatchSize( 300 );
29    }
30
31    protected function init() {
32        $this->dbr = PageTriageUtil::getReplicaConnection();
33    }
34
35    /**
36     * @suppress PhanPossiblyUndeclaredVariable False positive with $row
37     */
38    public function execute() {
39        $this->init();
40        $this->output( "Started processing... \n" );
41
42        // Scan for data updated more than a day ago
43        $startTime = (int)wfTimestamp( TS_UNIX ) - 60 * 60 * 24;
44        $count = $this->getBatchSize();
45
46        $idRow = $this->dbr->newSelectQueryBuilder()
47            ->select( [ 'max_id' => 'MAX(ptrp_page_id)' ] )
48            ->from( 'pagetriage_page' )
49            ->caller( __METHOD__ )
50            ->fetchRow();
51
52        // No data to process, exit
53        if ( $idRow === false ) {
54            return;
55        }
56
57        $startId = $idRow->max_id + 1;
58
59        $pageTriageNamespaces = PageTriageUtil::getNamespaces();
60        if ( count( $pageTriageNamespaces ) > 0 ) {
61            $namespace = $pageTriageNamespaces;
62        } else {
63            $namespace = NS_MAIN;
64        }
65
66        while ( $count === $this->getBatchSize() ) {
67            $count = 0;
68            $res = $this->dbr->newSelectQueryBuilder()
69                ->select( [ 'ptrp_page_id', 'ptrp_tags_updated' ] )
70                ->from( 'pagetriage_page' )
71                ->join( 'page', null, 'page_id = ptrp_page_id' )
72                ->where( [
73                    $this->dbr->buildComparison( '<', [
74                        'ptrp_tags_updated' => $this->dbr->timestamp( $startTime ),
75                        'ptrp_page_id' => $startId,
76                    ] ),
77                    'page_namespace' => $namespace
78                ] )
79                ->limit( $this->getBatchSize() )
80                ->orderBy( [ 'ptrp_tags_updated', 'ptrp_page_id' ], SelectQueryBuilder::SORT_DESC )
81                ->caller( __METHOD__ )
82                ->fetchResultSet();
83
84            $pageId = [];
85            foreach ( $res as $row ) {
86                $pageId[] = $row->ptrp_page_id;
87                $count++;
88            }
89
90            if ( $pageId ) {
91                // update the startTime with the last row if it's set, check in case it's not set
92                if ( $row->ptrp_tags_updated ) {
93                    $startTime = wfTimestamp( TS_UNIX, $row->ptrp_tags_updated );
94                }
95                $startId = (int)$row->ptrp_page_id;
96
97                $acp = ArticleCompileProcessor::newFromPageId( $pageId );
98                if ( $acp ) {
99                    $acp->registerComponent( 'UserData' );
100                    // safe to use replica db for data compilation
101                    $acp->configComponentDb( [ 'UserData' => DB_REPLICA ] );
102                    $acp->compileMetadata();
103                }
104
105                $this->output( "processed $count \n" );
106                $this->waitForReplication();
107            }
108        }
109
110        $this->output( "Completed \n" );
111    }
112}