Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 71 |
|
0.00% |
0 / 9 |
CRAP | |
0.00% |
0 / 1 |
QualityGateDecorator | |
0.00% |
0 / 71 |
|
0.00% |
0 / 9 |
306 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
2 | |||
suggest | |
0.00% |
0 / 35 |
|
0.00% |
0 / 1 |
30 | |||
filter | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
isImageRecommendationDailyTaskLimitExceeded | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
getImageRecommendationTasksDoneByUserForCurrentDay | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
6 | |||
isLinkRecommendationDailyTaskLimitExceeded | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
getLinkRecommendationTasksDoneByUserForCurrentDay | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
6 | |||
isSectionImageRecommendationDailyTaskLimitExceeded | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
getSectionImageRecommendationTasksDoneByUserForCurrentDay | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
6 |
1 | <?php |
2 | |
3 | namespace GrowthExperiments\NewcomerTasks\TaskSuggester; |
4 | |
5 | use GrowthExperiments\NewcomerTasks\AddImage\ImageRecommendationSubmissionLogFactory; |
6 | use GrowthExperiments\NewcomerTasks\AddLink\LinkRecommendationSubmissionLogFactory; |
7 | use GrowthExperiments\NewcomerTasks\AddSectionImage\SectionImageRecommendationSubmissionLogFactory; |
8 | use GrowthExperiments\NewcomerTasks\CampaignConfig; |
9 | use GrowthExperiments\NewcomerTasks\ConfigurationLoader\ConfigurationLoader; |
10 | use GrowthExperiments\NewcomerTasks\Task\TaskSet; |
11 | use GrowthExperiments\NewcomerTasks\Task\TaskSetFilters; |
12 | use GrowthExperiments\NewcomerTasks\TaskType\ImageRecommendationTaskType; |
13 | use GrowthExperiments\NewcomerTasks\TaskType\ImageRecommendationTaskTypeHandler; |
14 | use GrowthExperiments\NewcomerTasks\TaskType\LinkRecommendationTaskType; |
15 | use GrowthExperiments\NewcomerTasks\TaskType\LinkRecommendationTaskTypeHandler; |
16 | use GrowthExperiments\NewcomerTasks\TaskType\SectionImageRecommendationTaskType; |
17 | use GrowthExperiments\NewcomerTasks\TaskType\SectionImageRecommendationTaskTypeHandler; |
18 | use MediaWiki\User\UserIdentity; |
19 | |
20 | /** |
21 | * A TaskSuggester decorator that injects data for task type "quality gates" into a TaskSet. |
22 | * |
23 | */ |
24 | class QualityGateDecorator implements TaskSuggester { |
25 | |
26 | /** @var TaskSuggester */ |
27 | private $taskSuggester; |
28 | |
29 | /** @var ImageRecommendationSubmissionLogFactory */ |
30 | private $imageRecommendationSubmissionLogFactory; |
31 | |
32 | /** @var LinkRecommendationSubmissionLogFactory */ |
33 | private $linkRecommendationSubmissionLogFactory; |
34 | |
35 | /** @var ConfigurationLoader */ |
36 | private $configurationLoader; |
37 | |
38 | /** @var int */ |
39 | private $imageRecommendationCountForUser; |
40 | |
41 | /** @var int */ |
42 | private $linkRecommendationCountForUser; |
43 | |
44 | private SectionImageRecommendationSubmissionLogFactory $sectionImageRecommendationSubmissionLogFactory; |
45 | private ?int $sectionImageRecommendationCountForUser = null; |
46 | |
47 | /** @var CampaignConfig */ |
48 | private $campaignConfig; |
49 | |
50 | /** |
51 | * @param TaskSuggester $taskSuggester |
52 | * @param ConfigurationLoader $configurationLoader |
53 | * @param ImageRecommendationSubmissionLogFactory $imageRecommendationSubmissionLogFactory |
54 | * @param SectionImageRecommendationSubmissionLogFactory $sectionImageRecommendationSubmissionLogFactory |
55 | * @param LinkRecommendationSubmissionLogFactory $linkRecommendationSubmissionLogFactory |
56 | * @param CampaignConfig $campaignConfig |
57 | */ |
58 | public function __construct( |
59 | TaskSuggester $taskSuggester, |
60 | ConfigurationLoader $configurationLoader, |
61 | ImageRecommendationSubmissionLogFactory $imageRecommendationSubmissionLogFactory, |
62 | SectionImageRecommendationSubmissionLogFactory $sectionImageRecommendationSubmissionLogFactory, |
63 | LinkRecommendationSubmissionLogFactory $linkRecommendationSubmissionLogFactory, |
64 | CampaignConfig $campaignConfig |
65 | ) { |
66 | $this->taskSuggester = $taskSuggester; |
67 | $this->imageRecommendationSubmissionLogFactory = $imageRecommendationSubmissionLogFactory; |
68 | $this->sectionImageRecommendationSubmissionLogFactory = $sectionImageRecommendationSubmissionLogFactory; |
69 | $this->configurationLoader = $configurationLoader; |
70 | $this->linkRecommendationSubmissionLogFactory = $linkRecommendationSubmissionLogFactory; |
71 | $this->campaignConfig = $campaignConfig; |
72 | } |
73 | |
74 | /** @inheritDoc */ |
75 | public function suggest( |
76 | UserIdentity $user, |
77 | TaskSetFilters $taskSetFilters, |
78 | ?int $limit = null, |
79 | ?int $offset = null, |
80 | array $options = [] |
81 | ) { |
82 | $tasks = $this->taskSuggester->suggest( $user, $taskSetFilters, $limit, $offset, $options ); |
83 | // TODO: Split out QualityGates methods into separate classes per task type. |
84 | if ( $tasks instanceof TaskSet ) { |
85 | $imageRecommendationTaskType = |
86 | $this->configurationLoader->getTaskTypes()[ImageRecommendationTaskTypeHandler::TASK_TYPE_ID] ?? null; |
87 | if ( $imageRecommendationTaskType instanceof ImageRecommendationTaskType ) { |
88 | $tasks->setQualityGateConfigForTaskType( ImageRecommendationTaskTypeHandler::TASK_TYPE_ID, [ |
89 | 'dailyLimit' => $this->isImageRecommendationDailyTaskLimitExceeded( |
90 | $user, |
91 | $imageRecommendationTaskType |
92 | ), |
93 | 'dailyCount' => $this->getImageRecommendationTasksDoneByUserForCurrentDay( $user ), |
94 | ] ); |
95 | } |
96 | $sectionImageRecommendationTaskType = |
97 | $this->configurationLoader->getTaskTypes()[SectionImageRecommendationTaskTypeHandler::TASK_TYPE_ID] |
98 | ?? null; |
99 | if ( $sectionImageRecommendationTaskType instanceof SectionImageRecommendationTaskType ) { |
100 | $tasks->setQualityGateConfigForTaskType( SectionImageRecommendationTaskTypeHandler::TASK_TYPE_ID, [ |
101 | 'dailyLimit' => $this->isSectionImageRecommendationDailyTaskLimitExceeded( |
102 | $user, |
103 | $sectionImageRecommendationTaskType |
104 | ), |
105 | 'dailyCount' => $this->getSectionImageRecommendationTasksDoneByUserForCurrentDay( $user ), |
106 | ] ); |
107 | } |
108 | |
109 | $linkRecommendationTaskType = |
110 | $this->configurationLoader->getTaskTypes()[LinkRecommendationTaskTypeHandler::TASK_TYPE_ID] ?? null; |
111 | if ( $linkRecommendationTaskType instanceof LinkRecommendationTaskType ) { |
112 | $tasks->setQualityGateConfigForTaskType( LinkRecommendationTaskTypeHandler::TASK_TYPE_ID, |
113 | [ |
114 | 'dailyLimit' => $this->isLinkRecommendationDailyTaskLimitExceeded( |
115 | $user, |
116 | $linkRecommendationTaskType |
117 | ), |
118 | 'dailyCount' => $this->getLinkRecommendationTasksDoneByUserForCurrentDay( $user ) |
119 | ] ); |
120 | } |
121 | } |
122 | return $tasks; |
123 | } |
124 | |
125 | /** @inheritDoc */ |
126 | public function filter( UserIdentity $user, TaskSet $taskSet ) { |
127 | return $this->taskSuggester->filter( $user, $taskSet ); |
128 | } |
129 | |
130 | /** |
131 | * Check if daily limit of image recommendation is exceeded for a user. |
132 | * |
133 | * TODO: Move this into a image-recommendation specific class. |
134 | * |
135 | * @param UserIdentity $user |
136 | * @param ImageRecommendationTaskType $imageRecommendationTaskType |
137 | * @return bool|null |
138 | */ |
139 | private function isImageRecommendationDailyTaskLimitExceeded( |
140 | UserIdentity $user, |
141 | ImageRecommendationTaskType $imageRecommendationTaskType |
142 | ): ?bool { |
143 | if ( $this->campaignConfig->shouldSkipImageRecommendationDailyTaskLimitForUser( $user ) ) { |
144 | return false; |
145 | } |
146 | return $this->getImageRecommendationTasksDoneByUserForCurrentDay( $user ) |
147 | >= $imageRecommendationTaskType->getMaxTasksPerDay(); |
148 | } |
149 | |
150 | /** |
151 | * @param UserIdentity $user |
152 | * @return int |
153 | */ |
154 | private function getImageRecommendationTasksDoneByUserForCurrentDay( |
155 | UserIdentity $user |
156 | ): int { |
157 | if ( $this->imageRecommendationCountForUser ) { |
158 | return $this->imageRecommendationCountForUser; |
159 | } |
160 | $imageRecommendationSubmissionLog = |
161 | $this->imageRecommendationSubmissionLogFactory |
162 | ->newImageRecommendationSubmissionLog( $user ); |
163 | $this->imageRecommendationCountForUser = $imageRecommendationSubmissionLog->count(); |
164 | return $this->imageRecommendationCountForUser; |
165 | } |
166 | |
167 | /** |
168 | * Check if daily limit of link recommendation is exceeded for a user. |
169 | * |
170 | * TODO: Move this into a link-recommendation specific class. |
171 | * |
172 | * @param UserIdentity $user |
173 | * @param LinkRecommendationTaskType $linkRecommendationTaskType |
174 | * @return bool|null |
175 | */ |
176 | private function isLinkRecommendationDailyTaskLimitExceeded( |
177 | UserIdentity $user, |
178 | LinkRecommendationTaskType $linkRecommendationTaskType |
179 | ): ?bool { |
180 | return $this->getLinkRecommendationTasksDoneByUserForCurrentDay( $user ) |
181 | >= $linkRecommendationTaskType->getMaxTasksPerDay(); |
182 | } |
183 | |
184 | /** |
185 | * @param UserIdentity $user |
186 | * @return int |
187 | */ |
188 | private function getLinkRecommendationTasksDoneByUserForCurrentDay( |
189 | UserIdentity $user |
190 | ): int { |
191 | if ( $this->linkRecommendationCountForUser ) { |
192 | return $this->linkRecommendationCountForUser; |
193 | } |
194 | $linkRecommendationSubmissionLog = |
195 | $this->linkRecommendationSubmissionLogFactory |
196 | ->newLinkRecommendationSubmissionLog( $user ); |
197 | $this->linkRecommendationCountForUser = $linkRecommendationSubmissionLog->count(); |
198 | return $this->linkRecommendationCountForUser; |
199 | } |
200 | |
201 | /** |
202 | * Check if daily limit of section image recommendation is exceeded for a user. |
203 | * |
204 | * TODO: Move this into a section-image-recommendation specific class. |
205 | * |
206 | * @param UserIdentity $user |
207 | * @param SectionImageRecommendationTaskType $sectionImageRecommendationTaskType |
208 | * @return bool|null |
209 | */ |
210 | private function isSectionImageRecommendationDailyTaskLimitExceeded( |
211 | UserIdentity $user, |
212 | SectionImageRecommendationTaskType $sectionImageRecommendationTaskType |
213 | ): ?bool { |
214 | return $this->getSectionImageRecommendationTasksDoneByUserForCurrentDay( $user ) |
215 | >= $sectionImageRecommendationTaskType->getMaxTasksPerDay(); |
216 | } |
217 | |
218 | /** |
219 | * @param UserIdentity $user |
220 | * @return int |
221 | */ |
222 | private function getSectionImageRecommendationTasksDoneByUserForCurrentDay( |
223 | UserIdentity $user |
224 | ): int { |
225 | if ( $this->sectionImageRecommendationCountForUser ) { |
226 | return $this->sectionImageRecommendationCountForUser; |
227 | } |
228 | $sectionImageRecommendationSubmissionLog = |
229 | $this->sectionImageRecommendationSubmissionLogFactory |
230 | ->newSectionImageRecommendationSubmissionLog( $user ); |
231 | $this->sectionImageRecommendationCountForUser = $sectionImageRecommendationSubmissionLog->count(); |
232 | return $this->sectionImageRecommendationCountForUser; |
233 | } |
234 | |
235 | } |