User:Fish1203/TransformChanges.php

From mediawiki.org
<?
# Extension:TransformChanges
# - See http://www.mediawiki.org/Extension:TransformChanges for installation and usage details
# - Licenced under LGPL (http://www.gnu.org/copyleft/lesser.html)
 
if (!defined('MEDIAWIKI')) die('Not an entry point.');
 
define('TRANSFORMCHANGES_VERSION','1.0.7, 2007-09-08');
 
$wgExtensionCredits['other'][] = array(
	'name'        => 'TransformChanges',
	'author'      => '[http://www.organicdesign.co.nz/nad User:Nad]',
	'description' => 'Makes recent-changes and watchlists render in nice columns for easier reading.',
	'url'         => 'http://www.organicdesign.co.nz/Extension:TransformChanges',
	'version'     => TRANSFORMCHANGES_VERSION
);
 
## 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]);
}
 
# Disable enhanced recent changes
$wgExtensionFunctions[] = 'wfSetupTransformChanges';
function wfSetupTransformChanges() {
	global $wgUser;
	$wgUser->setOption('usenewrc',false);
}
 
$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('|(</ul>\\s*)?<h4>(.+?)</h4>\\s*(<ul class="special">)<li>|s','$3<li $2>',$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('<ul class="special">',$text);

	$first = 1;
	$nbedits = 50;
	
	$text = $parts[0] . "<table class=\"changes\">";
	foreach($parts as $part) {
		if ($first == 1) {	## skipping first part (= Special:RecentChanges "header")
			$first = 0;
		}
		else {
			
			$nbsubparts = (substr_count($part,"</li>") - 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,"</li>",($lp+1)*$nbedits))-$start );
					$start = (strposn($part,"</li>",($lp+1)*$nbedits));
				}
				$parts2[$divide] = substr($part, $start, strlen($part));	## last part for the day
				
				foreach($parts2 as $part2) {
					$part2 = '<ul class="special">' . $part2 . '</ul>';
					$text .= preg_replace_callback('|<ul class="special">(.+?)</ul>|s','wfTransformChangesUL',$part2);
				}
			}
			else {
				$part = '<ul class="special">' . $part . '</ul>';
				$text .= preg_replace_callback('|<ul class="special">(.+?)</ul>|s','wfTransformChangesUL',$part);
			}
		}
	}
	
	## there may be one last </ul> tag remaining...
	## just remove it... :-)
	$text = str_replace("</ul>","",$text);
	
	$text .= "</table>";
	return true;
}
 
function wfTransformChangesUL($match) {
	global $wgTransformChangesRow;
	$wgTransformChangesRow = 'odd';		## was originally $wgTransformChangesRow = 0
	$rows = preg_replace_callback('|<li\\s*(.*?)>(.+?)</li>|s','wfTransformChangesLI',$match[1]);
	return $rows;
}
 
function wfTransformChangesLI($match) {
	global $wgTransformChangesRow,$wgSimpleSecurity;
	$wgTransformChangesRow = $wgTransformChangesRow == 'even' ? 'odd' : 'even';
	list(,$date,$text) = $match;
	$cols = array('time','title','user','talk','info','comment','diff');
	$ncols = count($cols);
	$row = '';
	$error = '<td colspan="$ncols"><font color="red"><b>Error: match failed!</b></font></td>';
	if ($date) {
		$row = "<tr><td class=\"heading\" colspan=\"$ncols\">$date</td></tr>\n"; 
		$wgTransformChangesRow = 'even';
	}
	$row .= "<tr class=\"$wgTransformChangesRow\">";
	if (preg_match('|^(.*?); (\\d+:\\d+)(.+?)(<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 .= "<small>$m[1]</small>";
		if (preg_match('|(<a.+?</a>).+?(\\(.+?\\))|',$user,$m)) {
			# Remove talk for email or IP users and make user lowercase
			list(,$user,$talk) = $m;
			if (ereg('@',$user) || !eregi('[a-z]',$user)) { $talk = ''; $user = strtolower($user); }
			}
		if (preg_match('|\\((.+)\\)|',$comment,$m)) $comment = $m[1];
		$allowed = true;
		if (preg_match('|title="(.+?)"|',$title,$m) && is_object($wgSimpleSecurity)) {
			# Only show row if ok by SimpleSecurity extension
			$t = Title::newFromText($m[1]);
			$allowed = $wgSimpleSecurity->validateTitle('view',$t);
			}
		if ($allowed) foreach ($cols as $col) $row .= "<td class=\"$col\">{$$col}</td>";
		} else $row = $error;
	$row .= "</tr>\n";
	return $row;
}
?>