Index: branches/change-tagging/extensions/AbuseFilter/edit.js |
— | — | @@ -1,61 +0,0 @@ |
2 | | -function doSyntaxCheck() |
3 | | -{ |
4 | | - var filter = document.getElementById('wpFilterRules').value; |
5 | | - injectSpinner( document.getElementById( 'mw-abusefilter-syntaxcheck' ), 'abusefilter-syntaxcheck' ); |
6 | | - sajax_do_call( 'AbuseFilter::ajaxCheckSyntax', [filter], processSyntaxResult ); |
7 | | -} |
8 | | -function processSyntaxResult( request ) { |
9 | | - var response = request.responseText; |
10 | | - |
11 | | - removeSpinner( 'abusefilter-syntaxcheck' ); |
12 | | - |
13 | | - var el = document.getElementById( 'mw-abusefilter-syntaxresult' ); |
14 | | - el.style.display = 'block'; |
15 | | - |
16 | | - if (response.match( /OK/ )) { |
17 | | - // Successful |
18 | | - changeText( el, 'No syntax errors.' ); |
19 | | - el.syntaxOk = true; |
20 | | - } else { |
21 | | - var error = response.substr(4); |
22 | | - changeText( el, 'Syntax error: '+error ); |
23 | | - el.syntaxOk = false; |
24 | | - } |
25 | | -} |
26 | | -function addText() { |
27 | | - if (document.getElementById('wpFilterBuilder').selectedIndex == 0) { |
28 | | - return; |
29 | | - } |
30 | | - |
31 | | - insertAtCursor(document.getElementById('wpFilterRules'), document.getElementById('wpFilterBuilder').value + " "); |
32 | | - document.getElementById('wpFilterBuilder').selectedIndex = 0; |
33 | | -} |
34 | | - |
35 | | -//From http://clipmarks.com/clipmark/CEFC94CB-94D6-4495-A7AA-791B7355E284/ |
36 | | -function insertAtCursor(myField, myValue) { |
37 | | - //IE support |
38 | | - if (document.selection) { |
39 | | - myField.focus(); |
40 | | - sel = document.selection.createRange(); |
41 | | - sel.text = myValue; |
42 | | - } |
43 | | - //MOZILLA/NETSCAPE support |
44 | | - else if (myField.selectionStart || myField.selectionStart == '0') { |
45 | | - var startPos = myField.selectionStart; |
46 | | - var endPos = myField.selectionEnd; |
47 | | - myField.value = myField.value.substring(0, startPos) |
48 | | - + myValue |
49 | | - + myField.value.substring(endPos, myField.value.length); |
50 | | - } else { |
51 | | - myField.value += myValue; |
52 | | - } |
53 | | -} |
54 | | - |
55 | | -addOnloadHook( function() { |
56 | | - addHandler( document.getElementById( 'wpFilterRules' ), 'keyup', function() { |
57 | | - el = document.getElementById( 'mw-abusefilter-syntaxresult' ); |
58 | | - if (el.syntaxOk == true) { |
59 | | - el.style.display = 'none'; |
60 | | - } |
61 | | - } ); |
62 | | -} ); |
\ No newline at end of file |
Index: branches/change-tagging/extensions/AbuseFilter/AbuseFilter.class.php |
— | — | @@ -73,7 +73,7 @@ |
74 | 74 | } |
75 | 75 | } |
76 | 76 | |
77 | | - // Find last 5 authors, for testing. |
| 77 | + // Find last 5 authors. |
78 | 78 | $dbr = wfGetDB( DB_SLAVE ); |
79 | 79 | $res = $dbr->select( 'revision', 'distinct rev_user_text', array('rev_page' => $title->getArticleId() ), __METHOD__, array( 'order by' => 'rev_timestamp desc', 'limit' => 10 ) ); |
80 | 80 | $users = array(); |
Index: branches/change-tagging/extensions/AbuseFilter/AbuseFilter.php |
— | — | @@ -33,6 +33,12 @@ |
34 | 34 | $wgAutoloadClasses['SpecialAbuseLog'] = "$dir/SpecialAbuseLog.php"; |
35 | 35 | $wgAutoloadClasses['SpecialAbuseFilter'] = "$dir/SpecialAbuseFilter.php"; |
36 | 36 | |
| 37 | +$wgAutoloadClasses['AbuseFilterViewList'] = "$dir/Views/AbuseFilterViewList.php"; |
| 38 | +$wgAutoloadClasses['AbuseFilterView'] = "$dir/Views/AbuseFilterView.php"; |
| 39 | +$wgAutoloadClasses['AbuseFilterViewEdit'] = "$dir/Views/AbuseFilterViewEdit.php"; |
| 40 | +$wgAutoloadClasses['AbuseFilterViewTools'] = "$dir/Views/AbuseFilterViewTools.php"; |
| 41 | +$wgAutoloadClasses['AbuseFilterViewHistory'] = "$dir/Views/AbuseFilterViewHistory.php"; |
| 42 | + |
37 | 43 | $wgSpecialPages['AbuseLog'] = 'SpecialAbuseLog'; |
38 | 44 | $wgSpecialPages['AbuseFilter'] = 'SpecialAbuseFilter'; |
39 | 45 | |
Index: branches/change-tagging/extensions/AbuseFilter/SpecialAbuseFilter.php |
— | — | @@ -5,8 +5,6 @@ |
6 | 6 | class SpecialAbuseFilter extends SpecialPage { |
7 | 7 | |
8 | 8 | var $mSkin; |
9 | | - |
10 | | - static $history_mappings = array( 'af_pattern' => 'afh_pattern', 'af_user' => 'afh_user', 'af_user_text' => 'afh_user_text', 'af_timestamp' => 'afh_timestamp', 'af_comments' => 'afh_comments', 'af_public_comments' => 'afh_public_comments', 'af_deleted' => 'afh_deleted', 'af_id' => 'afh_filter' ); |
11 | 9 | |
12 | 10 | function __construct() { |
13 | 11 | wfLoadExtensionMessages('AbuseFilter'); |
— | — | @@ -17,6 +15,7 @@ |
18 | 16 | global $wgUser,$wgOut,$wgRequest, $wgAbuseFilterStyleVersion, $wgScriptPath; |
19 | 17 | |
20 | 18 | $wgOut->addExtensionStyle( "{$wgScriptPath}/extensions/AbuseFilter/abusefilter.css?{$wgAbuseFilterStyleVersion}" ); |
| 19 | + $view = 'AbuseFilterViewList'; |
21 | 20 | |
22 | 21 | $this->setHeaders(); |
23 | 22 | |
— | — | @@ -28,7 +27,6 @@ |
29 | 28 | |
30 | 29 | // Are we allowed? |
31 | 30 | if ( !$wgUser->isAllowed( 'abusefilter-view' ) ) { |
32 | | - // Go away. |
33 | 31 | $this->displayRestrictionError(); |
34 | 32 | return; |
35 | 33 | } |
— | — | @@ -39,13 +37,12 @@ |
40 | 38 | } |
41 | 39 | |
42 | 40 | $this->mSkin = $wgUser->getSkin(); |
| 41 | + $this->mHistoryID = null; |
43 | 42 | |
44 | 43 | $params = array_filter( explode( '/', $subpage ) ); |
45 | 44 | |
46 | 45 | if ($subpage == 'tools') { |
47 | | - // Some useful tools |
48 | | - $this->doTools(); |
49 | | - return; |
| 46 | + $view = 'AbuseFilterViewTools'; |
50 | 47 | } |
51 | 48 | |
52 | 49 | if (!empty($params[0]) && $params[0] == 'history') { |
— | — | @@ -53,572 +50,24 @@ |
54 | 51 | // ... useless? |
55 | 52 | } elseif (count($params) == 2) { |
56 | 53 | ## Second param is a filter ID |
57 | | - $this->showHistory($params[1]); |
58 | | - return; |
| 54 | + $view = 'AbuseFilterViewHistory'; |
| 55 | + $this->mFilter = $params[1]; |
59 | 56 | } elseif (count($params) == 4 && $params[2] == 'item') { |
60 | | - $wgOut->addWikiMsg( 'abusefilter-edit-oldwarning', $params[3], $params[1] ); |
61 | | - $out = $this->buildFilterEditor( null, $params[1], $params[3] ); |
62 | | - $wgOut->addHTML( $out ); |
63 | | - $wgOut->addWikiMsg( 'abusefilter-edit-oldwarning', $params[3], $params[1] ); |
64 | | - return; |
| 57 | + $this->mFilter = $params[1]; |
| 58 | + $this->mHistoryID = $params[3]; |
| 59 | + $view = 'AbuseFilterViewEdit'; |
65 | 60 | } |
66 | 61 | } |
67 | 62 | |
68 | | - if ($output = $this->doEdit()) { |
69 | | - $wgOut->addHTML( $output ); |
70 | | - return; |
| 63 | + if ( is_numeric($subpage) || $subpage == 'new' ) { |
| 64 | + $this->mFilter = $subpage; |
| 65 | + $view = 'AbuseFilterViewEdit'; |
71 | 66 | } |
72 | | - |
73 | | - // Show list of filters. |
74 | | - $this->showStatus(); |
75 | | - |
76 | | - // Quick links |
77 | | - $wgOut->addWikiMsg( 'abusefilter-links' ); |
78 | | - $lists = array( 'tools' ); |
79 | | - if ($this->canEdit()) |
80 | | - $lists[] = 'new'; |
81 | | - $links = ''; |
82 | | - $sk = $wgUser->getSkin(); |
83 | | - foreach( $lists as $list ) { |
84 | | - $title = $this->getTitle( $list ); |
85 | | - |
86 | | - $link = $sk->link( $title, wfMsg( "abusefilter-$list" ) ); |
87 | | - $links .= Xml::tags( 'li', null, $link ) . "\n"; |
88 | | - } |
89 | | - $links .= Xml::tags( 'li', null, $sk->link( SpecialPage::getTitleFor( 'AbuseLog' ), wfMsg( 'abusefilter-loglink' ) ) ); |
90 | | - $links = Xml::tags( 'ul', null, $links ); |
91 | | - $wgOut->addHTML( $links ); |
92 | | - |
93 | | - // Options. |
94 | | - $conds = array(); |
95 | | - $deleted = $wgRequest->getVal( 'deletedfilters' ); |
96 | | - $hidedisabled = $wgRequest->getBool( 'hidedisabled' ); |
97 | | - if ($deleted == 'show') { |
98 | | - ## Nothing |
99 | | - } elseif ($deleted == 'only') { |
100 | | - $conds['af_deleted'] = 1; |
101 | | - } else { ## hide, or anything else. |
102 | | - $conds['af_deleted'] = 0; |
103 | | - $deleted = 'hide'; |
104 | | - } |
105 | | - if ($hidedisabled) { |
106 | | - $conds['af_deleted'] = 0; |
107 | | - $conds['af_enabled'] = 1; |
108 | | - } |
109 | | - |
110 | | - $this->showList( $conds, compact( 'deleted', 'hidedisabled' ) ); |
111 | | - } |
112 | | - |
113 | | - function showDeleted() { |
114 | | - $this->showList( array( 'af_deleted' => 1 ) ); |
115 | | - } |
116 | | - |
117 | | - function showActive() { |
118 | | - $this->showList( array( 'af_deleted' => 0, 'af_enabled' => 1 ) ); |
119 | | - } |
120 | | - |
121 | | - function showHistory( $filter ) { |
122 | | - global $wgRequest,$wgOut; |
123 | | - |
124 | | - global $wgUser; |
125 | | - $sk = $wgUser->getSkin(); |
126 | | - $wgOut->setPageTitle( wfMsg( 'abusefilter-history', $filter ) ); |
127 | | - $backToFilter_label = wfMsgExt( 'abusefilter-history-backedit', array('parseinline') ); |
128 | | - $backToList_label = wfMsgExt( 'abusefilter-history-backlist', array('parseinline') ); |
129 | | - $backlinks = $sk->makeKnownLinkObj( $this->getTitle( $filter ), $backToFilter_label ) . ' • ' . |
130 | | - $sk->makeKnownLinkObj( $this->getTitle( ), $backToList_label ); |
131 | | - $wgOut->addHTML( Xml::tags( 'p', null, $backlinks ) ); |
132 | | - |
133 | | - $pager = new AbuseFilterHistoryPager( $filter, $this ); |
134 | | - $table = $pager->getBody(); |
135 | | - |
136 | | - $wgOut->addHTML( $pager->getNavigationBar() . $table . $pager->getNavigationBar() ); |
137 | | - |
138 | | - return true; |
139 | | - } |
140 | | - |
141 | | - function doTools() { |
142 | | - global $wgRequest,$wgOut; |
143 | | - |
144 | | - // Header |
145 | | - $wgOut->setSubTitle( wfMsg( 'abusefilter-tools-subtitle' ) ); |
146 | | - $wgOut->addWikiMsg( 'abusefilter-tools-text' ); |
147 | 67 | |
148 | | - // Expression evaluator |
149 | | - $eval = ''; |
150 | | - $eval .= Xml::textarea( 'wpTestExpr', "" ); |
151 | | - $eval .= Xml::tags( 'p', null, Xml::element( 'input', array( 'type' => 'button', 'id' => 'mw-abusefilter-submitexpr', 'onclick' => 'doExprSubmit();', 'value' => wfMsg( 'abusefilter-tools-submitexpr' ) ) ) ); |
152 | | - $eval .= Xml::element( 'p', array( 'id' => 'mw-abusefilter-expr-result' ), ' ' ); |
153 | | - $eval = Xml::fieldset( wfMsg( 'abusefilter-tools-expr' ), $eval ); |
154 | | - $wgOut->addHTML( $eval ); |
155 | | - |
156 | | - // Associated script |
157 | | - $exprScript = "function doExprSubmit() |
158 | | - { |
159 | | - var expr = document.getElementById('wpTestExpr').value; |
160 | | - injectSpinner( document.getElementById( 'mw-abusefilter-submitexpr' ), 'abusefilter-expr' ); |
161 | | - sajax_do_call( 'AbuseFilter::ajaxEvaluateExpression', [expr], processExprResult ); |
162 | | - } |
163 | | - function processExprResult( request ) { |
164 | | - var response = request.responseText; |
165 | | - |
166 | | - removeSpinner( 'abusefilter-expr' ); |
167 | | - |
168 | | - var el = document.getElementById( 'mw-abusefilter-expr-result' ); |
169 | | - changeText( el, response ); |
170 | | - } |
171 | | - function doReautoSubmit() |
172 | | - { |
173 | | - var name = document.getElementById('reautoconfirm-user').value; |
174 | | - injectSpinner( document.getElementById( 'mw-abusefilter-reautoconfirmsubmit' ), 'abusefilter-reautoconfirm' ); |
175 | | - sajax_do_call( 'AbuseFilter::ajaxReAutoconfirm', [name], processReautoconfirm ); |
176 | | - } |
177 | | - function processReautoconfirm( request ) { |
178 | | - var response = request.responseText; |
179 | | - |
180 | | - if (strlen(response)) { |
181 | | - jsMsg( response ); |
182 | | - } |
183 | | - |
184 | | - removeSpinner( 'abusefilter-reautoconfirm' ); |
185 | | - } |
186 | | - "; |
187 | | - |
188 | | - $wgOut->addInlineScript( $exprScript ); |
189 | | - |
190 | | - global $wgUser; |
191 | | - |
192 | | - if ($wgUser->isAllowed( 'abusefilter-modify' )) { |
193 | | - // Hacky little box to re-enable autoconfirmed if it got disabled |
194 | | - $rac = ''; |
195 | | - $rac .= Xml::inputLabel( wfMsg( 'abusefilter-tools-reautoconfirm-user' ), 'wpReAutoconfirmUser', 'reautoconfirm-user', 45 ); |
196 | | - $rac .= Xml::element( 'input', array( 'type' => 'button', 'id' => 'mw-abusefilter-reautoconfirmsubmit', 'onclick' => 'doReautoSubmit();', 'value' => wfMsg( 'abusefilter-tools-reautoconfirm-submit' ) ) ); |
197 | | - $rac = Xml::fieldset( wfMsg( 'abusefilter-tools-reautoconfirm' ), $rac ); |
198 | | - $wgOut->addHTML( $rac ); |
199 | | - } |
| 68 | + $v = new $view( $this, $params ); |
| 69 | + $v->show( ); |
200 | 70 | } |
201 | 71 | |
202 | | - function showStatus() { |
203 | | - global $wgMemc,$wgAbuseFilterConditionLimit,$wgOut, $wgLang; |
204 | | - |
205 | | - $overflow_count = (int)$wgMemc->get( AbuseFilter::filterLimitReachedKey() ); |
206 | | - $match_count = (int) $wgMemc->get( AbuseFilter::filterMatchesKey() ); |
207 | | - $total_count = (int)$wgMemc->get( AbuseFilter::filterUsedKey() ); |
208 | | - |
209 | | - if ($total_count>0) { |
210 | | - $overflow_percent = sprintf( "%.2f", 100 * $overflow_count / $total_count ); |
211 | | - $match_percent = sprintf( "%.2f", 100 * $match_count / $total_count ); |
212 | | - |
213 | | - $status = wfMsgExt( 'abusefilter-status', array( 'parsemag', 'escape' ), |
214 | | - $wgLang->formatNum($total_count), |
215 | | - $wgLang->formatNum($overflow_count), |
216 | | - $wgLang->formatNum($overflow_percent), |
217 | | - $wgLang->formatNum($wgAbuseFilterConditionLimit), |
218 | | - $wgLang->formatNum($match_count), |
219 | | - $wgLang->formatNum($match_percent) |
220 | | - ); |
221 | | - |
222 | | - $status = Xml::tags( 'div', array( 'class' => 'mw-abusefilter-status' ), $status ); |
223 | | - $wgOut->addHTML( $status ); |
224 | | - } |
225 | | - } |
226 | | - |
227 | | - function doEdit( $history_id = null ) { |
228 | | - global $wgRequest, $wgUser; |
229 | | - |
230 | | - $filter = $this->mFilter; |
231 | | - |
232 | | - $editToken = $wgRequest->getVal( 'wpEditToken' ); |
233 | | - $didEdit = $this->canEdit() && $wgUser->matchEditToken( $editToken, array( 'abusefilter', $filter ) ); |
234 | | - |
235 | | - if ($didEdit) { |
236 | | - // Check syntax |
237 | | - $syntaxerr = AbuseFilter::checkSyntax( $wgRequest->getVal( 'wpFilterRules' ) ); |
238 | | - if ($syntaxerr !== true ) { |
239 | | - return $this->buildFilterEditor( wfMsgExt( 'abusefilter-edit-badsyntax', array( 'parseinline' ), array( $syntaxerr ) ), $filter, $history_id ); |
240 | | - } |
241 | | - |
242 | | - $dbw = wfGetDB( DB_MASTER ); |
243 | | - |
244 | | - list ($newRow, $actions) = $this->loadRequest($filter); |
245 | | - |
246 | | - $newRow = get_object_vars($newRow); // Convert from object to array |
247 | | - |
248 | | - // Set last modifier. |
249 | | - $newRow['af_timestamp'] = $dbw->timestamp( wfTimestampNow() ); |
250 | | - $newRow['af_user'] = $wgUser->getId(); |
251 | | - $newRow['af_user_text'] = $wgUser->getName(); |
252 | | - |
253 | | - $dbw->begin(); |
254 | | - |
255 | | - if ($filter == 'new') { |
256 | | - $new_id = $dbw->nextSequenceValue( 'abuse_filter_af_id_seq' ); |
257 | | - $is_new = true; |
258 | | - } else { |
259 | | - $new_id = $this->mFilter; |
260 | | - $is_new = false; |
261 | | - } |
262 | | - |
263 | | - $newRow['af_throttled'] = $newRow['af_throttled'] && !$newRow['af_enabled']; |
264 | | - |
265 | | - $newRow['af_id'] = $new_id; |
266 | | - |
267 | | - $dbw->replace( 'abuse_filter', array( 'af_id' ), $newRow, __METHOD__ ); |
268 | | - |
269 | | - if ($is_new) { |
270 | | - $new_id = $dbw->insertId(); |
271 | | - } |
272 | | - |
273 | | - // Actions |
274 | | - global $wgAbuseFilterAvailableActions; |
275 | | - $deadActions = array(); |
276 | | - $actionsRows = array(); |
277 | | - foreach( $wgAbuseFilterAvailableActions as $action ) { |
278 | | - // Check if it's set |
279 | | - $enabled = isset($actions[$action]) && (bool)$actions[$action]; |
280 | | - |
281 | | - if ($enabled) { |
282 | | - $parameters = $actions[$action]['parameters']; |
283 | | - |
284 | | - $thisRow = array( 'afa_filter' => $new_id, 'afa_consequence' => $action, 'afa_parameters' => implode( "\n", $parameters ) ); |
285 | | - $actionsRows[] = $thisRow; |
286 | | - } else { |
287 | | - $deadActions[] = $action; |
288 | | - } |
289 | | - } |
290 | | - |
291 | | - // Create a history row |
292 | | - $afh_row = array(); |
293 | | - |
294 | | - foreach( self::$history_mappings as $af_col => $afh_col ) { |
295 | | - $afh_row[$afh_col] = $newRow[$af_col]; |
296 | | - } |
297 | | - |
298 | | - // Actions |
299 | | - $displayActions = array(); |
300 | | - foreach( $actions as $action ) { |
301 | | - $displayActions[$action['action']] = $action['parameters']; |
302 | | - } |
303 | | - $afh_row['afh_actions'] = serialize($displayActions); |
304 | | - |
305 | | - // Flags |
306 | | - $flags = array(); |
307 | | - if ($newRow['af_hidden']) |
308 | | - $flags[] = 'hidden'; |
309 | | - if ($newRow['af_enabled']) |
310 | | - $flags[] = 'enabled'; |
311 | | - if ($newRow['af_deleted']) |
312 | | - $flags[] = 'deleted'; |
313 | | - |
314 | | - $afh_row['afh_flags'] = implode( ",", $flags ); |
315 | | - |
316 | | - $afh_row['afh_filter'] = $new_id; |
317 | | - |
318 | | - // Do the update |
319 | | - $dbw->insert( 'abuse_filter_history', $afh_row, __METHOD__ ); |
320 | | - $dbw->delete( 'abuse_filter_action', array( 'afa_filter' => $filter, 'afa_consequence' => $deadActions ), __METHOD__ ); |
321 | | - $dbw->replace( 'abuse_filter_action', array( array( 'afa_filter', 'afa_consequence' ) ), $actionsRows, __METHOD__ ); |
322 | | - |
323 | | - $dbw->commit(); |
324 | | - |
325 | | - global $wgOut; |
326 | | - |
327 | | - $wgOut->redirect( $this->getTitle()->getLocalURL( 'result=success&changedfilter='.$new_id ) ); |
328 | | - } else { |
329 | | - return $this->buildFilterEditor( null, $filter, $history_id ); |
330 | | - } |
331 | | - } |
332 | | - |
333 | | - function buildFilterEditor( $error = '', $filter, $history_id=null ) { |
334 | | - if( $filter === null ) { |
335 | | - return false; |
336 | | - } |
337 | | - |
338 | | - // Build the edit form |
339 | | - global $wgOut,$wgLang,$wgUser; |
340 | | - $sk = $this->mSkin; |
341 | | - |
342 | | - list ($row, $actions) = $this->loadRequest($filter, $history_id); |
343 | | - |
344 | | - if( !$row ) { |
345 | | - return false; |
346 | | - } |
347 | | - |
348 | | - $wgOut->setSubtitle( wfMsg( 'abusefilter-edit-subtitle', $filter, $history_id ) ); |
349 | | - |
350 | | - if (isset($row->af_hidden) && $row->af_hidden && !$this->canEdit()) { |
351 | | - return wfMsg( 'abusefilter-edit-denied' ); |
352 | | - } |
353 | | - |
354 | | - $output = ''; |
355 | | - if ($error) { |
356 | | - $wgOut->addHTML( "<span class=\"error\">$error</span>" ); |
357 | | - } |
358 | | - |
359 | | - $wgOut->addHTML( $sk->link( $this->getTitle(), wfMsg( 'abusefilter-history-backlist' ) ) ); |
360 | | - |
361 | | - $fields = array(); |
362 | | - |
363 | | - $fields['abusefilter-edit-id'] = $this->mFilter == 'new' ? wfMsg( 'abusefilter-edit-new' ) : $filter; |
364 | | - $fields['abusefilter-edit-description'] = Xml::input( 'wpFilterDescription', 45, isset( $row->af_public_comments ) ? $row->af_public_comments : '' ); |
365 | | - |
366 | | - // Hit count display |
367 | | - if( !empty($row->af_hit_count) ){ |
368 | | - $count = (int)$row->af_hit_count; |
369 | | - $count_display = wfMsgExt( 'abusefilter-hitcount', array( 'parseinline' ), |
370 | | - $wgLang->formatNum( $count ) |
371 | | - ); |
372 | | - $hitCount = $sk->makeKnownLinkObj( SpecialPage::getTitleFor( 'AbuseLog' ), $count_display, 'wpSearchFilter='.$row->af_id ); |
373 | | - |
374 | | - $fields['abusefilter-edit-hitcount'] = $hitCount; |
375 | | - } |
376 | | - |
377 | | - if ($filter !== 'new') { |
378 | | - // Statistics |
379 | | - global $wgMemc, $wgLang; |
380 | | - $matches_count = $wgMemc->get( AbuseFilter::filterMatchesKey( $filter ) ); |
381 | | - $total = $wgMemc->get( AbuseFilter::filterUsedKey() ); |
382 | | - |
383 | | - if ($total > 0) { |
384 | | - $matches_percent = sprintf( '%.2f', 100 * $matches_count / $total ); |
385 | | - $fields['abusefilter-edit-status-label'] = |
386 | | - wfMsgExt( 'abusefilter-edit-status', array( 'parsemag', 'escape' ), |
387 | | - $wgLang->formatNum($total), |
388 | | - $wgLang->formatNum($matches_count), |
389 | | - $wgLang->formatNum($matches_percent) |
390 | | - ); |
391 | | - } |
392 | | - } |
393 | | - |
394 | | - $fields['abusefilter-edit-rules'] = $this->buildEditBox($row); |
395 | | - $fields['abusefilter-edit-notes'] = Xml::textarea( 'wpFilterNotes', ( isset( $row->af_comments ) ? $row->af_comments."\n" : "\n" ) ); |
396 | | - |
397 | | - // Build checkboxen |
398 | | - $checkboxes = array( 'hidden', 'enabled', 'deleted' ); |
399 | | - $flags = ''; |
400 | | - |
401 | | - if (isset($row->af_throttled) && $row->af_throttled) { |
402 | | - global $wgAbuseFilterEmergencyDisableThreshold; |
403 | | - $threshold_percent = sprintf( '%.2f', $wgAbuseFilterEmergencyDisableThreshold * 100 ); |
404 | | - $flags .= $wgOut->parse( wfMsg( 'abusefilter-edit-throttled', $wgLang->formatNum( $threshold_percent ) ) ); |
405 | | - } |
406 | | - |
407 | | - foreach( $checkboxes as $checkboxId ) { |
408 | | - $message = "abusefilter-edit-$checkboxId"; |
409 | | - $dbField = "af_$checkboxId"; |
410 | | - $postVar = "wpFilter".ucfirst($checkboxId); |
411 | | - |
412 | | - $checkbox = Xml::checkLabel( wfMsg( $message ), $postVar, $postVar, isset( $row->$dbField ) ? $row->$dbField : false ); |
413 | | - $checkbox = Xml::tags( 'p', null, $checkbox ); |
414 | | - $flags .= $checkbox; |
415 | | - } |
416 | | - $fields['abusefilter-edit-flags'] = $flags; |
417 | | - |
418 | | - if ($filter != 'new') { |
419 | | - // Last modification details |
420 | | - $user = $sk->userLink( $row->af_user, $row->af_user_text ) . $sk->userToolLinks( $row->af_user, $row->af_user_text ); |
421 | | - $fields['abusefilter-edit-lastmod'] = wfMsgExt( 'abusefilter-edit-lastmod-text', array( 'parseinline', 'replaceafter' ), array( $wgLang->timeanddate( $row->af_timestamp ), $user ) ); |
422 | | - $history_display = wfMsgExt( 'abusefilter-edit-viewhistory', array( 'parseinline' ) ); |
423 | | - $fields['abusefilter-edit-history'] = $sk->makeKnownLinkObj( $this->getTitle( 'history/'.$filter ), $history_display ); |
424 | | - } |
425 | | - |
426 | | - $form = Xml::buildForm( $fields ); |
427 | | - $form = Xml::fieldset( wfMsg( 'abusefilter-edit-main' ), $form ); |
428 | | - $form .= Xml::fieldset( wfMsg( 'abusefilter-edit-consequences' ), $this->buildConsequenceEditor( $row, $actions ) ); |
429 | | - |
430 | | - if ($this->canEdit()) { |
431 | | - $form .= Xml::submitButton( wfMsg( 'abusefilter-edit-save' ) ); |
432 | | - $form .= Xml::hidden( 'wpEditToken', $wgUser->editToken( array( 'abusefilter', $filter )) ); |
433 | | - } |
434 | | - |
435 | | - $form = Xml::tags( 'form', array( 'action' => $this->getTitle( $filter )->getFullURL(), 'method' => 'POST' ), $form ); |
436 | | - |
437 | | - $output .= $form; |
438 | | - |
439 | | - return $output; |
440 | | - } |
441 | | - |
442 | | - function buildEditBox( $row ) { |
443 | | - global $wgOut; |
444 | | - |
445 | | - $rules = Xml::textarea( 'wpFilterRules', ( isset( $row->af_pattern ) ? $row->af_pattern."\n" : "\n" ) ); |
446 | | - |
447 | | - $dropDown = array( |
448 | | - 'op-arithmetic' => array('+' => 'addition', '-' => 'subtraction', '*' => 'multiplication', '/' => 'divide', '%' => 'modulo', '**' => 'pow'), |
449 | | - 'op-comparison' => array('==' => 'equal', '!=' => 'notequal', '<' => 'lt', '>' => 'gt', '<=' => 'lte', '>=' => 'gte'), |
450 | | - 'op-bool' => array( '!' => 'not', '&' => 'and', '|' => 'or', '^' => 'xor' ), |
451 | | - 'misc' => array( 'val1 ? iftrue : iffalse' => 'ternary', 'in' => 'in', 'like' => 'like', '""' => 'stringlit', ), |
452 | | - 'funcs' => array( 'length(string)' => 'length', 'lcase(string)' => 'lcase', 'ccnorm(string)' => 'ccnorm', 'rmdoubles(string)' => 'rmdoubles', 'specialratio(string)' => 'specialratio', 'norm(string)' => 'norm', 'count(needle,haystack)' => 'count' ), |
453 | | - 'vars' => array( 'ACCOUNTNAME' => 'accountname', 'ACTION' => 'action', 'ADDED_LINES' => 'addedlines', 'EDIT_DELTA' => 'delta', 'EDIT_DIFF' => 'diff', 'NEW_SIZE' => 'newsize', 'OLD_SIZE' => 'oldsize', 'REMOVED_LINES' => 'removedlines', 'SUMMARY' => 'summary', 'ARTICLE_ARTICLEID' => 'article-id', 'ARTICLE_NAMESPACE' => 'article-ns', 'ARTICLE_TEXT' => 'article-text', 'ARTICLE_PREFIXEDTEXT' => 'article-prefixedtext', 'MOVED_FROM_ARTICLEID' => 'movedfrom-id', 'MOVED_FROM_NAMESPACE' => 'movedfrom-ns', 'MOVED_FROM_TEXT' => 'movedfrom-text', 'MOVED_FROM_PREFIXEDTEXT' => 'movedfrom-prefixedtext', 'MOVED_TO_ARTICLEID' => 'movedto-id', 'MOVED_TO_NAMESPACE' => 'movedto-ns', 'MOVED_TO_TEXT' => 'movedto-text', 'MOVED_TO_PREFIXEDTEXT' => 'movedto-prefixedtext', 'USER_EDITCOUNT' => 'user-editcount', 'USER_AGE' => 'user-age', 'USER_NAME' => 'user-name', 'USER_GROUPS' => 'user-groups', 'USER_EMAILCONFIRM' => 'user-emailconfirm'), |
454 | | - ); |
455 | | - |
456 | | - // Generate builder drop-down |
457 | | - $builder = ''; |
458 | | - |
459 | | - $builder .= Xml::option( wfMsg( "abusefilter-edit-builder-select") ); |
460 | | - |
461 | | - foreach( $dropDown as $group => $values ) { |
462 | | - $builder .= Xml::openElement( 'optgroup', array( 'label' => wfMsg( "abusefilter-edit-builder-group-$group" ) ) ) . "\n"; |
463 | | - |
464 | | - foreach( $values as $content => $name ) { |
465 | | - $builder .= Xml::option( wfMsg( "abusefilter-edit-builder-$group-$name" ), $content ) . "\n"; |
466 | | - } |
467 | | - |
468 | | - $builder .= Xml::closeElement( 'optgroup' ) . "\n"; |
469 | | - } |
470 | | - |
471 | | - $rules .= Xml::tags( 'select', array( 'id' => 'wpFilterBuilder', 'onchange' => 'addText();' ), $builder ); |
472 | | - |
473 | | - // Add syntax checking |
474 | | - $rules .= Xml::element( 'input', array( 'type' => 'button', 'onclick' => 'doSyntaxCheck()', 'value' => wfMsg( 'abusefilter-edit-check' ), 'id' => 'mw-abusefilter-syntaxcheck' ) ); |
475 | | - $rules .= Xml::element( 'div', array( 'id' => 'mw-abusefilter-syntaxresult', 'style' => 'display: none;' ), ' ' ); |
476 | | - |
477 | | - // Add script |
478 | | - $wgOut->addInlineScript( file_get_contents(dirname(__FILE__)."/edit.js") ); |
479 | | - |
480 | | - return $rules; |
481 | | - } |
482 | | - |
483 | | - function buildConsequenceEditor( $row, $actions ) { |
484 | | - global $wgAbuseFilterAvailableActions; |
485 | | - $setActions = array(); |
486 | | - foreach( $wgAbuseFilterAvailableActions as $action ) { |
487 | | - $setActions[$action] = array_key_exists( $action, $actions ); |
488 | | - } |
489 | | - |
490 | | - $output = ''; |
491 | | - |
492 | | - // Special case: flagging - always on. |
493 | | - $checkbox = Xml::checkLabel( wfMsg( 'abusefilter-edit-action-flag' ), 'wpFilterActionFlag', 'wpFilterActionFlag', true, array( 'disabled' => '1' ) ); |
494 | | - $output .= Xml::tags( 'p', null, $checkbox ); |
495 | | - |
496 | | - // Special case: throttling |
497 | | - $throttleSettings = Xml::checkLabel( wfMsg( 'abusefilter-edit-action-throttle' ), 'wpFilterActionThrottle', 'wpFilterActionThrottle', $setActions['throttle'] ); |
498 | | - $throttleFields = array(); |
499 | | - |
500 | | - if ($setActions['throttle']) { |
501 | | - array_shift( $actions['throttle']['parameters'] ); |
502 | | - $throttleRate = explode(',',$actions['throttle']['parameters'][0]); |
503 | | - $throttleCount = $throttleRate[0]; |
504 | | - $throttlePeriod = $throttleRate[1]; |
505 | | - |
506 | | - $throttleGroups = implode("\n", array_slice($actions['throttle']['parameters'], 1 ) ); |
507 | | - } else { |
508 | | - $throttleCount = 3; |
509 | | - $throttlePeriod = 60; |
510 | | - |
511 | | - $throttleGroups = "user\n"; |
512 | | - } |
513 | | - |
514 | | - $throttleFields['abusefilter-edit-throttle-count'] = Xml::input( 'wpFilterThrottleCount', 20, $throttleCount ); |
515 | | - $throttleFields['abusefilter-edit-throttle-period'] = wfMsgExt( 'abusefilter-edit-throttle-seconds', array( 'parseinline', 'replaceafter' ), array(Xml::input( 'wpFilterThrottlePeriod', 20, $throttlePeriod ) ) ); |
516 | | - $throttleFields['abusefilter-edit-throttle-groups'] = Xml::textarea( 'wpFilterThrottleGroups', $throttleGroups."\n" ); |
517 | | - $throttleSettings .= Xml::buildForm( $throttleFields ); |
518 | | - $output .= Xml::tags( 'p', null, $throttleSettings ); |
519 | | - |
520 | | - // Special case: Warning |
521 | | - $checkbox = Xml::checkLabel( wfMsg( 'abusefilter-edit-action-warn' ), 'wpFilterActionWarn', 'wpFilterActionWarn', $setActions['warn'] ); |
522 | | - $output .= Xml::tags( 'p', null, $checkbox ); |
523 | | - |
524 | | - $warnMsg = empty($setActions['warn']) ? 'abusefilter-warning' : $actions['warn']['parameters'][0]; |
525 | | - $warnFields['abusefilter-edit-warn-message'] = Xml::input( 'wpFilterWarnMessage', 45, $warnMsg ); |
526 | | - $output .= Xml::tags( 'p', null, Xml::buildForm( $warnFields ) ); |
527 | | - |
528 | | - // Special case: tagging |
529 | | - if ($setActions['tag']) { |
530 | | - $tags = $actions['tag']['parameters']; |
531 | | - } else { |
532 | | - $tags = array(); |
533 | | - } |
534 | | - |
535 | | - $checkbox = Xml::checkLabel( wfMsg('abusefilter-edit-action-tag'), 'wpFilterActionTag', 'wpFilterActionTag', $setActions['tag'] ); |
536 | | - $output .= Xml::tags( 'p', null, $checkbox ); |
537 | | - |
538 | | - $tagFields['abusefilter-edit-tag-tag'] = Xml::textarea( 'wpFilterTags', implode( "\n", $tags ) ); |
539 | | - $output .= Xml::tags( 'p', null, Xml::buildForm( $tagFields ) ); |
540 | | - |
541 | | - // The remainder are just toggles |
542 | | - $remainingActions = array_diff( $wgAbuseFilterAvailableActions, array( 'flag', 'throttle', 'warn', 'tag' ) ); |
543 | | - |
544 | | - foreach( $remainingActions as $action ) { |
545 | | - $message = 'abusefilter-edit-action-'.$action; |
546 | | - $form_field = 'wpFilterAction' . ucfirst($action); |
547 | | - $status = $setActions[$action]; |
548 | | - |
549 | | - $thisAction = Xml::checkLabel( wfMsg( $message ), $form_field, $form_field, $status ); |
550 | | - $thisAction = Xml::tags( 'p', null, $thisAction ); |
551 | | - |
552 | | - $output .= $thisAction; |
553 | | - } |
554 | | - |
555 | | - return $output; |
556 | | - } |
557 | | - |
558 | | - function loadFilterData( $id ) { |
559 | | - |
560 | | - if ($id == 'new') { |
561 | | - return array( new StdClass, array() ); |
562 | | - } |
563 | | - |
564 | | - $dbr = wfGetDB( DB_SLAVE ); |
565 | | - |
566 | | - // Load the main row |
567 | | - $row = $dbr->selectRow( 'abuse_filter', '*', array( 'af_id' => $id ), __METHOD__ ); |
568 | | - |
569 | | - if (!isset($row) || !isset($row->af_id) || !$row->af_id) |
570 | | - return null; |
571 | | - |
572 | | - // Load the actions |
573 | | - $actions = array(); |
574 | | - $res = $dbr->select( 'abuse_filter_action', '*', array( 'afa_filter' => $id), __METHOD__ ); |
575 | | - while ( $actionRow = $dbr->fetchObject( $res ) ) { |
576 | | - $thisAction = array(); |
577 | | - $thisAction['action'] = $actionRow->afa_consequence; |
578 | | - $thisAction['parameters'] = explode( "\n", $actionRow->afa_parameters ); |
579 | | - |
580 | | - $actions[$actionRow->afa_consequence] = $thisAction; |
581 | | - } |
582 | | - |
583 | | - return array( $row, $actions ); |
584 | | - } |
585 | | - |
586 | | - function loadHistoryItem( $id ) { |
587 | | - $dbr = wfGetDB( DB_SLAVE ); |
588 | | - |
589 | | - // Load the row. |
590 | | - $row = $dbr->selectRow( 'abuse_filter_history', '*', array( 'afh_id' => $id ), __METHOD__ ); |
591 | | - |
592 | | - ## Translate into an abuse_filter row with some black magic. This is ever so slightly evil! |
593 | | - $af_row = new StdClass; |
594 | | - |
595 | | - foreach (self::$history_mappings as $af_col => $afh_col ) { |
596 | | - $af_row->$af_col = $row->$afh_col; |
597 | | - } |
598 | | - |
599 | | - ## Process flags |
600 | | - |
601 | | - $af_row->af_deleted = 0; |
602 | | - $af_row->af_hidden = 0; |
603 | | - $af_row->af_enabled = 0; |
604 | | - |
605 | | - $flags = explode(',', $row->afh_flags ); |
606 | | - foreach( $flags as $flag ) { |
607 | | - $col_name = "af_$flag"; |
608 | | - $af_row->$col_name = 1; |
609 | | - } |
610 | | - |
611 | | - ## Process actions |
612 | | - $actions_raw = unserialize($row->afh_actions); |
613 | | - $actions_output = array(); |
614 | | - |
615 | | - foreach( $actions_raw as $action => $parameters ) { |
616 | | - $actions_output[$action] = array( 'action' => $action, 'parameters' => $parameters ); |
617 | | - } |
618 | | - |
619 | | - |
620 | | - return array( $af_row, $actions_output ); |
621 | | - } |
622 | | - |
623 | 72 | function loadParameters( $subpage ) { |
624 | 73 | global $wgRequest; |
625 | 74 | |
— | — | @@ -629,302 +78,4 @@ |
630 | 79 | } |
631 | 80 | $this->mFilter = $filter; |
632 | 81 | } |
633 | | - |
634 | | - function loadRequest( $filter, $history_id = null ) { |
635 | | - static $row = null; |
636 | | - static $actions = null; |
637 | | - global $wgRequest; |
638 | | - |
639 | | - if (!is_null($actions) && !is_null($row)) { |
640 | | - return array($row,$actions); |
641 | | - } elseif ($wgRequest->wasPosted()) { |
642 | | - ## Nothing, we do it all later |
643 | | - } elseif ( $history_id ) { |
644 | | - return $this->loadHistoryItem( $history_id ); |
645 | | - } else { |
646 | | - return $this->loadFilterData( $filter ); |
647 | | - } |
648 | | - |
649 | | - // We need some details like last editor |
650 | | - list($row) = $this->loadFilterData( $filter ); |
651 | | - |
652 | | - $textLoads = array( 'af_public_comments' => 'wpFilterDescription', 'af_pattern' => 'wpFilterRules', 'af_comments' => 'wpFilterNotes' ); |
653 | | - |
654 | | - foreach( $textLoads as $col => $field ) { |
655 | | - $row->$col = trim($wgRequest->getVal( $field )); |
656 | | - } |
657 | | - |
658 | | - $row->af_deleted = $wgRequest->getBool( 'wpFilterDeleted' ); |
659 | | - $row->af_enabled = $wgRequest->getBool( 'wpFilterEnabled' ) && !$row->af_deleted; |
660 | | - $row->af_hidden = $wgRequest->getBool( 'wpFilterHidden' ); |
661 | | - |
662 | | - // Actions |
663 | | - global $wgAbuseFilterAvailableActions; |
664 | | - $actions = array(); |
665 | | - foreach( $wgAbuseFilterAvailableActions as $action ) { |
666 | | - // Check if it's set |
667 | | - $enabled = $wgRequest->getBool( 'wpFilterAction'.ucfirst($action) ); |
668 | | - |
669 | | - if ($enabled) { |
670 | | - $parameters = array(); |
671 | | - |
672 | | - if ($action == 'throttle') { |
673 | | - // Grumble grumble. |
674 | | - // We need to load the parameters |
675 | | - $throttleCount = $wgRequest->getIntOrNull( 'wpFilterThrottleCount' ); |
676 | | - $throttlePeriod = $wgRequest->getIntOrNull( 'wpFilterThrottlePeriod' ); |
677 | | - $throttleGroups = explode("\n", trim( $wgRequest->getText( 'wpFilterThrottleGroups' ) ) ); |
678 | | - |
679 | | - $parameters[0] = $this->mFilter; // For now, anyway |
680 | | - $parameters[1] = "$throttleCount,$throttlePeriod"; |
681 | | - $parameters = array_merge( $parameters, $throttleGroups ); |
682 | | - } elseif ($action == 'warn') { |
683 | | - $parameters[0] = $wgRequest->getVal( 'wpFilterWarnMessage' ); |
684 | | - } elseif ($action == 'tag') { |
685 | | - $parameters = explode("\n", $wgRequest->getText( 'wpFilterTags' ) ); |
686 | | - } |
687 | | - |
688 | | - $thisAction = array( 'action' => $action, 'parameters' => $parameters ); |
689 | | - $actions[$action] = $thisAction; |
690 | | - } |
691 | | - } |
692 | | - |
693 | | - return array( $row, $actions ); |
694 | | - } |
695 | | - |
696 | | - function canEdit() { |
697 | | - global $wgUser; |
698 | | - static $canEdit = 'unset'; |
699 | | - |
700 | | - if ($canEdit == 'unset') { |
701 | | - $canEdit = $wgUser->isAllowed( 'abusefilter-modify' ); |
702 | | - } |
703 | | - |
704 | | - return $canEdit; |
705 | | - } |
706 | | - |
707 | | - function showList( $conds = array( 'af_deleted' => 0 ), $optarray = array() ) { |
708 | | - global $wgOut,$wgUser; |
709 | | - |
710 | | - $sk = $this->mSkin = $wgUser->getSkin(); |
711 | | - |
712 | | - $output = ''; |
713 | | - $output .= Xml::element( 'h2', null, wfMsgExt( 'abusefilter-list', array( 'parseinline' ) ) ); |
714 | | - |
715 | | - $pager = new AbuseFilterPager( $this, $conds ); |
716 | | - |
717 | | - extract($optarray); |
718 | | - |
719 | | - ## Options form |
720 | | - $options = ''; |
721 | | - $fields = array(); |
722 | | - $fields['abusefilter-list-options-deleted'] = Xml::radioLabel( wfMsg( 'abusefilter-list-options-deleted-show' ), 'deletedfilters', 'show', 'mw-abusefilter-deletedfilters-show', $deleted == 'show' ); |
723 | | - $fields['abusefilter-list-options-deleted'] .= Xml::radioLabel( wfMsg( 'abusefilter-list-options-deleted-hide' ), 'deletedfilters', 'hide', 'mw-abusefilter-deletedfilters-hide', $deleted == 'hide' ); |
724 | | - $fields['abusefilter-list-options-deleted'] .= Xml::radioLabel( wfMsg( 'abusefilter-list-options-deleted-only' ), 'deletedfilters', 'only', 'mw-abusefilter-deletedfilters-only', $deleted == 'only' ); |
725 | | - $fields['abusefilter-list-options-disabled'] = Xml::checkLabel( wfMsg( 'abusefilter-list-options-hidedisabled' ), 'hidedisabled', 'mw-abusefilter-disabledfilters-hide', $hidedisabled ); |
726 | | - $fields['abusefilter-list-limit'] = $pager->getLimitSelect(); |
727 | | - |
728 | | - $options = Xml::buildForm( $fields, 'abusefilter-list-options-submit' ); |
729 | | - $options .= Xml::hidden( 'title', $this->getTitle()->getPrefixedText() ); |
730 | | - $options = Xml::tags( 'form', array( 'method' => 'get', 'action' => $this->getTitle()->getFullURL() ), $options ); |
731 | | - $options = Xml::fieldset( wfMsg( 'abusefilter-list-options' ), $options ); |
732 | | - |
733 | | - $output .= $options; |
734 | | - |
735 | | - $output .= |
736 | | - $pager->getNavigationBar() . |
737 | | - $pager->getBody() . |
738 | | - $pager->getNavigationBar(); |
739 | | - |
740 | | - $wgOut->addHTML( $output ); |
741 | | - } |
742 | | -} |
743 | | - |
744 | | -class AbuseFilterPager extends TablePager { |
745 | | - |
746 | | - function __construct( $page, $conds ) { |
747 | | - $this->mPage = $page; |
748 | | - $this->mConds = $conds; |
749 | | - parent::__construct(); |
750 | | - } |
751 | | - |
752 | | - function getQueryInfo() { |
753 | | - $dbr = wfGetDB( DB_SLAVE ); |
754 | | - #$this->mConds[] = 'afa_filter=af_id'; |
755 | | - $abuse_filter = $dbr->tableName( 'abuse_filter' ); |
756 | | - return array( 'tables' => array('abuse_filter', 'abuse_filter_action'), |
757 | | - 'fields' => array( 'af_id', '(af_enabled | af_deleted << 1) AS status', 'af_public_comments', 'af_hidden', 'af_hit_count', 'af_timestamp', 'af_user_text', 'af_user', 'group_concat(afa_consequence) AS consequences' ), |
758 | | - 'conds' => $this->mConds, |
759 | | - 'options' => array( 'GROUP BY' => 'af_id' ), |
760 | | - 'join_conds' => array( 'abuse_filter_action' => array( 'LEFT JOIN', 'afa_filter=af_id' ) ) ); |
761 | | - } |
762 | | - |
763 | | - function getIndexField() { |
764 | | - return 'af_id'; |
765 | | - } |
766 | | - |
767 | | - function getFieldNames() { |
768 | | - static $headers = null; |
769 | | - |
770 | | - if (!empty($headers)) { |
771 | | - return $headers; |
772 | | - } |
773 | | - |
774 | | - $headers = array( 'af_id' => 'abusefilter-list-id', 'af_public_comments' => 'abusefilter-list-public', 'consequences' => 'abusefilter-list-consequences', 'status' => 'abusefilter-list-status', 'af_timestamp' => 'abusefilter-list-lastmodified', 'af_hidden' => 'abusefilter-list-visibility', 'af_hit_count' => 'abusefilter-list-hitcount' ); |
775 | | - |
776 | | - $headers = array_map( 'wfMsg', $headers ); |
777 | | - |
778 | | - return $headers; |
779 | | - } |
780 | | - |
781 | | - function formatValue( $name, $value ) { |
782 | | - global $wgOut,$wgLang; |
783 | | - |
784 | | - static $sk=null; |
785 | | - |
786 | | - if (empty($sk)) { |
787 | | - global $wgUser; |
788 | | - $sk = $wgUser->getSkin(); |
789 | | - } |
790 | | - |
791 | | - $row = $this->mCurrentRow; |
792 | | - |
793 | | - switch($name) { |
794 | | - case 'af_id': |
795 | | - return $sk->link( SpecialPage::getTitleFor( 'AbuseFilter', intval($value) ), intval($value) ); |
796 | | - case 'af_public_comments': |
797 | | - return $wgOut->parse( $value ); |
798 | | - case 'consequences': |
799 | | - return htmlspecialchars($value); |
800 | | - case 'status': |
801 | | - if ($value & 2) |
802 | | - return wfMsgExt( 'abusefilter-deleted', 'parseinline' ); |
803 | | - elseif ($value & 1) |
804 | | - return wfMsgExt( 'abusefilter-enabled', 'parseinline' ); |
805 | | - else |
806 | | - return wfMsgExt( 'abusefilter-disabled', 'parseinline' ); |
807 | | - case 'af_hidden': |
808 | | - $msg = $value ? 'abusefilter-hidden' : 'abusefilter-unhidden'; |
809 | | - return wfMsgExt( $msg, 'parseinline' ); |
810 | | - case 'af_hit_count': |
811 | | - $count_display = wfMsgExt( 'abusefilter-hitcount', array( 'parseinline' ), $wgLang->formatNum( $value ) ); |
812 | | - $link = $sk->makeKnownLinkObj( SpecialPage::getTitleFor( 'AbuseLog' ), $count_display, 'wpSearchFilter='.$row->af_id ); |
813 | | - return $link; |
814 | | - case 'af_timestamp': |
815 | | - $userLink = $sk->userLink( $row->af_user, $row->af_user_text ) . $sk->userToolLinks( $row->af_user, $row->af_user_text ); |
816 | | - return wfMsgExt( 'abusefilter-edit-lastmod-text', array( 'replaceafter', 'parseinline' ), array( $wgLang->timeanddate($value), $userLink ) ); |
817 | | - default: |
818 | | - throw new MWException( "Unknown row type $name!" ); |
819 | | - } |
820 | | - } |
821 | | - |
822 | | - function getDefaultSort() { |
823 | | - return 'af_id'; |
824 | | - } |
825 | | - |
826 | | - function isFieldSortable($name) { |
827 | | - $sortable_fields = array( 'af_id', 'status', 'af_hit_count', 'af_throttled', 'af_user_text', 'af_timestamp' ); |
828 | | - return in_array( $name, $sortable_fields ); |
829 | | - } |
830 | | -} |
831 | | - |
832 | | -class AbuseFilterHistoryPager extends TablePager { |
833 | | - |
834 | | - function __construct( $filter, $page ) { |
835 | | - $this->mFilter = $filter; |
836 | | - $this->mPage = $page; |
837 | | - $this->mDefaultDirection = true; |
838 | | - parent::__construct(); |
839 | | - } |
840 | | - |
841 | | - function getFieldNames() { |
842 | | - static $headers = null; |
843 | | - |
844 | | - if (!empty($headers)) { |
845 | | - return $headers; |
846 | | - } |
847 | | - |
848 | | - $headers = array( 'afh_timestamp' => 'abusefilter-history-timestamp', 'afh_user_text' => 'abusefilter-history-user', 'afh_public_comments' => 'abusefilter-history-public', |
849 | | - 'afh_flags' => 'abusefilter-history-flags', 'afh_pattern' => 'abusefilter-history-filter', 'afh_comments' => 'abusefilter-history-comments', 'afh_actions' => 'abusefilter-history-actions' ); |
850 | | - |
851 | | - $headers = array_map( 'wfMsg', $headers ); |
852 | | - |
853 | | - return $headers; |
854 | | - } |
855 | | - |
856 | | - function formatValue( $name, $value ) { |
857 | | - global $wgOut,$wgLang; |
858 | | - |
859 | | - static $sk=null; |
860 | | - |
861 | | - if (empty($sk)) { |
862 | | - global $wgUser; |
863 | | - $sk = $wgUser->getSkin(); |
864 | | - } |
865 | | - |
866 | | - $row = $this->mCurrentRow; |
867 | | - |
868 | | - switch($name) { |
869 | | - case 'afh_timestamp': |
870 | | - $title = SpecialPage::getTitleFor( 'AbuseFilter', 'history/'.$this->mFilter.'/item/'.$row->afh_id ); |
871 | | - return $sk->link( $title, $wgLang->timeanddate( $row->afh_timestamp ) ); |
872 | | - case 'afh_user_text': |
873 | | - return $sk->userLink( $row->afh_user, $row->afh_user_text ) . ' ' . $sk->userToolLinks( $row->afh_user, $row->afh_user_text ); |
874 | | - case 'afh_public_comments': |
875 | | - return $wgOut->parse( $value ); |
876 | | - case 'afh_flags': |
877 | | - $flags = array_filter( explode( ',', $value ) ); |
878 | | - $flags_display = array(); |
879 | | - foreach( $flags as $flag ) { |
880 | | - $flags_display[] = wfMsg( "abusefilter-history-$flag" ); |
881 | | - } |
882 | | - return implode( ', ', $flags_display ); |
883 | | - case 'afh_pattern': |
884 | | - return htmlspecialchars( $wgLang->truncate( $value, 200, '...' ) ); |
885 | | - case 'afh_comments': |
886 | | - return htmlspecialchars( $wgLang->truncate( $value, 200, '...' ) ); |
887 | | - case 'afh_actions': |
888 | | - $actions = unserialize( $value ); |
889 | | - |
890 | | - $display_actions = ''; |
891 | | - |
892 | | - foreach( $actions as $action => $parameters ) { |
893 | | - $display_actions .= Xml::tags( 'li', null, wfMsgExt( 'abusefilter-history-action', array( 'parseinline' ), array($action, implode('; ', $parameters)) ) ); |
894 | | - } |
895 | | - $display_actions = Xml::tags( 'ul', null, $display_actions ); |
896 | | - |
897 | | - return $display_actions; |
898 | | - } |
899 | | - |
900 | | - return "Unable to format name $name\n"; |
901 | | - } |
902 | | - |
903 | | - function getQueryInfo() { |
904 | | - return array( |
905 | | - 'tables' => 'abuse_filter_history', |
906 | | - 'fields' => array( 'afh_timestamp', 'afh_user_text', 'afh_public_comments', 'afh_flags', 'afh_pattern', 'afh_comments', 'afh_actions', 'afh_id', 'afh_user' ), |
907 | | - 'conds' => array( 'afh_filter' => $this->mFilter ), |
908 | | - ); |
909 | | - } |
910 | | - |
911 | | - function getIndexField() { |
912 | | - return 'afh_timestamp'; |
913 | | - } |
914 | | - |
915 | | - function getDefaultSort() { |
916 | | - return 'afh_timestamp'; |
917 | | - } |
918 | | - |
919 | | - function isFieldSortable($name) { |
920 | | - $sortable_fields = array( 'afh_timestamp', 'afh_user_text' ); |
921 | | - return in_array( $name, $sortable_fields ); |
922 | | - } |
923 | | - |
924 | | - /** |
925 | | - * Title used for self-links. Override this if you want to be able to |
926 | | - * use a title other than $wgTitle |
927 | | - */ |
928 | | - function getTitle() { |
929 | | - return $this->mPage->getTitle( "history/".$this->mFilter ); |
930 | | - } |
931 | 82 | } |
\ No newline at end of file |
Index: branches/change-tagging/extensions/AbuseFilter/Views/edit.js |
— | — | @@ -0,0 +1,61 @@ |
| 2 | +function doSyntaxCheck() |
| 3 | +{ |
| 4 | + var filter = document.getElementById('wpFilterRules').value; |
| 5 | + injectSpinner( document.getElementById( 'mw-abusefilter-syntaxcheck' ), 'abusefilter-syntaxcheck' ); |
| 6 | + sajax_do_call( 'AbuseFilter::ajaxCheckSyntax', [filter], processSyntaxResult ); |
| 7 | +} |
| 8 | +function processSyntaxResult( request ) { |
| 9 | + var response = request.responseText; |
| 10 | + |
| 11 | + removeSpinner( 'abusefilter-syntaxcheck' ); |
| 12 | + |
| 13 | + var el = document.getElementById( 'mw-abusefilter-syntaxresult' ); |
| 14 | + el.style.display = 'block'; |
| 15 | + |
| 16 | + if (response.match( /OK/ )) { |
| 17 | + // Successful |
| 18 | + changeText( el, 'No syntax errors.' ); |
| 19 | + el.syntaxOk = true; |
| 20 | + } else { |
| 21 | + var error = response.substr(4); |
| 22 | + changeText( el, 'Syntax error: '+error ); |
| 23 | + el.syntaxOk = false; |
| 24 | + } |
| 25 | +} |
| 26 | +function addText() { |
| 27 | + if (document.getElementById('wpFilterBuilder').selectedIndex == 0) { |
| 28 | + return; |
| 29 | + } |
| 30 | + |
| 31 | + insertAtCursor(document.getElementById('wpFilterRules'), document.getElementById('wpFilterBuilder').value + " "); |
| 32 | + document.getElementById('wpFilterBuilder').selectedIndex = 0; |
| 33 | +} |
| 34 | + |
| 35 | +//From http://clipmarks.com/clipmark/CEFC94CB-94D6-4495-A7AA-791B7355E284/ |
| 36 | +function insertAtCursor(myField, myValue) { |
| 37 | + //IE support |
| 38 | + if (document.selection) { |
| 39 | + myField.focus(); |
| 40 | + sel = document.selection.createRange(); |
| 41 | + sel.text = myValue; |
| 42 | + } |
| 43 | + //MOZILLA/NETSCAPE support |
| 44 | + else if (myField.selectionStart || myField.selectionStart == '0') { |
| 45 | + var startPos = myField.selectionStart; |
| 46 | + var endPos = myField.selectionEnd; |
| 47 | + myField.value = myField.value.substring(0, startPos) |
| 48 | + + myValue |
| 49 | + + myField.value.substring(endPos, myField.value.length); |
| 50 | + } else { |
| 51 | + myField.value += myValue; |
| 52 | + } |
| 53 | +} |
| 54 | + |
| 55 | +addOnloadHook( function() { |
| 56 | + addHandler( document.getElementById( 'wpFilterRules' ), 'keyup', function() { |
| 57 | + el = document.getElementById( 'mw-abusefilter-syntaxresult' ); |
| 58 | + if (el.syntaxOk == true) { |
| 59 | + el.style.display = 'none'; |
| 60 | + } |
| 61 | + } ); |
| 62 | +} ); |
\ No newline at end of file |
Property changes on: branches/change-tagging/extensions/AbuseFilter/Views/edit.js |
___________________________________________________________________ |
Name: svn:eol-style |
1 | 63 | + native |
Index: branches/change-tagging/extensions/AbuseFilter/Views/AbuseFilterViewList.php |
— | — | @@ -0,0 +1,202 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +if (!defined( 'MEDIAWIKI' )) |
| 5 | + die(); |
| 6 | + |
| 7 | +class AbuseFilterViewList extends AbuseFilterView { |
| 8 | + function show( ) { |
| 9 | + global $wgUser, $wgOut, $wgRequest; |
| 10 | + |
| 11 | + $sk = $wgUser->getSkin(); |
| 12 | + |
| 13 | + // Show list of filters. |
| 14 | + $this->showStatus(); |
| 15 | + |
| 16 | + // Quick links |
| 17 | + $wgOut->addWikiMsg( 'abusefilter-links' ); |
| 18 | + $lists = array( 'tools' ); |
| 19 | + if ($this->canEdit()) |
| 20 | + $lists[] = 'new'; |
| 21 | + $links = ''; |
| 22 | + $sk = $wgUser->getSkin(); |
| 23 | + foreach( $lists as $list ) { |
| 24 | + $title = $this->getTitle( $list ); |
| 25 | + |
| 26 | + $link = $sk->link( $title, wfMsg( "abusefilter-$list" ) ); |
| 27 | + $links .= Xml::tags( 'li', null, $link ) . "\n"; |
| 28 | + } |
| 29 | + $links .= Xml::tags( 'li', null, $sk->link( SpecialPage::getTitleFor( 'AbuseLog' ), wfMsg( 'abusefilter-loglink' ) ) ); |
| 30 | + $links = Xml::tags( 'ul', null, $links ); |
| 31 | + $wgOut->addHTML( $links ); |
| 32 | + |
| 33 | + // Options. |
| 34 | + $conds = array(); |
| 35 | + $deleted = $wgRequest->getVal( 'deletedfilters' ); |
| 36 | + $hidedisabled = $wgRequest->getBool( 'hidedisabled' ); |
| 37 | + if ($deleted == 'show') { |
| 38 | + ## Nothing |
| 39 | + } elseif ($deleted == 'only') { |
| 40 | + $conds['af_deleted'] = 1; |
| 41 | + } else { ## hide, or anything else. |
| 42 | + $conds['af_deleted'] = 0; |
| 43 | + $deleted = 'hide'; |
| 44 | + } |
| 45 | + if ($hidedisabled) { |
| 46 | + $conds['af_deleted'] = 0; |
| 47 | + $conds['af_enabled'] = 1; |
| 48 | + } |
| 49 | + |
| 50 | + $this->showList( $conds, compact( 'deleted', 'hidedisabled' ) ); |
| 51 | + } |
| 52 | + |
| 53 | + function showList( $conds = array( 'af_deleted' => 0 ), $optarray = array() ) { |
| 54 | + global $wgOut,$wgUser; |
| 55 | + |
| 56 | + $sk = $this->mSkin = $wgUser->getSkin(); |
| 57 | + |
| 58 | + $output = ''; |
| 59 | + $output .= Xml::element( 'h2', null, wfMsgExt( 'abusefilter-list', array( 'parseinline' ) ) ); |
| 60 | + |
| 61 | + $pager = new AbuseFilterPager( $this, $conds ); |
| 62 | + |
| 63 | + extract($optarray); |
| 64 | + |
| 65 | + ## Options form |
| 66 | + $options = ''; |
| 67 | + $fields = array(); |
| 68 | + $fields['abusefilter-list-options-deleted'] = Xml::radioLabel( wfMsg( 'abusefilter-list-options-deleted-show' ), 'deletedfilters', 'show', 'mw-abusefilter-deletedfilters-show', $deleted == 'show' ); |
| 69 | + $fields['abusefilter-list-options-deleted'] .= Xml::radioLabel( wfMsg( 'abusefilter-list-options-deleted-hide' ), 'deletedfilters', 'hide', 'mw-abusefilter-deletedfilters-hide', $deleted == 'hide' ); |
| 70 | + $fields['abusefilter-list-options-deleted'] .= Xml::radioLabel( wfMsg( 'abusefilter-list-options-deleted-only' ), 'deletedfilters', 'only', 'mw-abusefilter-deletedfilters-only', $deleted == 'only' ); |
| 71 | + $fields['abusefilter-list-options-disabled'] = Xml::checkLabel( wfMsg( 'abusefilter-list-options-hidedisabled' ), 'hidedisabled', 'mw-abusefilter-disabledfilters-hide', $hidedisabled ); |
| 72 | + $fields['abusefilter-list-limit'] = $pager->getLimitSelect(); |
| 73 | + |
| 74 | + $options = Xml::buildForm( $fields, 'abusefilter-list-options-submit' ); |
| 75 | + $options .= Xml::hidden( 'title', $this->getTitle()->getPrefixedText() ); |
| 76 | + $options = Xml::tags( 'form', array( 'method' => 'get', 'action' => $this->getTitle()->getFullURL() ), $options ); |
| 77 | + $options = Xml::fieldset( wfMsg( 'abusefilter-list-options' ), $options ); |
| 78 | + |
| 79 | + $output .= $options; |
| 80 | + |
| 81 | + $output .= |
| 82 | + $pager->getNavigationBar() . |
| 83 | + $pager->getBody() . |
| 84 | + $pager->getNavigationBar(); |
| 85 | + |
| 86 | + $wgOut->addHTML( $output ); |
| 87 | + } |
| 88 | + |
| 89 | + function showStatus() { |
| 90 | + global $wgMemc,$wgAbuseFilterConditionLimit,$wgOut, $wgLang; |
| 91 | + |
| 92 | + $overflow_count = (int)$wgMemc->get( AbuseFilter::filterLimitReachedKey() ); |
| 93 | + $match_count = (int) $wgMemc->get( AbuseFilter::filterMatchesKey() ); |
| 94 | + $total_count = (int)$wgMemc->get( AbuseFilter::filterUsedKey() ); |
| 95 | + |
| 96 | + if ($total_count>0) { |
| 97 | + $overflow_percent = sprintf( "%.2f", 100 * $overflow_count / $total_count ); |
| 98 | + $match_percent = sprintf( "%.2f", 100 * $match_count / $total_count ); |
| 99 | + |
| 100 | + $status = wfMsgExt( 'abusefilter-status', array( 'parsemag', 'escape' ), |
| 101 | + $wgLang->formatNum($total_count), |
| 102 | + $wgLang->formatNum($overflow_count), |
| 103 | + $wgLang->formatNum($overflow_percent), |
| 104 | + $wgLang->formatNum($wgAbuseFilterConditionLimit), |
| 105 | + $wgLang->formatNum($match_count), |
| 106 | + $wgLang->formatNum($match_percent) |
| 107 | + ); |
| 108 | + |
| 109 | + $status = Xml::tags( 'div', array( 'class' => 'mw-abusefilter-status' ), $status ); |
| 110 | + $wgOut->addHTML( $status ); |
| 111 | + } |
| 112 | + } |
| 113 | +} |
| 114 | + |
| 115 | + |
| 116 | +// Probably no need to autoload this class, as it will only be called from the class above. |
| 117 | +class AbuseFilterPager extends TablePager { |
| 118 | + |
| 119 | + function __construct( $page, $conds ) { |
| 120 | + $this->mPage = $page; |
| 121 | + $this->mConds = $conds; |
| 122 | + parent::__construct(); |
| 123 | + } |
| 124 | + |
| 125 | + function getQueryInfo() { |
| 126 | + $dbr = wfGetDB( DB_SLAVE ); |
| 127 | + #$this->mConds[] = 'afa_filter=af_id'; |
| 128 | + $abuse_filter = $dbr->tableName( 'abuse_filter' ); |
| 129 | + return array( 'tables' => array('abuse_filter', 'abuse_filter_action'), |
| 130 | + 'fields' => array( 'af_id', '(af_enabled | af_deleted << 1) AS status', 'af_public_comments', 'af_hidden', 'af_hit_count', 'af_timestamp', 'af_user_text', 'af_user', 'group_concat(afa_consequence) AS consequences' ), |
| 131 | + 'conds' => $this->mConds, |
| 132 | + 'options' => array( 'GROUP BY' => 'af_id' ), |
| 133 | + 'join_conds' => array( 'abuse_filter_action' => array( 'LEFT JOIN', 'afa_filter=af_id' ) ) ); |
| 134 | + } |
| 135 | + |
| 136 | + function getIndexField() { |
| 137 | + return 'af_id'; |
| 138 | + } |
| 139 | + |
| 140 | + function getFieldNames() { |
| 141 | + static $headers = null; |
| 142 | + |
| 143 | + if (!empty($headers)) { |
| 144 | + return $headers; |
| 145 | + } |
| 146 | + |
| 147 | + $headers = array( 'af_id' => 'abusefilter-list-id', 'af_public_comments' => 'abusefilter-list-public', 'consequences' => 'abusefilter-list-consequences', 'status' => 'abusefilter-list-status', 'af_timestamp' => 'abusefilter-list-lastmodified', 'af_hidden' => 'abusefilter-list-visibility', 'af_hit_count' => 'abusefilter-list-hitcount' ); |
| 148 | + |
| 149 | + $headers = array_map( 'wfMsg', $headers ); |
| 150 | + |
| 151 | + return $headers; |
| 152 | + } |
| 153 | + |
| 154 | + function formatValue( $name, $value ) { |
| 155 | + global $wgOut,$wgLang; |
| 156 | + |
| 157 | + static $sk=null; |
| 158 | + |
| 159 | + if (empty($sk)) { |
| 160 | + global $wgUser; |
| 161 | + $sk = $wgUser->getSkin(); |
| 162 | + } |
| 163 | + |
| 164 | + $row = $this->mCurrentRow; |
| 165 | + |
| 166 | + switch($name) { |
| 167 | + case 'af_id': |
| 168 | + return $sk->link( SpecialPage::getTitleFor( 'AbuseFilter', intval($value) ), intval($value) ); |
| 169 | + case 'af_public_comments': |
| 170 | + return $wgOut->parse( $value ); |
| 171 | + case 'consequences': |
| 172 | + return htmlspecialchars($value); |
| 173 | + case 'status': |
| 174 | + if ($value & 2) |
| 175 | + return wfMsgExt( 'abusefilter-deleted', 'parseinline' ); |
| 176 | + elseif ($value & 1) |
| 177 | + return wfMsgExt( 'abusefilter-enabled', 'parseinline' ); |
| 178 | + else |
| 179 | + return wfMsgExt( 'abusefilter-disabled', 'parseinline' ); |
| 180 | + case 'af_hidden': |
| 181 | + $msg = $value ? 'abusefilter-hidden' : 'abusefilter-unhidden'; |
| 182 | + return wfMsgExt( $msg, 'parseinline' ); |
| 183 | + case 'af_hit_count': |
| 184 | + $count_display = wfMsgExt( 'abusefilter-hitcount', array( 'parseinline' ), $wgLang->formatNum( $value ) ); |
| 185 | + $link = $sk->makeKnownLinkObj( SpecialPage::getTitleFor( 'AbuseLog' ), $count_display, 'wpSearchFilter='.$row->af_id ); |
| 186 | + return $link; |
| 187 | + case 'af_timestamp': |
| 188 | + $userLink = $sk->userLink( $row->af_user, $row->af_user_text ) . $sk->userToolLinks( $row->af_user, $row->af_user_text ); |
| 189 | + return wfMsgExt( 'abusefilter-edit-lastmod-text', array( 'replaceafter', 'parseinline' ), array( $wgLang->timeanddate($value), $userLink ) ); |
| 190 | + default: |
| 191 | + throw new MWException( "Unknown row type $name!" ); |
| 192 | + } |
| 193 | + } |
| 194 | + |
| 195 | + function getDefaultSort() { |
| 196 | + return 'af_id'; |
| 197 | + } |
| 198 | + |
| 199 | + function isFieldSortable($name) { |
| 200 | + $sortable_fields = array( 'af_id', 'status', 'af_hit_count', 'af_throttled', 'af_user_text', 'af_timestamp' ); |
| 201 | + return in_array( $name, $sortable_fields ); |
| 202 | + } |
| 203 | +} |
\ No newline at end of file |
Index: branches/change-tagging/extensions/AbuseFilter/Views/AbuseFilterView.php |
— | — | @@ -0,0 +1,28 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +if (!defined( 'MEDIAWIKI' )) |
| 5 | + die(); |
| 6 | + |
| 7 | +abstract class AbuseFilterView { |
| 8 | + function __construct( $page, $params ) { |
| 9 | + $this->mPage = $page; |
| 10 | + $this->mParams = $params; |
| 11 | + } |
| 12 | + |
| 13 | + function getTitle( $subpage='' ) { |
| 14 | + return $this->mPage->getTitle( $subpage ); |
| 15 | + } |
| 16 | + |
| 17 | + abstract function show(); |
| 18 | + |
| 19 | + function canEdit() { |
| 20 | + global $wgUser; |
| 21 | + static $canEdit = 'unset'; |
| 22 | + |
| 23 | + if ($canEdit == 'unset') { |
| 24 | + $canEdit = $wgUser->isAllowed( 'abusefilter-modify' ); |
| 25 | + } |
| 26 | + |
| 27 | + return $canEdit; |
| 28 | + } |
| 29 | +} |
\ No newline at end of file |
Index: branches/change-tagging/extensions/AbuseFilter/Views/AbuseFilterViewTools.php |
— | — | @@ -0,0 +1,67 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +if (!defined( 'MEDIAWIKI' )) |
| 5 | + die(); |
| 6 | + |
| 7 | +class AbuseFilterViewTools extends AbuseFilterView { |
| 8 | + function show( ) { |
| 9 | + global $wgRequest,$wgOut; |
| 10 | + |
| 11 | + // Header |
| 12 | + $wgOut->setSubTitle( wfMsg( 'abusefilter-tools-subtitle' ) ); |
| 13 | + $wgOut->addWikiMsg( 'abusefilter-tools-text' ); |
| 14 | + |
| 15 | + // Expression evaluator |
| 16 | + $eval = ''; |
| 17 | + $eval .= Xml::textarea( 'wpTestExpr', "" ); |
| 18 | + $eval .= Xml::tags( 'p', null, Xml::element( 'input', array( 'type' => 'button', 'id' => 'mw-abusefilter-submitexpr', 'onclick' => 'doExprSubmit();', 'value' => wfMsg( 'abusefilter-tools-submitexpr' ) ) ) ); |
| 19 | + $eval .= Xml::element( 'p', array( 'id' => 'mw-abusefilter-expr-result' ), ' ' ); |
| 20 | + $eval = Xml::fieldset( wfMsg( 'abusefilter-tools-expr' ), $eval ); |
| 21 | + $wgOut->addHTML( $eval ); |
| 22 | + |
| 23 | + // Associated script |
| 24 | + $exprScript = "function doExprSubmit() |
| 25 | + { |
| 26 | + var expr = document.getElementById('wpTestExpr').value; |
| 27 | + injectSpinner( document.getElementById( 'mw-abusefilter-submitexpr' ), 'abusefilter-expr' ); |
| 28 | + sajax_do_call( 'AbuseFilter::ajaxEvaluateExpression', [expr], processExprResult ); |
| 29 | + } |
| 30 | + function processExprResult( request ) { |
| 31 | + var response = request.responseText; |
| 32 | + |
| 33 | + removeSpinner( 'abusefilter-expr' ); |
| 34 | + |
| 35 | + var el = document.getElementById( 'mw-abusefilter-expr-result' ); |
| 36 | + changeText( el, response ); |
| 37 | + } |
| 38 | + function doReautoSubmit() |
| 39 | + { |
| 40 | + var name = document.getElementById('reautoconfirm-user').value; |
| 41 | + injectSpinner( document.getElementById( 'mw-abusefilter-reautoconfirmsubmit' ), 'abusefilter-reautoconfirm' ); |
| 42 | + sajax_do_call( 'AbuseFilter::ajaxReAutoconfirm', [name], processReautoconfirm ); |
| 43 | + } |
| 44 | + function processReautoconfirm( request ) { |
| 45 | + var response = request.responseText; |
| 46 | + |
| 47 | + if (strlen(response)) { |
| 48 | + jsMsg( response ); |
| 49 | + } |
| 50 | + |
| 51 | + removeSpinner( 'abusefilter-reautoconfirm' ); |
| 52 | + } |
| 53 | + "; |
| 54 | + |
| 55 | + $wgOut->addInlineScript( $exprScript ); |
| 56 | + |
| 57 | + global $wgUser; |
| 58 | + |
| 59 | + if ($wgUser->isAllowed( 'abusefilter-modify' )) { |
| 60 | + // Hacky little box to re-enable autoconfirmed if it got disabled |
| 61 | + $rac = ''; |
| 62 | + $rac .= Xml::inputLabel( wfMsg( 'abusefilter-tools-reautoconfirm-user' ), 'wpReAutoconfirmUser', 'reautoconfirm-user', 45 ); |
| 63 | + $rac .= Xml::element( 'input', array( 'type' => 'button', 'id' => 'mw-abusefilter-reautoconfirmsubmit', 'onclick' => 'doReautoSubmit();', 'value' => wfMsg( 'abusefilter-tools-reautoconfirm-submit' ) ) ); |
| 64 | + $rac = Xml::fieldset( wfMsg( 'abusefilter-tools-reautoconfirm' ), $rac ); |
| 65 | + $wgOut->addHTML( $rac ); |
| 66 | + } |
| 67 | + } |
| 68 | +} |
\ No newline at end of file |
Index: branches/change-tagging/extensions/AbuseFilter/Views/AbuseFilterViewHistory.php |
— | — | @@ -0,0 +1,134 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +if (!defined( 'MEDIAWIKI' )) |
| 5 | + die(); |
| 6 | + |
| 7 | +class AbuseFilterViewHistory extends AbuseFilterView { |
| 8 | + |
| 9 | + function __construct( $page, $params ) { |
| 10 | + parent::__construct( $page, $params ); |
| 11 | + $this->mFilter = $page->mFilter; |
| 12 | + } |
| 13 | + |
| 14 | + function show() { |
| 15 | + global $wgRequest,$wgOut; |
| 16 | + |
| 17 | + global $wgUser; |
| 18 | + |
| 19 | + $filter = $this->mFilter; |
| 20 | + |
| 21 | + $sk = $wgUser->getSkin(); |
| 22 | + $wgOut->setPageTitle( wfMsg( 'abusefilter-history', $filter ) ); |
| 23 | + $backToFilter_label = wfMsgExt( 'abusefilter-history-backedit', array('parseinline') ); |
| 24 | + $backToList_label = wfMsgExt( 'abusefilter-history-backlist', array('parseinline') ); |
| 25 | + $backlinks = $sk->makeKnownLinkObj( $this->getTitle( $filter ), $backToFilter_label ) . ' • ' . |
| 26 | + $sk->makeKnownLinkObj( $this->getTitle( ), $backToList_label ); |
| 27 | + $wgOut->addHTML( Xml::tags( 'p', null, $backlinks ) ); |
| 28 | + |
| 29 | + $pager = new AbuseFilterHistoryPager( $filter, $this ); |
| 30 | + $table = $pager->getBody(); |
| 31 | + |
| 32 | + $wgOut->addHTML( $pager->getNavigationBar() . $table . $pager->getNavigationBar() ); |
| 33 | + } |
| 34 | +} |
| 35 | + |
| 36 | +class AbuseFilterHistoryPager extends TablePager { |
| 37 | + |
| 38 | + function __construct( $filter, $page ) { |
| 39 | + $this->mFilter = $filter; |
| 40 | + $this->mPage = $page; |
| 41 | + $this->mDefaultDirection = true; |
| 42 | + parent::__construct(); |
| 43 | + } |
| 44 | + |
| 45 | + function getFieldNames() { |
| 46 | + static $headers = null; |
| 47 | + |
| 48 | + if (!empty($headers)) { |
| 49 | + return $headers; |
| 50 | + } |
| 51 | + |
| 52 | + $headers = array( 'afh_timestamp' => 'abusefilter-history-timestamp', 'afh_user_text' => 'abusefilter-history-user', 'afh_public_comments' => 'abusefilter-history-public', |
| 53 | + 'afh_flags' => 'abusefilter-history-flags', 'afh_pattern' => 'abusefilter-history-filter', 'afh_comments' => 'abusefilter-history-comments', 'afh_actions' => 'abusefilter-history-actions' ); |
| 54 | + |
| 55 | + $headers = array_map( 'wfMsg', $headers ); |
| 56 | + |
| 57 | + return $headers; |
| 58 | + } |
| 59 | + |
| 60 | + function formatValue( $name, $value ) { |
| 61 | + global $wgOut,$wgLang; |
| 62 | + |
| 63 | + static $sk=null; |
| 64 | + |
| 65 | + if (empty($sk)) { |
| 66 | + global $wgUser; |
| 67 | + $sk = $wgUser->getSkin(); |
| 68 | + } |
| 69 | + |
| 70 | + $row = $this->mCurrentRow; |
| 71 | + |
| 72 | + switch($name) { |
| 73 | + case 'afh_timestamp': |
| 74 | + $title = SpecialPage::getTitleFor( 'AbuseFilter', 'history/'.$this->mFilter.'/item/'.$row->afh_id ); |
| 75 | + return $sk->link( $title, $wgLang->timeanddate( $row->afh_timestamp ) ); |
| 76 | + case 'afh_user_text': |
| 77 | + return $sk->userLink( $row->afh_user, $row->afh_user_text ) . ' ' . $sk->userToolLinks( $row->afh_user, $row->afh_user_text ); |
| 78 | + case 'afh_public_comments': |
| 79 | + return $wgOut->parse( $value ); |
| 80 | + case 'afh_flags': |
| 81 | + $flags = array_filter( explode( ',', $value ) ); |
| 82 | + $flags_display = array(); |
| 83 | + foreach( $flags as $flag ) { |
| 84 | + $flags_display[] = wfMsg( "abusefilter-history-$flag" ); |
| 85 | + } |
| 86 | + return implode( ', ', $flags_display ); |
| 87 | + case 'afh_pattern': |
| 88 | + return htmlspecialchars( $wgLang->truncate( $value, 200, '...' ) ); |
| 89 | + case 'afh_comments': |
| 90 | + return htmlspecialchars( $wgLang->truncate( $value, 200, '...' ) ); |
| 91 | + case 'afh_actions': |
| 92 | + $actions = unserialize( $value ); |
| 93 | + |
| 94 | + $display_actions = ''; |
| 95 | + |
| 96 | + foreach( $actions as $action => $parameters ) { |
| 97 | + $display_actions .= Xml::tags( 'li', null, wfMsgExt( 'abusefilter-history-action', array( 'parseinline' ), array($action, implode('; ', $parameters)) ) ); |
| 98 | + } |
| 99 | + $display_actions = Xml::tags( 'ul', null, $display_actions ); |
| 100 | + |
| 101 | + return $display_actions; |
| 102 | + } |
| 103 | + |
| 104 | + return "Unable to format name $name\n"; |
| 105 | + } |
| 106 | + |
| 107 | + function getQueryInfo() { |
| 108 | + return array( |
| 109 | + 'tables' => 'abuse_filter_history', |
| 110 | + 'fields' => array( 'afh_timestamp', 'afh_user_text', 'afh_public_comments', 'afh_flags', 'afh_pattern', 'afh_comments', 'afh_actions', 'afh_id', 'afh_user' ), |
| 111 | + 'conds' => array( 'afh_filter' => $this->mFilter ), |
| 112 | + ); |
| 113 | + } |
| 114 | + |
| 115 | + function getIndexField() { |
| 116 | + return 'afh_timestamp'; |
| 117 | + } |
| 118 | + |
| 119 | + function getDefaultSort() { |
| 120 | + return 'afh_timestamp'; |
| 121 | + } |
| 122 | + |
| 123 | + function isFieldSortable($name) { |
| 124 | + $sortable_fields = array( 'afh_timestamp', 'afh_user_text' ); |
| 125 | + return in_array( $name, $sortable_fields ); |
| 126 | + } |
| 127 | + |
| 128 | + /** |
| 129 | + * Title used for self-links. Override this if you want to be able to |
| 130 | + * use a title other than $wgTitle |
| 131 | + */ |
| 132 | + function getTitle() { |
| 133 | + return $this->mPage->getTitle( "history/".$this->mFilter ); |
| 134 | + } |
| 135 | +} |
\ No newline at end of file |
Index: branches/change-tagging/extensions/AbuseFilter/Views/AbuseFilterViewEdit.php |
— | — | @@ -0,0 +1,483 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +if (!defined( 'MEDIAWIKI' )) |
| 5 | + die(); |
| 6 | + |
| 7 | +class AbuseFilterViewEdit extends AbuseFilterView { |
| 8 | + |
| 9 | + static $history_mappings = array( 'af_pattern' => 'afh_pattern', 'af_user' => 'afh_user', 'af_user_text' => 'afh_user_text', 'af_timestamp' => 'afh_timestamp', 'af_comments' => 'afh_comments', 'af_public_comments' => 'afh_public_comments', 'af_deleted' => 'afh_deleted', 'af_id' => 'afh_filter' ); |
| 10 | + |
| 11 | + function __construct( $page, $params ) { |
| 12 | + parent::__construct( $page, $params ); |
| 13 | + $this->mFilter = $page->mFilter; |
| 14 | + $this->mHistoryID = $page->mHistoryID; |
| 15 | + } |
| 16 | + |
| 17 | + function show( ) { |
| 18 | + global $wgRequest, $wgUser, $wgOut; |
| 19 | + |
| 20 | + $filter = $this->mFilter; |
| 21 | + $history_id = $this->mHistoryID; |
| 22 | + $this->mSkin = $wgUser->getSkin(); |
| 23 | + |
| 24 | + $editToken = $wgRequest->getVal( 'wpEditToken' ); |
| 25 | + $didEdit = $this->canEdit() && $wgUser->matchEditToken( $editToken, array( 'abusefilter', $filter ) ); |
| 26 | + |
| 27 | + if ($didEdit) { |
| 28 | + // Check syntax |
| 29 | + $syntaxerr = AbuseFilter::checkSyntax( $wgRequest->getVal( 'wpFilterRules' ) ); |
| 30 | + if ($syntaxerr !== true ) { |
| 31 | + $wgOut->addHTML( $this->buildFilterEditor( wfMsgExt( 'abusefilter-edit-badsyntax', array( 'parseinline' ), array( $syntaxerr ) ), $filter, $history_id ) ); |
| 32 | + } |
| 33 | + |
| 34 | + $dbw = wfGetDB( DB_MASTER ); |
| 35 | + |
| 36 | + list ($newRow, $actions) = $this->loadRequest($filter); |
| 37 | + |
| 38 | + $newRow = get_object_vars($newRow); // Convert from object to array |
| 39 | + |
| 40 | + // Set last modifier. |
| 41 | + $newRow['af_timestamp'] = $dbw->timestamp( wfTimestampNow() ); |
| 42 | + $newRow['af_user'] = $wgUser->getId(); |
| 43 | + $newRow['af_user_text'] = $wgUser->getName(); |
| 44 | + |
| 45 | + $dbw->begin(); |
| 46 | + |
| 47 | + if ($filter == 'new') { |
| 48 | + $new_id = $dbw->nextSequenceValue( 'abuse_filter_af_id_seq' ); |
| 49 | + $is_new = true; |
| 50 | + } else { |
| 51 | + $new_id = $this->mFilter; |
| 52 | + $is_new = false; |
| 53 | + } |
| 54 | + |
| 55 | + $newRow['af_throttled'] = $newRow['af_throttled'] && !$newRow['af_enabled']; |
| 56 | + |
| 57 | + $newRow['af_id'] = $new_id; |
| 58 | + |
| 59 | + $dbw->replace( 'abuse_filter', array( 'af_id' ), $newRow, __METHOD__ ); |
| 60 | + |
| 61 | + if ($is_new) { |
| 62 | + $new_id = $dbw->insertId(); |
| 63 | + } |
| 64 | + |
| 65 | + // Actions |
| 66 | + global $wgAbuseFilterAvailableActions; |
| 67 | + $deadActions = array(); |
| 68 | + $actionsRows = array(); |
| 69 | + foreach( $wgAbuseFilterAvailableActions as $action ) { |
| 70 | + // Check if it's set |
| 71 | + $enabled = isset($actions[$action]) && (bool)$actions[$action]; |
| 72 | + |
| 73 | + if ($enabled) { |
| 74 | + $parameters = $actions[$action]['parameters']; |
| 75 | + |
| 76 | + $thisRow = array( 'afa_filter' => $new_id, 'afa_consequence' => $action, 'afa_parameters' => implode( "\n", $parameters ) ); |
| 77 | + $actionsRows[] = $thisRow; |
| 78 | + } else { |
| 79 | + $deadActions[] = $action; |
| 80 | + } |
| 81 | + } |
| 82 | + |
| 83 | + // Create a history row |
| 84 | + $afh_row = array(); |
| 85 | + |
| 86 | + foreach( self::$history_mappings as $af_col => $afh_col ) { |
| 87 | + $afh_row[$afh_col] = $newRow[$af_col]; |
| 88 | + } |
| 89 | + |
| 90 | + // Actions |
| 91 | + $displayActions = array(); |
| 92 | + foreach( $actions as $action ) { |
| 93 | + $displayActions[$action['action']] = $action['parameters']; |
| 94 | + } |
| 95 | + $afh_row['afh_actions'] = serialize($displayActions); |
| 96 | + |
| 97 | + // Flags |
| 98 | + $flags = array(); |
| 99 | + if ($newRow['af_hidden']) |
| 100 | + $flags[] = 'hidden'; |
| 101 | + if ($newRow['af_enabled']) |
| 102 | + $flags[] = 'enabled'; |
| 103 | + if ($newRow['af_deleted']) |
| 104 | + $flags[] = 'deleted'; |
| 105 | + |
| 106 | + $afh_row['afh_flags'] = implode( ",", $flags ); |
| 107 | + |
| 108 | + $afh_row['afh_filter'] = $new_id; |
| 109 | + |
| 110 | + // Do the update |
| 111 | + $dbw->insert( 'abuse_filter_history', $afh_row, __METHOD__ ); |
| 112 | + $dbw->delete( 'abuse_filter_action', array( 'afa_filter' => $filter, 'afa_consequence' => $deadActions ), __METHOD__ ); |
| 113 | + $dbw->replace( 'abuse_filter_action', array( array( 'afa_filter', 'afa_consequence' ) ), $actionsRows, __METHOD__ ); |
| 114 | + |
| 115 | + $dbw->commit(); |
| 116 | + |
| 117 | + global $wgOut; |
| 118 | + |
| 119 | + $wgOut->redirect( $this->getTitle()->getLocalURL( 'result=success&changedfilter='.$new_id ) ); |
| 120 | + } else { |
| 121 | + if ($history_id) { |
| 122 | + $wgOut->addWikiMsg( 'abusefilter-edit-oldwarning', $this->mHistoryID, $this->mFilter ); |
| 123 | + } |
| 124 | + |
| 125 | + $wgOut->addHTML( $this->buildFilterEditor( null, $this->mFilter, $history_id ) ); |
| 126 | + |
| 127 | + if ($history_id) { |
| 128 | + $wgOut->addWikiMsg( 'abusefilter-edit-oldwarning', $this->mHistoryID, $this->mFilter ); |
| 129 | + } |
| 130 | + } |
| 131 | + } |
| 132 | + |
| 133 | + function buildFilterEditor( $error, $filter, $history_id=null ) { |
| 134 | + if( $filter === null ) { |
| 135 | + return false; |
| 136 | + } |
| 137 | + |
| 138 | + // Build the edit form |
| 139 | + global $wgOut,$wgLang,$wgUser; |
| 140 | + $sk = $this->mSkin; |
| 141 | + |
| 142 | + list ($row, $actions) = $this->loadRequest($filter, $history_id); |
| 143 | + |
| 144 | + if( !$row ) { |
| 145 | + return false; |
| 146 | + } |
| 147 | + |
| 148 | + $wgOut->setSubtitle( wfMsg( 'abusefilter-edit-subtitle', $filter, $history_id ) ); |
| 149 | + |
| 150 | + if (isset($row->af_hidden) && $row->af_hidden && !$this->canEdit()) { |
| 151 | + return wfMsg( 'abusefilter-edit-denied' ); |
| 152 | + } |
| 153 | + |
| 154 | + $output = ''; |
| 155 | + if ($error) { |
| 156 | + $wgOut->addHTML( "<span class=\"error\">$error</span>" ); |
| 157 | + } |
| 158 | + |
| 159 | + $wgOut->addHTML( $sk->link( $this->getTitle(), wfMsg( 'abusefilter-history-backlist' ) ) ); |
| 160 | + |
| 161 | + $fields = array(); |
| 162 | + |
| 163 | + $fields['abusefilter-edit-id'] = $this->mFilter == 'new' ? wfMsg( 'abusefilter-edit-new' ) : $filter; |
| 164 | + $fields['abusefilter-edit-description'] = Xml::input( 'wpFilterDescription', 45, isset( $row->af_public_comments ) ? $row->af_public_comments : '' ); |
| 165 | + |
| 166 | + // Hit count display |
| 167 | + if( !empty($row->af_hit_count) ){ |
| 168 | + $count = (int)$row->af_hit_count; |
| 169 | + $count_display = wfMsgExt( 'abusefilter-hitcount', array( 'parseinline' ), |
| 170 | + $wgLang->formatNum( $count ) |
| 171 | + ); |
| 172 | + $hitCount = $sk->makeKnownLinkObj( SpecialPage::getTitleFor( 'AbuseLog' ), $count_display, 'wpSearchFilter='.$row->af_id ); |
| 173 | + |
| 174 | + $fields['abusefilter-edit-hitcount'] = $hitCount; |
| 175 | + } |
| 176 | + |
| 177 | + if ($filter !== 'new') { |
| 178 | + // Statistics |
| 179 | + global $wgMemc, $wgLang; |
| 180 | + $matches_count = $wgMemc->get( AbuseFilter::filterMatchesKey( $filter ) ); |
| 181 | + $total = $wgMemc->get( AbuseFilter::filterUsedKey() ); |
| 182 | + |
| 183 | + if ($total > 0) { |
| 184 | + $matches_percent = sprintf( '%.2f', 100 * $matches_count / $total ); |
| 185 | + $fields['abusefilter-edit-status-label'] = |
| 186 | + wfMsgExt( 'abusefilter-edit-status', array( 'parsemag', 'escape' ), |
| 187 | + $wgLang->formatNum($total), |
| 188 | + $wgLang->formatNum($matches_count), |
| 189 | + $wgLang->formatNum($matches_percent) |
| 190 | + ); |
| 191 | + } |
| 192 | + } |
| 193 | + |
| 194 | + $fields['abusefilter-edit-rules'] = $this->buildEditBox($row); |
| 195 | + $fields['abusefilter-edit-notes'] = Xml::textarea( 'wpFilterNotes', ( isset( $row->af_comments ) ? $row->af_comments."\n" : "\n" ) ); |
| 196 | + |
| 197 | + // Build checkboxen |
| 198 | + $checkboxes = array( 'hidden', 'enabled', 'deleted' ); |
| 199 | + $flags = ''; |
| 200 | + |
| 201 | + if (isset($row->af_throttled) && $row->af_throttled) { |
| 202 | + global $wgAbuseFilterEmergencyDisableThreshold; |
| 203 | + $threshold_percent = sprintf( '%.2f', $wgAbuseFilterEmergencyDisableThreshold * 100 ); |
| 204 | + $flags .= $wgOut->parse( wfMsg( 'abusefilter-edit-throttled', $wgLang->formatNum( $threshold_percent ) ) ); |
| 205 | + } |
| 206 | + |
| 207 | + foreach( $checkboxes as $checkboxId ) { |
| 208 | + $message = "abusefilter-edit-$checkboxId"; |
| 209 | + $dbField = "af_$checkboxId"; |
| 210 | + $postVar = "wpFilter".ucfirst($checkboxId); |
| 211 | + |
| 212 | + $checkbox = Xml::checkLabel( wfMsg( $message ), $postVar, $postVar, isset( $row->$dbField ) ? $row->$dbField : false ); |
| 213 | + $checkbox = Xml::tags( 'p', null, $checkbox ); |
| 214 | + $flags .= $checkbox; |
| 215 | + } |
| 216 | + $fields['abusefilter-edit-flags'] = $flags; |
| 217 | + |
| 218 | + if ($filter != 'new') { |
| 219 | + // Last modification details |
| 220 | + $user = $sk->userLink( $row->af_user, $row->af_user_text ) . $sk->userToolLinks( $row->af_user, $row->af_user_text ); |
| 221 | + $fields['abusefilter-edit-lastmod'] = wfMsgExt( 'abusefilter-edit-lastmod-text', array( 'parseinline', 'replaceafter' ), array( $wgLang->timeanddate( $row->af_timestamp ), $user ) ); |
| 222 | + $history_display = wfMsgExt( 'abusefilter-edit-viewhistory', array( 'parseinline' ) ); |
| 223 | + $fields['abusefilter-edit-history'] = $sk->makeKnownLinkObj( $this->getTitle( 'history/'.$filter ), $history_display ); |
| 224 | + } |
| 225 | + |
| 226 | + $form = Xml::buildForm( $fields ); |
| 227 | + $form = Xml::fieldset( wfMsg( 'abusefilter-edit-main' ), $form ); |
| 228 | + $form .= Xml::fieldset( wfMsg( 'abusefilter-edit-consequences' ), $this->buildConsequenceEditor( $row, $actions ) ); |
| 229 | + |
| 230 | + if ($this->canEdit()) { |
| 231 | + $form .= Xml::submitButton( wfMsg( 'abusefilter-edit-save' ) ); |
| 232 | + $form .= Xml::hidden( 'wpEditToken', $wgUser->editToken( array( 'abusefilter', $filter )) ); |
| 233 | + } |
| 234 | + |
| 235 | + $form = Xml::tags( 'form', array( 'action' => $this->getTitle( $filter )->getFullURL(), 'method' => 'POST' ), $form ); |
| 236 | + |
| 237 | + $output .= $form; |
| 238 | + |
| 239 | + return $output; |
| 240 | + } |
| 241 | + |
| 242 | + function buildEditBox( $row ) { |
| 243 | + global $wgOut; |
| 244 | + |
| 245 | + $rules = Xml::textarea( 'wpFilterRules', ( isset( $row->af_pattern ) ? $row->af_pattern."\n" : "\n" ) ); |
| 246 | + |
| 247 | + $dropDown = array( |
| 248 | + 'op-arithmetic' => array('+' => 'addition', '-' => 'subtraction', '*' => 'multiplication', '/' => 'divide', '%' => 'modulo', '**' => 'pow'), |
| 249 | + 'op-comparison' => array('==' => 'equal', '!=' => 'notequal', '<' => 'lt', '>' => 'gt', '<=' => 'lte', '>=' => 'gte'), |
| 250 | + 'op-bool' => array( '!' => 'not', '&' => 'and', '|' => 'or', '^' => 'xor' ), |
| 251 | + 'misc' => array( 'val1 ? iftrue : iffalse' => 'ternary', 'in' => 'in', 'like' => 'like', '""' => 'stringlit', ), |
| 252 | + 'funcs' => array( 'length(string)' => 'length', 'lcase(string)' => 'lcase', 'ccnorm(string)' => 'ccnorm', 'rmdoubles(string)' => 'rmdoubles', 'specialratio(string)' => 'specialratio', 'norm(string)' => 'norm', 'count(needle,haystack)' => 'count' ), |
| 253 | + 'vars' => array( 'ACCOUNTNAME' => 'accountname', 'ACTION' => 'action', 'ADDED_LINES' => 'addedlines', 'EDIT_DELTA' => 'delta', 'EDIT_DIFF' => 'diff', 'NEW_SIZE' => 'newsize', 'OLD_SIZE' => 'oldsize', 'REMOVED_LINES' => 'removedlines', 'SUMMARY' => 'summary', 'ARTICLE_ARTICLEID' => 'article-id', 'ARTICLE_NAMESPACE' => 'article-ns', 'ARTICLE_TEXT' => 'article-text', 'ARTICLE_PREFIXEDTEXT' => 'article-prefixedtext', 'MOVED_FROM_ARTICLEID' => 'movedfrom-id', 'MOVED_FROM_NAMESPACE' => 'movedfrom-ns', 'MOVED_FROM_TEXT' => 'movedfrom-text', 'MOVED_FROM_PREFIXEDTEXT' => 'movedfrom-prefixedtext', 'MOVED_TO_ARTICLEID' => 'movedto-id', 'MOVED_TO_NAMESPACE' => 'movedto-ns', 'MOVED_TO_TEXT' => 'movedto-text', 'MOVED_TO_PREFIXEDTEXT' => 'movedto-prefixedtext', 'USER_EDITCOUNT' => 'user-editcount', 'USER_AGE' => 'user-age', 'USER_NAME' => 'user-name', 'USER_GROUPS' => 'user-groups', 'USER_EMAILCONFIRM' => 'user-emailconfirm'), |
| 254 | + ); |
| 255 | + |
| 256 | + // Generate builder drop-down |
| 257 | + $builder = ''; |
| 258 | + |
| 259 | + $builder .= Xml::option( wfMsg( "abusefilter-edit-builder-select") ); |
| 260 | + |
| 261 | + foreach( $dropDown as $group => $values ) { |
| 262 | + $builder .= Xml::openElement( 'optgroup', array( 'label' => wfMsg( "abusefilter-edit-builder-group-$group" ) ) ) . "\n"; |
| 263 | + |
| 264 | + foreach( $values as $content => $name ) { |
| 265 | + $builder .= Xml::option( wfMsg( "abusefilter-edit-builder-$group-$name" ), $content ) . "\n"; |
| 266 | + } |
| 267 | + |
| 268 | + $builder .= Xml::closeElement( 'optgroup' ) . "\n"; |
| 269 | + } |
| 270 | + |
| 271 | + $rules .= Xml::tags( 'select', array( 'id' => 'wpFilterBuilder', 'onchange' => 'addText();' ), $builder ); |
| 272 | + |
| 273 | + // Add syntax checking |
| 274 | + $rules .= Xml::element( 'input', array( 'type' => 'button', 'onclick' => 'doSyntaxCheck()', 'value' => wfMsg( 'abusefilter-edit-check' ), 'id' => 'mw-abusefilter-syntaxcheck' ) ); |
| 275 | + $rules .= Xml::element( 'div', array( 'id' => 'mw-abusefilter-syntaxresult', 'style' => 'display: none;' ), ' ' ); |
| 276 | + |
| 277 | + // Add script |
| 278 | + $wgOut->addInlineScript( file_get_contents(dirname(__FILE__)."/edit.js") ); |
| 279 | + |
| 280 | + return $rules; |
| 281 | + } |
| 282 | + |
| 283 | + function buildConsequenceEditor( $row, $actions ) { |
| 284 | + global $wgAbuseFilterAvailableActions; |
| 285 | + $setActions = array(); |
| 286 | + foreach( $wgAbuseFilterAvailableActions as $action ) { |
| 287 | + $setActions[$action] = array_key_exists( $action, $actions ); |
| 288 | + } |
| 289 | + |
| 290 | + $output = ''; |
| 291 | + |
| 292 | + // Special case: flagging - always on. |
| 293 | + $checkbox = Xml::checkLabel( wfMsg( 'abusefilter-edit-action-flag' ), 'wpFilterActionFlag', 'wpFilterActionFlag', true, array( 'disabled' => '1' ) ); |
| 294 | + $output .= Xml::tags( 'p', null, $checkbox ); |
| 295 | + |
| 296 | + // Special case: throttling |
| 297 | + $throttleSettings = Xml::checkLabel( wfMsg( 'abusefilter-edit-action-throttle' ), 'wpFilterActionThrottle', 'wpFilterActionThrottle', $setActions['throttle'] ); |
| 298 | + $throttleFields = array(); |
| 299 | + |
| 300 | + if ($setActions['throttle']) { |
| 301 | + array_shift( $actions['throttle']['parameters'] ); |
| 302 | + $throttleRate = explode(',',$actions['throttle']['parameters'][0]); |
| 303 | + $throttleCount = $throttleRate[0]; |
| 304 | + $throttlePeriod = $throttleRate[1]; |
| 305 | + |
| 306 | + $throttleGroups = implode("\n", array_slice($actions['throttle']['parameters'], 1 ) ); |
| 307 | + } else { |
| 308 | + $throttleCount = 3; |
| 309 | + $throttlePeriod = 60; |
| 310 | + |
| 311 | + $throttleGroups = "user\n"; |
| 312 | + } |
| 313 | + |
| 314 | + $throttleFields['abusefilter-edit-throttle-count'] = Xml::input( 'wpFilterThrottleCount', 20, $throttleCount ); |
| 315 | + $throttleFields['abusefilter-edit-throttle-period'] = wfMsgExt( 'abusefilter-edit-throttle-seconds', array( 'parseinline', 'replaceafter' ), array(Xml::input( 'wpFilterThrottlePeriod', 20, $throttlePeriod ) ) ); |
| 316 | + $throttleFields['abusefilter-edit-throttle-groups'] = Xml::textarea( 'wpFilterThrottleGroups', $throttleGroups."\n" ); |
| 317 | + $throttleSettings .= Xml::buildForm( $throttleFields ); |
| 318 | + $output .= Xml::tags( 'p', null, $throttleSettings ); |
| 319 | + |
| 320 | + // Special case: Warning |
| 321 | + $checkbox = Xml::checkLabel( wfMsg( 'abusefilter-edit-action-warn' ), 'wpFilterActionWarn', 'wpFilterActionWarn', $setActions['warn'] ); |
| 322 | + $output .= Xml::tags( 'p', null, $checkbox ); |
| 323 | + |
| 324 | + $warnMsg = empty($setActions['warn']) ? 'abusefilter-warning' : $actions['warn']['parameters'][0]; |
| 325 | + $warnFields['abusefilter-edit-warn-message'] = Xml::input( 'wpFilterWarnMessage', 45, $warnMsg ); |
| 326 | + $output .= Xml::tags( 'p', null, Xml::buildForm( $warnFields ) ); |
| 327 | + |
| 328 | + // Special case: tagging |
| 329 | + if ($setActions['tag']) { |
| 330 | + $tags = $actions['tag']['parameters']; |
| 331 | + } else { |
| 332 | + $tags = array(); |
| 333 | + } |
| 334 | + |
| 335 | + $checkbox = Xml::checkLabel( wfMsg('abusefilter-edit-action-tag'), 'wpFilterActionTag', 'wpFilterActionTag', $setActions['tag'] ); |
| 336 | + $output .= Xml::tags( 'p', null, $checkbox ); |
| 337 | + |
| 338 | + $tagFields['abusefilter-edit-tag-tag'] = Xml::textarea( 'wpFilterTags', implode( "\n", $tags ) ); |
| 339 | + $output .= Xml::tags( 'p', null, Xml::buildForm( $tagFields ) ); |
| 340 | + |
| 341 | + // The remainder are just toggles |
| 342 | + $remainingActions = array_diff( $wgAbuseFilterAvailableActions, array( 'flag', 'throttle', 'warn', 'tag' ) ); |
| 343 | + |
| 344 | + foreach( $remainingActions as $action ) { |
| 345 | + $message = 'abusefilter-edit-action-'.$action; |
| 346 | + $form_field = 'wpFilterAction' . ucfirst($action); |
| 347 | + $status = $setActions[$action]; |
| 348 | + |
| 349 | + $thisAction = Xml::checkLabel( wfMsg( $message ), $form_field, $form_field, $status ); |
| 350 | + $thisAction = Xml::tags( 'p', null, $thisAction ); |
| 351 | + |
| 352 | + $output .= $thisAction; |
| 353 | + } |
| 354 | + |
| 355 | + return $output; |
| 356 | + } |
| 357 | + |
| 358 | + function loadFilterData( $id ) { |
| 359 | + |
| 360 | + if ($id == 'new') { |
| 361 | + return array( new StdClass, array() ); |
| 362 | + } |
| 363 | + |
| 364 | + $dbr = wfGetDB( DB_SLAVE ); |
| 365 | + |
| 366 | + // Load the main row |
| 367 | + $row = $dbr->selectRow( 'abuse_filter', '*', array( 'af_id' => $id ), __METHOD__ ); |
| 368 | + |
| 369 | + if (!isset($row) || !isset($row->af_id) || !$row->af_id) |
| 370 | + return null; |
| 371 | + |
| 372 | + // Load the actions |
| 373 | + $actions = array(); |
| 374 | + $res = $dbr->select( 'abuse_filter_action', '*', array( 'afa_filter' => $id), __METHOD__ ); |
| 375 | + while ( $actionRow = $dbr->fetchObject( $res ) ) { |
| 376 | + $thisAction = array(); |
| 377 | + $thisAction['action'] = $actionRow->afa_consequence; |
| 378 | + $thisAction['parameters'] = explode( "\n", $actionRow->afa_parameters ); |
| 379 | + |
| 380 | + $actions[$actionRow->afa_consequence] = $thisAction; |
| 381 | + } |
| 382 | + |
| 383 | + return array( $row, $actions ); |
| 384 | + } |
| 385 | + |
| 386 | + function loadRequest( $filter, $history_id = null ) { |
| 387 | + static $row = null; |
| 388 | + static $actions = null; |
| 389 | + global $wgRequest; |
| 390 | + |
| 391 | + if (!is_null($actions) && !is_null($row)) { |
| 392 | + return array($row,$actions); |
| 393 | + } elseif ($wgRequest->wasPosted()) { |
| 394 | + ## Nothing, we do it all later |
| 395 | + } elseif ( $history_id ) { |
| 396 | + return $this->loadHistoryItem( $history_id ); |
| 397 | + } else { |
| 398 | + return $this->loadFilterData( $filter ); |
| 399 | + } |
| 400 | + |
| 401 | + // We need some details like last editor |
| 402 | + list($row) = $this->loadFilterData( $filter ); |
| 403 | + |
| 404 | + $textLoads = array( 'af_public_comments' => 'wpFilterDescription', 'af_pattern' => 'wpFilterRules', 'af_comments' => 'wpFilterNotes' ); |
| 405 | + |
| 406 | + foreach( $textLoads as $col => $field ) { |
| 407 | + $row->$col = trim($wgRequest->getVal( $field )); |
| 408 | + } |
| 409 | + |
| 410 | + $row->af_deleted = $wgRequest->getBool( 'wpFilterDeleted' ); |
| 411 | + $row->af_enabled = $wgRequest->getBool( 'wpFilterEnabled' ) && !$row->af_deleted; |
| 412 | + $row->af_hidden = $wgRequest->getBool( 'wpFilterHidden' ); |
| 413 | + |
| 414 | + // Actions |
| 415 | + global $wgAbuseFilterAvailableActions; |
| 416 | + $actions = array(); |
| 417 | + foreach( $wgAbuseFilterAvailableActions as $action ) { |
| 418 | + // Check if it's set |
| 419 | + $enabled = $wgRequest->getBool( 'wpFilterAction'.ucfirst($action) ); |
| 420 | + |
| 421 | + if ($enabled) { |
| 422 | + $parameters = array(); |
| 423 | + |
| 424 | + if ($action == 'throttle') { |
| 425 | + // Grumble grumble. |
| 426 | + // We need to load the parameters |
| 427 | + $throttleCount = $wgRequest->getIntOrNull( 'wpFilterThrottleCount' ); |
| 428 | + $throttlePeriod = $wgRequest->getIntOrNull( 'wpFilterThrottlePeriod' ); |
| 429 | + $throttleGroups = explode("\n", trim( $wgRequest->getText( 'wpFilterThrottleGroups' ) ) ); |
| 430 | + |
| 431 | + $parameters[0] = $this->mFilter; // For now, anyway |
| 432 | + $parameters[1] = "$throttleCount,$throttlePeriod"; |
| 433 | + $parameters = array_merge( $parameters, $throttleGroups ); |
| 434 | + } elseif ($action == 'warn') { |
| 435 | + $parameters[0] = $wgRequest->getVal( 'wpFilterWarnMessage' ); |
| 436 | + } elseif ($action == 'tag') { |
| 437 | + $parameters = explode("\n", $wgRequest->getText( 'wpFilterTags' ) ); |
| 438 | + } |
| 439 | + |
| 440 | + $thisAction = array( 'action' => $action, 'parameters' => $parameters ); |
| 441 | + $actions[$action] = $thisAction; |
| 442 | + } |
| 443 | + } |
| 444 | + |
| 445 | + return array( $row, $actions ); |
| 446 | + } |
| 447 | + |
| 448 | + function loadHistoryItem( $id ) { |
| 449 | + $dbr = wfGetDB( DB_SLAVE ); |
| 450 | + |
| 451 | + // Load the row. |
| 452 | + $row = $dbr->selectRow( 'abuse_filter_history', '*', array( 'afh_id' => $id ), __METHOD__ ); |
| 453 | + |
| 454 | + ## Translate into an abuse_filter row with some black magic. This is ever so slightly evil! |
| 455 | + $af_row = new StdClass; |
| 456 | + |
| 457 | + foreach (self::$history_mappings as $af_col => $afh_col ) { |
| 458 | + $af_row->$af_col = $row->$afh_col; |
| 459 | + } |
| 460 | + |
| 461 | + ## Process flags |
| 462 | + |
| 463 | + $af_row->af_deleted = 0; |
| 464 | + $af_row->af_hidden = 0; |
| 465 | + $af_row->af_enabled = 0; |
| 466 | + |
| 467 | + $flags = explode(',', $row->afh_flags ); |
| 468 | + foreach( $flags as $flag ) { |
| 469 | + $col_name = "af_$flag"; |
| 470 | + $af_row->$col_name = 1; |
| 471 | + } |
| 472 | + |
| 473 | + ## Process actions |
| 474 | + $actions_raw = unserialize($row->afh_actions); |
| 475 | + $actions_output = array(); |
| 476 | + |
| 477 | + foreach( $actions_raw as $action => $parameters ) { |
| 478 | + $actions_output[$action] = array( 'action' => $action, 'parameters' => $parameters ); |
| 479 | + } |
| 480 | + |
| 481 | + |
| 482 | + return array( $af_row, $actions_output ); |
| 483 | + } |
| 484 | +} |
\ No newline at end of file |