Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
43.69% |
45 / 103 |
|
0.00% |
0 / 5 |
CRAP | |
0.00% |
0 / 1 |
ApiManageMentorList | |
43.69% |
45 / 103 |
|
0.00% |
0 / 5 |
126.85 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
2 | |||
execute | |
68.18% |
45 / 66 |
|
0.00% |
0 / 1 |
32.89 | |||
isWriteMode | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
needsToken | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getAllowedParams | |
0.00% |
0 / 31 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | |
3 | namespace GrowthExperiments\Api; |
4 | |
5 | use GrowthExperiments\MentorDashboard\MentorTools\IMentorWeights; |
6 | use GrowthExperiments\MentorDashboard\MentorTools\MentorStatusManager; |
7 | use GrowthExperiments\Mentorship\Provider\IMentorWriter; |
8 | use GrowthExperiments\Mentorship\Provider\MentorProvider; |
9 | use LogicException; |
10 | use MediaWiki\Api\ApiBase; |
11 | use MediaWiki\Api\ApiMain; |
12 | use MediaWiki\ParamValidator\TypeDef\UserDef; |
13 | use Wikimedia\ParamValidator\ParamValidator; |
14 | use Wikimedia\Rdbms\IDBAccessObject; |
15 | |
16 | class ApiManageMentorList extends ApiBase { |
17 | |
18 | private MentorProvider $mentorProvider; |
19 | private IMentorWriter $mentorWriter; |
20 | private MentorStatusManager $mentorStatusManager; |
21 | |
22 | public function __construct( |
23 | ApiMain $mainModule, |
24 | string $moduleName, |
25 | MentorProvider $mentorProvider, |
26 | IMentorWriter $mentorWriter, |
27 | MentorStatusManager $mentorStatusManager |
28 | ) { |
29 | parent::__construct( $mainModule, $moduleName ); |
30 | |
31 | $this->mentorProvider = $mentorProvider; |
32 | $this->mentorWriter = $mentorWriter; |
33 | $this->mentorStatusManager = $mentorStatusManager; |
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 | // if the user is not a mentor, require enrollasmentor or managementors; the if is here to |
46 | // allow users to remove themselves, even after they lost the ability to enroll themselves. |
47 | if ( !$this->mentorProvider->isMentor( $this->getUser() ) ) { |
48 | $this->checkUserRightsAny( [ 'enrollasmentor', 'managementors' ] ); |
49 | } |
50 | |
51 | $params = $this->extractRequestParams(); |
52 | |
53 | if ( $params['username'] !== null ) { |
54 | $this->checkUserRightsAny( 'managementors' ); |
55 | // despite the name, $params['username'] is converted to an UserIdentity |
56 | // via UserDef::PARAM_RETURN_OBJECT in getAllowedParams(). |
57 | $mentorUser = $params['username']; |
58 | } else { |
59 | $mentorUser = $this->getUser(); |
60 | } |
61 | |
62 | $mentor = $this->mentorProvider->newMentorFromUserIdentity( $mentorUser ); |
63 | |
64 | if ( $params['message'] !== null ) { |
65 | $mentor->setIntroText( $params['message'] !== '' ? $params['message'] : null ); |
66 | } |
67 | if ( $params['weight'] !== null ) { |
68 | $mentor->setWeight( (int)$params['weight'] ); |
69 | } |
70 | |
71 | // ensure awaytimestamp is provided when isaway=true |
72 | if ( $params['isaway'] && $params['awaytimestamp'] === null ) { |
73 | $this->dieWithError( |
74 | 'growthexperiments-api-managementors-error-no-away-timestamp', |
75 | 'away-timestamp' |
76 | ); |
77 | } |
78 | |
79 | switch ( $params['geaction'] ) { |
80 | case 'add': |
81 | $statusValue = $this->mentorWriter->addMentor( |
82 | $mentor, |
83 | $this->getUser(), |
84 | $params['summary'] |
85 | ); |
86 | break; |
87 | case 'change': |
88 | $statusValue = $this->mentorWriter->changeMentor( |
89 | $mentor, |
90 | $this->getUser(), |
91 | $params['summary'] |
92 | ); |
93 | break; |
94 | case 'remove': |
95 | $statusValue = $this->mentorWriter->removeMentor( |
96 | $mentor, |
97 | $this->getUser(), |
98 | $params['summary'] |
99 | ); |
100 | break; |
101 | default: |
102 | // this should never happen, unless getAllowedParams is wrong |
103 | throw new LogicException( 'Invalid geaction passed validation' ); |
104 | } |
105 | |
106 | if ( !$statusValue->isOK() ) { |
107 | $this->dieStatus( $statusValue ); |
108 | } |
109 | |
110 | if ( $params['geaction'] !== 'remove' ) { |
111 | if ( $params['isaway'] ) { |
112 | $result = $this->mentorStatusManager->markMentorAsAwayTimestamp( |
113 | $mentorUser, |
114 | $params['awaytimestamp'] |
115 | ); |
116 | if ( !$result->isOK() ) { |
117 | $this->dieStatus( $result ); |
118 | } |
119 | } else { |
120 | $this->mentorStatusManager->markMentorAsActive( $mentorUser ); |
121 | } |
122 | } |
123 | |
124 | $rawBackTs = $this->mentorStatusManager->getMentorBackTimestamp( $mentorUser ); |
125 | $this->getResult()->addValue( null, $this->getModuleName(), [ |
126 | 'status' => 'ok', |
127 | 'mentor' => [ |
128 | 'message' => $mentor->hasCustomIntroText() ? $mentor->getIntroText() : null, |
129 | 'weight' => $mentor->getWeight(), |
130 | 'awayTimestamp' => $rawBackTs, |
131 | 'awayTimestampHuman' => $rawBackTs !== null ? $this->getContext() |
132 | ->getLanguage()->date( $rawBackTs, true ) : null, |
133 | |
134 | // NOTE: Legacy attribute, weight provides the same info. |
135 | 'automaticallyAssigned' => $mentor->getWeight() !== IMentorWeights::WEIGHT_NONE, |
136 | ] |
137 | ] ); |
138 | } |
139 | |
140 | /** |
141 | * @inheritDoc |
142 | */ |
143 | public function isWriteMode() { |
144 | return true; |
145 | } |
146 | |
147 | /** |
148 | * @inheritDoc |
149 | */ |
150 | public function needsToken() { |
151 | return 'csrf'; |
152 | } |
153 | |
154 | /** |
155 | * @inheritDoc |
156 | */ |
157 | protected function getAllowedParams() { |
158 | return [ |
159 | 'geaction' => [ |
160 | ParamValidator::PARAM_REQUIRED => true, |
161 | ParamValidator::PARAM_TYPE => [ |
162 | 'add', |
163 | 'change', |
164 | 'remove', |
165 | ] |
166 | ], |
167 | 'message' => [ |
168 | ParamValidator::PARAM_TYPE => 'string' |
169 | ], |
170 | 'weight' => [ |
171 | ParamValidator::PARAM_TYPE => array_map( 'strval', IMentorWeights::WEIGHTS ) |
172 | ], |
173 | 'isaway' => [ |
174 | ParamValidator::PARAM_TYPE => 'boolean', |
175 | ], |
176 | 'awaytimestamp' => [ |
177 | ParamValidator::PARAM_TYPE => 'timestamp', |
178 | ], |
179 | 'summary' => [ |
180 | ParamValidator::PARAM_TYPE => 'string', |
181 | ParamValidator::PARAM_DEFAULT => '', |
182 | ], |
183 | 'username' => [ |
184 | ParamValidator::PARAM_TYPE => 'user', |
185 | UserDef::PARAM_ALLOWED_USER_TYPES => [ 'name' ], |
186 | UserDef::PARAM_RETURN_OBJECT => true, |
187 | ], |
188 | ]; |
189 | } |
190 | } |