Index: trunk/extensions/CleanChanges/CleanChanges.php |
— | — | @@ -11,7 +11,7 @@ |
12 | 12 | /* Extension information */ |
13 | 13 | $wgExtensionCredits['other'][] = array( |
14 | 14 | 'name' => 'Clean Changes', |
15 | | - 'version' => '1.1', |
| 15 | + 'version' => '2008-04-05', |
16 | 16 | 'author' => 'Niklas Laxström', |
17 | 17 | 'descriptionmsg' => 'cleanchanges-desc', |
18 | 18 | 'url' => 'http://www.mediawiki.org/wiki/Extension:CleanChanges', |
Index: trunk/extensions/CleanChanges/CleanChanges_body.php |
— | — | @@ -67,7 +67,6 @@ |
68 | 68 | $this->dir = $wgLang->getDirMark(); |
69 | 69 | } |
70 | 70 | |
71 | | - |
72 | 71 | function beginRecentChangesList() { |
73 | 72 | parent::beginRecentChangesList(); |
74 | 73 | $dir = $this->direction ? 'ltr' : 'rtl'; |
— | — | @@ -78,15 +77,63 @@ |
79 | 78 | ); |
80 | 79 | } |
81 | 80 | |
| 81 | + function endRecentChangesList() { |
82 | 82 | /* |
83 | 83 | * Have to output the accumulated javascript stuff before any output is send. |
84 | 84 | */ |
85 | | - function endRecentChangesList() { |
86 | 85 | global $wgOut; |
87 | 86 | $wgOut->addScript( Skin::makeVariablesScript( $this->userinfo ) ); |
88 | 87 | return parent::endRecentChangesList() . '</div>'; |
89 | 88 | } |
90 | 89 | |
| 90 | + function isLog( $rc ) { |
| 91 | + if ( $rc->getAttribute( 'rc_namespace ' ) == NS_SPECIAL ) { |
| 92 | + return 1; |
| 93 | + } elseif ( $rc->getAttribute( 'rc_type' ) == RC_LOG ) { |
| 94 | + return 2; |
| 95 | + } else { |
| 96 | + return 0; |
| 97 | + } |
| 98 | + } |
| 99 | + |
| 100 | + function getLogTitle( $type, $rc ) { |
| 101 | + if ( $type === 1 ) { |
| 102 | + $title = $rc->getAttribute( 'rc_title' ); |
| 103 | + list( $specialName, $logtype ) = SpecialPage::resolveAliasWithSubpage( $title ); |
| 104 | + |
| 105 | + if ( $specialName === 'Log' ) { |
| 106 | + $titleObj = $rc->getTitle(); |
| 107 | + $logname = LogPage::logName( $logtype ); |
| 108 | + return '(' . $this->skin->makeKnownLinkObj( $titleObj, $logname ) . ')'; |
| 109 | + } else { |
| 110 | + throw new MWException( "Unknown special page name $specialName ($title). Log expected." ); |
| 111 | + } |
| 112 | + } elseif ( $type === 2 ) { |
| 113 | + $logtype = $rc->getAttribute( 'rc_log_type' ); |
| 114 | + $logname = LogPage::logName( $logtype ); |
| 115 | + $titleObj = SpecialPage::getTitleFor( 'Log', $logtype ); |
| 116 | + return '(' . $this->skin->makeKnownLinkObj( $titleObj, $logname ) . ')'; |
| 117 | + } else { |
| 118 | + throw new MWException( 'Unknown type' ); |
| 119 | + } |
| 120 | + } |
| 121 | + |
| 122 | + protected function getLogAction( $rc ) { |
| 123 | + if ( $this->isDeleted($rc, LogPage::DELETED_ACTION) ) { |
| 124 | + return $this->XMLwrapper( 'history-deleted', wfMsg('rev-deleted-event') ); |
| 125 | + } else { |
| 126 | + return LogPage::actionText( |
| 127 | + $rc->getAttribute('rc_log_type'), |
| 128 | + $rc->getAttribute('rc_log_action'), |
| 129 | + $rc->getTitle(), |
| 130 | + $this->skin, |
| 131 | + LogPage::extractParams( $rc->getAttribute('rc_params') ), |
| 132 | + true, |
| 133 | + true |
| 134 | + ); |
| 135 | + } |
| 136 | + } |
| 137 | + |
91 | 138 | /** |
92 | 139 | * Format a line for enhanced recentchange (aka with javascript and block of lines). |
93 | 140 | */ |
— | — | @@ -105,29 +152,20 @@ |
106 | 153 | $time = $wgLang->time( $timestamp, /* adj */ true, /* format */ true ); |
107 | 154 | |
108 | 155 | # Should patrol-related stuff be shown? |
109 | | - $rc->unpatrolled = $this->usePatrol() ? !$rc->getAttribute( 'rc_patrolled' ) : false; |
| 156 | + $rc->unpatrolled = self::usePatrol() ? !$rc->getAttribute( 'rc_patrolled' ) : false; |
110 | 157 | |
111 | | - if( $rc->getAttribute( 'rc_namespace' ) == NS_SPECIAL ) { |
112 | | - list( $specialName, $logtype ) = SpecialPage::resolveAliasWithSubpage( |
113 | | - $rc->getAttribute( 'rc_title' ) |
114 | | - ); |
115 | | - if ( $specialName === 'Log' ) { |
116 | | - # Log updates, etc |
117 | | - $logname = LogPage::logName( $logtype ); |
118 | | - $clink = '(' . $this->skin->makeKnownLinkObj( $titleObj, $logname ) . ')'; |
119 | | - } else { |
120 | | - wfDebug( "Unknown special page name $specialName, Log expected" ); |
121 | | - return ''; |
122 | | - } |
| 158 | + $logEntry = $this->isLog( $rc ); |
| 159 | + if( $logEntry ) { |
| 160 | + $clink = $this->getLogTitle( $logEntry, $rc ); |
123 | 161 | } elseif( $rc->unpatrolled && $rc->getAttribute( 'rc_type' ) == RC_NEW ) { |
124 | 162 | # Unpatrolled new page, give rc_id in query |
125 | 163 | $clink = $this->skin->makeKnownLinkObj( $titleObj, '', "rcid={$rc_id}" ); |
126 | 164 | } else { |
127 | | - $clink = $this->skin->makeKnownLinkObj( $titleObj, '' ); |
| 165 | + $clink = $this->skin->makeKnownLinkObj( $titleObj ); |
128 | 166 | } |
129 | 167 | |
130 | 168 | $rc->watched = $watched; |
131 | | - $rc->link = $clink; |
| 169 | + $rc->link = $this->maybeWatchedLink( $clink, $watched ); |
132 | 170 | $rc->timestamp = $time; |
133 | 171 | $rc->numberofWatchingusers = $baseRC->numberofWatchingusers; |
134 | 172 | |
— | — | @@ -146,6 +184,10 @@ |
147 | 185 | $rc->_comment = $this->skin->commentBlock( |
148 | 186 | $rc->getAttribute( 'rc_comment' ), $titleObj ); |
149 | 187 | |
| 188 | + if ( $logEntry ) { |
| 189 | + $rc->_comment = $this->getLogAction( $rc ) . ' ' . $rc->_comment; |
| 190 | + } |
| 191 | + |
150 | 192 | $rc->_watching = $this->numberofWatchingusers( $baseRC->numberofWatchingusers ); |
151 | 193 | |
152 | 194 | |
— | — | @@ -161,7 +203,11 @@ |
162 | 204 | |
163 | 205 | # Put accumulated information into the cache, for later display |
164 | 206 | # Page moves go on their own line |
165 | | - $secureName = $titleObj->getPrefixedDBkey(); |
| 207 | + if ( $logEntry ) { |
| 208 | + $secureName = $this->getLogTitle( $logEntry, $rc ); |
| 209 | + } else { |
| 210 | + $secureName = $titleObj->getPrefixedDBkey(); |
| 211 | + } |
166 | 212 | $this->rc_cache[$secureName][] = $rc; |
167 | 213 | |
168 | 214 | return $ret; |
— | — | @@ -174,8 +220,7 @@ |
175 | 221 | $rc->_lastLink = $this->message['last']; |
176 | 222 | $rc->_histLink = $this->message['hist']; |
177 | 223 | |
178 | | - /* Logs link only to Special:Log/type */ |
179 | | - if( $rc->getAttribute( 'rc_type' ) != RC_LOG ) { |
| 224 | + if( !$this->isLog( $rc ) ) { |
180 | 225 | # Make cur, diff and last links |
181 | 226 | $querycur = wfArrayToCGI( array( 'diff' => 0 ) + $rc->_reqCurId + $rc->_reqOldId ); |
182 | 227 | $querydiff = wfArrayToCGI( array( |
— | — | @@ -212,30 +257,29 @@ |
213 | 258 | global $wgLang; |
214 | 259 | |
215 | 260 | # Collate list of users |
216 | | - $isnew = false; |
217 | | - $unpatrolled = false; |
| 261 | + $isnew = $unpatrolled = false; |
218 | 262 | $userlinks = array(); |
| 263 | + $overrides = array( 'minor' => false, 'bot' => false ); |
219 | 264 | foreach( $block as $rcObj ) { |
220 | 265 | $oldid = $rcObj->mAttribs['rc_last_oldid']; |
221 | 266 | if( $rcObj->mAttribs['rc_new'] ) { |
222 | | - $isnew = true; |
| 267 | + $isnew = $overrides['new'] = true; |
223 | 268 | } |
224 | 269 | $u = $rcObj->_user; |
225 | 270 | if( !isset( $userlinks[$u] ) ) { |
226 | 271 | $userlinks[$u] = 0; |
227 | 272 | } |
228 | 273 | if( $rcObj->unpatrolled ) { |
229 | | - $unpatrolled = true; |
| 274 | + $unpatrolled = $overrides['patrol'] = true; |
230 | 275 | } |
231 | | - $bot = $rcObj->mAttribs['rc_bot']; |
| 276 | + |
232 | 277 | $userlinks[$u]++; |
233 | 278 | } |
234 | 279 | |
235 | 280 | # Main line, flags and timestamp |
236 | 281 | |
237 | | - $info = Xml::openElement( 'tt' ) . |
238 | | - $this->getFlags( $block[0], $isnew, false, false, $unpatrolled ) . |
239 | | - ' ' . $block[0]->timestamp . '</tt>'; |
| 282 | + $info = Xml::tags( 'tt', null, |
| 283 | + $this->getFlags( $block[0], $overrides ) . ' ' . $block[0]->timestamp ); |
240 | 284 | $rci = 'RCI' . $this->rcCacheIndex; |
241 | 285 | $rcl = 'RCL' . $this->rcCacheIndex; |
242 | 286 | $rcm = 'RCM' . $this->rcCacheIndex; |
— | — | @@ -249,11 +293,13 @@ |
250 | 294 | $items[] = $tl . $info; |
251 | 295 | |
252 | 296 | # Article link |
253 | | - $items[] = $this->maybeWatchedLink( $block[0]->link, $block[0]->watched ); |
| 297 | + $items[] = $block[0]->link; |
254 | 298 | |
255 | 299 | $curIdEq = 'curid=' . $block[0]->mAttribs['rc_cur_id']; |
256 | 300 | $currentRevision = $block[0]->mAttribs['rc_this_oldid']; |
257 | | - if( $block[0]->mAttribs['rc_type'] != RC_LOG ) { |
| 301 | + |
| 302 | + $log = $this->isLog( $block[0] ); |
| 303 | + if( !$log ) { |
258 | 304 | # Changes |
259 | 305 | $n = count($block); |
260 | 306 | static $nchanges = array(); |
— | — | @@ -270,19 +316,9 @@ |
271 | 317 | $changes = $nchanges[$n]; |
272 | 318 | } |
273 | 319 | |
274 | | - # Character difference |
275 | | - $size = $rcObj->getCharacterDifference( $block[ count( $block ) - 1 ]->mAttribs['rc_old_len'], |
276 | | - $block[0]->mAttribs['rc_new_len'] ); |
| 320 | + $size = $this->getCharacterDifference( $block[0], $block[count($block)-1] ); |
| 321 | + $items[] = $this->changeInfo( $changes, $block[0]->_histLink, $size ); |
277 | 322 | |
278 | | - # History link |
279 | | - $hist = $block[0]->_histLink; |
280 | | - |
281 | | - if ( $size ) { |
282 | | - $items[] = "($changes; $hist $size)"; |
283 | | - } else { |
284 | | - $items[] = "($changes; $hist)"; |
285 | | - } |
286 | | - |
287 | 323 | } |
288 | 324 | |
289 | 325 | $items[] = $this->userSeparator; |
— | — | @@ -291,7 +327,7 @@ |
292 | 328 | $items[] = $this->makeUserlinks( $userlinks ); |
293 | 329 | $items[] = $block[0]->_watching; |
294 | 330 | |
295 | | - $lines = '<div>' . implode( " {$this->dir}", $items ) . "</div>\n"; |
| 331 | + $lines = Xml::tags( 'div', null, implode( " {$this->dir}", $items ) ) . "\n" ; |
296 | 332 | |
297 | 333 | # Sub-entries |
298 | 334 | $lines .= Xml::tags( 'div', |
— | — | @@ -300,16 +336,17 @@ |
301 | 337 | ) . "\n"; |
302 | 338 | |
303 | 339 | $this->rcCacheIndex++; |
304 | | - return $lines; |
| 340 | + return $lines . "\n"; |
305 | 341 | } |
306 | 342 | |
307 | 343 | function subEntries( $block ) { |
308 | 344 | $lines = ''; |
309 | 345 | foreach( $block as $rcObj ) { |
310 | 346 | $items = array(); |
| 347 | + $log = $this->isLog( $rcObj ); |
311 | 348 | |
312 | 349 | $time = $rcObj->timestamp; |
313 | | - if( $rcObj->getAttribute( 'rc_type' ) != RC_LOG ) { |
| 350 | + if( !$log ) { |
314 | 351 | $time = $this->skin->makeKnownLinkObj( $rcObj->getTitle(), |
315 | 352 | $rcObj->timestamp, wfArrayToCGI( $rcObj->_reqOldId, $rcObj->_reqCurId ) ); |
316 | 353 | } |
— | — | @@ -317,7 +354,7 @@ |
318 | 355 | $info = $this->getFlags( $rcObj ) . ' ' . $time; |
319 | 356 | $items[] = $this->spacerArrow() . Xml::tags( 'tt', null, $info ); |
320 | 357 | |
321 | | - if ( $rcObj->getAttribute( 'rc_type' ) != RC_LOG ) { |
| 358 | + if ( !$log ) { |
322 | 359 | $cur = $rcObj->_curLink; |
323 | 360 | $last = $rcObj->_lastLink; |
324 | 361 | |
— | — | @@ -326,12 +363,7 @@ |
327 | 364 | $cur = $this->message['cur']; |
328 | 365 | } |
329 | 366 | |
330 | | - $size = $rcObj->getCharacterDifference(); |
331 | | - if ( $size ) { |
332 | | - $items[] = "($cur; $last $size)"; |
333 | | - } else { |
334 | | - $items[] = "($cur; $last)"; |
335 | | - } |
| 367 | + $items[] = $this->changeInfo( $cur, $last, $this->getCharacterDifference( $rcObj ) ); |
336 | 368 | } |
337 | 369 | |
338 | 370 | $items[] = $this->userSeparator; |
— | — | @@ -344,6 +376,15 @@ |
345 | 377 | return $lines; |
346 | 378 | } |
347 | 379 | |
| 380 | + protected function changeInfo( $diff, $hist, $size ) { |
| 381 | + if ( $size ) { |
| 382 | + $size = $this->wrapCharacterDifference( $size ); |
| 383 | + return "($diff; $hist; $size)"; |
| 384 | + } else { |
| 385 | + return "($diff; $hist)"; |
| 386 | + } |
| 387 | + } |
| 388 | + |
348 | 389 | /** |
349 | 390 | * Enhanced RC ungrouped line. |
350 | 391 | * @return string a HTML formated line |
— | — | @@ -354,19 +395,12 @@ |
355 | 396 | $items[] = $this->spacerArrow() . Xml::tags( 'tt', null, $info ); |
356 | 397 | |
357 | 398 | # Article link |
358 | | - $items[] = $this->maybeWatchedLink( $rcObj->link, $rcObj->watched ); |
| 399 | + $items[] = $rcObj->link; |
359 | 400 | |
360 | | - if ( $rcObj->getAttribute( 'rc_type' ) != RC_LOG) { |
361 | | - $diff = $rcObj->_diffLink; |
362 | | - $hist = $rcObj->_histLink; |
363 | | - |
364 | | - # Character diff |
365 | | - $size = $rcObj->getCharacterDifference(); |
366 | | - if ( $size ) { |
367 | | - $items[] = "($diff; $hist $size)"; |
368 | | - } else { |
369 | | - $items[] = "($diff; $hist)"; |
370 | | - } |
| 401 | + if ( !$this->isLog( $rcObj ) ) { |
| 402 | + $items[] = $this->changeInfo( $rcObj->_diffLink, $rcObj->_histLink, |
| 403 | + $this->getCharacterDifference( $rcObj ) |
| 404 | + ); |
371 | 405 | } |
372 | 406 | |
373 | 407 | $items[] = $this->userSeparator; |
— | — | @@ -407,12 +441,18 @@ |
408 | 442 | } |
409 | 443 | |
410 | 444 | |
| 445 | + global $wgStylePath; |
| 446 | + $image = Xml::element( 'img', array( 'height' => '12', |
| 447 | + 'src' => $wgStylePath . '/common/images/magnify-clip.png' ) |
| 448 | + ); |
| 449 | + |
| 450 | + |
411 | 451 | $rci = 'RCUI' . $userindex; |
412 | 452 | $rcl = 'RCUL' . $linkindex; |
413 | 453 | $rcm = 'RCUM' . $linkindex; |
414 | 454 | $toggleLink = "javascript:showUserInfo('wgUserInfo$rci', '$rcl' )"; |
415 | 455 | $tl = Xml::tags('span', array( 'id' => $rcm ), |
416 | | - Xml::tags( 'a', array( 'href' => $toggleLink ), $this->arrow($this->direction ? 'r' : 'l') ) ); |
| 456 | + Xml::tags( 'a', array( 'href' => $toggleLink ), $image ) ); |
417 | 457 | $tl .= Xml::element('span', array( 'id' => $rcl ), ' ' ); |
418 | 458 | |
419 | 459 | $items = array(); |
— | — | @@ -461,32 +501,77 @@ |
462 | 502 | $text = $userlink; |
463 | 503 | if( $count > 1 ) { |
464 | 504 | $count = $wgLang->formatNum( $count ); |
465 | | - $text .= " {$wgLang->getDirMark()}({$count}×)"; |
| 505 | + $text .= "{$wgLang->getDirMark()}×$count"; |
466 | 506 | } |
467 | 507 | array_push( $users, $text ); |
468 | 508 | } |
469 | 509 | $text = implode('; ', $users); |
470 | | - $enclosure = |
471 | | - Xml::openElement( 'span', array( 'class' => 'changedby' ) ) . "[$text]" . |
472 | | - Xml::closeElement( 'span' ); |
473 | | - return $enclosure; |
| 510 | + return $this->XMLwrapper( 'changedby', "[$text]", 'span', false ); |
474 | 511 | } |
475 | 512 | |
476 | | - function getFlags( $object, $_new = null, $_minor = null, $_bot = null, $_unpatrolled = null ) { |
| 513 | + function getFlags( $rc, Array $overrides = null ) { |
477 | 514 | // TODO: we assume all characters are of equal width, which they may be not |
478 | | - $nothing = "\xc2\xa0"; |
| 515 | + $map = array( |
| 516 | + # item => field class letter |
| 517 | + 'new' => array( 'rc_new', 'newpage', $this->message['newpageletter'] ), |
| 518 | + 'minor' => array( 'rc_minor', 'minor', $this->message['minoreditletter'] ), |
| 519 | + 'bot' => array( 'rc_bot', 'bot', $this->message['boteditletter'] ), |
| 520 | + ); |
| 521 | + if ( self::usePatrol() ) { |
| 522 | + $map['patrol'] = array( 'rc_patrolled', 'unpatrolled', '!' ); |
| 523 | + } |
479 | 524 | |
480 | | - $new = is_null( $_new ) ? $object->getAttribute( 'rc_new' ) : $_new; |
481 | | - $minor = is_null( $_minor ) ? $object->getAttribute( 'rc_minor' ) : $_minor; |
482 | | - $bot = $object->getAttribute( 'rc_bot' ); |
483 | | - $patrolled = !$object->getAttribute( 'rc_patrolled' ) && $this->usePatrol(); |
484 | 525 | |
485 | | - $f = $new ? Xml::element( 'span', array( 'class' => 'newpage' ), $this->message['newpageletter'] ) |
486 | | - : $nothing; |
487 | | - $f .= $minor ? Xml::element( 'span', array( 'class' => 'minor' ), $this->message['minoreditletter'] ) |
488 | | - : $nothing; |
489 | | - $f .= $bot ? Xml::element( 'span', array( 'class' => 'bot' ), $this->message['boteditletter'] ) : $nothing; |
490 | | - $f .= $patrolled ? Xml::element( 'span', array( 'class' => 'unpatrolled' ), '!' ) : $nothing; |
491 | | - return $nothing. Xml::tags( 'span', $this->infoStyle, $f ); |
| 526 | + static $nothing = "\xc2\xa0"; |
| 527 | + |
| 528 | + $items = array(); |
| 529 | + foreach ( $map as $item => $data ) { |
| 530 | + $bool = isset($overrides[$item]) ? $overrides[$item] : $rc->getAttribute( $data[0] ); |
| 531 | + $items[] = $this->XMLwrapper( $data[1], $bool ? $data[2] : $nothing ); |
| 532 | + } |
| 533 | + |
| 534 | + return Xml::tags( 'span', $this->infoStyle, implode( '', $items ) ); |
492 | 535 | } |
| 536 | + |
| 537 | + protected function getCharacterDifference( $new, $old = null ) { |
| 538 | + if ( $old === null ) $old = $new; |
| 539 | + |
| 540 | + $newSize = $new->getAttribute('rc_new_len'); |
| 541 | + $oldSize = $old->getAttribute('rc_old_len'); |
| 542 | + if ( $newSize === null || $oldSize === null ) { |
| 543 | + return ''; |
| 544 | + } |
| 545 | + |
| 546 | + return $newSize - $oldSize; |
| 547 | + } |
| 548 | + |
| 549 | + public function wrapCharacterDifference( $szdiff ) { |
| 550 | + global $wgRCChangedSizeThreshold, $wgLang; |
| 551 | + static $cache = array(); |
| 552 | + if ( !isset($cache[$szdiff]) ) { |
| 553 | + $prefix = $szdiff > 0 ? '+' : ''; |
| 554 | + $cache[$szdiff] = wfMsgExt( 'rc-change-size', 'parsemag', |
| 555 | + $prefix . $wgLang->formatNum( $szdiff ) |
| 556 | + ); |
| 557 | + } |
| 558 | + |
| 559 | + if( $szdiff < $wgRCChangedSizeThreshold ) { |
| 560 | + return $this->XMLwrapper( 'mw-plusminus-neg', $cache[$szdiff], 'strong' ); |
| 561 | + } elseif( $szdiff === 0 ) { |
| 562 | + return $this->XMLwrapper( 'mw-plusminus-null', $cache[$szdiff] ); |
| 563 | + } elseif( $szdiff > 0 ) { |
| 564 | + return $this->XMLwrapper( 'mw-plusminus-pos', $cache[$szdiff] ); |
| 565 | + } else { |
| 566 | + return $this->XMLwrapper( 'mw-plusminus-neg', $cache[$szdiff] ); |
| 567 | + } |
| 568 | + } |
| 569 | + |
| 570 | + protected function XMLwrapper( $class, $content, $tag = 'span', $escape = true ) { |
| 571 | + if ( $escape ) { |
| 572 | + return Xml::element( $tag, array( 'class' => $class ), $content ); |
| 573 | + } else { |
| 574 | + return Xml::tags( $tag, array( 'class' => $class ), $content ); |
| 575 | + } |
| 576 | + } |
| 577 | + |
493 | 578 | } |