User:Jeblad/DataTable

From MediaWiki.org
Jump to: navigation, search

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 );
    }
}