Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
50.00% |
13 / 26 |
|
20.00% |
1 / 5 |
CRAP | |
0.00% |
0 / 1 |
ExperimentUserManager | |
50.00% |
13 / 26 |
|
20.00% |
1 / 5 |
13.12 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
2 | |||
getVariant | |
100.00% |
13 / 13 |
|
100.00% |
1 / 1 |
3 | |||
setVariant | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
2 | |||
isUserInVariant | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
isValidVariant | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | |
3 | namespace GrowthExperiments; |
4 | |
5 | use MediaWiki\Config\ServiceOptions; |
6 | use MediaWiki\User\Options\UserOptionsLookup; |
7 | use MediaWiki\User\Options\UserOptionsManager; |
8 | use MediaWiki\User\UserFactory; |
9 | use MediaWiki\User\UserIdentity; |
10 | use Psr\Log\LoggerInterface; |
11 | |
12 | /** |
13 | * Service for handling experiment / variant related functions for users. |
14 | */ |
15 | class ExperimentUserManager { |
16 | |
17 | private LoggerInterface $logger; |
18 | private ServiceOptions $options; |
19 | private UserOptionsLookup $userOptionsLookup; |
20 | private UserOptionsManager $userOptionsManager; |
21 | private UserFactory $userFactory; |
22 | |
23 | public const CONSTRUCTOR_OPTIONS = [ |
24 | 'GEHomepageDefaultVariant', |
25 | ]; |
26 | |
27 | /** |
28 | * @param LoggerInterface $logger |
29 | * @param ServiceOptions $options |
30 | * @param UserOptionsManager $userOptionsManager |
31 | * @param UserOptionsLookup $userOptionsLookup |
32 | * @param UserFactory $userFactory |
33 | */ |
34 | public function __construct( |
35 | LoggerInterface $logger, |
36 | ServiceOptions $options, |
37 | UserOptionsManager $userOptionsManager, |
38 | UserOptionsLookup $userOptionsLookup, |
39 | UserFactory $userFactory |
40 | ) { |
41 | $options->assertRequiredOptions( self::CONSTRUCTOR_OPTIONS ); |
42 | $this->logger = $logger; |
43 | $this->options = $options; |
44 | $this->userOptionsLookup = $userOptionsLookup; |
45 | $this->userOptionsManager = $userOptionsManager; |
46 | $this->userFactory = $userFactory; |
47 | } |
48 | |
49 | /** |
50 | * @param UserIdentity $user |
51 | * @return string |
52 | */ |
53 | public function getVariant( UserIdentity $user ): string { |
54 | if ( !$this->userFactory->newFromUserIdentity( $user )->isNamed() ) { |
55 | $this->logger->debug( __METHOD__ . ' suspicious evaluation of unamed user', [ |
56 | 'exception' => new \RuntimeException, |
57 | 'userName' => $user->getName(), |
58 | 'trace' => \debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS ) |
59 | ] ); |
60 | } |
61 | $variant = $this->userOptionsLookup->getOption( |
62 | $user, |
63 | VariantHooks::USER_PREFERENCE |
64 | ); |
65 | if ( !in_array( $variant, VariantHooks::VARIANTS ) ) { |
66 | $variant = $this->options->get( 'GEHomepageDefaultVariant' ); |
67 | } |
68 | return $variant; |
69 | } |
70 | |
71 | /** |
72 | * Set (but does not save) the variant for a user. |
73 | * |
74 | * @param UserIdentity $user |
75 | * @param string $variant |
76 | */ |
77 | public function setVariant( UserIdentity $user, string $variant ): void { |
78 | $this->userOptionsManager->setOption( |
79 | $user, |
80 | VariantHooks::USER_PREFERENCE, |
81 | $variant |
82 | ); |
83 | } |
84 | |
85 | /** |
86 | * @param UserIdentity $user |
87 | * @param string|string[] $variant |
88 | * @return bool |
89 | */ |
90 | public function isUserInVariant( UserIdentity $user, $variant ): bool { |
91 | return in_array( $this->getVariant( $user ), (array)$variant ); |
92 | } |
93 | |
94 | /** |
95 | * @param string $variant |
96 | * @return bool |
97 | */ |
98 | public function isValidVariant( string $variant ): bool { |
99 | return in_array( $variant, VariantHooks::VARIANTS ); |
100 | } |
101 | } |