Difference between revisions of "Extension:TransformChanges.php"

From Organic Design wiki
(code was missing php at the top)
(1.1.5 - working better now)
Line 1: Line 1:
<?php
+
<?
 
/**
 
/**
 
  * TransformChanges extension - Makes recent-changes and watchlists render in nice columns for easier reading
 
  * TransformChanges extension - Makes recent-changes and watchlists render in nice columns for easier reading
Line 12: Line 12:
 
  */
 
  */
  
if (!defined('MEDIAWIKI')) die('Not an entry point.');
+
if ( !defined( 'MEDIAWIKI' ) ) die( 'Not an entry point.' );
  
define('TRANSFORMCHANGES_VERSION', '1.1.4, 2009-03-06');
+
define( 'TRANSFORMCHANGES_VERSION', '1.1.5, 2009-03-24' );
  
 
$wgExtensionCredits['other'][] = array(
 
$wgExtensionCredits['other'][] = array(
'name'        => 'TransformChanges',
+
'name'        => "TransformChanges",
'author'      => '[http://www.organicdesign.co.nz/nad User:Nad], [http://www.mediawiki.org/wikiUser:Fish1203 User:Fish1203]',
+
'author'      => "[http://www.organicdesign.co.nz/nad User:Nad], [http://www.mediawiki.org/wikiUser:Fish1203 User:Fish1203]",
'description' => 'Makes recent-changes and watchlists render in nice columns for easier reading.',
+
'description' => "Makes recent-changes and watchlists render in nice columns for easier reading.",
'url'        => 'http://www.organicdesign.co.nz/Extension:TransformChanges',
+
'url'        => "http://www.organicdesign.co.nz/Extension:TransformChanges",
 
'version'    => TRANSFORMCHANGES_VERSION
 
'version'    => TRANSFORMCHANGES_VERSION
 
);
 
);
Line 28: Line 28:
 
function wfSetupTransformChanges() {
 
function wfSetupTransformChanges() {
 
global $wgUser;
 
global $wgUser;
$wgUser->setOption('usenewrc', false);
+
$wgUser->setOption( 'usenewrc', false );
 
}
 
}
  
Line 37: Line 37:
 
# Bail if already done
 
# Bail if already done
 
static $done = 0;
 
static $done = 0;
if ($done++) return true;
+
if ( $done++ ) return true;
  
 
# Create a replica of the OutputPage class which calls the SpecialPageExecuteAfterPage after recentchanges rendered
 
# Create a replica of the OutputPage class which calls the SpecialPageExecuteAfterPage after recentchanges rendered
 
class OutputPage2 extends OutputPage {
 
class OutputPage2 extends OutputPage {
function addHTML($text) {
+
function addHTML( $text ) {
parent::addHTML($text);
+
parent::addHTML( $text );
if (ereg('^<h4>', $text)) wfRunHooks('SpecialPageExecuteAfterPage', array());
+
if ( ereg( '^<h4>', $text ) ) wfRunHooks( 'SpecialPageExecuteAfterPage', array() );
 
}
 
}
 
}
 
}
Line 51: Line 51:
 
$oldOut = $wgOut;
 
$oldOut = $wgOut;
 
$wgOut = new OutputPage2();
 
$wgOut = new OutputPage2();
foreach (array_keys(get_class_vars('OutputPage')) as $k) $wgOut->$k = $oldOut->$k;
+
foreach ( array_keys( get_class_vars( 'OutputPage' ) ) as $k ) $wgOut->$k = $oldOut->$k;
 
 
 
return true;
 
return true;
Line 60: Line 60:
 
global $wgOut;
 
global $wgOut;
 
$title = $wgOut->getPageTitle();
 
$title = $wgOut->getPageTitle();
if ($title != wfMsgForContent('recentchanges') && $title != wfMsgForContent('watchlist')) return true;
+
if ( $title != wfMsgForContent( 'recentchanges' ) && $title != wfMsgForContent( 'watchlist' ) ) return true;
 
$text =& $wgOut->mBodytext;
 
$text =& $wgOut->mBodytext;
$text = preg_replace('|(</ul>\\s*)?<h4>(.+?)</h4>\\s*(<ul class="special">)<li>|s', '$3<li $2>', $text);
+
$text = preg_replace( '|(</ul>\\s*)?<h4>(.+?)</h4>\\s*(<ul class="special">)<li>|s', '$3<li $2>', $text );
  
 
# Edits by Fish1203
 
# Edits by Fish1203
Line 69: Line 69:
  
 
# splitting in days
 
# splitting in days
$parts = explode("<ul class=\"special\">", $text);
+
$parts = explode( "<ul class=\"special\">", $text );
  
 
$first = 1;
 
$first = 1;
 
$nbedits = 50;
 
$nbedits = 50;
 
$text = $parts[0] . "<table class=\"changes\">";
 
$text = $parts[0] . "<table class=\"changes\">";
foreach ($parts as $part) {
+
foreach ( $parts as $part ) {
 
# skipping first part (= Special:RecentChanges "header")
 
# skipping first part (= Special:RecentChanges "header")
if ($first == 1) $first = 0;
+
if ( $first == 1 ) $first = 0;
 
else {
 
else {
  
$nbsubparts = (substr_count($part, "</li>")-1); # how many edits for this day ?
+
$nbsubparts = ( substr_count( $part, "</li>" ) - 1 ); # how many edits for this day ?
  
 
# if more than $nbedits edits for this day
 
# if more than $nbedits edits for this day
if ($nbsubparts > $nbedits) {    
+
if ( $nbsubparts > $nbedits ) {
$divide = intval(abs($nbsubparts/$nbedits));
+
$divide = intval( abs( $nbsubparts / $nbedits ) );
  
 
# splits each day in parts containing $nbedits edits (max.)
 
# splits each day in parts containing $nbedits edits (max.)
 
$start = 0;
 
$start = 0;
 
$parts2 = array();
 
$parts2 = array();
for ($lp=0; $lp<$divide; $lp++) {
+
for ( $lp=0; $lp < $divide; $lp++ ) {
$parts2[$lp] = substr($part, $start, (strposn($part, "</li>", ($lp+1)*$nbedits))-$start );
+
$parts2[$lp] = substr( $part, $start, ( strposn( $part, "</li>", ( $lp + 1 ) * $nbedits ) ) - $start );
$start = (strposn($part, "</li>", ($lp+1)*$nbedits));
+
$start = ( strposn( $part, "</li>", ( $lp + 1 ) * $nbedits ) );
 
}
 
}
 
 
 
# last part for the day
 
# last part for the day
$parts2[$divide] = substr($part, $start, strlen($part));
+
$parts2[$divide] = substr( $part, $start, strlen( $part ) );
 
   
 
   
foreach($parts2 as $part2) {
+
foreach ( $parts2 as $part2 ) {
 
$part2 = "<ul class=\"special\">$part2</ul>";
 
$part2 = "<ul class=\"special\">$part2</ul>";
$text .= preg_replace_callback("|<ul class=\"special\">(.+?)</ul>|s", 'wfTransformChangesUL', $part2);
+
$text .= preg_replace_callback( "|<ul class=\"special\">(.+?)</ul>|s", 'wfTransformChangesUL', $part2 );
 
}
 
}
 
}
 
}
 
else {
 
else {
 
$part = "<ul class=\"special\">$part</ul>";
 
$part = "<ul class=\"special\">$part</ul>";
$text .= preg_replace_callback("|<ul class=\"special\">(.+?)</ul>|s", 'wfTransformChangesUL', $part);
+
$text .= preg_replace_callback( "|<ul class=\"special\">(.+?)</ul>|s", 'wfTransformChangesUL', $part );
 
}
 
}
 
}
 
}
Line 109: Line 109:
  
 
# there may be one last </ul> tag remaining... just remove it... :-)
 
# there may be one last </ul> tag remaining... just remove it... :-)
$text = str_replace("</ul>", "", $text);
+
$text = str_replace( "</ul>", "", $text );
 
 
 
$text .= "</table>";
 
$text .= "</table>";
 
return true;
 
return true;
 
}
 
}
  
function wfTransformChangesUL($match) {
+
function wfTransformChangesUL( $match ) {
 
global $wgTransformChangesRow;
 
global $wgTransformChangesRow;
 
$wgTransformChangesRow = 'odd';
 
$wgTransformChangesRow = 'odd';
$rows = preg_replace_callback('|<li\\s*(.*?)>(.+?)</li>|s', 'wfTransformChangesLI', $match[1]);
+
$rows = preg_replace_callback( '|<li\\s*(.*?)>(.+?)</li>|s', 'wfTransformChangesLI', $match[1] );
 
return $rows;
 
return $rows;
 
}
 
}
  
function wfTransformChangesLI($match) {
+
function wfTransformChangesLI( $match ) {
 
global $wgTransformChangesRow, $wgSimpleSecurity;
 
global $wgTransformChangesRow, $wgSimpleSecurity;
 
$wgTransformChangesRow = $wgTransformChangesRow == 'even' ? 'odd' : 'even';
 
$wgTransformChangesRow = $wgTransformChangesRow == 'even' ? 'odd' : 'even';
 
$talk = '';
 
$talk = '';
list(, $date, $text) = $match;
+
list( , $date, $text ) = $match;
$cols = array('time', 'title', 'user', 'talk', 'info', 'comment', 'diff');
+
#$cols = array('time', 'title', 'user', 'talk', 'info', 'comment', 'diff');
  
 
# OrganicDesign has different columns and order
 
# OrganicDesign has different columns and order
#$cols = array('time','diff','title','comment','user','info');
+
$cols = array( 'time', 'diff', 'title', 'comment', 'user', 'info' );
  
$ncols = count($cols);
+
$ncols = count( $cols );
 
$row = '';
 
$row = '';
 
$error = '<td colspan="$ncols"><font color="red"><b>Error: match failed!</b></font></td>';
 
$error = '<td colspan="$ncols"><font color="red"><b>Error: match failed!</b></font></td>';
if ($date) {
+
if ( $date ) {
 
$row = "<tr><td class=\"heading\" colspan=\"$ncols\">$date</td></tr>\n";  
 
$row = "<tr><td class=\"heading\" colspan=\"$ncols\">$date</td></tr>\n";  
 
$wgTransformChangesRow = 'even';
 
$wgTransformChangesRow = 'even';
  
 
# OrganicDesign's table header
 
# OrganicDesign's table header
#static $head = "<tr><th>Time</th><th>Actions</th><th>Item changed</th><th>Description of change</th><th>Changed by</th><th>Details</th>";
+
static $head = "<tr><th>Time</th><th>Actions</th><th>Item changed</th><th>Description of change</th><th>Changed by</th><th>Details</th>";
#$row .= $head;
+
$row .= $head;
#$head = '';
+
$head = '';
 
}
 
}
 
$row .= "<tr class=\"$wgTransformChangesRow\">";
 
$row .= "<tr class=\"$wgTransformChangesRow\">";
if (preg_match('%^(.*?);(&#32;|\\s+)(\\d+:\\d+)(.+?)(<a.+?</a>\\))(</span>)?\\s*(.*?)$%', $text, $m)) {
+
 
list(, $diff,, $time, $bytes, $user,, $comment) = $m;
+
if (preg_match( '%^(.*?);(&#32;|\\s+)(\\d+:\\d+)(.+?)(<a.+?</a>\\))</span>\\s*(.*?)$%', $text, $m ) ) {
if (preg_match('|^(.+\\)).*?\\. \\.\\s*(.*?)\\s*(<a.+)$|', $diff, $m)) list(, $diff, $info, $title) = $m; else $info = $title = '';
+
list( , $diff,, $time, $bytes, $user, $comment ) = $m;
if (preg_match('|(\\(.+?\\))|', $bytes, $m)) $info .= "<small>$m[1]</small>";
+
 
 +
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>";
  
 
# Remove talk for email or IP users and make user lowercase
 
# Remove talk for email or IP users and make user lowercase
if (preg_match('|(<a.+?</a>).+?(\\(.+?</a>\\))|', $user, $m)) {
+
if ( preg_match('|(<a.+?</a>).+?(\\(.+?</a>\\))|', $user, $m ) ) {
list(, $user, $talk) = $m;
+
list( , $user, $talk ) = $m;
if (ereg('@', $user) || !eregi('[a-z]',$user)) { $talk = ''; $user = strtolower($user); }
+
if ( ereg( '@', $user ) || !eregi( '[a-z]',$user ) ) {
 +
$talk = '';
 +
$user = strtolower( $user );
 +
}
 
}
 
}
if (preg_match('|\\((.+)\\)|', $comment, $m)) $comment = $m[1];
 
  
 
# Only show row if ok by SimpleSecurity extension
 
# Only show row if ok by SimpleSecurity extension
 
$allowed = true;
 
$allowed = true;
if (preg_match('|title="(.+?)"|', $title, $m) && is_object($wgSimpleSecurity)) {
+
if ( preg_match('|title="(.+?)"|', $title, $m ) && is_object( $wgSimpleSecurity ) ) {
 
global $wgUser;
 
global $wgUser;
$t = Title::newFromText($m[1]);
+
$t = Title::newFromText( $m[1] );
$allowed = version_compare(SIMPLESECURITY_VERSION, '4.0.0') < 0
+
$allowed = version_compare( SIMPLESECURITY_VERSION, '4.0.0' ) < 0
? $wgSimpleSecurity->validateTitle('view', $t)
+
? $wgSimpleSecurity->validateTitle( 'view', $t )
: $wgSimpleSecurity->userCanReadTitle($wgUser, $t, $error);
+
: $wgSimpleSecurity->userCanReadTitle( $wgUser, $t, $error );
 
}
 
}
  
 
# OrganicDesign has an edit link instead of talk and hist
 
# OrganicDesign has an edit link instead of talk and hist
#$talk = preg_replace('| \\|.+</a>|','',$talk);
+
$talk = preg_replace( '| \\|.+</a>|', '', $talk );
#$diff = preg_replace('|curid=[0-9]+&(amp;)?action=history|','action=edit',$diff);
+
$diff = preg_replace( '|curid=[0-9]+&(amp;)?action=history|', 'action=edit', $diff );
#$diff = preg_replace('|>hist<|','>edit<',$diff);
+
$diff = preg_replace( '|>hist<|', '>edit<', $diff );
#$user .= "&nbsp;<small>$talk</small>";
+
$user .= "&nbsp;<small>$talk</small>";
  
if ($allowed) foreach ($cols as $col) {
+
if ( $allowed ) foreach ( $cols as $col ) {
 
$val = isset($$col) ? $$col : '';
 
$val = isset($$col) ? $$col : '';
 
$row .= "<td class=\"$col\">$val</td>";
 
$row .= "<td class=\"$col\">$val</td>";
Line 183: Line 186:
  
 
# Returns the position of the $n-th $c token (string) in $haystack (= position at the end of the token)
 
# Returns the position of the $n-th $c token (string) in $haystack (= position at the end of the token)
function strposn($haystack, $c, $n) {
+
function strposn( $haystack, $c, $n ) {
$a = explode($c, $haystack, $n+1);
+
$a = explode( $c, $haystack, $n + 1 );
if ($n <= 0 || count($a) <= $n) return false;
+
if ( $n <= 0 || count( $a ) <= $n ) return false;
return strlen($haystack)-strlen($a[$n]);
+
return strlen( $haystack ) - strlen( $a[$n] );
 
}
 
}

Revision as of 12:31, 23 March 2009

<? /**

* TransformChanges extension - Makes recent-changes and watchlists render in nice columns for easier reading
* Template:Php
Info.svg These are the MediaWiki extensions we're using and/or developing. Please refer to the information on the mediawiki.org wiki for installation and usage details. Extensions here which have no corresponding mediawiki article are either not ready for use or have been superseded. You can also browse our extension code in our local Subversion repository or our GitHub mirror.
* 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.5, 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 );

  1. Disable enhanced recent changes

$wgExtensionFunctions[] = 'wfSetupTransformChanges'; function wfSetupTransformChanges() { global $wgUser; $wgUser->setOption( 'usenewrc', false ); }

  1. 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 ); } } # 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; }
      1. 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] ); }