Extension:DataTable/Source

From MediaWiki.org

Jump to: navigation, search

Contents


[edit] SQL Script

For MySQL, run the following from an admin account to create a new database table:

CREATE TABLE datatable_data (
    dtd_page INT(8) UNSIGNED NOT NULL DEFAULT 0,
    dtd_table CHAR(255) NOT NULL,
    c1 TEXT(1024),
    c2 TEXT(1024),
    c3 TEXT(1024),
    c4 TEXT(1024),
    c5 TEXT(1024),
    c6 TEXT(1024),
    c7 TEXT(1024),
    c8 TEXT(1024),
    c9 TEXT(1024),
    c10 TEXT(1024),
    c11 TEXT(1024),
    c12 TEXT(1024),
    c13 TEXT(1024),
    c14 TEXT(1024),
    c15 TEXT(1024),
    c16 TEXT(1024),
    c17 TEXT(1024),
    c18 TEXT(1024),
    c19 TEXT(1024),
    c20 TEXT(1024),
    KEY datatable_data_page(dtd_page),
    KEY datatable_data_table(dtd_table)
);

grant select on datatable_data to wikiuser;
grant insert on datatable_data to wikiuser;
grant delete on datatable_data to wikiuser;

For PostgreSQL, run the following from the wikiuser account to create a new database table:

create table datatable_data (
    dtd_page integer not null default 0,
    dtd_table text not null,
    c1 text,
    c2 text,
    c3 text,
    c4 text,
    c5 text,
    c6 text,
    c7 text,
    c8 text,
    c9 text,
    c10 text,
    c11 text,
    c12 text,
    c13 text,
    c14 text,
    c15 text,
    c16 text,
    c17 text,
    c18 text,
    c19 text,
    c20 text
);

create index datatable_data_page on datatable_data(dtd_page);
create index datatable_data_table on datatable_data(dtd_table);

[edit] Extension Source

<?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();
 
      if( !$columns )
	$columns = '*';
 
      if( $condition )
        $condition = 'and ' . $condition;
 
      if( $sort )
        $sort = 'order by ' . $sort;
 
      $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 );
    }
}