Extension:TransformChanges.php
<? /**
* TransformChanges extension - Makes recent-changes and watchlists render in nice columns for easier reading * Template:Php
* See http://www.mediawiki.org/wiki/Extension:TransformChanges for installation and usage details * * @package MediaWiki * @subpackage Extensions * @author Aran Dunkley User:Nad * @copyright © 2007 Aran Dunkley * @licence GNU General Public Licence 2.0 or later */
if ( !defined( 'MEDIAWIKI' ) ) die( 'Not an entry point.' );
define( 'TRANSFORMCHANGES_VERSION', '1.1.6, 2009-03-24' );
$wgExtensionCredits['other'][] = array( 'name' => "TransformChanges", 'author' => "User:Nad, User:Fish1203", 'description' => "Makes recent-changes and watchlists render in nice columns for easier reading.", 'url' => "http://www.organicdesign.co.nz/Extension:TransformChanges", 'version' => TRANSFORMCHANGES_VERSION );
- Disable enhanced recent changes
$wgExtensionFunctions[] = 'wfSetupTransformChanges'; function wfSetupTransformChanges() { global $wgUser; $wgUser->setOption( 'usenewrc', false ); }
- A hack for 1.12+ to ensure the SpecialPageExecuteAfterPage hook gets called
$wgHooks['ChangesListInsertArticleLink'][] = 'wfRunSpecialPageExecuteAfterPageHook'; function wfRunSpecialPageExecuteAfterPageHook() {
# Bail if already done static $done = 0; if ( $done++ ) return true;
# Create a replica of the OutputPage class which calls the SpecialPageExecuteAfterPage after recentchanges rendered class OutputPage2 extends OutputPage { function addHTML( $text ) { parent::addHTML( $text );
if ( ereg( '^
', $text ) ) wfRunHooks( 'SpecialPageExecuteAfterPage', array() );
}
}
# Replace the global $wgOut object with an identical instance of the new OutputPage2 class
global $wgOut;
$oldOut = $wgOut;
$wgOut = new OutputPage2();
foreach ( array_keys( get_class_vars( 'OutputPage' ) ) as $k ) $wgOut->$k = $oldOut->$k;
return true;
}
$wgHooks['SpecialPageExecuteAfterPage'][] = 'wfTransformChanges';
function wfTransformChanges() {
global $wgOut;
$title = $wgOut->getPageTitle();
if ( $title != wfMsgForContent( 'recentchanges' ) && $title != wfMsgForContent( 'watchlist' ) ) return true;
$text =& $wgOut->mBodytext;
$text = preg_replace( '|(\\s*)?(.+?)
\\s*()- |s', '$3
- ', $text );
# Edits by Fish1203
# (http://www.mediawiki.org/wiki/User:Fish1203)
# solving the PHP preg_replace_callback() pcre.backtrack_limit problem
# splitting in days
$parts = explode( "", $text );
$first = 1;
$nbedits = 50;
$text = $parts[0] . "";
foreach ( $parts as $part ) {
# skipping first part (= Special:RecentChanges "header")
if ( $first == 1 ) $first = 0;
else {
$nbsubparts = ( substr_count( $part, "" ) - 1 ); # how many edits for this day ?
# if more than $nbedits edits for this day
if ( $nbsubparts > $nbedits ) {
$divide = intval( abs( $nbsubparts / $nbedits ) );
# splits each day in parts containing $nbedits edits (max.)
$start = 0;
$parts2 = array();
for ( $lp=0; $lp < $divide; $lp++ ) {
$parts2[$lp] = substr( $part, $start, ( strposn( $part, "", ( $lp + 1 ) * $nbedits ) ) - $start );
$start = ( strposn( $part, "", ( $lp + 1 ) * $nbedits ) );
}
# last part for the day
$parts2[$divide] = substr( $part, $start, strlen( $part ) );
foreach ( $parts2 as $part2 ) {
$part2 = "$part2
";
$text .= preg_replace_callback( "|(.+?)
|s", 'wfTransformChangesUL', $part2 );
}
}
else {
$part = "$part
";
$text .= preg_replace_callback( "|(.+?)
|s", 'wfTransformChangesUL', $part );
}
}
}
# there may be one last tag remaining... just remove it... :-)
$text = str_replace( "", "", $text );
$text .= "
";
return true;
}
function wfTransformChangesUL( $match ) {
global $wgTransformChangesRow;
$wgTransformChangesRow = 'odd';
$rows = preg_replace_callback( '|<li\\s*(.*?)>(.+?)|s', 'wfTransformChangesLI', $match[1] );
return $rows;
}
function wfTransformChangesLI( $match ) {
global $wgTransformChangesRow, $wgSimpleSecurity;
$wgTransformChangesRow = $wgTransformChangesRow == 'even' ? 'odd' : 'even';
$talk = ;
list( , $date, $text ) = $match;
#$cols = array('time', 'title', 'user', 'talk', 'info', 'comment', 'diff');
# OrganicDesign has different columns and order
$cols = array( 'time', 'diff', 'title', 'comment', 'user', 'info' );
$ncols = count( $cols );
$row = ;
$error = 'Error: match failed!';
if ( $date ) {
$row = "$date\n";
$wgTransformChangesRow = 'even';
# OrganicDesign's table header
static $head = "TimeActionsItem changedDescription of changeChanged byDetails";
$row .= $head;
$head = ;
}
$row .= "";
if (preg_match( '%^(.*?);( |\\s+)(\\d+:\\d+)(.+?)(<a.+?</a>\\))()?\\s*(.*?)$%', $text, $m ) ) {
list( , $diff,, $time, $bytes, $user,, $comment ) = $m;
if ( preg_match( '|^(.+\\)).*?\\. \\.\\s*(.*?)\\s*(<a.+)$|', $diff, $m ) ) list( , $diff, $info, $title ) = $m; else $info = $title = ;
if ( preg_match( '|(\\(.+?\\))|', $bytes, $m ) ) $info .= "$m[1]";
# Remove talk for email or IP users and make user lowercase
if ( preg_match('|(<a.+?</a>).+?(\\(.+?</a>\\))|', $user, $m ) ) {
list( , $user, $talk ) = $m;
if ( ereg( '@', $user ) || !eregi( '[a-z]',$user ) ) {
$talk = ;
$user = strtolower( $user );
}
}
# Remove brackets from comment
if (preg_match('|^<.+?>\\((.+)\\)<|', $comment, $m)) $comment = $m[1];
# Only show row if ok by SimpleSecurity extension
$allowed = true;
if ( preg_match('|title="(.+?)"|', $title, $m ) && is_object( $wgSimpleSecurity ) ) {
global $wgUser;
$t = Title::newFromText( $m[1] );
$allowed = version_compare( SIMPLESECURITY_VERSION, '4.0.0' ) < 0
? $wgSimpleSecurity->validateTitle( 'view', $t )
: $wgSimpleSecurity->userCanReadTitle( $wgUser, $t, $error );
}
# OrganicDesign has an edit link instead of talk and hist
$talk = preg_replace( '| \\|.+</a>|', , $talk );
$diff = preg_replace( '|curid=[0-9]+&(amp;)?action=history|', 'action=edit', $diff );
$diff = preg_replace( '|>hist<|', '>edit<', $diff );
$user .= " $talk";
if ( $allowed ) foreach ( $cols as $col ) {
$val = isset($$col) ? $$col : ;
$row .= "$val";
}
} else $row = $error;
$row .= "\n";
return $row;
}
- Returns the position of the $n-th $c token (string) in $haystack (= position at the end of the token)
function strposn( $haystack, $c, $n ) {
$a = explode( $c, $haystack, $n + 1 );
if ( $n <= 0 || count( $a ) <= $n ) return false;
return strlen( $haystack ) - strlen( $a[$n] );
}
# Edits by Fish1203 # (http://www.mediawiki.org/wiki/User:Fish1203) # solving the PHP preg_replace_callback() pcre.backtrack_limit problem
# splitting in days
$parts = explode( "- ", $text );
$first = 1;
$nbedits = 50;
$text = $parts[0] . "";
foreach ( $parts as $part ) {
# skipping first part (= Special:RecentChanges "header")
if ( $first == 1 ) $first = 0;
else {
$nbsubparts = ( substr_count( $part, "" ) - 1 ); # how many edits for this day ?
- Returns the position of the $n-th $c token (string) in $haystack (= position at the end of the token)
# if more than $nbedits edits for this day if ( $nbsubparts > $nbedits ) { $divide = intval( abs( $nbsubparts / $nbedits ) );
# splits each day in parts containing $nbedits edits (max.) $start = 0; $parts2 = array(); for ( $lp=0; $lp < $divide; $lp++ ) {
$parts2[$lp] = substr( $part, $start, ( strposn( $part, "", ( $lp + 1 ) * $nbedits ) ) - $start ); $start = ( strposn( $part, "", ( $lp + 1 ) * $nbedits ) );}
# last part for the day $parts2[$divide] = substr( $part, $start, strlen( $part ) );
foreach ( $parts2 as $part2 ) {
$part2 = "- $part2
- (.+?)
} } else {
$part = "- $part
- (.+?)
} } }
# there may be one last tag remaining... just remove it... :-) $text = str_replace( "", "", $text ); $text .= "return true; }
function wfTransformChangesUL( $match ) { global $wgTransformChangesRow; $wgTransformChangesRow = 'odd';
$rows = preg_replace_callback( '|<li\\s*(.*?)>(.+?)|s', 'wfTransformChangesLI', $match[1] );return $rows; }
function wfTransformChangesLI( $match ) { global $wgTransformChangesRow, $wgSimpleSecurity; $wgTransformChangesRow = $wgTransformChangesRow == 'even' ? 'odd' : 'even'; $talk = ; list( , $date, $text ) = $match; #$cols = array('time', 'title', 'user', 'talk', 'info', 'comment', 'diff');
# OrganicDesign has different columns and order $cols = array( 'time', 'diff', 'title', 'comment', 'user', 'info' );
$ncols = count( $cols ); $row = ;
$error = 'Error: match failed!';if ( $date ) {
$row = "$date\n";$wgTransformChangesRow = 'even';
# OrganicDesign's table header
static $head = "TimeActionsItem changedDescription of changeChanged byDetails";$row .= $head; $head = ; }
$row .= ""; if (preg_match( '%^(.*?);( |\\s+)(\\d+:\\d+)(.+?)(<a.+?</a>\\))()?\\s*(.*?)$%', $text, $m ) ) { list( , $diff,, $time, $bytes, $user,, $comment ) = $m; if ( preg_match( '|^(.+\\)).*?\\. \\.\\s*(.*?)\\s*(<a.+)$|', $diff, $m ) ) list( , $diff, $info, $title ) = $m; else $info = $title = ; if ( preg_match( '|(\\(.+?\\))|', $bytes, $m ) ) $info .= "$m[1]"; # Remove talk for email or IP users and make user lowercase if ( preg_match('|(<a.+?</a>).+?(\\(.+?</a>\\))|', $user, $m ) ) { list( , $user, $talk ) = $m; if ( ereg( '@', $user ) || !eregi( '[a-z]',$user ) ) { $talk = ; $user = strtolower( $user ); } } # Remove brackets from comment if (preg_match('|^<.+?>\\((.+)\\)<|', $comment, $m)) $comment = $m[1]; # Only show row if ok by SimpleSecurity extension $allowed = true; if ( preg_match('|title="(.+?)"|', $title, $m ) && is_object( $wgSimpleSecurity ) ) { global $wgUser; $t = Title::newFromText( $m[1] ); $allowed = version_compare( SIMPLESECURITY_VERSION, '4.0.0' ) < 0 ? $wgSimpleSecurity->validateTitle( 'view', $t ) : $wgSimpleSecurity->userCanReadTitle( $wgUser, $t, $error ); } # OrganicDesign has an edit link instead of talk and hist $talk = preg_replace( '| \\|.+</a>|', , $talk ); $diff = preg_replace( '|curid=[0-9]+&(amp;)?action=history|', 'action=edit', $diff ); $diff = preg_replace( '|>hist<|', '>edit<', $diff ); $user .= " $talk"; if ( $allowed ) foreach ( $cols as $col ) { $val = isset($$col) ? $$col : ; $row .= "$val";} } else $row = $error;
$row .= "\n"; return $row; }