Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 52
0.00% covered (danger)
0.00%
0 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
ReassignMenteesJob
0.00% covered (danger)
0.00%
0 / 52
0.00% covered (danger)
0.00%
0 / 5
132
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
2
 ignoreDuplicates
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getDeduplicationInfo
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
12
 getBatchSize
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 run
0.00% covered (danger)
0.00%
0 / 37
0.00% covered (danger)
0.00%
0 / 1
30
1<?php
2
3namespace GrowthExperiments\Mentorship;
4
5use GenericParameterJob;
6use GrowthExperiments\GrowthExperimentsServices;
7use GrowthExperiments\Mentorship\Store\MentorStore;
8use Job;
9use MediaWiki\Config\Config;
10use MediaWiki\Context\RequestContext;
11use MediaWiki\Logger\LoggerFactory;
12use MediaWiki\MediaWikiServices;
13use MediaWiki\User\UserIdentityLookup;
14use Psr\Log\LoggerInterface;
15
16/**
17 * Job to reassign all mentees operated by a given mentor
18 *
19 * The following job parameters are required:
20 *  - mentorId: user ID of the mentor to process
21 *  - reassignMessageKey: Message to store in logs as well as in notifications to mentees
22 */
23class ReassignMenteesJob extends Job implements GenericParameterJob {
24
25    public const JOB_NAME = 'reassignMenteesJob';
26
27    private Config $config;
28    private UserIdentityLookup $userIdentityLookup;
29    private MentorStore $mentorStore;
30    private ReassignMenteesFactory $reassignMenteesFactory;
31    private LoggerInterface $logger;
32
33    /**
34     * @inheritDoc
35     */
36    public function __construct( $params = null ) {
37        parent::__construct( self::JOB_NAME, $params );
38
39        // init services
40        $services = MediaWikiServices::getInstance();
41        $geServices = GrowthExperimentsServices::wrap( $services );
42        $this->config = $services->getMainConfig();
43        $this->userIdentityLookup = $services->getUserIdentityLookup();
44        $this->mentorStore = $geServices->getMentorStore();
45        $this->reassignMenteesFactory = $geServices->getReassignMenteesFactory();
46        $this->logger = LoggerFactory::getInstance( 'GrowthExperiments' );
47    }
48
49    /**
50     * @inheritDoc
51     */
52    public function ignoreDuplicates() {
53        return true;
54    }
55
56    /**
57     * @inheritDoc
58     */
59    public function getDeduplicationInfo() {
60        $info = parent::getDeduplicationInfo();
61
62        // When deduplicating, ignore performerId, reassignMessageKey and
63        // reassignMessageAdditionalParams. The reason for deduplication
64        // is to avoid reassigning mentees assigned to the same mentor more
65        // than once (see T322374).
66        foreach ( [ 'performerId', 'reassignMessageKey', 'reassignMessageAdditionalParams' ] as $ignoredParam ) {
67            if ( isset( $info['params'][$ignoredParam] ) ) {
68                unset( $info['params'][$ignoredParam] );
69            }
70        }
71
72        return $info;
73    }
74
75    private function getBatchSize(): int {
76        return $this->config->get( 'GEMentorshipReassignMenteesBatchSize' );
77    }
78
79    /**
80     * @inheritDoc
81     */
82    public function run() {
83        $mentor = $this->userIdentityLookup->getUserIdentityByUserId( $this->params['mentorId'] );
84        $performer = $this->userIdentityLookup->getUserIdentityByUserId( $this->params['performerId'] );
85        if ( !$mentor || !$performer ) {
86            $this->logger->error(
87                'ReassignMenteesJob trigerred with invalid parameters',
88                [
89                    'performerId' => $this->params['performerId'],
90                    'mentorId' => $this->params['mentorId'],
91                ]
92            );
93            return false;
94        }
95
96        $reassignMentees = $this->reassignMenteesFactory->newReassignMentees(
97            $performer,
98            $mentor,
99            RequestContext::getMain()
100        );
101        $status = $reassignMentees->doReassignMentees(
102            $this->getBatchSize(),
103            $this->params['reassignMessageKey'],
104            ...$this->params['reassignMessageAdditionalParams']
105        );
106        $this->logger->info( 'ReassignMenteesJob finished reassignment with {status} status', [
107            'status' => $status,
108        ] );
109
110        if ( $status ) {
111            if ( $this->mentorStore->hasAnyMentees( $mentor, MentorStore::ROLE_PRIMARY ) ) {
112                $this->logger->info( 'ReassignMenteesJob did not reassign all mentees, scheduling new job', [
113                    'mentor' => $mentor->getName(),
114                ] );
115                $reassignMentees->scheduleReassignMenteesJob(
116                    $this->params['reassignMessageKey'],
117                    ...$this->params['reassignMessageAdditionalParams']
118                );
119            } else {
120                $this->logger->info( 'ReassignMenteesJob finished reassigning all mentees', [
121                    'mentor' => $mentor->getName(),
122                ] );
123            }
124        }
125
126        return true;
127    }
128}