Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 141 |
|
0.00% |
0 / 3 |
CRAP | |
0.00% |
0 / 1 |
MenteesHandler | |
0.00% |
0 / 141 |
|
0.00% |
0 / 3 |
306 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
2 | |||
run | |
0.00% |
0 / 88 |
|
0.00% |
0 / 1 |
240 | |||
getParamSettings | |
0.00% |
0 / 47 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | |
3 | namespace GrowthExperiments\Rest\Handler; |
4 | |
5 | use GrowthExperiments\MentorDashboard\MenteeOverview\MenteeOverviewDataFilter; |
6 | use GrowthExperiments\MentorDashboard\MenteeOverview\MenteeOverviewDataProvider; |
7 | use GrowthExperiments\MentorDashboard\MenteeOverview\StarredMenteesStore; |
8 | use GrowthExperiments\Util; |
9 | use MediaWiki\Cache\LinkBatchFactory; |
10 | use MediaWiki\Rest\HttpException; |
11 | use MediaWiki\Rest\SimpleHandler; |
12 | use MediaWiki\Title\TitleFactory; |
13 | use MediaWiki\Title\TitleParser; |
14 | use MediaWiki\User\UserFactory; |
15 | use MediaWiki\User\UserIdentity; |
16 | use MediaWiki\Utils\MWTimestamp; |
17 | use RequestContext; |
18 | use Wikimedia\Assert\ParameterAssertionException; |
19 | use Wikimedia\ParamValidator\ParamValidator; |
20 | |
21 | /** |
22 | * Returns information about user's mentees. |
23 | * |
24 | * The class intentionally does not check the user is currently |
25 | * listed as a mentor, because users who were previously mentors may still have |
26 | * mentees. Users who never were a mentor will receive an empty array anyway. |
27 | */ |
28 | class MenteesHandler extends SimpleHandler { |
29 | /** @var MenteeOverviewDataProvider */ |
30 | private $dataProvider; |
31 | |
32 | /** @var StarredMenteesStore */ |
33 | private $starredMenteesStore; |
34 | |
35 | /** @var UserFactory */ |
36 | private $userFactory; |
37 | |
38 | /** @var TitleFactory */ |
39 | private $titleFactory; |
40 | |
41 | /** @var TitleParser */ |
42 | private $titleParser; |
43 | |
44 | /** @var LinkBatchFactory */ |
45 | private $linkBatchFactory; |
46 | |
47 | /** |
48 | * @param MenteeOverviewDataProvider $dataProvider |
49 | * @param StarredMenteesStore $starredMenteesStore |
50 | * @param UserFactory $userFactory |
51 | * @param TitleFactory $titleFactory |
52 | * @param TitleParser $titleParser |
53 | * @param LinkBatchFactory $linkBatchFactory |
54 | */ |
55 | public function __construct( |
56 | MenteeOverviewDataProvider $dataProvider, |
57 | StarredMenteesStore $starredMenteesStore, |
58 | UserFactory $userFactory, |
59 | TitleFactory $titleFactory, |
60 | TitleParser $titleParser, |
61 | LinkBatchFactory $linkBatchFactory |
62 | ) { |
63 | $this->dataProvider = $dataProvider; |
64 | $this->starredMenteesStore = $starredMenteesStore; |
65 | $this->userFactory = $userFactory; |
66 | $this->titleFactory = $titleFactory; |
67 | $this->titleParser = $titleParser; |
68 | $this->linkBatchFactory = $linkBatchFactory; |
69 | } |
70 | |
71 | /** |
72 | * @return array |
73 | * @throws HttpException |
74 | */ |
75 | public function run() { |
76 | $authority = $this->getAuthority(); |
77 | if ( !$authority->isNamed() ) { |
78 | throw new HttpException( 'You must be logged in', 403 ); |
79 | } |
80 | $user = $authority->getUser(); |
81 | |
82 | $params = $this->getValidatedParams(); |
83 | $limit = $params['limit'] ?? 10; |
84 | $offset = $params['offset'] ?? 0; |
85 | |
86 | $allData = $this->dataProvider->getFormattedDataForMentor( $user ); |
87 | $dataFilter = new MenteeOverviewDataFilter( $allData ); |
88 | $dataFilter |
89 | ->limit( $limit ) |
90 | ->offset( $offset ); |
91 | |
92 | if ( $params['prefix'] !== null ) { |
93 | $dataFilter->prefix( $params['prefix'] ); |
94 | } |
95 | if ( $params['minedits'] !== null ) { |
96 | $dataFilter->minEdits( $params['minedits'] ); |
97 | } |
98 | if ( $params['maxedits'] !== null ) { |
99 | $dataFilter->maxEdits( $params['maxedits'] ); |
100 | } |
101 | if ( $params['activedaysago'] !== null ) { |
102 | $dataFilter->activeDaysAgo( $params['activedaysago'] ); |
103 | } |
104 | if ( $params['onlystarred'] === true ) { |
105 | $dataFilter->onlyIds( |
106 | array_map( static function ( UserIdentity $mentee ) { |
107 | return $mentee->getId(); |
108 | }, $this->starredMenteesStore->getStarredMentees( $user ) ) |
109 | ); |
110 | } |
111 | if ( $params['sortby'] !== null ) { |
112 | // validation is done by data filter |
113 | try { |
114 | $orderRaw = $params['order'] ?? 'desc'; |
115 | if ( $orderRaw === 'desc' ) { |
116 | $order = MenteeOverviewDataFilter::SORT_ORDER_DESCENDING; |
117 | } elseif ( $orderRaw === 'asc' ) { |
118 | $order = MenteeOverviewDataFilter::SORT_ORDER_ASCENDING; |
119 | } else { |
120 | throw new HttpException( 'Invalid order', 400 ); |
121 | } |
122 | $dataFilter->sort( $params['sortby'], $order ); |
123 | } catch ( ParameterAssertionException $e ) { |
124 | throw new HttpException( 'Invalid sortby', 400 ); |
125 | } |
126 | } |
127 | |
128 | $data = $dataFilter->filter(); |
129 | $context = RequestContext::getMain(); |
130 | $nowUnix = (int)MWTimestamp::now( TS_UNIX ); |
131 | $batch = $this->linkBatchFactory->newLinkBatch(); |
132 | $batch->setCaller( __METHOD__ ); |
133 | array_walk( $data, function ( &$menteeData ) use ( $context, $nowUnix, $batch ) { |
134 | if ( isset( $menteeData['last_active'] ) ) { |
135 | $menteeData['last_active'] = [ |
136 | 'raw' => $menteeData['last_active'], |
137 | 'human' => Util::getRelativeTime( |
138 | $context, |
139 | $nowUnix - (int)MWTimestamp::getInstance( |
140 | $menteeData['last_active'] |
141 | )->getTimestamp( TS_UNIX ) |
142 | ) |
143 | ]; |
144 | } |
145 | |
146 | if ( $menteeData['registration'] ) { |
147 | $menteeData['registration'] = [ |
148 | 'raw' => $menteeData['registration'], |
149 | 'human' => $context->getLanguage()->sprintfDate( |
150 | 'Y-m-d', |
151 | $menteeData['registration'] |
152 | ) |
153 | ]; |
154 | } |
155 | |
156 | if ( $menteeData['username'] ) { |
157 | $batch->addObj( $this->titleParser->parseTitle( |
158 | $menteeData['username'], |
159 | NS_USER |
160 | ) ); |
161 | } |
162 | } ); |
163 | |
164 | $batch->execute(); |
165 | array_walk( $data, function ( &$menteeData ) { |
166 | if ( $menteeData['username'] ) { |
167 | $menteeData['userpage_exists'] = $this->titleFactory->newFromText( |
168 | $menteeData['username'], |
169 | NS_USER |
170 | )->isKnown(); |
171 | $menteeData['usertalk_exists'] = $this->titleFactory->newFromText( |
172 | $menteeData['username'], |
173 | NS_USER_TALK |
174 | )->isKnown(); |
175 | $menteeData['user_is_hidden'] = $this->userFactory->newFromName( |
176 | $menteeData['username'] |
177 | )->isHidden(); |
178 | } |
179 | } ); |
180 | |
181 | return [ |
182 | 'mentees' => array_values( $data ), |
183 | 'totalRows' => $dataFilter->getTotalRows(), |
184 | 'assignedMentees' => count( $allData ), |
185 | 'limit' => $limit, |
186 | 'offset' => $offset |
187 | ]; |
188 | } |
189 | |
190 | /** @inheritDoc */ |
191 | public function getParamSettings() { |
192 | return [ |
193 | 'limit' => [ |
194 | self::PARAM_SOURCE => 'query', |
195 | ParamValidator::PARAM_TYPE => 'integer', |
196 | ParamValidator::PARAM_REQUIRED => false, |
197 | ], |
198 | 'offset' => [ |
199 | self::PARAM_SOURCE => 'query', |
200 | ParamValidator::PARAM_TYPE => 'integer', |
201 | ParamValidator::PARAM_REQUIRED => false, |
202 | ], |
203 | 'prefix' => [ |
204 | self::PARAM_SOURCE => 'query', |
205 | ParamValidator::PARAM_TYPE => 'string', |
206 | ParamValidator::PARAM_REQUIRED => false, |
207 | ], |
208 | 'activedaysago' => [ |
209 | self::PARAM_SOURCE => 'query', |
210 | ParamValidator::PARAM_TYPE => 'integer', |
211 | ParamValidator::PARAM_REQUIRED => false, |
212 | ], |
213 | 'minedits' => [ |
214 | self::PARAM_SOURCE => 'query', |
215 | ParamValidator::PARAM_TYPE => 'integer', |
216 | ParamValidator::PARAM_REQUIRED => false, |
217 | ], |
218 | 'maxedits' => [ |
219 | self::PARAM_SOURCE => 'query', |
220 | ParamValidator::PARAM_TYPE => 'integer', |
221 | ParamValidator::PARAM_REQUIRED => false, |
222 | ], |
223 | 'onlystarred' => [ |
224 | self::PARAM_SOURCE => 'query', |
225 | ParamValidator::PARAM_TYPE => 'boolean', |
226 | ParamValidator::PARAM_REQUIRED => false, |
227 | ], |
228 | 'sortby' => [ |
229 | self::PARAM_SOURCE => 'query', |
230 | ParamValidator::PARAM_TYPE => 'string', |
231 | ParamValidator::PARAM_REQUIRED => false, |
232 | ], |
233 | 'order' => [ |
234 | self::PARAM_SOURCE => 'query', |
235 | ParamValidator::PARAM_TYPE => 'string', |
236 | ParamValidator::PARAM_REQUIRED => false, |
237 | ], |
238 | ]; |
239 | } |
240 | } |