Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
58.25% covered (warning)
58.25%
60 / 103
20.00% covered (danger)
20.00%
3 / 15
CRAP
0.00% covered (danger)
0.00%
0 / 1
SpecialClaimMentee
58.25% covered (warning)
58.25%
60 / 103
20.00% covered (danger)
20.00%
3 / 15
90.19
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 getGroupName
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 doesWrites
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getDescription
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 preHtml
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 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 isListed
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 userCanExecute
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 displayRestrictionError
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
6
 getFormFields
100.00% covered (success)
100.00%
25 / 25
100.00% covered (success)
100.00%
1 / 1
3
 getDisplayFormat
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 onSubmit
91.30% covered (success)
91.30%
21 / 23
0.00% covered (danger)
0.00%
0 / 1
7.03
 onSuccess
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
1
 setMentees
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
12
 validateMentees
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
20
1<?php
2
3namespace GrowthExperiments\Specials;
4
5use GrowthExperiments\Mentorship\ChangeMentorFactory;
6use GrowthExperiments\Mentorship\Provider\MentorProvider;
7use MediaWiki\Config\Config;
8use MediaWiki\Html\Html;
9use MediaWiki\Linker\Linker;
10use MediaWiki\Logger\LoggerFactory;
11use MediaWiki\Message\Message;
12use MediaWiki\SpecialPage\FormSpecialPage;
13use MediaWiki\Status\Status;
14use MediaWiki\User\User;
15use MediaWiki\User\UserIdentity;
16use PermissionsError;
17
18class SpecialClaimMentee extends FormSpecialPage {
19
20    /** @var User[] */
21    private array $mentees;
22
23    private ?User $newMentor;
24    private MentorProvider $mentorProvider;
25    private ChangeMentorFactory $changeMentorFactory;
26    private Config $wikiConfig;
27
28    /**
29     * @param MentorProvider $mentorProvider
30     * @param ChangeMentorFactory $changeMentorFactory
31     * @param Config $wikiConfig
32     */
33    public function __construct(
34        MentorProvider $mentorProvider,
35        ChangeMentorFactory $changeMentorFactory,
36        Config $wikiConfig
37    ) {
38        parent::__construct( 'ClaimMentee' );
39
40        $this->mentorProvider = $mentorProvider;
41        $this->changeMentorFactory = $changeMentorFactory;
42        $this->wikiConfig = $wikiConfig;
43    }
44
45    /** @inheritDoc */
46    protected function getGroupName() {
47        return 'growth-tools';
48    }
49
50    public function doesWrites() {
51        return true;
52    }
53
54    /**
55     * @inheritDoc
56     */
57    public function getDescription() {
58        return $this->msg( 'growthexperiments-homepage-claimmentee-title' );
59    }
60
61    protected function preHtml() {
62        return Html::element(
63            'p',
64            [],
65            $this->msg( 'growthexperiments-homepage-claimmentee-pretext' )->params(
66                $this->getUser()->getName()
67            )->text()
68        );
69    }
70
71    /**
72     * @inheritDoc
73     */
74    public function execute( $par ) {
75        $this->requireNamedUser();
76        $this->addHelpLink( 'Help:Growth/Tools/How to claim a mentee' );
77        parent::execute( $par );
78    }
79
80    /**
81     * @inheritDoc
82     */
83    public function isListed() {
84        return $this->userCanExecute( $this->getUser() );
85    }
86
87    /**
88     * @inheritDoc
89     */
90    public function userCanExecute( User $user ) {
91        return $this->mentorProvider->isMentor( $user );
92    }
93
94    /**
95     * @inheritDoc
96     */
97    public function displayRestrictionError() {
98        $signupTitle = $this->mentorProvider->getSignupTitle();
99
100        if ( $signupTitle === null ) {
101            throw new PermissionsError(
102                null,
103                [ 'growthexperiments-homepage-mentors-list-missing-or-misconfigured-generic' ]
104            );
105        }
106
107        throw new PermissionsError(
108            null,
109            [ [ 'growthexperiments-homepage-claimmentee-must-be-mentor',
110                $this->getUser()->getName(),
111                $signupTitle->getPrefixedText() ] ]
112        );
113    }
114
115    /**
116     * Get an HTMLForm descriptor array
117     * @return array
118     */
119    protected function getFormFields() {
120        $req = $this->getRequest();
121        $fields = [
122            'mentees' => [
123                'label-message' => 'growthexperiments-homepage-claimmentee-mentee',
124                'type'          => 'usersmultiselect',
125                'exists'        => true,
126                'required'      => true,
127                'excludetemp'   => true,
128            ],
129            'reason' => [
130                'label-message' => 'growthexperiments-homepage-claimmentee-reason',
131                'type'          => 'text',
132            ],
133            'stage' => [ 'type' => 'hidden', 'default' => 2 ]
134        ];
135        $stage = $req->getInt( 'wpstage', 1 );
136        $this->setMentees( $req->getVal( 'wpmentees', '' ) );
137        if ( $stage >= 2 && $this->validateMentees() ) {
138            $fields['stage']['default'] = 3;
139            $fields['confirm'] = [
140                'label-message' => 'growthexperiments-claimmentee-confirm',
141                'type' => 'check',
142                'default' => false,
143            ];
144        }
145        return $fields;
146    }
147
148    /**
149     * @return string
150     */
151    protected function getDisplayFormat() {
152        return 'ooui';
153    }
154
155    /**
156     * @inheritDoc
157     */
158    public function onSubmit( array $data ) {
159        $this->setMentees( $data['mentees'] );
160
161        // Should be caught by exits => true, but just to be sure
162        if ( !$this->validateMentees() ) {
163            return Status::newFatal( 'growthexperiments-homepage-claimmentee-invalid-username' );
164        }
165
166        $this->newMentor = $this->getUser();
167
168        $status = Status::newGood();
169        $logger = LoggerFactory::getInstance( 'GrowthExperiments' );
170        foreach ( $this->mentees as $mentee ) {
171            $changementor = $this->changeMentorFactory->newChangeMentor(
172                $mentee,
173                $this->newMentor
174            );
175
176            if (
177                $data['confirm'] !== true
178                && $data['stage'] !== 3
179                && $changementor->wasMentorChanged()
180            ) {
181                return Status::newFatal(
182                    'growthexperiments-homepage-claimmentee-alreadychanged',
183                    $mentee,
184                    $this->newMentor
185                );
186            }
187
188            $status->merge( $changementor->execute( $this->newMentor, $data['reason'] ) );
189            if ( !$status->isOK() ) {
190                // Do not process next users if at least one failed
191                return $status;
192            }
193        }
194
195        return $status;
196    }
197
198    public function onSuccess() {
199        $mentees = array_map( static function ( UserIdentity $user ) {
200            return Linker::userLink( $user->getId(), $user->getName() );
201        }, $this->mentees );
202
203        $language = $this->getLanguage();
204
205        $this->getOutput()->addWikiMsg(
206            'growthexperiments-homepage-claimmentee-success',
207            Message::rawParam( $language->listToText( $mentees ) ),
208            $language->formatNum( count( $mentees ) ),
209            $this->getUser()->getName(),
210            $this->newMentor->getName(),
211            Message::rawParam( $this->getLinkRenderer()->makeLink(
212                $this->newMentor->getUserPage(), $this->newMentor->getName() ) )
213        );
214    }
215
216    private function setMentees( string $namesRaw = '' ) {
217        $names = explode( "\n", $namesRaw );
218        $this->mentees = [];
219
220        foreach ( $names as $name ) {
221            $user = User::newFromName( $name );
222            if ( $user !== false ) {
223                $this->mentees[] = $user;
224            }
225        }
226    }
227
228    private function validateMentees() {
229        foreach ( $this->mentees as $mentee ) {
230            if ( !( $mentee instanceof User && $mentee->isNamed() ) ) {
231                return false;
232            }
233        }
234        return true;
235    }
236}