Difference between revisions of "Extension:TransformChanges.php"

From Organic Design wiki
m
(almost working for 1.12+ but not quite)
Line 1: Line 1:
 
<?
 
<?
# Extension:TransformChanges{{php}}{{Category:Extensions|TransformChanges}}
+
/**
# - See http://www.mediawiki.org/Extension:TransformChanges for installation and usage details
+
* TransformChanges extension - Makes recent-changes and watchlists render in nice columns for easier reading
# - Licenced under LGPL (http://www.gnu.org/copyleft/lesser.html)
+
* {{php}}{{Category:Extensions|TransformChanges}}
 +
* See http://www.mediawiki.org/wiki/Extension:TransformChanges for installation and usage details
 +
*
 +
* @package MediaWiki
 +
* @subpackage Extensions
 +
* @author Aran Dunkley [http://www.organicdesign.co.nz/nad User:Nad]
 +
* @copyright © 2007 Aran Dunkley
 +
* @licence GNU General Public Licence 2.0 or later
 +
*/
  
 
if (!defined('MEDIAWIKI')) die('Not an entry point.');
 
if (!defined('MEDIAWIKI')) die('Not an entry point.');
  
define('TRANSFORMCHANGES_VERSION','1.0.8, 2008-02-07');
+
define('TRANSFORMCHANGES_VERSION', '1.1.0, 2009-01-13');
  
 
$wgExtensionCredits['other'][] = array(
 
$wgExtensionCredits['other'][] = array(
        'name'        => 'TransformChanges',
+
'name'        => 'TransformChanges',
        'author'      => '[http://www.organicdesign.co.nz/nad User:Nad]',
+
'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
 
);
 
);
 
## 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
 
# Disable enhanced recent changes
 
$wgExtensionFunctions[] = 'wfSetupTransformChanges';
 
$wgExtensionFunctions[] = 'wfSetupTransformChanges';
 
function wfSetupTransformChanges() {
 
function wfSetupTransformChanges() {
        global $wgUser;
+
global $wgUser;
        $wgUser->setOption('usenewrc',false);
+
$wgUser->setOption('usenewrc', false);
 +
}
 +
 
 +
# A hack for 1.12+ to ensure the SpecialPageExecuteAfterPage hook gets called
 +
$wgHooks['ChangesListInsertArticleLink'][] = 'wfRunSpecialPageExecuteAfterPageHook';
 +
function wfRunSpecialPageExecuteAfterPageHook() {
 +
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('^<h4>', $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';
 
$wgHooks['SpecialPageExecuteAfterPage'][] = 'wfTransformChanges';
 
function wfTransformChanges() {
 
function wfTransformChanges() {
        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
        ## (http://www.mediawiki.org/wiki/User:Fish1203)
+
# (http://www.mediawiki.org/wiki/User:Fish1203)
        ## solving the PHP preg_replace_callback() pcre.backtrack_limit problem
+
# solving the PHP preg_replace_callback() pcre.backtrack_limit problem
  
        ## 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\">";
 +
foreach ($parts as $part) {
 +
# skipping first part (= Special:RecentChanges "header")
 +
if ($first == 1) $first = 0;
 +
else {
  
        $text = $parts[0] . "<table class=\"changes\">";
+
$nbsubparts = (substr_count($part, "</li>")-1); # how many edits for this day ?
        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));
  
                        ## if more than $nbedits edits for this day
+
# splits each day in parts containing $nbedits edits (max.)
                        if ($nbsubparts > $nbedits) {           
+
$start = 0;
                                $divide = intval(abs($nbsubparts/$nbedits));
+
$parts2 = array();
 
+
for ($lp=0; $lp<$divide; $lp++) {
                                ## splits each day in parts containing $nbedits edits (max.)
+
$parts2[$lp] = substr($part, $start, (strposn($part, "</li>", ($lp+1)*$nbedits))-$start );
                                $start = 0;
+
$start = (strposn($part, "</li>", ($lp+1)*$nbedits));
                                $parts2 = array();
+
}
                                for($lp=0; $lp<$divide; $lp++) {
+
                                        $parts2[$lp] = substr($part, $start, (strposn($part,"</li>",($lp+1)*$nbedits))-$start );
+
# last part for the day
                                        $start = (strposn($part,"</li>",($lp+1)*$nbedits));
+
$parts2[$divide] = substr($part, $start, strlen($part));
                                }
 
                                $parts2[$divide] = substr($part, $start, strlen($part));   ## last part for the day
 
 
   
 
   
                                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);
                        }
+
}
                }
+
}
        }
+
}
  
        ## there may be one last </ul> tag remaining...
+
# there may be one last </ul> tag remaining... just remove it... :-)
        ## 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';               ## was originally $wgTransformChangesRow = 0
+
$wgTransformChangesRow = 'odd';       ## was originally $wgTransformChangesRow = 0
        $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';
        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');
        $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';
        }
+
}
        $row .= "<tr class=\"$wgTransformChangesRow\">";
+
$row .= "<tr class=\"$wgTransformChangesRow\">";
        if (preg_match('|^(.*?); (\\d+:\\d+)(.+?)(<a.+?\\))\\s*(.*?)$|',$text,$m)) {
+
if (preg_match('|^(.*?); (\\d+:\\d+)(.+?)(<a.+?\\))\\s*(.*?)$|', $text, $m)) {
                list(,$diff,$time,$bytes,$user,$comment) = $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('|^(.+\\)).*?\\. \\.\\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('|(\\(.+?\\))|', $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
+
# Remove talk for email or IP users and make user lowercase
                        list(,$user,$talk) = $m;
+
if (preg_match('|(<a.+?</a>).+?(\\(.+?\\))|', $user, $m)) {
                        if (ereg('@',$user) || !eregi('[a-z]',$user)) { $talk = ''; $user = strtolower($user); }
+
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('|\\((.+)\\)|', $comment, $m)) $comment = $m[1];
                if (preg_match('|title="(.+?)"|',$title,$m) && is_object($wgSimpleSecurity)) {
+
 
                        # Only show row if ok by SimpleSecurity extension
+
# Only show row if ok by SimpleSecurity extension
                        $t = Title::newFromText($m[1]);
+
$allowed = true;
                        $allowed = $wgSimpleSecurity->validateTitle('view',$t);
+
if (preg_match('|title="(.+?)"|', $title, $m) && is_object($wgSimpleSecurity)) {
                        }
+
$t = Title::newFromText($m[1]);
                if ($allowed) foreach ($cols as $col) $row .= "<td class=\"$col\">{$$col}</td>";
+
$allowed = version_compare(SIMPLESECURITY_VERSION, '4.0.0') < 0
                } else $row = $error;
+
? $wgSimpleSecurity->validateTitle('view', $t)
        $row .= "</tr>\n";
+
: $t->userCan($action);
        return $row;
+
}
 +
if ($allowed) foreach ($cols as $col) {
 +
$val = isset($$col) ? $$col : '';
 +
$row .= "<td class=\"$col\">$val</td>";
 +
}
 +
} else $row = $error;
 +
$row .= "</tr>\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]);
 
}
 
}

Revision as of 06:39, 13 January 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.0, 2009-01-13');

$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() { 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'; ## was originally $wgTransformChangesRow = 0

      $rows = preg_replace_callback('|<li\\s*(.*?)>(.+?)|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 = 'Error: match failed!';

      if ($date) {

      $row = "$date\n";

      $wgTransformChangesRow = 'even'; }

      $row .= ""; 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 .= "$m[1]"; # Remove talk for email or IP users and make user lowercase if (preg_match('|(<a.+?</a>).+?(\\(.+?\\))|', $user, $m)) { list(, $user, $talk) = $m; 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 $allowed = true; if (preg_match('|title="(.+?)"|', $title, $m) && is_object($wgSimpleSecurity)) { $t = Title::newFromText($m[1]); $allowed = version_compare(SIMPLESECURITY_VERSION, '4.0.0') < 0 ? $wgSimpleSecurity->validateTitle('view', $t) : $t->userCan($action); } 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]); }