r48337 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r48336‎ | r48337 | r48338 >
Date:05:04, 12 March 2009
Author:werdna
Status:ok
Tags:
Comment:
Add diffs to AbuseFilter. Includes a related pare-down of history, under the assumption that diffs will take up the slack
Modified paths:
  • /trunk/extensions/AbuseFilter/AbuseFilter.class.php (modified) (history)
  • /trunk/extensions/AbuseFilter/AbuseFilter.i18n.php (modified) (history)
  • /trunk/extensions/AbuseFilter/AbuseFilter.php (modified) (history)
  • /trunk/extensions/AbuseFilter/SpecialAbuseFilter.php (modified) (history)
  • /trunk/extensions/AbuseFilter/Views/AbuseFilterViewDiff.php (added) (history)
  • /trunk/extensions/AbuseFilter/Views/AbuseFilterViewHistory.php (modified) (history)
  • /trunk/extensions/AbuseFilter/abusefilter.css (modified) (history)

Diff [purge]

Index: trunk/extensions/AbuseFilter/AbuseFilter.php
@@ -44,6 +44,8 @@
4545 $wgAutoloadClasses['AbuseFilterViewTestBatch'] = "$dir/Views/AbuseFilterViewTestBatch.php";
4646 $wgAutoloadClasses['AbuseFilterViewExamine'] = "$dir/Views/AbuseFilterViewExamine.php";
4747 $wgAutoloadClasses['AbuseFilterChangesList'] = "$dir/Views/AbuseFilterViewExamine.php";
 48+$wgAutoloadClasses['AbuseFilterViewDiff'] = "$dir/Views/AbuseFilterViewDiff.php";
 49+
4850 $wgAutoloadClasses['AbuseFilterVariableHolder'] = "$dir/AbuseFilterVariableHolder.php";
4951 $wgAutoloadClasses['AFComputedVariable'] = "$dir/AbuseFilterVariableHolder.php";
5052 $wgAutoloadClasses['AFPData'] = "$dir/AbuseFilter.parser.php";
Index: trunk/extensions/AbuseFilter/SpecialAbuseFilter.php
@@ -66,6 +66,7 @@
6767 }
6868
6969 if (!empty($params[0]) && ($params[0] == 'history' || $params[0] == 'log') ) {
 70+ $pageType = '';
7071 if (count($params) == 1) {
7172 $view = 'AbuseFilterViewHistory';
7273 $pageType = 'recentchanges';
@@ -77,6 +78,9 @@
7879 $this->mFilter = $params[1];
7980 $this->mHistoryID = $params[3];
8081 $view = 'AbuseFilterViewEdit';
 82+ } elseif (count($params) == 5 && $params[2] == 'diff') {
 83+ // Special:AbuseFilter/history/<filter>/diff/<oldid>/<newid>
 84+ $view = 'AbuseFilterViewDiff';
8185 }
8286 }
8387
Index: trunk/extensions/AbuseFilter/abusefilter.css
@@ -72,4 +72,46 @@
7373
7474 .mw-abusefilter-navigation {
7575 text-align: center;
 76+}
 77+
 78+table.mw-abusefilter-diff {
 79+ width: 80%;
 80+ border-collapse: collapse;
 81+}
 82+
 83+table.mw-abusefilter-diff td,
 84+table.mw-abusefilter-diff th {
 85+ border: 1px solid #888888;
 86+}
 87+
 88+.mw-abusefilter-diff-added,
 89+.mw-abusefilter-diff-multiline .diff-addedline {
 90+ background: #cfc;
 91+}
 92+
 93+.mw-abusefilter-diff-removed,
 94+.mw-abusefilter-diff-multiline .diff-deletedline {
 95+ background: #ffa;
 96+}
 97+
 98+.mw-abusefilter-diff-context,
 99+.mw-abusefilter-diff-multiline .diff-context {
 100+ background: #eee;
 101+}
 102+
 103+.mw-abusefilter-diff-multiline {
 104+ width: 100%;
 105+}
 106+
 107+.mw-abusefilter-diff-multiline td {
 108+ border: none !important;
 109+}
 110+
 111+.mw-abusefilter-diff-multiline .diff-marker {
 112+ font-size: 0.8em;
 113+}
 114+
 115+.mw-abusefilter-diff-multiline td.diff-addedline,
 116+.mw-abusefilter-diff-multiline td.diff-deletedline {
 117+ width: 50%;
76118 }
\ No newline at end of file
Index: trunk/extensions/AbuseFilter/Views/AbuseFilterViewDiff.php
@@ -0,0 +1,304 @@
 2+<?php
 3+
 4+if (!defined( 'MEDIAWIKI' ))
 5+ die();
 6+
 7+class AbuseFilterViewDiff extends AbuseFilterView {
 8+ var $mOldVersion = null;
 9+ var $mNewVersion = null;
 10+ var $mFilter = null;
 11+
 12+ function show( ) {
 13+ $show = $this->loadData();
 14+
 15+ global $wgOut, $wgUser, $wgLang;
 16+ $this->mSkin = $wgUser->getSkin();
 17+
 18+ $links = array();
 19+ if ($this->mFilter) {
 20+ $links['abusefilter-history-backedit'] = $this->getTitle( $this->mFilter );
 21+ $links['abusefilter-diff-backhistory'] = $this->getTitle( "history/".$this->mFilter );
 22+ }
 23+
 24+ foreach( $links as $msg => $title ) {
 25+ $links[$msg] = $this->mSkin->link( $title, wfMsgExt( $msg, 'parseinline' ) );
 26+ }
 27+
 28+ $backlinks = $wgLang->pipeList( $links );
 29+ $wgOut->addHTML( Xml::tags( 'p', null, $backlinks ) );
 30+
 31+ if ($show)
 32+ $wgOut->addHTML( $this->formatDiff() );
 33+ }
 34+
 35+ function loadData() {
 36+ $oldSpec = $this->mParams[3];
 37+ $newSpec = $this->mParams[4];
 38+ $this->mFilter = $this->mParams[1];
 39+
 40+ $this->mOldVersion = $this->loadSpec( $oldSpec, $newSpec );
 41+ $this->mNewVersion = $this->loadSpec( $newSpec, $oldSpec );
 42+
 43+ if (is_null( $this->mOldVersion) || is_null( $this->mNewVersion ) ) {
 44+ global $wgOut;
 45+ $wgOut->addWikiMsg( 'abusefilter-diff-invalid' );
 46+ return false;
 47+ }
 48+
 49+ return true;
 50+ }
 51+
 52+ function loadSpec( $spec, $otherSpec ) {
 53+ static $dependentSpecs = array( 'prev', 'next' );
 54+ static $cache = array();
 55+
 56+ if ( isset( $cache[$spec] ) )
 57+ return $cache[$spec];
 58+
 59+ $dbr = wfGetDB( DB_SLAVE );
 60+ if ( is_numeric($spec) ) {
 61+ $row = $dbr->selectRow(
 62+ 'abuse_filter_history',
 63+ '*',
 64+ array( 'afh_id' => $spec ),
 65+ __METHOD__
 66+ );
 67+ } elseif ( $spec == 'cur' ) {
 68+ $row = $dbr->selectRow(
 69+ 'abuse_filter_history',
 70+ '*',
 71+ array( 'afh_filter' => $this->mFilter ),
 72+ __METHOD__,
 73+ array( 'ORDER BY' => 'afh_timestamp desc' )
 74+ );
 75+ } elseif ($spec == 'prev' && !in_array( $otherSpec, $dependentSpecs ) ) {
 76+ // cached
 77+ $other = $this->loadSpec( $otherSpec, $spec );
 78+
 79+ $row = $dbr->selectRow(
 80+ 'abuse_filter_history',
 81+ '*',
 82+ array(
 83+ 'afh_filter' => $this->mFilter,
 84+ 'afh_id<'.$dbr->addQuotes( $other['meta']['history_id'] ),
 85+ ),
 86+ __METHOD__,
 87+ array( 'ORDER BY' => 'afh_timestamp desc' )
 88+ );
 89+ } elseif ($spec == 'next' && !in_array( $otherSpec, $dependentSpecs ) ) {
 90+ // cached
 91+ $other = $this->loadSpec( $otherSpec, $spec );
 92+
 93+ $row = $dbr->selectRow(
 94+ 'abuse_filter_history',
 95+ '*',
 96+ array(
 97+ 'afh_filter' => $this->mFilter,
 98+ 'afh_id>'.$dbr->addQuotes( $other['meta']['history_id'] ),
 99+ ),
 100+ __METHOD__,
 101+ array( 'ORDER BY' => 'afh_timestamp desc' )
 102+ );
 103+ }
 104+
 105+ if (!$row)
 106+ return null;
 107+
 108+ $data = $this->loadFromHistoryRow( $row );
 109+ $cache[$spec] = $data;
 110+ return $data;
 111+ }
 112+
 113+ function loadFromHistoryRow( $row ) {
 114+ return array(
 115+ 'meta' => array(
 116+ 'history_id' => $row->afh_id,
 117+ 'modified_by' => $row->afh_user,
 118+ 'modified_by_text' => $row->afh_user_text,
 119+ 'modified' => $row->afh_timestamp,
 120+ ),
 121+ 'info' => array(
 122+ 'description' => $row->afh_public_comments,
 123+ 'flags' => $row->afh_flags,
 124+ 'notes' => $row->afh_comments,
 125+ ),
 126+ 'pattern' => $row->afh_pattern,
 127+ 'actions' => unserialize( $row->afh_actions ),
 128+ );
 129+ }
 130+
 131+ function formatVersionLink( $timestamp, $history_id ) {
 132+ global $wgLang, $wgUser;
 133+ $sk = $wgUser->getSkin();
 134+
 135+ $filter = $this->mFilter;
 136+ $text = $wgLang->timeanddate( $timestamp );
 137+ $title = $this->getTitle( "history/$filter/item/$history_id" );
 138+
 139+ $link = $sk->link( $title, $text );
 140+
 141+ return $link;
 142+ }
 143+
 144+ function formatDiff() {
 145+ $oldVersion = $this->mOldVersion;
 146+ $newVersion = $this->mNewVersion;
 147+
 148+ // headings
 149+ $oldLink = $this->formatVersionLink(
 150+ $oldVersion['meta']['modified'],
 151+ $oldVersion['meta']['history_id']
 152+ );
 153+ $newLink = $this->formatVersionLink(
 154+ $newVersion['meta']['modified'],
 155+ $newVersion['meta']['history_id']
 156+ );
 157+
 158+ $sk = $this->mSkin;
 159+ $oldUserLink = $sk->userLink(
 160+ $oldVersion['meta']['modified_by'],
 161+ $oldVersion['meta']['modified_by_text']
 162+ );
 163+ $newUserLink = $sk->userLink(
 164+ $newVersion['meta']['modified_by'],
 165+ $newVersion['meta']['modified_by_text']
 166+ );
 167+
 168+ $headings = '';
 169+ $headings .= Xml::tags( 'th', null,
 170+ wfMsgExt( 'abusefilter-diff-item', 'parseinline' ) );
 171+ $headings .= Xml::tags( 'th', null,
 172+ wfMsgExt( 'abusefilter-diff-version',
 173+ array( 'parseinline', 'replaceafter' ),
 174+ array( $oldLink, $oldUserLink )
 175+ )
 176+ );
 177+ $headings .= Xml::tags( 'th', null,
 178+ wfMsgExt( 'abusefilter-diff-version',
 179+ array( 'parseinline', 'replaceafter' ),
 180+ array( $newLink, $newUserLink )
 181+ )
 182+ );
 183+
 184+ $headings = Xml::tags( 'tr', null, $headings );
 185+
 186+ // Basic info
 187+ $info = '';
 188+ $info .= $this->getHeaderRow( 'abusefilter-diff-info' );
 189+ $info .= $this->getSimpleRow(
 190+ 'abusefilter-edit-description',
 191+ $oldVersion['info']['description'],
 192+ $newVersion['info']['description'],
 193+ 'wikitext'
 194+ );
 195+ $info .= $this->getSimpleRow(
 196+ 'abusefilter-edit-flags',
 197+ AbuseFilter::formatFlags( $oldVersion['info']['flags'] ),
 198+ AbuseFilter::formatFlags( $newVersion['info']['flags'] )
 199+ );
 200+
 201+ $info .= $this->getMultiLineRow(
 202+ 'abusefilter-edit-notes',
 203+ $oldVersion['info']['notes'],
 204+ $newVersion['info']['notes']
 205+ );
 206+
 207+ // Pattern
 208+ $info .= $this->getHeaderRow( 'abusefilter-diff-pattern' );
 209+ $info .= $this->getMultiLineRow(
 210+ 'abusefilter-edit-rules',
 211+ $oldVersion['pattern'],
 212+ $newVersion['pattern']
 213+ );
 214+
 215+ // Actions
 216+ $oldActions = $this->stringifyActions( $oldVersion['actions'] );
 217+ $newActions = $this->stringifyActions( $newVersion['actions'] );
 218+
 219+ $info .= $this->getHeaderRow( 'abusefilter-edit-consequences' );
 220+ $info .= $this->getMultiLineRow(
 221+ 'abusefilter-edit-consequences',
 222+ $oldActions,
 223+ $newActions
 224+ );
 225+
 226+ $html = "<table class='mw-abusefilter-diff'>
 227+ <thead>$headings</thead>
 228+ <tbody>$info</tbody>
 229+</table>";
 230+
 231+ $html = Xml::tags( 'h2', null, wfMsgExt( 'abusefilter-diff-title', 'parseinline' ) ) . $html;
 232+
 233+ return $html;
 234+ }
 235+
 236+ function stringifyActions( $actions ) {
 237+ $lines = array();
 238+
 239+ ksort( $actions );
 240+ foreach( $actions as $action => $parameters ) {
 241+ $lines[] = AbuseFilter::formatAction( $action, $parameters );
 242+ }
 243+
 244+ if ( !count($lines) )
 245+ $lines[] = '';
 246+
 247+ return $lines;
 248+ }
 249+
 250+ function getHeaderRow( $msg ) {
 251+ $html = wfMsgExt( $msg, 'parseinline' );
 252+ $html = Xml::tags( 'th', array( 'colspan' => 3 ), $html );
 253+ $html = Xml::tags( 'tr', array( 'class' => 'mw-abusefilter-diff-header' ), $html );
 254+
 255+ return $html;
 256+ }
 257+
 258+ function getSimpleRow( $msg, $old, $new, $format='wikitext' ) {
 259+ $row = '';
 260+
 261+ $row .= Xml::tags( 'th', null, wfMsgExt( $msg, 'parseinline' ) );
 262+
 263+ $oldClass = $newClass = 'mw-abusefilter-diff-context';
 264+ if ( trim($old) != trim($new) ) {
 265+ $oldClass = 'mw-abusefilter-diff-removed';
 266+ $newClass = 'mw-abusefilter-diff-added';
 267+ }
 268+
 269+ if ($format == 'wikitext') {
 270+ global $wgOut;
 271+ $old = $wgOut->parseInline( $old );
 272+ $new = $wgOut->parseInline( $new );
 273+ }
 274+
 275+ $row .= Xml::tags( 'td', array( 'class' => $oldClass ), $old );
 276+ $row .= Xml::tags( 'td', array( 'class' => $newClass ), $new );
 277+
 278+ return Xml::tags( 'tr', null, $row )."\n";
 279+ }
 280+
 281+ function getMultiLineRow( $msg, $old, $new ) {
 282+ if (!is_array($old))
 283+ $old = explode( "\n", $old );
 284+ if (!is_array($new))
 285+ $new = explode( "\n", $new );
 286+
 287+ if ( $old == $new ) {
 288+ $old = implode( "\n", $old );
 289+ $new = implode( "\n", $new );
 290+ return $this->getSimpleRow( $msg, $old, $new );
 291+ }
 292+
 293+ $row = '';
 294+ $row .= Xml::tags( 'th', null, wfMsgExt( $msg, 'parseinline' ) );
 295+
 296+ $diff = new Diff( $old, $new );
 297+ $formatter = new TableDiffFormatter();
 298+ $formattedDiff = $formatter->format( $diff );
 299+ $formattedDiff =
 300+ "<table class='mw-abusefilter-diff-multiline'><tbody>$formattedDiff</tbody></table>";
 301+ $row .= Xml::tags( 'td', array( 'colspan' => 2 ), $formattedDiff );
 302+
 303+ return Xml::tags( 'tr', null, $row )."\n";
 304+ }
 305+}
Index: trunk/extensions/AbuseFilter/Views/AbuseFilterViewHistory.php
@@ -88,9 +88,8 @@
8989 'afh_user_text' => 'abusefilter-history-user',
9090 'afh_public_comments' => 'abusefilter-history-public',
9191 'afh_flags' => 'abusefilter-history-flags',
92 - 'afh_pattern' => 'abusefilter-history-filter',
93 - 'afh_comments' => 'abusefilter-history-comments',
94 - 'afh_actions' => 'abusefilter-history-actions' );
 92+ 'afh_actions' => 'abusefilter-history-actions',
 93+ 'afh_id' => 'abusefilter-history-diff');
9594
9695 if (!$this->mFilter) {
9796 // awful hack
@@ -132,32 +131,15 @@
133132 $formatted = $wgOut->parse( $value );
134133 break;
135134 case 'afh_flags':
136 - $flags = array_filter( explode( ',', $value ) );
137 - $flags_display = array();
138 - foreach( $flags as $flag ) {
139 - $flags_display[] = wfMsg( "abusefilter-history-$flag" );
140 - }
141 - $formatted = $wgLang->commaList( $flags_display );
 135+ $formatted = AbuseFilter::formatFlags( $value );
142136 break;
143 - case 'afh_pattern':
144 - $formatted = htmlspecialchars( $wgLang->truncate( $value, 200 ) );
145 - break;
146 - case 'afh_comments':
147 - $formatted = htmlspecialchars( $wgLang->truncate( $value, 200 ) );
148 - break;
149137 case 'afh_actions':
150138 $actions = unserialize( $value );
151139
152140 $display_actions = '';
153141
154142 foreach( $actions as $action => $parameters ) {
155 - if( count( $parameters ) == 0 ) {
156 - $displayAction = AbuseFilter::getActionDisplay( $action );
157 - } else {
158 - $displayAction = AbuseFilter::getActionDisplay( $action ) .
159 - wfMsgExt( 'colon-separator', 'escapenoentities' ) .
160 - $wgLang->semicolonList( $parameters );
161 - }
 143+ $displayAction = AbuseFilter::formatAction( $action, $parameters );
162144 $display_actions .= Xml::tags( 'li', null, $displayAction );
163145 }
164146 $display_actions = Xml::tags( 'ul', null, $display_actions );
@@ -168,13 +150,18 @@
169151 $title = $this->mPage->getTitle( strval($value) );
170152 $formatted = $sk->link( $title, $value );
171153 break;
 154+ case 'afh_id':
 155+ $title = $this->mPage->getTitle(
 156+ "history/".$row->afh_filter."/diff/prev/$value" );
 157+ $formatted = $sk->link( $title, wfMsgExt( 'abusefilter-history-diff', 'parseinline' ) );
 158+ break;
172159 default:
173160 $formatted = "Unable to format $name";
174161 break;
175162 }
176163
177164 $mappings = array_flip(AbuseFilter::$history_mappings) +
178 - array( 'afh_actions' => 'actions' );
 165+ array( 'afh_actions' => 'actions', 'afh_id' => 'id' );
179166 $changed = explode( ',', $row->afh_changed_fields );
180167
181168 $fieldChanged = false;
@@ -212,7 +199,8 @@
213200 'afh_id',
214201 'afh_user',
215202 'afh_changed_fields',
216 - 'afh_pattern' ),
 203+ 'afh_pattern',
 204+ 'afh_id' ),
217205 'conds' => array(),
218206 );
219207
Index: trunk/extensions/AbuseFilter/AbuseFilter.class.php
@@ -1352,7 +1352,7 @@
13531353
13541354 $filter_link = $sk ? $sk->link( $title ) : $title->getFullURL();
13551355
1356 - $details_title = SpecialPage::getTitleFor( 'AbuseFilter', "history/$filter_id/item/$history_id" );
 1356+ $details_title = SpecialPage::getTitleFor( 'AbuseFilter', "history/$filter_id/diff/prev/$history_id" );
13571357 $details_text = wfMsgExt( 'abusefilter-log-detailslink', 'parseinline' );
13581358 $details_link =
13591359 $sk ? $sk->link( $details_title, $details_text ) : $details_title->getFullURL();
@@ -1360,4 +1360,26 @@
13611361 return wfMsgExt( 'abusefilter-log-entry-modify',
13621362 array('parseinline','replaceafter'), array( $filter_link, $details_link ) );
13631363 }
 1364+
 1365+ static function formatAction( $action, $parameters ) {
 1366+ global $wgLang;
 1367+ if( count( $parameters ) == 0 ) {
 1368+ $displayAction = AbuseFilter::getActionDisplay( $action );
 1369+ } else {
 1370+ $displayAction = AbuseFilter::getActionDisplay( $action ) .
 1371+ wfMsgExt( 'colon-separator', 'escapenoentities' ) .
 1372+ $wgLang->semicolonList( $parameters );
 1373+ }
 1374+ return $displayAction;
 1375+ }
 1376+
 1377+ static function formatFlags( $value ) {
 1378+ global $wgLang;
 1379+ $flags = array_filter( explode( ',', $value ) );
 1380+ $flags_display = array();
 1381+ foreach( $flags as $flag ) {
 1382+ $flags_display[] = wfMsg( "abusefilter-history-$flag" );
 1383+ }
 1384+ return $wgLang->commaList( $flags_display );
 1385+ }
13641386 }
Index: trunk/extensions/AbuseFilter/AbuseFilter.i18n.php
@@ -300,6 +300,7 @@
301301 'abusefilter-history-select-legend' => 'Refine search',
302302 'abusefilter-history-select-user' => 'User:',
303303 'abusefilter-history-select-submit' => 'Refine',
 304+ 'abusefilter-history-diff' => 'Changes',
304305
305306 // Exceptions
306307 'abusefilter-exception-unexpectedatend' => 'Unexpected "$2" at character $1.',
@@ -387,6 +388,15 @@
388389 'abusefilter-log-header' => "This log shows a summary of changes made to filters.
389390 For full details, see [[Special:AbuseFilter/history|the list]] of recent filter changes.",
390391 'abusefilter-log-entry-modify' => 'modified $1 ($2)',
 392+
 393+ // Diffs
 394+ 'abusefilter-diff-title' => 'Differences between versions',
 395+ 'abusefilter-diff-item' => 'Item',
 396+ 'abusefilter-diff-version' => 'Version from $1 by $2',
 397+ 'abusefilter-diff-info' => 'Basic information',
 398+ 'abusefilter-diff-pattern' => 'Filter conditions',
 399+ 'abusefilter-diff-invalid' => 'Unable to fetch the requested versions',
 400+ 'abusefilter-diff-backhistory' => 'Back to filter history',
391401 );
392402
393403 /** Message documentation (Message documentation)

Status & tagging log