Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
4.72% |
5 / 106 |
|
16.67% |
1 / 6 |
CRAP | |
0.00% |
0 / 1 |
AbuseFilterView | |
4.72% |
5 / 106 |
|
16.67% |
1 / 6 |
267.00 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
1 | |||
getTitle | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
show | n/a |
0 / 0 |
n/a |
0 / 0 |
0 | |||||
buildFilterLoader | |
0.00% |
0 / 28 |
|
0.00% |
0 / 1 |
2 | |||
buildTestConditions | |
0.00% |
0 / 60 |
|
0.00% |
0 / 1 |
90 | |||
buildVisibilityConditions | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
20 | |||
getLinkToLatestDiff | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | |
3 | namespace MediaWiki\Extension\AbuseFilter\View; |
4 | |
5 | use ContextSource; |
6 | use Flow\Data\Listener\RecentChangesListener; |
7 | use IContextSource; |
8 | use MediaWiki\Extension\AbuseFilter\AbuseFilterPermissionManager; |
9 | use MediaWiki\Linker\LinkRenderer; |
10 | use MediaWiki\Permissions\Authority; |
11 | use MediaWiki\Revision\RevisionRecord; |
12 | use MediaWiki\SpecialPage\SpecialPage; |
13 | use MediaWiki\Title\Title; |
14 | use OOUI; |
15 | use RecentChange; |
16 | use UnexpectedValueException; |
17 | use Wikimedia\Rdbms\Platform\ISQLPlatform; |
18 | use Xml; |
19 | |
20 | abstract class AbuseFilterView extends ContextSource { |
21 | |
22 | /** |
23 | * @var AbuseFilterPermissionManager |
24 | */ |
25 | protected $afPermManager; |
26 | |
27 | /** |
28 | * @var array The parameters of the current request |
29 | */ |
30 | protected $mParams; |
31 | |
32 | /** |
33 | * @var LinkRenderer |
34 | */ |
35 | protected $linkRenderer; |
36 | |
37 | /** @var string */ |
38 | protected $basePageName; |
39 | |
40 | /** |
41 | * @param AbuseFilterPermissionManager $afPermManager |
42 | * @param IContextSource $context |
43 | * @param LinkRenderer $linkRenderer |
44 | * @param string $basePageName |
45 | * @param array $params |
46 | */ |
47 | public function __construct( |
48 | AbuseFilterPermissionManager $afPermManager, |
49 | IContextSource $context, |
50 | LinkRenderer $linkRenderer, |
51 | string $basePageName, |
52 | array $params |
53 | ) { |
54 | $this->mParams = $params; |
55 | $this->setContext( $context ); |
56 | $this->linkRenderer = $linkRenderer; |
57 | $this->basePageName = $basePageName; |
58 | $this->afPermManager = $afPermManager; |
59 | } |
60 | |
61 | /** |
62 | * @param string|int $subpage |
63 | * @return Title |
64 | */ |
65 | public function getTitle( $subpage = '' ) { |
66 | return SpecialPage::getTitleFor( $this->basePageName, $subpage ); |
67 | } |
68 | |
69 | /** |
70 | * Function to show the page |
71 | */ |
72 | abstract public function show(); |
73 | |
74 | /** |
75 | * Build input and button for loading a filter |
76 | * |
77 | * @return string |
78 | */ |
79 | public function buildFilterLoader() { |
80 | $loadText = |
81 | new OOUI\TextInputWidget( |
82 | [ |
83 | 'type' => 'number', |
84 | 'name' => 'wpInsertFilter', |
85 | 'id' => 'mw-abusefilter-load-filter' |
86 | ] |
87 | ); |
88 | $loadButton = |
89 | new OOUI\ButtonWidget( |
90 | [ |
91 | 'label' => $this->msg( 'abusefilter-test-load' )->text(), |
92 | 'id' => 'mw-abusefilter-load' |
93 | ] |
94 | ); |
95 | $loadGroup = |
96 | new OOUI\ActionFieldLayout( |
97 | $loadText, |
98 | $loadButton, |
99 | [ |
100 | 'label' => $this->msg( 'abusefilter-test-load-filter' )->text() |
101 | ] |
102 | ); |
103 | // CSS class for reducing default input field width |
104 | return Xml::tags( |
105 | 'div', |
106 | [ 'class' => 'mw-abusefilter-load-filter-id' ], |
107 | $loadGroup |
108 | ); |
109 | } |
110 | |
111 | /** |
112 | * @param ISQLPlatform $db |
113 | * @param string|false $action 'edit', 'move', 'createaccount', 'delete' or false for all |
114 | * @return string |
115 | */ |
116 | public function buildTestConditions( ISQLPlatform $db, $action = false ) { |
117 | $editSources = [ |
118 | RecentChange::SRC_EDIT, |
119 | RecentChange::SRC_NEW, |
120 | ]; |
121 | if ( in_array( 'flow', $this->getConfig()->get( 'AbuseFilterValidGroups' ), true ) ) { |
122 | // TODO Should this be separated somehow? Also, this case should be handled via a hook, not |
123 | // by special-casing Flow here. |
124 | // @phan-suppress-next-line PhanUndeclaredClassConstant Temporary solution |
125 | $editSources[] = RecentChangesListener::SRC_FLOW; |
126 | } |
127 | // If one of these is true, we're abusefilter compatible. |
128 | switch ( $action ) { |
129 | case 'edit': |
130 | return $db->makeList( [ |
131 | // Actually, this is only one condition, but this way we get it as string |
132 | 'rc_source' => $editSources |
133 | ], LIST_AND ); |
134 | case 'move': |
135 | return $db->makeList( [ |
136 | 'rc_source' => RecentChange::SRC_LOG, |
137 | 'rc_log_type' => 'move', |
138 | 'rc_log_action' => 'move' |
139 | ], LIST_AND ); |
140 | case 'createaccount': |
141 | return $db->makeList( [ |
142 | 'rc_source' => RecentChange::SRC_LOG, |
143 | 'rc_log_type' => 'newusers', |
144 | 'rc_log_action' => [ 'create', 'autocreate' ] |
145 | ], LIST_AND ); |
146 | case 'delete': |
147 | return $db->makeList( [ |
148 | 'rc_source' => RecentChange::SRC_LOG, |
149 | 'rc_log_type' => 'delete', |
150 | 'rc_log_action' => 'delete' |
151 | ], LIST_AND ); |
152 | case 'upload': |
153 | return $db->makeList( [ |
154 | 'rc_source' => RecentChange::SRC_LOG, |
155 | 'rc_log_type' => 'upload', |
156 | 'rc_log_action' => [ 'upload', 'overwrite', 'revert' ] |
157 | ], LIST_AND ); |
158 | case false: |
159 | // Done later |
160 | break; |
161 | default: |
162 | throw new UnexpectedValueException( __METHOD__ . ' called with invalid action: ' . $action ); |
163 | } |
164 | |
165 | return $db->makeList( [ |
166 | 'rc_source' => $editSources, |
167 | $db->makeList( [ |
168 | 'rc_source' => RecentChange::SRC_LOG, |
169 | $db->makeList( [ |
170 | $db->makeList( [ |
171 | 'rc_log_type' => 'move', |
172 | 'rc_log_action' => 'move' |
173 | ], LIST_AND ), |
174 | $db->makeList( [ |
175 | 'rc_log_type' => 'newusers', |
176 | 'rc_log_action' => [ 'create', 'autocreate' ] |
177 | ], LIST_AND ), |
178 | $db->makeList( [ |
179 | 'rc_log_type' => 'delete', |
180 | 'rc_log_action' => 'delete' |
181 | ], LIST_AND ), |
182 | $db->makeList( [ |
183 | 'rc_log_type' => 'upload', |
184 | 'rc_log_action' => [ 'upload', 'overwrite', 'revert' ] |
185 | ], LIST_AND ), |
186 | ], LIST_OR ), |
187 | ], LIST_AND ), |
188 | ], LIST_OR ); |
189 | } |
190 | |
191 | /** |
192 | * @todo Core should provide a method for this (T233222) |
193 | * @param ISQLPlatform $db |
194 | * @param Authority $authority |
195 | * @return array |
196 | */ |
197 | public function buildVisibilityConditions( ISQLPlatform $db, Authority $authority ): array { |
198 | if ( !$authority->isAllowed( 'deletedhistory' ) ) { |
199 | $bitmask = RevisionRecord::DELETED_USER; |
200 | } elseif ( !$authority->isAllowedAny( 'suppressrevision', 'viewsuppressed' ) ) { |
201 | $bitmask = RevisionRecord::DELETED_USER | RevisionRecord::DELETED_RESTRICTED; |
202 | } else { |
203 | $bitmask = 0; |
204 | } |
205 | return $bitmask |
206 | ? [ $db->bitAnd( 'rc_deleted', $bitmask ) . " != $bitmask" ] |
207 | : []; |
208 | } |
209 | |
210 | /** |
211 | * @param string|int $id |
212 | * @param string|null $text |
213 | * @return string HTML |
214 | */ |
215 | public function getLinkToLatestDiff( $id, $text = null ) { |
216 | return $this->linkRenderer->makeKnownLink( |
217 | $this->getTitle( "history/$id/diff/prev/cur" ), |
218 | $text |
219 | ); |
220 | } |
221 | |
222 | } |