Extension talk:TemplateTable

Another useful feature
This would be a more useful extension (IMHO) if you could filter the table based on a parameter (or an expression of parameters), and also possibly have an option to only show include template usages on the current page. In the example, then, this could let you build a table of all restaurants in the $$$ price range, or make a page of Boston Restaurants that uses this template, and summarize them all in a table at the top.

Also note that for this to work the code should look for more than one template per page! It currently only finds the first one. Vash 16:15, 24 April 2007 (UTC)

re. Another useful feature

 * Yes! I agree. '''This would be a more useful extension (IMHO) if you could filter the table based on a parameter (or an expression of parameters).
 * Some examples belows here would be nice.

 
 * Other ideas which can be found it written in DynamicPageList2 0.9.
 * --Roc michael 14:52, 25 April 2007 (UTC)

re. Another useful feature
Ask and Ye shall receive. We are finding this particular extension VERY useful in our environment, and adding the exclusion filter makes it even better.

Exclude filter for 
 * Pass exclude filters to the ttable with simple arguments (
 * Can accept multiple excludes

Below is a diff to enable excludes in the templatetable extension. 40a41,45 > * You can also filter the table rows based on an exclude list > * passed as an argument to the : > *  * excludes="header1=value1|header2=value2"> > * 93a99,100 >  $excludesArray = array; >  $excludeFlag = False; 98a106,112 >  if(isset($argv["excludes"])) { >      $excludesArray = explode("|",$argv["excludes"]); >      foreach($excludesArray as $excludeValues) { >          list($excludeKey,$excludeVal) = explode("=",$excludeValues); >          $excludesArray[strtolower($excludeKey)] = $excludeVal; >      } >   } 150a165,169 >                      // Check to see if this header is excluded >                      if(isset($excludesArray[$key]) && >                       !strcmp(strtolower($excludesArray[$key]), strtolower($val))) { >                          $excludeFlag=True; >                          break; >                      } 154c173 <                  if(sizeof($item) > 0) --- >                  if(sizeof($item) > 0 && !$excludeFlag) { 155a175,176 >                  } >                   $excludeFlag = False;

TerrySoucy 18:20, 22 Jan 2010 (UTC)

Two bugs
This is a great extension, but there are two pretty simple but significant bugs i've encountered.


 * 1) MediaWiki installations with a db table prefix will not work with this extension, as all three queries did not take this into account.
 * 2) The article links in the resulting table do not have their namespaces in them.

Both are pretty easily fixed.

Additional:
 * 1) It does not work if the template does not use named parameters

Suggested: (sorry lots of debug lines... I don't have any PHP background. took apart this ext slowly to try to understand it.) 
 * 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 .
 * !!!IMPORTANT NOTE!!!
 * For technical reasons, TemplateName is case-sensitive. That means
 * that if you have Template:MyTemplate, you must use:
 * 
 * However, it will find data in pages that use
 * 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:
 * 
 * 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 and 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).
 * 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).
 * Change it to whatever you like (it can even be an image).

Added:
 * prefixes
 * check if mediawiki
 * argument: styleclass (for table formatting)

Changed: (commented out, can be restored easily)
 * to stop supporting named parameters and support only unnamed parameters

//if not MediaWiki - abort (security feature) if( !defined( 'MEDIAWIKI' ) ) { die; }

// Register the tag. $wgExtensionFunctions[] = "wfTemplateTable"; $wgExtensionCredits['parserhook'][] = array(	'name' => 'TemplateTable',	'author' => 'CS Wagner (modified)',	'url' => 'http://meta.wikimedia.org/wiki/TemplateTable_extension',	'description' => 'Auto-generates a table derived from the template parameters of every instance of a template', );

function wfTemplateTable {       global $wgParser; $wgParser->setHook("ttable", "renderTemplateTable"); }

/** 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 ... ";
 * This function renders the TemplateTable.
 * $input = text between and
 * $argv = key/val array of options in the tag.

// 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 and 		$output = $input; //debug		$output .= "Hello..." . mysql_escape_string($argv["template"]); 		// 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; $prefix = $wgDBprefix; // add this so because my wiki uses prefixes in front of table names $data = array; $query = "select * from ". $prefix. "templatelinks left join ". $prefix. "page on ". $prefix. "templatelinks.tl_from=". $prefix. "page.page_id where tl_title='".$argv["template"]."' order by page_title"; //This unfortunately selects records irrespective of case: ABC, Abc, abc, etc $result = mysql_query($query); while($row = mysql_fetch_object($result)) {

//debug:  $output .= "\n\n=". $row->page_title; //Page title is the title of the page $q2 = "select rev_text_id from ". $prefix. "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 ". $prefix. "text where old_id=".$row2->rev_text_id; if(($res3 = mysql_query($q3)) && ($row3 = mysql_fetch_object($res3))) {

//$row3->old_text is the whole text of the file //debug(show whole file text):          $output .= "\n"."\n"."===".$row2->rev_text_id."==="."\n"."\n". $row3->old_text ;

$row3->old_text = str_replace("\n", " ", $row3->old_text); //Unsure of function... works well without //Works out starting postion of so that can extract/copy this information $start = stripos($row3->old_text, "{{".$argv["template"]); //If you specifically only use your template at the beginning of your file: //Only accepts this file if the header is at the beginning of the file, else ignore //                       if($start == 0) //						{                                if($start === false) continue;

$end = strpos($row3->old_text, "}}", $start); if($end === false) continue; //Debug (position)//  $output .= "\n"."\n"."===xx2xx".$start. " to ".$end."==="."\n"."\n";

//The extracted wanted text in raw form $tmp = substr($row3->old_text, $start+strlen("{{".$argv["template"]), $end-strlen("{{".$argv["template"])); //Debug (raw extracted text)//  $output .= "\n\n==".$tmp ;

$item = array; $kvs = explode("|", $tmp); //separate out each of the parameters separated by "|"

//changed so that it will work with template unnamed parameters $key = 0 ; //counter foreach($kvs as $kv) {

$kv = trim($kv); if($kv == "") continue; //                                       $eq = strpos($kv, "="); //  $output .= "\n"."\n"."===xxEq5xx: ".$eq; //                                       if($eq === false) continue; //                                       $key = strtolower(trim(substr($kv, 0, $eq))); $key = $key + 1; //                                       $val = trim(substr($kv, $eq+1)); $val = $kv; $item[$key] = $val; //debug (all items)//  $output .= "\n\n*item(". $key. ")=" .$item[$key]; if($dynhead && !in_array($key, $headers)) array_push($headers, $key); //probably can delete this line too }                               if(sizeof($item) > 0) $data[$row->page_title] = $item; //enable this for: if (beginning of file)://   } }               }        }

// Skip this if there's no data to display. // Otherwise, create our pretty little table! if(sizeof($data) < 1) {               // Print a nice (no data found) message: $output.= "Template ".$argv["template"]." has no data."; }       else {               $output.= " \n";

//Display the output data }       return $output; } ?>

Cache Problem
While the suggestions and bugs above are nice, there is a crippling problem with this extension - it suffers from the MediaWiki cache. When a template is changed, the ttable needs to change also. How can that be done? The templates do not know if they are part of a ttable, so there's no reasonable way to get them to flush the cache. Because the ttable is cached, it isn't processed - which means that the ttable can't force itself to flush the cache. It would be nice if there was some magical keyword that would tell MediaWiki to never cache a certain page, then that could be added to ttable pages. Kainaw 19:16, 25 July 2007 (UTC)

Scripting vulnerability
The input text between the opening and closing tags is passed through without further processing as it seems and arbitrary HTML (including Javascript) can be inserted in the resulting page. As a workaround one can replace the line  with

Problably  can also be used to solve this problem. --Schevv 09:15, 10 November 2010 (UTC)

About Cache Problem
There is extention Extension:Labeled Section Transclusion that allows you to include section of one page into another page. You just add " " into your target page, and there is no "Cache Problem" then you have edited source page, but did not edit target page.

It may be somebody can try to see the salvation way which is used there?

Templates inside of Templates
This code needs to recusively search for pairs. I am going to try and write the code today maybe through regular expressions. Something like this:

\{\{     # match two opening brackets (?:      # start non-capturing group 1  [^{}]   #   match any character except '{' and '}'  |       #   OR  (?R)    #   recursively call the entire pattern: \{\{(?:[^{}]|(?R))*}} )         # end non-capturing group 1 }}       # match two closing brackets
 * # repeat non-capturing group 1 zero or more times