Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
94.12% covered (success)
94.12%
48 / 51
71.43% covered (warning)
71.43%
5 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
ApiSetMentor
94.12% covered (success)
94.12%
48 / 51
71.43% covered (warning)
71.43%
5 / 7
13.03
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
 execute
91.67% covered (success)
91.67%
22 / 24
0.00% covered (danger)
0.00%
0 / 1
6.02
 assertUserExists
50.00% covered (danger)
50.00%
1 / 2
0.00% covered (danger)
0.00%
0 / 1
2.50
 mustBePosted
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 needsToken
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 isWriteMode
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getAllowedParams
100.00% covered (success)
100.00%
18 / 18
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3namespace GrowthExperiments\Api;
4
5use GrowthExperiments\Mentorship\ChangeMentorFactory;
6use GrowthExperiments\Mentorship\Mentor;
7use GrowthExperiments\Mentorship\MentorManager;
8use MediaWiki\Api\ApiBase;
9use MediaWiki\Api\ApiMain;
10use MediaWiki\Api\ApiUsageException;
11use MediaWiki\ParamValidator\TypeDef\UserDef;
12use MediaWiki\User\UserIdentity;
13use MediaWiki\User\UserIdentityUtils;
14use Wikimedia\ParamValidator\ParamValidator;
15use Wikimedia\Rdbms\IDBAccessObject;
16
17class ApiSetMentor extends ApiBase {
18    private MentorManager $mentorManager;
19    private ChangeMentorFactory $changeMentorFactory;
20    private UserIdentityUtils $userIdentityUtils;
21
22    public function __construct(
23        ApiMain $mainModule,
24        string $moduleName,
25        MentorManager $mentorManager,
26        ChangeMentorFactory $changeMentorFactory,
27        UserIdentityUtils $userIdentityUtils
28    ) {
29        parent::__construct( $mainModule, $moduleName );
30
31        $this->mentorManager = $mentorManager;
32        $this->changeMentorFactory = $changeMentorFactory;
33        $this->userIdentityUtils = $userIdentityUtils;
34    }
35
36    /**
37     * @inheritDoc
38     */
39    public function execute() {
40        $block = $this->getUser()->getBlock( IDBAccessObject::READ_LATEST );
41        if ( $block && $block->isSitewide() ) {
42            $this->dieBlocked( $block );
43        }
44
45        $params = $this->extractRequestParams();
46        /** @var UserIdentity $mentee */
47        $mentee = $params['mentee'];
48        /** @var UserIdentity $mentor */
49        $mentor = $params['mentor'];
50
51        if ( !in_array( $this->getUser()->getId(), [ $mentee->getId(), $mentor->getId() ] ) ) {
52            // If you're neither the mentee nor the (new) mentor,
53            // you must have setmentor rights.
54            $this->checkUserRightsAny( 'setmentor' );
55        }
56
57        $this->assertUserExists( $mentee );
58        $this->assertUserExists( $mentor );
59
60        $oldMentorObj = $this->mentorManager->getMentorForUserIfExists( $mentee );
61
62        $changeMentor = $this->changeMentorFactory->newChangeMentor(
63            $mentee,
64            $this->getUser()
65        );
66        $status = $changeMentor->execute( $mentor, $params['reason'] );
67        if ( !$status->isOK() ) {
68            $this->dieStatus( $status );
69        }
70
71        $this->getResult()->addValue( null, $this->getModuleName(), [
72            'status' => 'ok',
73            'mentee' => $mentee,
74            'newMentor' => $mentor,
75            'oldMentor' => $oldMentorObj instanceof Mentor ? $oldMentorObj->getUserIdentity() : false,
76        ] );
77    }
78
79    /**
80     * Throw an exception if the user is anonymous or temporary.
81     * @param UserIdentity $user
82     * @throws ApiUsageException
83     */
84    private function assertUserExists( UserIdentity $user ) {
85        if ( !$this->userIdentityUtils->isNamed( $user ) ) {
86            $this->dieWithError( [ 'nosuchusershort', $user->getName() ] );
87        }
88    }
89
90    /** @inheritDoc */
91    public function mustBePosted() {
92        return true;
93    }
94
95    /**
96     * @inheritDoc
97     */
98    public function needsToken() {
99        return 'csrf';
100    }
101
102    /** @inheritDoc */
103    public function isWriteMode() {
104        return true;
105    }
106
107    /**
108     * @inheritDoc
109     */
110    public function getAllowedParams() {
111        return [
112            'mentee' => [
113                ParamValidator::PARAM_REQUIRED => true,
114                ParamValidator::PARAM_TYPE => 'user',
115                UserDef::PARAM_ALLOWED_USER_TYPES => [ 'name' ],
116                UserDef::PARAM_RETURN_OBJECT => true,
117            ],
118            'mentor' => [
119                ParamValidator::PARAM_REQUIRED => true,
120                ParamValidator::PARAM_TYPE => 'user',
121                UserDef::PARAM_ALLOWED_USER_TYPES => [ 'name' ],
122                UserDef::PARAM_RETURN_OBJECT => true,
123            ],
124            'reason' => [
125                ParamValidator::PARAM_TYPE => 'string',
126                ParamValidator::PARAM_DEFAULT => '',
127            ],
128        ];
129    }
130}