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