Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
88.24% |
60 / 68 |
|
50.00% |
8 / 16 |
CRAP | |
0.00% |
0 / 1 |
RealTempUserConfig | |
88.24% |
60 / 68 |
|
50.00% |
8 / 16 |
46.01 | |
0.00% |
0 / 1 |
__construct | |
95.00% |
19 / 20 |
|
0.00% |
0 / 1 |
9 | |||
isEnabled | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
isKnown | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
isAutoCreateAction | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
3 | |||
shouldAutoCreate | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
3 | |||
isTempName | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
4 | |||
isReservedName | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
3 | |||
getPlaceholderName | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
3 | |||
getMatchPattern | |
75.00% |
3 / 4 |
|
0.00% |
0 / 1 |
2.06 | |||
getMatchPatterns | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
getMatchCondition | |
91.67% |
11 / 12 |
|
0.00% |
0 / 1 |
6.02 | |||
getExpireAfterDays | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getNotifyBeforeExpirationDays | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getGeneratorPattern | |
66.67% |
2 / 3 |
|
0.00% |
0 / 1 |
2.15 | |||
getSerialProviderConfig | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getSerialMappingConfig | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | |
3 | namespace MediaWiki\User\TempUser; |
4 | |
5 | use BadMethodCallException; |
6 | use InvalidArgumentException; |
7 | use MediaWiki\Permissions\Authority; |
8 | use MediaWiki\Utils\MWTimestamp; |
9 | use Wikimedia\Rdbms\IExpression; |
10 | use Wikimedia\Rdbms\IReadableDatabase; |
11 | |
12 | /** |
13 | * The real TempUserConfig including internal methods used by TempUserCreator. |
14 | * |
15 | * @since 1.39 |
16 | */ |
17 | class RealTempUserConfig implements TempUserConfig { |
18 | /** @var bool */ |
19 | private $known = false; |
20 | |
21 | /** @var bool */ |
22 | private $enabled = false; |
23 | |
24 | /** @var array */ |
25 | private $serialProviderConfig = []; |
26 | |
27 | /** @var array */ |
28 | private $serialMappingConfig = []; |
29 | |
30 | /** @var string[] */ |
31 | private $autoCreateActions; |
32 | |
33 | /** @var Pattern|null */ |
34 | private $genPattern; |
35 | |
36 | /** @var Pattern[]|null */ |
37 | private $matchPatterns; |
38 | |
39 | /** @var Pattern|null */ |
40 | private $reservedPattern; |
41 | |
42 | /** @var int|null */ |
43 | private $expireAfterDays; |
44 | |
45 | /** @var int|null */ |
46 | private $notifyBeforeExpirationDays; |
47 | |
48 | /** |
49 | * @param array $config See the documentation of $wgAutoCreateTempUser. |
50 | * - known: bool |
51 | * - enabled: bool |
52 | * - actions: array |
53 | * - genPattern: string |
54 | * - matchPattern: string|string[], optional |
55 | * - reservedPattern: string, optional |
56 | * - serialProvider: array |
57 | * - serialMapping: array |
58 | * - expireAfterDays: int, optional |
59 | * - notifyBeforeExpirationDays: int, optional |
60 | */ |
61 | public function __construct( $config ) { |
62 | $this->enabled = $config['enabled'] ?? false; |
63 | $this->known = $this->enabled || ( $config['known'] ?? false ); |
64 | |
65 | // Configuration related to creating new temporary accounts for some actions |
66 | if ( $this->enabled ) { |
67 | $this->autoCreateActions = $config['actions']; |
68 | $this->serialProviderConfig = $config['serialProvider']; |
69 | $this->serialMappingConfig = $config['serialMapping']; |
70 | } |
71 | |
72 | // Configuration related to managing and identifying existing temporary accounts, |
73 | // regardless of whether new temp accounts are being actively created via the |
74 | // 'enabled' config flag. |
75 | if ( $this->known || $this->enabled ) { |
76 | $this->genPattern = new Pattern( 'genPattern', $config['genPattern'] ); |
77 | $this->expireAfterDays = $config['expireAfterDays'] ?? null; |
78 | $this->notifyBeforeExpirationDays = $config['notifyBeforeExpirationDays'] ?? null; |
79 | if ( isset( $config['matchPattern'] ) ) { |
80 | $matchPatterns = $config['matchPattern']; |
81 | if ( !is_array( $config['matchPattern'] ) ) { |
82 | $matchPatterns = [ $matchPatterns ]; |
83 | } |
84 | foreach ( $matchPatterns as &$pattern ) { |
85 | $pattern = new Pattern( 'matchPattern', $pattern ); |
86 | } |
87 | $this->matchPatterns = $matchPatterns; |
88 | } else { |
89 | $this->matchPatterns = [ $this->genPattern ]; |
90 | } |
91 | } |
92 | |
93 | // Configuration that is set regardless of whether the feature is enabled or known. |
94 | if ( isset( $config['reservedPattern'] ) ) { |
95 | $this->reservedPattern = new Pattern( 'reservedPattern', $config['reservedPattern'] ); |
96 | } |
97 | } |
98 | |
99 | public function isEnabled() { |
100 | return $this->enabled; |
101 | } |
102 | |
103 | public function isKnown() { |
104 | return $this->known; |
105 | } |
106 | |
107 | public function isAutoCreateAction( string $action ) { |
108 | if ( $action === 'create' ) { |
109 | $action = 'edit'; |
110 | } |
111 | return $this->isEnabled() |
112 | && in_array( $action, $this->autoCreateActions, true ); |
113 | } |
114 | |
115 | public function shouldAutoCreate( Authority $authority, string $action ) { |
116 | return $this->isAutoCreateAction( $action ) |
117 | && !$authority->isRegistered() |
118 | && $authority->isAllowed( 'createaccount' ); |
119 | } |
120 | |
121 | public function isTempName( string $name ) { |
122 | if ( !$this->isKnown() ) { |
123 | return false; |
124 | } |
125 | foreach ( $this->matchPatterns as $pattern ) { |
126 | if ( $pattern->isMatch( $name ) ) { |
127 | return true; |
128 | } |
129 | } |
130 | return false; |
131 | } |
132 | |
133 | public function isReservedName( string $name ) { |
134 | return $this->isTempName( $name ) || ( $this->reservedPattern && $this->reservedPattern->isMatch( $name ) ); |
135 | } |
136 | |
137 | public function getPlaceholderName(): string { |
138 | $year = null; |
139 | if ( $this->serialProviderConfig['useYear'] ?? false ) { |
140 | $year = MWTimestamp::getInstance()->format( 'Y' ); |
141 | } |
142 | if ( $this->isEnabled() ) { |
143 | return $this->genPattern->generate( '*', $year ); |
144 | } else { |
145 | throw new BadMethodCallException( __METHOD__ . ' is disabled' ); |
146 | } |
147 | } |
148 | |
149 | /** |
150 | * @deprecated since 1.42. |
151 | */ |
152 | public function getMatchPattern(): Pattern { |
153 | wfDeprecated( __METHOD__, '1.42' ); |
154 | if ( $this->isKnown() ) { |
155 | // This method is deprecated to allow time for callers to update. |
156 | // This method only returns one Pattern, so just return the first one. |
157 | return $this->getMatchPatterns()[0]; |
158 | } else { |
159 | throw new BadMethodCallException( __METHOD__ . ' is disabled' ); |
160 | } |
161 | } |
162 | |
163 | public function getMatchPatterns(): array { |
164 | if ( $this->isKnown() ) { |
165 | return $this->matchPatterns; |
166 | } else { |
167 | throw new BadMethodCallException( __METHOD__ . ' is disabled' ); |
168 | } |
169 | } |
170 | |
171 | public function getMatchCondition( IReadableDatabase $db, string $field, string $op ): IExpression { |
172 | if ( $this->isKnown() ) { |
173 | $exprs = []; |
174 | foreach ( $this->getMatchPatterns() as $pattern ) { |
175 | $exprs[] = $db->expr( $field, $op, $pattern->toLikeValue( $db ) ); |
176 | } |
177 | if ( count( $exprs ) === 1 ) { |
178 | return $exprs[0]; |
179 | } |
180 | if ( $op === IExpression::LIKE ) { |
181 | return $db->orExpr( $exprs ); |
182 | } elseif ( $op === IExpression::NOT_LIKE ) { |
183 | return $db->andExpr( $exprs ); |
184 | } else { |
185 | throw new InvalidArgumentException( "Invalid operator $op" ); |
186 | } |
187 | } else { |
188 | throw new BadMethodCallException( __METHOD__ . ' is disabled' ); |
189 | } |
190 | } |
191 | |
192 | public function getExpireAfterDays(): ?int { |
193 | return $this->expireAfterDays; |
194 | } |
195 | |
196 | public function getNotifyBeforeExpirationDays(): ?int { |
197 | return $this->notifyBeforeExpirationDays; |
198 | } |
199 | |
200 | /** |
201 | * @internal For TempUserCreator only |
202 | * @return Pattern |
203 | */ |
204 | public function getGeneratorPattern(): Pattern { |
205 | if ( $this->isEnabled() ) { |
206 | return $this->genPattern; |
207 | } else { |
208 | throw new BadMethodCallException( __METHOD__ . ' is disabled' ); |
209 | } |
210 | } |
211 | |
212 | /** |
213 | * @internal For TempUserCreator only |
214 | * @return array |
215 | */ |
216 | public function getSerialProviderConfig(): array { |
217 | return $this->serialProviderConfig; |
218 | } |
219 | |
220 | /** |
221 | * @internal For TempUserCreator only |
222 | * @return array |
223 | */ |
224 | public function getSerialMappingConfig(): array { |
225 | return $this->serialMappingConfig; |
226 | } |
227 | } |