User:Jeblad/DataTable
From MediaWiki.org
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 ); } }