Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
100.00% |
40 / 40 |
|
100.00% |
5 / 5 |
CRAP | |
100.00% |
1 / 1 |
SettingsFormValidator | |
100.00% |
40 / 40 |
|
100.00% |
5 / 5 |
18 | |
100.00% |
1 / 1 |
__construct | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
validateAnonBot | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
3 | |||
validateAnonMinor | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
3 | |||
validateSitesChosen | |
100.00% |
26 / 26 |
|
100.00% |
1 / 1 |
9 | |||
requireShowingOneType | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 |
1 | <?php |
2 | |
3 | /** |
4 | * Implements validation for HTMLForm at Special:GlobalWatchlistSettings |
5 | * |
6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by |
8 | * the Free Software Foundation; either version 2 of the License, or |
9 | * (at your option) any later version. |
10 | * |
11 | * This program is distributed in the hope that it will be useful, |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | * GNU General Public License for more details. |
15 | * |
16 | * You should have received a copy of the GNU General Public License along |
17 | * with this program; if not, write to the Free Software Foundation, Inc., |
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
19 | * http://www.gnu.org/copyleft/gpl.html |
20 | * |
21 | * @file |
22 | */ |
23 | |
24 | namespace MediaWiki\Extension\GlobalWatchlist; |
25 | |
26 | use Message; |
27 | use MessageLocalizer; |
28 | |
29 | /** |
30 | * @author DannyS712 |
31 | * @internal |
32 | */ |
33 | class SettingsFormValidator { |
34 | |
35 | /** |
36 | * For formatting the relevant errors |
37 | * |
38 | * @var MessageLocalizer |
39 | */ |
40 | private $messageLocalizer; |
41 | |
42 | /** |
43 | * Reference to $wgGlobalWatchlistSiteLimit, limiting the number of sites a user can include |
44 | * |
45 | * @var int |
46 | */ |
47 | private $maxSites; |
48 | |
49 | /** |
50 | * Array of url forms of sites the user has attached accounts on (from CentralAuth), |
51 | * to check against, or null if CentralAuth is not available |
52 | * |
53 | * @var string[]|null |
54 | */ |
55 | private $validSites; |
56 | |
57 | /** |
58 | * @param MessageLocalizer $messageLocalizer |
59 | * @param int $maxSites |
60 | * @param string[]|null $validSites |
61 | */ |
62 | public function __construct( |
63 | MessageLocalizer $messageLocalizer, |
64 | int $maxSites, |
65 | ?array $validSites |
66 | ) { |
67 | $this->messageLocalizer = $messageLocalizer; |
68 | $this->maxSites = $maxSites; |
69 | $this->validSites = $validSites; |
70 | } |
71 | |
72 | /** |
73 | * Validation callback called from HTMLRadioField::validate. |
74 | * |
75 | * Ensure that user doesn't try to filter for anonymous bot edits |
76 | * |
77 | * @see HTMLRadioField::validate |
78 | * |
79 | * @param string $value for the specific field (bot edit filter) |
80 | * @param array $allData values for all of the form fields |
81 | * @return bool|string|Message True on success, or string/Message error to display, or |
82 | * false to fail validation without displaying an error. |
83 | */ |
84 | public function validateAnonBot( $value, $allData ) { |
85 | if ( (int)$value === SettingsManager::FILTER_REQUIRE && |
86 | (int)$allData['anon'] === SettingsManager::FILTER_REQUIRE |
87 | ) { |
88 | return $this->messageLocalizer->msg( 'globalwatchlist-settings-error-anon-bot' ); |
89 | } |
90 | return true; |
91 | } |
92 | |
93 | /** |
94 | * Validation callback called from HTMLRadioField::validate. |
95 | * |
96 | * Ensure that user doesn't try to filter for anonymous minor edits |
97 | * |
98 | * @see HTMLRadioField::validate |
99 | * |
100 | * @param string $value for the specific field (minor edit filter) |
101 | * @param array $allData values for all of the form fields |
102 | * @return bool|string|Message True on success, or string/Message error to display, or |
103 | * false to fail validation without displaying an error. |
104 | */ |
105 | public function validateAnonMinor( $value, $allData ) { |
106 | if ( (int)$value === SettingsManager::FILTER_REQUIRE && |
107 | (int)$allData['anon'] === SettingsManager::FILTER_REQUIRE |
108 | ) { |
109 | return $this->messageLocalizer->msg( 'globalwatchlist-settings-error-anon-minor' ); |
110 | } |
111 | return true; |
112 | } |
113 | |
114 | /** |
115 | * Validation callback called from HTMLFormFieldCloner::validate. |
116 | * |
117 | * Ensure that at least one site is chosen, that no site is chosen multiple times, and that |
118 | * the maximum number of sites is not exceeded. |
119 | * |
120 | * @see HTMLFormFieldCloner::validate |
121 | * |
122 | * @param array $value for the specific field (the cloned site fields) |
123 | * should always be a multidimensional array since this is for an HTMLFormFieldCloner field |
124 | * @param array $allData values for all of the form fields |
125 | * @return bool|string|Message True on success, or string/Message error to display, or |
126 | * false to fail validation without displaying an error. |
127 | */ |
128 | public function validateSitesChosen( $value, $allData ) { |
129 | $sitesChosen = []; |
130 | foreach ( $value as $row ) { |
131 | $site = trim( $row['site'] ?? '' ); |
132 | // Since there isn't an easy way to reorder sites other than just deleting |
133 | // the rows and adding them to the bottom manually, sometimes a field might |
134 | // be blank - thats okay, skip it |
135 | if ( $site === '' ) { |
136 | continue; |
137 | } |
138 | |
139 | // Accept and handle sites with a protocol, see T262762 |
140 | // normalize before checking for duplicates and invalid sites |
141 | $site = preg_replace( '/^(?:https?:)?\/\//', '', $site ); |
142 | |
143 | // Avoid duplicate sites, T273532 |
144 | if ( isset( $sitesChosen[$site] ) ) { |
145 | return $this->messageLocalizer |
146 | ->msg( 'globalwatchlist-settings-error-duplicate-site' ) |
147 | ->params( $site ); |
148 | } |
149 | |
150 | // Validate against CentralAuth, if available, T268210 |
151 | if ( $this->validSites !== null && |
152 | !in_array( $site, $this->validSites ) |
153 | ) { |
154 | return $this->messageLocalizer |
155 | ->msg( 'globalwatchlist-settings-error-invalid-site' ) |
156 | ->params( $site ); |
157 | } |
158 | |
159 | $sitesChosen[$site] = true; |
160 | } |
161 | |
162 | $siteCount = count( $sitesChosen ); |
163 | if ( $siteCount === 0 ) { |
164 | return $this->messageLocalizer->msg( |
165 | 'globalwatchlist-settings-error-no-sites' |
166 | ); |
167 | } |
168 | |
169 | if ( $this->maxSites && $siteCount > $this->maxSites ) { |
170 | return $this->messageLocalizer |
171 | ->msg( 'globalwatchlist-settings-error-too-many-sites' ) |
172 | ->numParams( $siteCount, $this->maxSites ); |
173 | } |
174 | |
175 | return true; |
176 | } |
177 | |
178 | /** |
179 | * Validation callback called from HTMLMultiSelectField::validate. |
180 | * |
181 | * Ensure that at least one type of change is shown |
182 | * |
183 | * @see HTMLMultiSelectField::validate |
184 | * |
185 | * @param array $value for the specific field (the checkboxes) |
186 | * @param array $allData values for all of the form fields |
187 | * @return bool|string|Message True on success, or string/Message error to display, or |
188 | * false to fail validation without displaying an error. |
189 | */ |
190 | public function requireShowingOneType( $value, $allData ) { |
191 | if ( $value === [] ) { |
192 | return $this->messageLocalizer->msg( 'globalwatchlist-settings-error-no-types' ); |
193 | } |
194 | return true; |
195 | } |
196 | |
197 | } |