Extension:TemplateTable

From MediaWiki.org
Jump to: navigation, search
MediaWiki extensions manual - list
Crystal Clear action run.png
TemplateTable

Release status: beta

Implementation Tag
Description Make a table from template data
Author(s) C. Shaun Wagner (Kainawtalk)
MediaWiki 1.18
License No License - Free
Download In this wiki page
Check usage and version matrix


TemplateTable is an extension that creates tables based on template data.

See also: Extension:SMW.

Contents

Example [edit]

Consider the situation where you have a wiki that has template:Restaurant with the fields Name, Price, and Cuisine. You want to have a single table somewhere that shows all the data and auto-updates when a template is updated for a restaurant or a new restaurant is added. You add the table with <ttable template='Restaurant'></ttable> and you would get something like:

  Name Price Cuisine
article Chopsticks $$ Chinese
article O'Henrys $$$ American
article Osaka $$ Asian

Documentation [edit]

Complete documentation is in the code.

The options available inside the ttable tag are:

  • template: This is required. It must match the case on the "Template:NameOfTemplate" page.
  • headers: You can customize which columns to show. Values are separated by |, as in: headers='Name|Price|Location'
  • Standard table tag options: border, cellspacing, cellpadding, align, style
  • Any text between <ttable> and </ttable> will appear above the table created.

History [edit]

2006-08-02 Version 1 of TemplateTable released.

Caching note [edit]

MediaWiki caches pages. So, a change to a template value will not immediately show up in the ttable table. You can force it to update by going to the page with the ttable, clicking on edit, and then either saving the page unchanged, or - in the URL - changing "edit" to "purge". It would be nice if this extension added a small "update" link that purges the page.

Without some additional cache management, the extension will always show the data that were present the last time someone manually saved or purged the page, making this extension problematic in practice.

Code [edit]

<?php
/*******************************************************************
* MediaWiki Extension: Template Table
* by CS "Kainaw" Wagner <http://shaunwagner.com>
********************************************************************
* COPYRIGHT & LICENSING:
* Feel free to use and abuse this script as you see fit.
* It is licensed under whatever license MediaWiki uses.
* I'm not into that legal junk.
*  -CS Wagner
********************************************************************
* A CALL FOR HELP!!!
* I am not the greatest programmer in the world.  If you see
* something in this script that can be improved (or something that
* is just plain idiotic), please fix it at
* http://www.mediawiki.org/w/index.php?title=Extension:TemplateTable
* and feel free to add comments about the work you've added!
********************************************************************
* DESCRIPTION
* This adds a ttable tag to MediaWiki to show template items from
* all pages in a single table.  This is very useful for creating an
* automatically generated comparison between common articles.
********************************************************************
* USAGE
* Simplest usage is <ttable template='TemplateName'></ttable>.
*
* !!!IMPORTANT NOTE!!!
* For technical reasons, TemplateName is case-sensitive.  That means
* that if you have Template:MyTemplate, you must use:
*  <ttable template='MyTemplate'></ttable>
* However, it will find data in pages that use {{mytemplate ...}}
* You just have to make sure the value in the ttable tag matches
* the case of the actual template page.
*
* ADVANCED USAGE
* You can choose which headers to display with the headers option:
*  <ttable template='MyTemplate' headers='Name|Address'></ttable>
* A | (vertical bar/pipe) separates each header.  If you do not
* supply this option, all headers used will be shown.
*
* You may customize the table with the standard table tags:
*  border, cellspacing, cellpadding, class, align, and style.
*
* Any text between <ttable> and </ttable> will appear ABOVE the
* table that is produced.
********************************************************************
* SPECIAL NOTE
* A side effect of how this script works is that you can have fields
* that display in this table and not in the actual template.  If you
* have made a template, you know that you can ignore variables that
* are sent to it.  If you do that and you do not ignore them in this
* table, they will show up here and not in the template.
********************************************************************
* INSTALLATION
* Put this in the extensions directory and include it in your
* LocalSettings.php file before the last ? > like:
*  include("extensions/templatetable.php");
********************************************************************
* CUSTOMIZATION
* The only thing I think anyone would customize is the text of the
* "article" link.  That is easy to change.  Just search the script
* for "article" and you will see it.  It looks like:
*  $output.= "article";
* Change it to whatever you like (it can even be an image).
********************************************************************
* CHANGES
* 2007-03-18 - Kainaw
*  Added database prefix as suggested on the talk page.
********************************************************************/
 
// Register the tag.
$wgExtensionFunctions[] = "wfTemplateTable";
function wfTemplateTable()
{
        global $wgParser;
        $wgParser->setHook("ttable", "renderTemplateTable");
}
 
/**
* This function renders the TemplateTable.
* $input = text between <ttable> and </ttable>
* $argv = key/val array of options in the <ttable> tag.
*/
function renderTemplateTable($input, $argv)
{
        global $wgScript;
        // Print a nice error if template is not given.
        if(!isset($argv["template"])) return "TemplateTable Error: No template given.  Please use the format <tt>&lt;ttable template='Name Of Template'&gt;...&lt;/ttable&gt;</tt>";
 
        // Header type.  If "headers" is given, use that.
        // Otherwise, use dynamic headers (every variable used in the template)
        $dynhead = true;
        $headers = array();
        if(isset($argv["headers"]))
        {
                $headers = explode("|", $argv["headers"]);
                $dynhead = false;
        }
 
        // Preset output to the input (stuff between <ttable> and </ttable>
        $output = $input;
 
        // Now the hard part: Hunt down the template data...
        /***************************************************************
        * Instead of commenting all through this, I will just describe
        * it here:
        * The goal is to have an array ($data) that looks like:
        * $data[page name] = array(key1=>val1, key2=>val2...);
        *
        * Step 1:
        * Get a list of all Page IDs that use the template.
        * For every page found...
        *   Step 2:
        *   Get the last Revision ID for each Page ID.
        *   Step 3:
        *   Get the text for the last Revision.
        *   Step 4:
        *   Extract the template text from the Revision.
        *   Step 5:
        *   If there is template text, parse it and create an item for
        *   the $data array.
        ****************************************************************/
        global $wgDBprefix, $wgContLang;
        $namespaceNames = $wgContLang->namespaceNames;
        $data = array();
        $query = "select * from ".$wgDBprefix."templatelinks left join ".$wgDBprefix."page on ".$wgDBprefix."templatelinks.tl_from=".$wgDBprefix."page.page_id where tl_title='".mysql_escape_string($argv["template"])."' order by page_title";
        $result = mysql_query($query);
        while($row = mysql_fetch_object($result))
        {
                $q2 = "select rev_text_id from ".$wgDBprefix."revision where rev_page=".$row->page_id." order by rev_timestamp desc limit 1";
                if(($res2 = mysql_query($q2)) && ($row2 = mysql_fetch_object($res2)))
                {
                        $q3 = "select * from ".$wgDBprefix."text where old_id=".$row2->rev_text_id;
                        if(($res3 = mysql_query($q3)) && ($row3 = mysql_fetch_object($res3)))
                        {
                                $row3->old_text = str_replace("\n", " ", $row3->old_text);      # turn the article into one long line
                                $start = stripos($row3->old_text, "{{".$argv["template"])+2;    # cursor after first occurence of {{
                                $end = strpos($row3->old_text, "}}", $start)-1;                 # cursor before first occurence of }}
                                if($start === false || $end === false) continue;                # not found -> cancel result processing

                                $item = array();
                                $kvs = explode( "|", substr($row3->old_text, $start, $end-$start+1) );  # create an array from of the template fields
                                unset( $kvs[0] );                                                       # remove first field: template name

                                foreach($kvs as $kv)
                                {
                                        $kv = trim($kv);
                                        if($kv == "") continue;
                                        $eq = strpos($kv, "=");
                                        if($eq === false) continue;
                                        $key = trim(substr($kv, 0, $eq));
                                        $val = trim(substr($kv, $eq+1));
                                        $item[$key] = $val;
                                        if($dynhead && !in_array($key, $headers)) array_push($headers, $key);
                                }
                                if(sizeof($item) > 0) {
                                        $title = str_replace("_", " ", $row->page_title);
                                        if ( $row->page_namespace != NS_MAIN ) {
                                                $title = $namespaceNames[$row->page_namespace].":".$title;
                                                }
                                        $data[$title] = $item;
                                        }
                        }
                }
        }
 
        // Skip this if there's no data to display.
        // Otherwise, create our pretty little table!
        if(sizeof($data) > 0)
        {
                $output.= "<table";
                foreach($argv as $key=>$val)
                {
                        if($key == "template" || $key == "headers") continue;
                        $output.= " $key=\"$val\"";
                }
                $output.= ">\n";
                $output.= "<tr><th>&nbsp;</th>\n";
                foreach($headers as $header)
                {
                        $output.= "<th>$header</th>\n";
                }
                $output.= "</tr>\n";
                foreach($data as $page=>$item)
                {
                        $link = $page;
                        $colon = strpos($link, ":");                            # page name as link title
                        if ( $colon >= 0 ) $link = substr($link, $colon);       # without leading Category:/Wiki:/Special: statements

                        // Changing this line will change the text that appears as the article link:
                        // $link = "article";
 
                        $output.= "<tr><td align='center'><a href='".$wgScript."?title=".urlencode($page)."'>$link</a></td>\n";
                        foreach($headers as $header)
                        {
                                if(isset($item[$header]))
                                        $output.= "<td>".$item[$header]."</td>\n";
                                else
                                        $output.= "<td>&nbsp;</td>\n";
                        }
                        $output.= "</tr>\n";
                }
                $output.= "</table>\n";
        }
        else
        {
                // Print a nice (no data found) message:
                $output.= "Template ".$argv["template"]." has no data.";
        }
 
        return $output;
}
?>