Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
65.67% |
44 / 67 |
|
60.00% |
3 / 5 |
CRAP | |
0.00% |
0 / 1 |
SpecialAbuseFilter | |
65.67% |
44 / 67 |
|
60.00% |
3 / 5 |
59.72 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
doesWrites | n/a |
0 / 0 |
n/a |
0 / 0 |
1 | |||||
getGroupName | n/a |
0 / 0 |
n/a |
0 / 0 |
1 | |||||
execute | |
0.00% |
0 / 22 |
|
0.00% |
0 / 1 |
6 | |||
instantiateView | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
1 | |||
getViewClassAndPageType | |
100.00% |
37 / 37 |
|
100.00% |
1 / 1 |
21 | |||
getTitleForSubpage | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | |
3 | namespace MediaWiki\Extension\AbuseFilter\Special; |
4 | |
5 | use Html; |
6 | use MediaWiki\Extension\AbuseFilter\AbuseFilterPermissionManager; |
7 | use MediaWiki\Extension\AbuseFilter\CentralDBManager; |
8 | use MediaWiki\Extension\AbuseFilter\Consequences\ConsequencesFactory; |
9 | use MediaWiki\Extension\AbuseFilter\Consequences\ConsequencesRegistry; |
10 | use MediaWiki\Extension\AbuseFilter\EditBox\EditBoxBuilderFactory; |
11 | use MediaWiki\Extension\AbuseFilter\FilterImporter; |
12 | use MediaWiki\Extension\AbuseFilter\FilterLookup; |
13 | use MediaWiki\Extension\AbuseFilter\FilterProfiler; |
14 | use MediaWiki\Extension\AbuseFilter\FilterStore; |
15 | use MediaWiki\Extension\AbuseFilter\Parser\RuleCheckerFactory; |
16 | use MediaWiki\Extension\AbuseFilter\SpecsFormatter; |
17 | use MediaWiki\Extension\AbuseFilter\VariableGenerator\VariableGeneratorFactory; |
18 | use MediaWiki\Extension\AbuseFilter\Variables\VariablesBlobStore; |
19 | use MediaWiki\Extension\AbuseFilter\Variables\VariablesFormatter; |
20 | use MediaWiki\Extension\AbuseFilter\Variables\VariablesManager; |
21 | use MediaWiki\Extension\AbuseFilter\View\AbuseFilterView; |
22 | use MediaWiki\Extension\AbuseFilter\View\AbuseFilterViewDiff; |
23 | use MediaWiki\Extension\AbuseFilter\View\AbuseFilterViewEdit; |
24 | use MediaWiki\Extension\AbuseFilter\View\AbuseFilterViewExamine; |
25 | use MediaWiki\Extension\AbuseFilter\View\AbuseFilterViewHistory; |
26 | use MediaWiki\Extension\AbuseFilter\View\AbuseFilterViewImport; |
27 | use MediaWiki\Extension\AbuseFilter\View\AbuseFilterViewList; |
28 | use MediaWiki\Extension\AbuseFilter\View\AbuseFilterViewRevert; |
29 | use MediaWiki\Extension\AbuseFilter\View\AbuseFilterViewTestBatch; |
30 | use MediaWiki\Extension\AbuseFilter\View\AbuseFilterViewTools; |
31 | use MediaWiki\Title\Title; |
32 | use Wikimedia\ObjectFactory\ObjectFactory; |
33 | |
34 | class SpecialAbuseFilter extends AbuseFilterSpecialPage { |
35 | |
36 | private const PAGE_NAME = 'AbuseFilter'; |
37 | |
38 | /** |
39 | * @var ObjectFactory |
40 | */ |
41 | private $objectFactory; |
42 | |
43 | private const SERVICES_PER_VIEW = [ |
44 | AbuseFilterViewDiff::class => [ |
45 | AbuseFilterPermissionManager::SERVICE_NAME, |
46 | SpecsFormatter::SERVICE_NAME, |
47 | FilterLookup::SERVICE_NAME, |
48 | ], |
49 | AbuseFilterViewEdit::class => [ |
50 | 'DBLoadBalancerFactory', |
51 | 'PermissionManager', |
52 | AbuseFilterPermissionManager::SERVICE_NAME, |
53 | FilterProfiler::SERVICE_NAME, |
54 | FilterLookup::SERVICE_NAME, |
55 | FilterImporter::SERVICE_NAME, |
56 | FilterStore::SERVICE_NAME, |
57 | EditBoxBuilderFactory::SERVICE_NAME, |
58 | ConsequencesRegistry::SERVICE_NAME, |
59 | SpecsFormatter::SERVICE_NAME, |
60 | ], |
61 | AbuseFilterViewExamine::class => [ |
62 | 'DBLoadBalancerFactory', |
63 | AbuseFilterPermissionManager::SERVICE_NAME, |
64 | FilterLookup::SERVICE_NAME, |
65 | EditBoxBuilderFactory::SERVICE_NAME, |
66 | VariablesBlobStore::SERVICE_NAME, |
67 | VariablesFormatter::SERVICE_NAME, |
68 | VariablesManager::SERVICE_NAME, |
69 | VariableGeneratorFactory::SERVICE_NAME, |
70 | ], |
71 | AbuseFilterViewHistory::class => [ |
72 | 'UserNameUtils', |
73 | 'LinkBatchFactory', |
74 | AbuseFilterPermissionManager::SERVICE_NAME, |
75 | FilterLookup::SERVICE_NAME, |
76 | SpecsFormatter::SERVICE_NAME, |
77 | ], |
78 | AbuseFilterViewImport::class => [ |
79 | AbuseFilterPermissionManager::SERVICE_NAME, |
80 | ], |
81 | AbuseFilterViewList::class => [ |
82 | 'LinkBatchFactory', |
83 | AbuseFilterPermissionManager::SERVICE_NAME, |
84 | FilterProfiler::SERVICE_NAME, |
85 | SpecsFormatter::SERVICE_NAME, |
86 | CentralDBManager::SERVICE_NAME, |
87 | ], |
88 | AbuseFilterViewRevert::class => [ |
89 | 'DBLoadBalancerFactory', |
90 | 'UserFactory', |
91 | AbuseFilterPermissionManager::SERVICE_NAME, |
92 | FilterLookup::SERVICE_NAME, |
93 | ConsequencesFactory::SERVICE_NAME, |
94 | VariablesBlobStore::SERVICE_NAME, |
95 | SpecsFormatter::SERVICE_NAME, |
96 | ], |
97 | AbuseFilterViewTestBatch::class => [ |
98 | 'DBLoadBalancerFactory', |
99 | AbuseFilterPermissionManager::SERVICE_NAME, |
100 | EditBoxBuilderFactory::SERVICE_NAME, |
101 | RuleCheckerFactory::SERVICE_NAME, |
102 | VariableGeneratorFactory::SERVICE_NAME, |
103 | ], |
104 | AbuseFilterViewTools::class => [ |
105 | AbuseFilterPermissionManager::SERVICE_NAME, |
106 | EditBoxBuilderFactory::SERVICE_NAME, |
107 | ], |
108 | ]; |
109 | |
110 | /** |
111 | * @param AbuseFilterPermissionManager $afPermissionManager |
112 | * @param ObjectFactory $objectFactory |
113 | */ |
114 | public function __construct( |
115 | AbuseFilterPermissionManager $afPermissionManager, |
116 | ObjectFactory $objectFactory |
117 | ) { |
118 | parent::__construct( self::PAGE_NAME, 'abusefilter-view', $afPermissionManager ); |
119 | $this->objectFactory = $objectFactory; |
120 | } |
121 | |
122 | /** |
123 | * @codeCoverageIgnore Merely declarative |
124 | * @inheritDoc |
125 | */ |
126 | public function doesWrites() { |
127 | return true; |
128 | } |
129 | |
130 | /** |
131 | * @codeCoverageIgnore Merely declarative |
132 | * @inheritDoc |
133 | */ |
134 | protected function getGroupName() { |
135 | return 'wiki'; |
136 | } |
137 | |
138 | /** |
139 | * @param string|null $subpage |
140 | */ |
141 | public function execute( $subpage ) { |
142 | $out = $this->getOutput(); |
143 | $request = $this->getRequest(); |
144 | |
145 | $out->addModuleStyles( 'ext.abuseFilter' ); |
146 | |
147 | $this->setHeaders(); |
148 | $this->addHelpLink( 'Extension:AbuseFilter' ); |
149 | |
150 | $this->checkPermissions(); |
151 | |
152 | if ( $request->getVal( 'result' ) === 'success' ) { |
153 | $out->setSubtitle( $this->msg( 'abusefilter-edit-done-subtitle' ) ); |
154 | $changedFilter = intval( $request->getVal( 'changedfilter' ) ); |
155 | $changeId = intval( $request->getVal( 'changeid' ) ); |
156 | $out->addHTML( Html::successBox( |
157 | $this->msg( |
158 | 'abusefilter-edit-done', |
159 | $changedFilter, |
160 | $changeId, |
161 | $this->getLanguage()->formatNum( $changedFilter ) |
162 | )->parse() |
163 | ) ); |
164 | } |
165 | |
166 | [ $view, $pageType, $params ] = $this->getViewClassAndPageType( $subpage ); |
167 | |
168 | // Links at the top |
169 | $this->addNavigationLinks( $pageType ); |
170 | |
171 | $view = $this->instantiateView( $view, $params ); |
172 | $view->show(); |
173 | } |
174 | |
175 | /** |
176 | * Instantiate the view class |
177 | * |
178 | * @suppress PhanTypeInvalidCallableArraySize |
179 | * |
180 | * @param class-string<AbuseFilterView> $viewClass |
181 | * @param array $params |
182 | * @return AbuseFilterView |
183 | */ |
184 | public function instantiateView( string $viewClass, array $params ): AbuseFilterView { |
185 | return $this->objectFactory->createObject( [ |
186 | 'class' => $viewClass, |
187 | 'services' => self::SERVICES_PER_VIEW[$viewClass], |
188 | 'args' => [ $this->getContext(), $this->getLinkRenderer(), self::PAGE_NAME, $params ] |
189 | ] ); |
190 | } |
191 | |
192 | /** |
193 | * Determine the view class to instantiate |
194 | * |
195 | * @param string|null $subpage |
196 | * @return array A tuple of three elements: |
197 | * - a subclass of AbuseFilterView |
198 | * - type of page for addNavigationLinks |
199 | * - array of parameters for the class |
200 | * @phan-return array{0:class-string,1:string,2:array} |
201 | */ |
202 | public function getViewClassAndPageType( $subpage ): array { |
203 | // Filter by removing blanks. |
204 | $params = array_values( array_filter( |
205 | explode( '/', $subpage ?: '' ), |
206 | static function ( $value ) { |
207 | return $value !== ''; |
208 | } |
209 | ) ); |
210 | |
211 | if ( $subpage === 'tools' ) { |
212 | return [ AbuseFilterViewTools::class, 'tools', [] ]; |
213 | } |
214 | |
215 | if ( $subpage === 'import' ) { |
216 | return [ AbuseFilterViewImport::class, 'import', [] ]; |
217 | } |
218 | |
219 | if ( is_numeric( $subpage ) || $subpage === 'new' ) { |
220 | return [ |
221 | AbuseFilterViewEdit::class, |
222 | 'edit', |
223 | [ 'filter' => is_numeric( $subpage ) ? (int)$subpage : null ] |
224 | ]; |
225 | } |
226 | |
227 | if ( $params ) { |
228 | if ( count( $params ) === 2 && $params[0] === 'revert' && is_numeric( $params[1] ) ) { |
229 | $params[1] = (int)$params[1]; |
230 | return [ AbuseFilterViewRevert::class, 'revert', $params ]; |
231 | } |
232 | |
233 | if ( $params[0] === 'test' ) { |
234 | return [ AbuseFilterViewTestBatch::class, 'test', $params ]; |
235 | } |
236 | |
237 | if ( $params[0] === 'examine' ) { |
238 | return [ AbuseFilterViewExamine::class, 'examine', $params ]; |
239 | } |
240 | |
241 | if ( $params[0] === 'history' || $params[0] === 'log' ) { |
242 | if ( count( $params ) <= 2 ) { |
243 | $params = isset( $params[1] ) ? [ 'filter' => (int)$params[1] ] : []; |
244 | return [ AbuseFilterViewHistory::class, 'recentchanges', $params ]; |
245 | } |
246 | if ( count( $params ) === 4 && $params[2] === 'item' ) { |
247 | return [ |
248 | AbuseFilterViewEdit::class, |
249 | '', |
250 | [ 'filter' => (int)$params[1], 'history' => (int)$params[3] ] |
251 | ]; |
252 | } |
253 | if ( count( $params ) === 5 && $params[2] === 'diff' ) { |
254 | // Special:AbuseFilter/history/<filter>/diff/<oldid>/<newid> |
255 | return [ AbuseFilterViewDiff::class, '', $params ]; |
256 | } |
257 | } |
258 | } |
259 | |
260 | return [ AbuseFilterViewList::class, 'home', [] ]; |
261 | } |
262 | |
263 | /** |
264 | * Static variant to get the associated Title. |
265 | * |
266 | * @param string|int $subpage |
267 | * @return Title |
268 | */ |
269 | public static function getTitleForSubpage( $subpage ): Title { |
270 | return self::getTitleFor( self::PAGE_NAME, $subpage ); |
271 | } |
272 | } |