Index: trunk/extensions/AbuseFilter/AbuseFilter.parser.php |
— | — | @@ -752,7 +752,8 @@ |
753 | 753 | |
754 | 754 | $float = in_string( '.', $tok ); |
755 | 755 | |
756 | | - return array( $float ? doubleval( $tok ) : intval( $tok ), $float ? AFPToken::TFloat : AFPToken::TInt, $code, $pos ); |
| 756 | + if (strlen($tok)) |
| 757 | + return array( $float ? doubleval( $tok ) : intval( $tok ), $float ? AFPToken::TFloat : AFPToken::TInt, $code, $pos ); |
757 | 758 | } |
758 | 759 | |
759 | 760 | if( ctype_punct( $code[0] ) ) { |
Index: trunk/extensions/AbuseFilter/AbuseFilter.php |
— | — | @@ -42,6 +42,7 @@ |
43 | 43 | $wgHooks['AbortMove'][] = 'AbuseFilterHooks::onAbortMove'; |
44 | 44 | $wgHooks['AbortNewAccount'][] = 'AbuseFilterHooks::onAbortNewAccount'; |
45 | 45 | $wgHooks['ArticleDelete'][] = 'AbuseFilterHooks::onArticleDelete'; |
| 46 | +$wgHooks['LoadExtensionSchemaUpdates'][] = 'AbuseFilterHooks::onSchemaUpdate'; |
46 | 47 | |
47 | 48 | $wgAvailableRights[] = 'abusefilter-modify'; |
48 | 49 | $wgAvailableRights[] = 'abusefilter-log-detail'; |
Index: trunk/extensions/AbuseFilter/SpecialAbuseFilter.php |
— | — | @@ -23,9 +23,9 @@ |
24 | 24 | $wgOut->enableClientCache( false ); |
25 | 25 | |
26 | 26 | // Are we allowed? |
27 | | - if ( count( $errors = $this->getTitle()->getUserPermissionsErrors( 'abusefilter-view', $wgUser, true, array( 'ns-specialprotected' ) ) ) ) { |
| 27 | + if ( !$wgUser->isAllowed( 'abusefilter-view' ) ) { |
28 | 28 | // Go away. |
29 | | - $wgOut->showPermissionsErrorPage( $errors, 'abusefilter-view' ); |
| 29 | + $this->displayRestrictionError(); |
30 | 30 | return; |
31 | 31 | } |
32 | 32 | |
— | — | @@ -46,14 +46,45 @@ |
47 | 47 | return; |
48 | 48 | } |
49 | 49 | |
50 | | - |
51 | | - $wgOut->addWikiMsg( 'abusefilter-tools' ); |
52 | 50 | // Show list of filters. |
53 | 51 | $this->showStatus(); |
54 | 52 | |
| 53 | + // Quick links |
| 54 | + $wgOut->addWikiMsg( 'abusefilter-links' ); |
| 55 | + $lists = array( 'active', 'deleted', 'all', 'tools' ); |
| 56 | + $links = ''; |
| 57 | + $sk = $wgUser->getSkin(); |
| 58 | + foreach( $lists as $list ) { |
| 59 | + $title = $this->getTitle( $list ); |
| 60 | + |
| 61 | + $link = $sk->link( $title, wfMsg( "abusefilter-show-$list" ) ); |
| 62 | + $links .= Xml::tags( 'li', null, $link ) . "\n"; |
| 63 | + } |
| 64 | + $links .= Xml::tags( 'li', null, $sk->link( SpecialPage::getTitleFor( 'AbuseLog' ), wfMsg( 'abusefilter-loglink' ) ) ); |
| 65 | + $links = Xml::tags( 'ul', null, $links ); |
| 66 | + $wgOut->addHTML( $links ); |
| 67 | + |
| 68 | + if ($subpage == 'deleted') { |
| 69 | + $this->showDeleted(); |
| 70 | + return; |
| 71 | + } |
| 72 | + |
| 73 | + if ($subpage == 'active') { |
| 74 | + $this->showActive(); |
| 75 | + return; |
| 76 | + } |
| 77 | + |
55 | 78 | $this->showList(); |
56 | 79 | } |
57 | 80 | |
| 81 | + function showDeleted() { |
| 82 | + $this->showList( array( 'af_deleted' => 1 ) ); |
| 83 | + } |
| 84 | + |
| 85 | + function showActive() { |
| 86 | + $this->showList( array( 'af_deleted' => 0, 'af_enabled' => 1 ) ); |
| 87 | + } |
| 88 | + |
58 | 89 | function showHistory() { |
59 | 90 | global $wgRequest,$wgOut; |
60 | 91 | |
— | — | @@ -192,7 +223,7 @@ |
193 | 224 | $actionsRows = array(); |
194 | 225 | foreach( $wgAbuseFilterAvailableActions as $action ) { |
195 | 226 | // Check if it's set |
196 | | - $enabled = (bool)$actions[$action]; |
| 227 | + $enabled = isset($actions[$action]) && (bool)$actions[$action]; |
197 | 228 | |
198 | 229 | if ($enabled) { |
199 | 230 | $parameters = $actions[$action]['parameters']; |
— | — | @@ -205,7 +236,7 @@ |
206 | 237 | } |
207 | 238 | |
208 | 239 | // Create a history row |
209 | | - $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' ); |
| 240 | + $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' ); |
210 | 241 | |
211 | 242 | $afh_row = array(); |
212 | 243 | |
— | — | @@ -226,6 +257,8 @@ |
227 | 258 | $flags[] = wfMsgForContent( 'abusefilter-history-hidden' ); |
228 | 259 | if ($newRow['af_enabled']) |
229 | 260 | $flags[] = wfMsgForContent( 'abusefilter-history-enabled' ); |
| 261 | + if ($newRow['af_deleted']) |
| 262 | + $flags[] = wfMsgForContent( 'abusefilter-history-deleted' ); |
230 | 263 | |
231 | 264 | $afh_row['afh_flags'] = implode( ",", $flags ); |
232 | 265 | |
— | — | @@ -311,7 +344,7 @@ |
312 | 345 | $fields['abusefilter-edit-notes'] = Xml::textarea( 'wpFilterNotes', ( isset( $row->af_comments ) ? $row->af_comments."\n" : "\n" ) ); |
313 | 346 | |
314 | 347 | // Build checkboxen |
315 | | - $checkboxes = array( 'hidden', 'enabled' ); |
| 348 | + $checkboxes = array( 'hidden', 'enabled', 'deleted' ); |
316 | 349 | $flags = ''; |
317 | 350 | |
318 | 351 | if (isset($row->af_throttled) && $row->af_throttled) { |
— | — | @@ -506,7 +539,8 @@ |
507 | 540 | $row->$col = $wgRequest->getVal( $field ); |
508 | 541 | } |
509 | 542 | |
510 | | - $row->af_enabled = $wgRequest->getBool( 'wpFilterEnabled' ); |
| 543 | + $row->af_deleted = $wgRequest->getBool( 'wpFilterDeleted' ); |
| 544 | + $row->af_enabled = $wgRequest->getBool( 'wpFilterEnabled' ) && !$row->af_deleted; |
511 | 545 | $row->af_hidden = $wgRequest->getBool( 'wpFilterHidden' ); |
512 | 546 | |
513 | 547 | // Actions |
— | — | @@ -550,7 +584,7 @@ |
551 | 585 | return $canEdit; |
552 | 586 | } |
553 | 587 | |
554 | | - function showList() { |
| 588 | + function showList( $conds = array( 'af_deleted' => 0 )) { |
555 | 589 | global $wgOut,$wgUser; |
556 | 590 | |
557 | 591 | $sk = $this->mSkin = $wgUser->getSkin(); |
— | — | @@ -562,7 +596,7 @@ |
563 | 597 | // We shouldn't have more than 100 filters, so don't bother paging. |
564 | 598 | $dbr = wfGetDB( DB_SLAVE ); |
565 | 599 | $abuse_filter = $dbr->tableName( 'abuse_filter' ); |
566 | | - $res = $dbr->select( array('abuse_filter', 'abuse_filter_action'), $abuse_filter.'.*,group_concat(afa_consequence) AS consequences', array( ), __METHOD__, array( 'LIMIT' => 100, 'GROUP BY' => 'af_id' ), |
| 600 | + $res = $dbr->select( array('abuse_filter', 'abuse_filter_action'), $abuse_filter.'.*,group_concat(afa_consequence) AS consequences', $conds, __METHOD__, array( 'LIMIT' => 100, 'GROUP BY' => 'af_id' ), |
567 | 601 | array( 'abuse_filter_action' => array('LEFT OUTER JOIN', 'afa_filter=af_id' ) ) ); |
568 | 602 | $list = ''; |
569 | 603 | $editLabel = $this->canEdit() ? 'abusefilter-list-edit' : 'abusefilter-list-details'; |
— | — | @@ -599,8 +633,12 @@ |
600 | 634 | // Build a table row |
601 | 635 | $trow = ''; |
602 | 636 | |
603 | | - $status = $row->af_enabled ? 'abusefilter-enabled' : 'abusefilter-disabled'; |
604 | | - $status = wfMsgExt( $status, array( 'parseinline' ) ); |
| 637 | + if ($row->af_deleted) { |
| 638 | + $status = wfMsgExt( 'abusefilter-deleted', array( 'parseinline' ) ); |
| 639 | + } else { |
| 640 | + $status = $row->af_enabled ? 'abusefilter-enabled' : 'abusefilter-disabled'; |
| 641 | + $status = wfMsgExt( $status, array( 'parseinline' ) ); |
| 642 | + } |
605 | 643 | |
606 | 644 | $visibility = $row->af_hidden ? 'abusefilter-hidden' : 'abusefilter-unhidden'; |
607 | 645 | $visibility = wfMsgExt( $visibility, array( 'parseinline' ) ); |
Index: trunk/extensions/AbuseFilter/AbuseFilter.class.php |
— | — | @@ -119,7 +119,7 @@ |
120 | 120 | |
121 | 121 | // Fetch from the database. |
122 | 122 | $dbr = wfGetDB( DB_SLAVE ); |
123 | | - $res = $dbr->select( 'abuse_filter', '*', array( 'af_enabled' => 1 ) ); |
| 123 | + $res = $dbr->select( 'abuse_filter', '*', array( 'af_enabled' => 1, 'af_deleted' => 0 ) ); |
124 | 124 | |
125 | 125 | $blocking_filters = array(); |
126 | 126 | $log_entries = array(); |
Index: trunk/extensions/AbuseFilter/AbuseFilter.i18n.php |
— | — | @@ -86,13 +86,19 @@ |
87 | 87 | 'abusefilter-hidden' => 'Private', |
88 | 88 | 'abusefilter-unhidden' => 'Public', |
89 | 89 | 'abusefilter-enabled' => 'Enabled', |
| 90 | + 'abusefilter-deleted' => 'Deleted', |
90 | 91 | 'abusefilter-disabled' => 'Disabled', |
91 | 92 | 'abusefilter-hitcount' => '$1 {{PLURAL:$1|hit|hits}}', |
92 | 93 | 'abusefilter-list-new' => 'New filter', |
| 94 | + 'abusefilter-links' => 'Useful links:', |
93 | 95 | 'abusefilter-tools-modifiertest-submit' => 'Test', |
| 96 | + 'abusefilter-show-deleted' => 'View deleted filters', |
| 97 | + 'abusefilter-show-all' => 'Show all undeleted filters', |
| 98 | + 'abusefilter-show-active' => 'Hide disabled filters', |
| 99 | + 'abusefilter-show-tools' => 'Abuse filter tools', |
| 100 | + 'abusefilter-loglink' => 'View the abuse log', |
94 | 101 | |
95 | 102 | // Abuse filter tools |
96 | | - 'abusefilter-tools' => 'Some [[Special:AbuseFilter/tools|tools]] are available to assist in formulating and debugging abuse filters.', |
97 | 103 | 'abusefilter-tools-subtitle' => 'Tools', |
98 | 104 | 'abusefilter-tools-text' => 'Here are some tools which may be useful in formulating and debugging abuse filters. [[Special:AbuseFilter|Return to main menu]]', |
99 | 105 | 'abusefilter-tools-expr' => 'Expression tester', |
— | — | @@ -112,6 +118,7 @@ |
113 | 119 | 'abusefilter-edit-description' => "Description:\n:''(publicly viewable)''", |
114 | 120 | 'abusefilter-edit-flags' => 'Flags:', |
115 | 121 | 'abusefilter-edit-enabled' => 'Enable this filter', |
| 122 | + 'abusefilter-edit-deleted' => 'Mark as deleted', |
116 | 123 | 'abusefilter-edit-hidden' => 'Hide details of this filter from public view', |
117 | 124 | 'abusefilter-edit-rules' => 'Conditions:', |
118 | 125 | 'abusefilter-edit-notes' => "Notes:\n:''(private)", |
— | — | @@ -216,6 +223,7 @@ |
217 | 224 | 'abusefilter-history-action' => '$1: $2', |
218 | 225 | 'abusefilter-history-backedit' => 'Back to filter editor', |
219 | 226 | 'abusefilter-history-backlist' => 'Back to filter list', |
| 227 | + 'abusefilter-history-deleted' => 'Deleted', |
220 | 228 | ); |
221 | 229 | |
222 | 230 | /** Message documentation (Message documentation) |
Index: trunk/extensions/AbuseFilter/abusefilter.tables.sql |
— | — | @@ -12,6 +12,7 @@ |
13 | 13 | af_hidden tinyint(1) not null default 0, |
14 | 14 | af_hit_count bigint not null default 0, |
15 | 15 | af_throttled tinyint(1) NOT NULL default 0, |
| 16 | + af_deleted tinyint(1) NOT NULL DEFAULT 0, |
16 | 17 | |
17 | 18 | PRIMARY KEY (af_id), |
18 | 19 | KEY (af_user) |
Index: trunk/extensions/AbuseFilter/AbuseFilter.hooks.php |
— | — | @@ -105,4 +105,19 @@ |
106 | 106 | |
107 | 107 | return $filter_result == '' || $filter_result === true; |
108 | 108 | } |
| 109 | + |
| 110 | + public static function onSchemaUpdate() { |
| 111 | + global $wgDatabase; |
| 112 | + |
| 113 | + if ( !$wgDatabase->tableExists( 'abuse_filter' ) ) { |
| 114 | + // Full tables |
| 115 | + dbsource( dirname(__FILE__).'/abusefilter.tables.sql', $wgDatabase ); |
| 116 | + } |
| 117 | + |
| 118 | + if ( ! $wgDatabase->fieldExists( 'abuse_filter', 'af_deleted' ) ) { |
| 119 | + dbsource( dirname( __FILE__ ) . '/db_patches/patch-af_deleted.sql' ); |
| 120 | + } |
| 121 | + |
| 122 | + return true; |
| 123 | + } |
109 | 124 | } |