Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 57
0.00% covered (danger)
0.00%
0 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
UpdateIsActiveFlagForMentees
0.00% covered (danger)
0.00%
0 / 51
0.00% covered (danger)
0.00%
0 / 3
90
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
2
 initServices
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
2
 execute
0.00% covered (danger)
0.00%
0 / 37
0.00% covered (danger)
0.00%
0 / 1
56
1<?php
2
3namespace GrowthExperiments\Maintenance;
4
5use GrowthExperiments\GrowthExperimentsServices;
6use GrowthExperiments\Mentorship\Store\MentorStore;
7use Maintenance;
8use MediaWiki\MediaWikiServices;
9use MediaWiki\User\UserEditTracker;
10use MediaWiki\User\UserFactory;
11use MediaWiki\User\UserIdentityLookup;
12use MediaWiki\User\UserIdentityValue;
13use Wikimedia\Rdbms\ILoadBalancer;
14
15$IP = getenv( 'MW_INSTALL_PATH' );
16if ( $IP === false ) {
17    $IP = __DIR__ . '/../../..';
18}
19require_once "$IP/maintenance/Maintenance.php";
20
21class UpdateIsActiveFlagForMentees extends Maintenance {
22
23    /** @var UserIdentityLookup */
24    private $userIdentityLookup;
25
26    /** @var UserEditTracker */
27    private $userEditTracker;
28
29    /** @var UserFactory */
30    private $userFactory;
31
32    /** @var ILoadBalancer */
33    private $growthLoadBalancer;
34
35    /** @var MentorStore */
36    private $mentorStore;
37
38    public function __construct() {
39        parent::__construct();
40        $this->setBatchSize( 200 );
41        $this->requireExtension( 'GrowthExperiments' );
42
43        $this->addDescription(
44            'Set gemm_mentee_is_active to false for users who are inactive for longer' .
45            'than $wgRCMaxAge.'
46        );
47    }
48
49    /**
50     * Init MediaWiki services
51     */
52    private function initServices(): void {
53        $services = MediaWikiServices::getInstance();
54        $geServices = GrowthExperimentsServices::wrap( $services );
55
56        $this->userIdentityLookup = $services->getUserIdentityLookup();
57        $this->userFactory = $services->getUserFactory();
58        $this->userEditTracker = $services->getUserEditTracker();
59        $this->growthLoadBalancer = $geServices->getLoadBalancer();
60        $this->mentorStore = $geServices->getMentorStore();
61    }
62
63    /**
64     * @inheritDoc
65     */
66    public function execute() {
67        $this->initServices();
68
69        $dbr = $this->growthLoadBalancer->getConnection( DB_REPLICA );
70        $menteeIds = $dbr->newSelectQueryBuilder()
71            ->select( 'gemm_mentee_id' )
72            ->from( 'growthexperiments_mentor_mentee' )
73            ->where( [
74                'gemm_mentor_role' => MentorStore::ROLE_PRIMARY,
75                'gemm_mentee_is_active' => true,
76            ] )
77            ->caller( __METHOD__ )
78            ->fetchFieldValues();
79
80        $thisBatch = 0;
81        foreach ( $menteeIds as $menteeId ) {
82            $menteeUser = $this->userIdentityLookup->getUserIdentityByUserId( $menteeId );
83            if ( !$menteeUser ) {
84                $this->output(
85                    "Deleting mentor/mentee relationship for $menteeId, user identity not found.\n"
86                );
87                $this->mentorStore->dropMenteeRelationship(
88                    // user does not exist; MentorStore only makes use of the user ID,
89                    // so construct UserIdentity manually for easier deletion.
90                    new UserIdentityValue( $menteeId, 'Mentee' )
91                );
92                continue;
93            }
94
95            $lastActivityTimestamp = $this->userEditTracker->getLatestEditTimestamp( $menteeUser );
96            if ( $lastActivityTimestamp === false ) {
97                $lastActivityTimestamp = $this->userFactory->newFromUserIdentity( $menteeUser )
98                    ->getRegistration();
99            }
100
101            $timeDelta = (int)wfTimestamp() - (int)wfTimestamp(
102                TS_UNIX,
103                $lastActivityTimestamp
104            );
105
106            if (
107                $lastActivityTimestamp === null ||
108                $timeDelta > (int)$this->getConfig()->get( 'RCMaxAge' )
109            ) {
110                $this->mentorStore->markMenteeAsInactive( $menteeUser );
111                $thisBatch++;
112
113                if ( $thisBatch >= $this->getBatchSize() ) {
114                    $this->waitForReplication();
115                    $thisBatch = 0;
116                }
117            }
118        }
119    }
120}
121
122$maintClass = UpdateIsActiveFlagForMentees::class;
123require_once RUN_MAINTENANCE_IF_MAIN;