User:Jeblad/DataTable
Some ideas for chnages…
<?php
$wgExtensionCredits['parserhook'][] = array(
'name' => 'DataTable',
'version' => ExtDataTable::$mVersion,
'author' => '[http://www.mediawiki.org/wiki/User:RV1971 RV1971]',
'url' => 'http://www.mediawiki.org/wiki/Extension:DataTable',
'description' => 'store data in a table and retrieve it on other pages'
);
// instance of this extension class
$wgExtDataTable = new ExtDataTable();
// register the extension
$wgExtensionFunctions[] = array( &$wgExtDataTable, 'setup' );
$wgHooks['LanguageGetMagic'][] = array( &$wgExtDataTable,
'onLanguageGetMagic' );
$wgHooks['ArticleDelete'][] = array( &$wgExtDataTable,
'onArticleDelete' );
$wgHooks['ArticleSaveComplete'][] = array( &$wgExtDataTable,
'onArticleSaveComplete' );
$wgHooks['NewRevisionFromEditComplete'][] =
array( &$wgExtDataTable,
'onNewRevisionFromEditComplete' );
class ExtDataTable
{
public static $mVersion = '0.5';
public function setup() {
global $wgParser;
// parser functions
$wgParser->setFunctionHook( 'data', array( &$this, 'data' ) );
// tags
$wgParser->setHook( 'datatable', array( &$this, 'datatable' ) );
}
public function onLanguageGetMagic( &$magicWords, $langCode ) {
$magicWords['data'] = array( 0, 'data' );
return true;
}
// hook to delete data when an article is deleted
public function onArticleDelete( $article )
{
$dtd_page = $article->getID();
$dbr =& wfGetDB( DB_MASTER );
// Delete all data for this page.
$dbr->delete( 'datatable_data', array( 'dtd_page' => $dtd_page ) );
return true;
}
// hook to save data when an article is saved
public function onArticleSaveComplete( $article, $user, $text )
{
return $this->saveData( $article, $text );
}
// hook to save data when an article is imported
public function onNewRevisionFromEditComplete( $article, $rev, $baseID )
{
return $this->saveData( $article, $article->getContent() );
}
// display data
public function datatable( $content, $params, &$parser)
{
extract( $params );
$output = '';
// parse head tag, if any
if( preg_match( '+<head>(.*)</head>+s', $content, $matches ) )
{
$head = $matches[1];
$content = str_replace( $matches[0], '', $content );
if( $class )
$class = "class='$class'";
$output .= "{| $class\n|-\n$head\n|-\n";
}
// parse template tag, if any
if( preg_match( '+<template>(.*)</template>+s', $content, $matches ) )
{
$inlinetemplate = $matches[1];
$content = str_replace( $matches[0], '', $content );
for( $i = 1; $i <= 20; $i++ )
$param_array[] = '{{{' . $i . '}}}';
}
foreach( preg_split( "/[\n\r]+/", $content ) as $row )
{
if( $row > '' )
{
$record = array();
foreach($this->splitRowByPipe( $row ) as $key => $value)
$record['c' . ($key + 1)] = $value;
if( $template )
{
// explicitely name positional parameters
// in order to allow equal signs within parameters
$count = 0;
foreach( $record as $key => $arg )
$params[$key] = ++$count . '=' . $arg;
$output .= '{{' . $template . '|'
. $this->templateArgString( $record ) . "}}\n";
}
elseif( $inlinetemplate )
{
$output .= str_replace( $param_array, $record,
$inlinetemplate );
}
else
$output .= '| ' . implode( "\n| ", $record ) . "\n|-\n";
}
}
if( $head )
$output .= "|-\n|}\n";
if( $display != 'no' )
return $parser->recursiveTagParse( $output );
}
// function save data from an article
function saveData( $article, $text )
{
$dtd_page = $article->getID();
$dbr =& wfGetDB( DB_MASTER );
// Delete all data for this page.
$dbr->delete( 'datatable_data', array( 'dtd_page' => $dtd_page ) );
// Collect data to save
Parser::extractTagsAndParams( array( 'datatable' ),
$text, $datatable_tags );
foreach( $datatable_tags as $tagdata )
{
list( $element, $content, $params, $tag ) = $tagdata;
unset( $table );
extract( $params );
// ignore if no table specified
if( !$table )
continue;
// eliminate internal tags
$content = preg_replace( '+<head>(.*)</head>+s', '', $content );
$content = preg_replace( '+<template>(.*)</template>+s', '',
$content );
foreach( preg_split( "/[\n\r]+/", $content ) as $row )
{
if( $row > '' )
{
$record = array( 'dtd_page' => $dtd_page,
'dtd_table' => $table );
foreach($this->splitRowByPipe( $row ) as $key => $value)
$record['c' . ($key + 1)] = $value;
$dbr->insert( 'datatable_data', $record );
}
}
}
return true;
}
// explicitely name positional parameters
// in order to allow equal signs within parameters
function templateArgString( $params )
{
$count = 0;
foreach($params as $key => $arg)
$params[$key] = ++$count . '=' . $arg;
return implode( '|', $params );
}
// split a pipe-separated row into an array
// such that pipes within template calls are protected
function splitRowByPipe( $string )
{
foreach(preg_split('//', $string, -1, PREG_SPLIT_NO_EMPTY) as $c)
{
switch($c)
{
case '{' :
case '[' :
$substring .= $c;
$par++;
break;
case '}' :
case ']' :
$substring .= $c;
$par--;
break;
case '|' :
if( !$par )
{
$string_array[] = $substring;
$substring = '';
}
else
$substring .= $c;
break;
default :
$substring .= $c;
}
}
$string_array[] = $substring;
return $string_array;
}
// retrieve data
function data( &$parser, $table, $columns, $template, $condition, $sort,
$p1, $p2, $p3, $p4 )
{
$dbr =& wfGetDB( DB_SLAVE );
$result = '';
$resarray = array();
// clean up table
$match = array();
if(preg_match( '([_\w]+)', $table, $match)
$table = $match[0];
else
;// woopsie, report an error
// clean up the columns
$c = array();
foreach(preg_split('\s*,\s*', $columns, -1, PREG_SPLIT_NO_EMPTY) as $str)
{
$match = array();
if(preg_match( '^\s*([_\w]+)\s*$', $str, $match)
$c[] = $match[1];
else
;// woopsie, report an error
}
$columns = implode( ',', $c );
if( !$columns )
$columns = '*';
// clean up the condition
// probably needs some kind of parser..
if( $condition )
$condition = 'and ' . $condition;
if( $sort ) {
$match = array();
if(preg_match( '([_\w]+\s+(asc|desc))', $sort, $match)
$sort = 'order by ' . $match[0];
else
;// woopsie, report an error
}
$res = $dbr->query( "select distinct $columns from datatable_data where dtd_table = '$table' $condition $sort" , __METHOD__ );
while( $record = $dbr->fetchRow( $res ) )
{
// fetchRow returns an array with both numeric and text keys
// we keep only the numeric keys
foreach( $record as $key => $value )
if( !is_int( $key ) )
unset( $record[$key] );
if( $columns == '*' )
{
// all columns except page ID and table name
unset($record[0]);
unset($record[1]);
}
if( $template )
$result .= "{{{$template}|" . $this->templateArgString( $record )
. "|p1=$p1|p2=$p2|p3=$p3|p4=$p4}}";
else
$resarray[] = implode( ', ', $record );
}
if( !$template )
$result = implode( '; ', $resarray );
$dbr->freeResult($res);
return $parser->replaceVariables( $result );
}
}