Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
56.17% |
91 / 162 |
|
0.00% |
0 / 4 |
CRAP | |
0.00% |
0 / 1 |
HomepageModuleRegistry | |
56.17% |
91 / 162 |
|
0.00% |
0 / 4 |
24.12 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
get | |
75.00% |
6 / 8 |
|
0.00% |
0 / 1 |
4.25 | |||
getModuleIds | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getWiring | |
55.92% |
85 / 152 |
|
0.00% |
0 / 1 |
9.08 |
1 | <?php |
2 | |
3 | namespace GrowthExperiments\Homepage; |
4 | |
5 | use ExtensionRegistry; |
6 | use GrowthExperiments\DashboardModule\IDashboardModule; |
7 | use GrowthExperiments\GrowthExperimentsServices; |
8 | use GrowthExperiments\HomepageModules\Banner; |
9 | use GrowthExperiments\HomepageModules\Help; |
10 | use GrowthExperiments\HomepageModules\Impact; |
11 | use GrowthExperiments\HomepageModules\Mentorship; |
12 | use GrowthExperiments\HomepageModules\MentorshipOptIn; |
13 | use GrowthExperiments\HomepageModules\NewImpact; |
14 | use GrowthExperiments\HomepageModules\StartEditing; |
15 | use GrowthExperiments\HomepageModules\StartEmail; |
16 | use GrowthExperiments\HomepageModules\SuggestedEdits; |
17 | use GrowthExperiments\HomepageModules\WelcomeSurveyReminder; |
18 | use GrowthExperiments\VariantHooks; |
19 | use IContextSource; |
20 | use MediaWiki\MediaWikiServices; |
21 | use OutOfBoundsException; |
22 | |
23 | /** |
24 | * Container class for handling dependency injection of homepage modules. |
25 | */ |
26 | class HomepageModuleRegistry { |
27 | |
28 | /** @var MediaWikiServices */ |
29 | private $services; |
30 | |
31 | /** @var callable[] id => factory method */ |
32 | private $wiring; |
33 | |
34 | /** @var IDashboardModule[] id => module */ |
35 | private $modules = []; |
36 | |
37 | /** |
38 | * @param MediaWikiServices $services |
39 | */ |
40 | public function __construct( MediaWikiServices $services ) { |
41 | $this->services = $services; |
42 | } |
43 | |
44 | /** |
45 | * @param string $id |
46 | * @param IContextSource $contextSource |
47 | * @return IDashboardModule |
48 | */ |
49 | public function get( string $id, IContextSource $contextSource ): IDashboardModule { |
50 | if ( $this->modules[$id] ?? null ) { |
51 | return $this->modules[$id]; |
52 | } |
53 | if ( $this->wiring === null ) { |
54 | $this->wiring = self::getWiring(); |
55 | } |
56 | if ( !array_key_exists( $id, $this->wiring ) ) { |
57 | throw new OutOfBoundsException( 'Module not found: ' . $id ); |
58 | } |
59 | $this->modules[$id] = $this->wiring[$id]( $this->services, $contextSource ); |
60 | return $this->modules[$id]; |
61 | } |
62 | |
63 | /** |
64 | * @internal for testing only |
65 | * @return string[] |
66 | */ |
67 | public static function getModuleIds(): array { |
68 | return array_keys( self::getWiring() ); |
69 | } |
70 | |
71 | /** |
72 | * Returns wiring callbacks for each module. |
73 | * The callback receives the service container and the request context, |
74 | * and must return a homepage module. |
75 | * @return callable[] module id => callback |
76 | */ |
77 | private static function getWiring() { |
78 | return [ |
79 | 'banner' => static function ( |
80 | MediaWikiServices $services, |
81 | IContextSource $context |
82 | ) { |
83 | $growthServices = GrowthExperimentsServices::wrap( $services ); |
84 | return new Banner( |
85 | $context, |
86 | $growthServices->getGrowthWikiConfig(), |
87 | $growthServices->getExperimentUserManager() |
88 | ); |
89 | }, |
90 | |
91 | 'welcomesurveyreminder' => static function ( |
92 | MediaWikiServices $services, |
93 | IContextSource $context |
94 | ) { |
95 | $growthServices = GrowthExperimentsServices::wrap( $services ); |
96 | return new WelcomeSurveyReminder( |
97 | $context, |
98 | $growthServices->getGrowthWikiConfig(), |
99 | $growthServices->getExperimentUserManager(), |
100 | $services->getSpecialPageFactory(), |
101 | $growthServices->getWelcomeSurveyFactory() |
102 | ); |
103 | }, |
104 | |
105 | 'startemail' => static function ( |
106 | MediaWikiServices $services, |
107 | IContextSource $context |
108 | ) { |
109 | $growthServices = GrowthExperimentsServices::wrap( $services ); |
110 | return new StartEmail( |
111 | $context, |
112 | $growthServices->getGrowthWikiConfig(), |
113 | $growthServices->getExperimentUserManager() |
114 | ); |
115 | }, |
116 | |
117 | 'suggested-edits' => static function ( |
118 | MediaWikiServices $services, |
119 | IContextSource $context |
120 | ) { |
121 | $growthServices = GrowthExperimentsServices::wrap( $services ); |
122 | $pageViewInfoEnabled = ExtensionRegistry::getInstance()->isLoaded( 'PageViewInfo' ); |
123 | return new SuggestedEdits( |
124 | $context, |
125 | $growthServices->getGrowthWikiConfig(), |
126 | $growthServices->getGrowthExperimentsCampaignConfig(), |
127 | $growthServices->getEditInfoService(), |
128 | $growthServices->getExperimentUserManager(), |
129 | $pageViewInfoEnabled ? $services->get( 'PageViewService' ) : null, |
130 | $growthServices->getNewcomerTasksConfigurationLoader(), |
131 | $growthServices->getNewcomerTasksUserOptionsLookup(), |
132 | $growthServices->getTaskSuggesterFactory()->create(), |
133 | $services->getTitleFactory(), |
134 | $growthServices->getProtectionFilter(), |
135 | $services->getUserOptionsLookup(), |
136 | $growthServices->getLinkRecommendationFilter(), |
137 | $growthServices->getImageRecommendationFilter() |
138 | ); |
139 | }, |
140 | |
141 | 'impact' => static function ( |
142 | MediaWikiServices $services, |
143 | IContextSource $context |
144 | ) { |
145 | $growthServices = GrowthExperimentsServices::wrap( $services ); |
146 | $experimentUserManager = $growthServices->getExperimentUserManager(); |
147 | $userOptionsLookup = $services->getUserOptionsLookup(); |
148 | $config = $context->getConfig(); |
149 | |
150 | // A/B test: use new impact module if explicitly requested, |
151 | // or the feature flag is on and user is in the test group. |
152 | if ( $context->getRequest()->getRawVal( 'new-impact' ) !== null ) { |
153 | $useNewImpactModule = $context->getRequest()->getBool( 'new-impact' ); |
154 | } else { |
155 | $useNewImpactModule = $config->get( 'GEUseNewImpactModule' ) |
156 | && !$experimentUserManager->isUserInVariant( |
157 | $context->getUser(), VariantHooks::VARIANT_OLDIMPACT |
158 | ); |
159 | } |
160 | |
161 | if ( $useNewImpactModule ) { |
162 | return new NewImpact( |
163 | $context, |
164 | $growthServices->getGrowthWikiConfig(), |
165 | $growthServices->getExperimentUserManager(), |
166 | $context->getUser(), |
167 | $growthServices->getUserImpactStore(), |
168 | $growthServices->getUserImpactFormatter(), |
169 | $growthServices->getUserDatabaseHelper(), |
170 | SuggestedEdits::isEnabled( $context->getConfig() ), |
171 | SuggestedEdits::isActivated( $context->getUser(), $userOptionsLookup ) |
172 | ); |
173 | } |
174 | $pageViewInfoEnabled = ExtensionRegistry::getInstance()->isLoaded( 'PageViewInfo' ); |
175 | return new Impact( |
176 | $context, |
177 | $growthServices->getGrowthWikiConfig(), |
178 | $services->getDBLoadBalancerFactory(), |
179 | $growthServices->getExperimentUserManager(), |
180 | [ |
181 | 'isSuggestedEditsEnabled' => SuggestedEdits::isEnabled( $context->getConfig() ), |
182 | 'isSuggestedEditsActivated' => SuggestedEdits::isActivated( |
183 | $context->getUser(), |
184 | $userOptionsLookup |
185 | ), |
186 | ], |
187 | $services->getTitleFactory(), |
188 | $pageViewInfoEnabled ? $services->get( 'PageViewService' ) : null |
189 | ); |
190 | }, |
191 | |
192 | 'mentorship' => static function ( |
193 | MediaWikiServices $services, |
194 | IContextSource $context |
195 | ) { |
196 | $growthServices = GrowthExperimentsServices::wrap( $services ); |
197 | return new Mentorship( |
198 | $context, |
199 | $growthServices->getGrowthWikiConfig(), |
200 | $growthServices->getExperimentUserManager(), |
201 | $growthServices->getMentorManager(), |
202 | $growthServices->getMentorStatusManager(), |
203 | $services->getGenderCache() |
204 | ); |
205 | }, |
206 | |
207 | 'mentorship-optin' => static function ( |
208 | MediaWikiServices $services, |
209 | IContextSource $context |
210 | ) { |
211 | $growthServices = GrowthExperimentsServices::wrap( $services ); |
212 | return new MentorshipOptIn( |
213 | $context, |
214 | $growthServices->getGrowthWikiConfig(), |
215 | $growthServices->getExperimentUserManager(), |
216 | $growthServices->getMentorManager() |
217 | ); |
218 | }, |
219 | |
220 | 'help' => static function ( |
221 | MediaWikiServices $services, |
222 | IContextSource $context |
223 | ) { |
224 | $growthServices = GrowthExperimentsServices::wrap( $services ); |
225 | return new Help( |
226 | $context, |
227 | $growthServices->getGrowthWikiConfig(), |
228 | $growthServices->getExperimentUserManager() |
229 | ); |
230 | }, |
231 | |
232 | 'start-startediting' => static function ( |
233 | MediaWikiServices $services, |
234 | IContextSource $context |
235 | ) { |
236 | $growthServices = GrowthExperimentsServices::wrap( $services ); |
237 | return new StartEditing( |
238 | $context, |
239 | $growthServices->getGrowthWikiConfig(), |
240 | $growthServices->getExperimentUserManager(), |
241 | $services->getUserOptionsLookup() |
242 | ); |
243 | } |
244 | |
245 | ]; |
246 | } |
247 | |
248 | } |