[Piwik-svn] r404 - in trunk: . misc modules modules/API modules/DataTable modules/DataTable/Filter modules/DataTable/Renderer modules/DataTable/Row modules/Log modules/LogStats modules/ViewDataTable plugins/Actions tests/modules/DataTable

svnmaster at piwik.org svnmaster at piwik.org
Sun Mar 23 02:10:08 CET 2008


Author: matt
Date: 2008-03-23 02:09:59 +0100 (Sun, 23 Mar 2008)
New Revision: 404

Added:
   trunk/misc/download-count.txt
Modified:
   trunk/modules/API/Request.php
   trunk/modules/Archive.php
   trunk/modules/DataTable.php
   trunk/modules/DataTable/Array.php
   trunk/modules/DataTable/Filter.php
   trunk/modules/DataTable/Filter/Sort.php
   trunk/modules/DataTable/Manager.php
   trunk/modules/DataTable/Renderer.php
   trunk/modules/DataTable/Renderer/Csv.php
   trunk/modules/DataTable/Renderer/Html.php
   trunk/modules/DataTable/Renderer/Json.php
   trunk/modules/DataTable/Renderer/Php.php
   trunk/modules/DataTable/Renderer/Rss.php
   trunk/modules/DataTable/Renderer/Xml.php
   trunk/modules/DataTable/Row.php
   trunk/modules/DataTable/Row/DataTableSummary.php
   trunk/modules/DataTable/Simple.php
   trunk/modules/Log/APICall.php
   trunk/modules/Log/Error.php
   trunk/modules/Log/Exception.php
   trunk/modules/Log/Message.php
   trunk/modules/LogStats/Action.php
   trunk/modules/LogStats/Config.php
   trunk/modules/LogStats/Db.php
   trunk/modules/LogStats/Generator.php
   trunk/modules/ViewDataTable.php
   trunk/modules/ViewDataTable/Html.php
   trunk/piwik.php
   trunk/plugins/Actions/API.php
   trunk/tests/modules/DataTable/Renderer.test.php
Log:
- fixed rendering of recursive dataTable (php / xml) eg. try http://piwik.org/demo/index.php?module=API&method=Actions.getActions&idSite=1&period=week&date=today&filter_column_recursive=label&filter_pattern_recursive=index&expanded=1&format=xml

- refs #33 work in progress

Added: trunk/misc/download-count.txt
===================================================================
--- trunk/misc/download-count.txt	                        (rev 0)
+++ trunk/misc/download-count.txt	2008-03-23 01:09:59 UTC (rev 404)
@@ -0,0 +1,6 @@
+Count the download for 'last.zip' on the 20th March
+
+/var/log/apache2$ cat access.log | grep "20/Mar" | grep "last.zip" | awk '{print $1}' | sort | uniq | wc -l
+
+
+Value to be compared with the one given by Piwik in Actions > Downloads
\ No newline at end of file

Modified: trunk/modules/API/Request.php
===================================================================
--- trunk/modules/API/Request.php	2008-03-22 14:46:25 UTC (rev 403)
+++ trunk/modules/API/Request.php	2008-03-23 01:09:59 UTC (rev 404)
@@ -427,7 +427,6 @@
 			// but by default it's not serialized
 			if($this->caseRendererPHPSerialize( $defaultSerialize = 0))
 			{
-//				var_export($dataTable);exit;
 				$dataTable = serialize($dataTable);
 			}
 			return $dataTable;

Modified: trunk/modules/Archive.php
===================================================================
--- trunk/modules/Archive.php	2008-03-22 14:46:25 UTC (rev 403)
+++ trunk/modules/Archive.php	2008-03-23 01:09:59 UTC (rev 404)
@@ -143,7 +143,7 @@
 	 * If a idSubTable is given, the method will return the subTable of $name 
 	 * 
 	 * @param string $name
-	 * @param int $idSubTable
+	 * @param int $idSubTable or null if requesting the parent table
 	 * @return Piwik_DataTable
 	 * @throws exception If the value cannot be found
 	 */
@@ -155,7 +155,7 @@
 	 * You can then access the subtables by using the Piwik_DataTable_Manager getTable() 
 	 *
 	 * @param string $name
-	 * @param int $idSubTable
+	 * @param int $idSubTable or null if requesting the parent table
 	 * @return Piwik_DataTable
 	 */
 	abstract public function getDataTableExpanded($name, $idSubTable = null);

Modified: trunk/modules/DataTable/Array.php
===================================================================
--- trunk/modules/DataTable/Array.php	2008-03-22 14:46:25 UTC (rev 403)
+++ trunk/modules/DataTable/Array.php	2008-03-23 01:09:59 UTC (rev 404)
@@ -10,7 +10,8 @@
  */
 
 /**
- * The DataTable_Array is a way to store an array of dataTable
+ * The DataTable_Array is a way to store an array of dataTable.
+ * The Piwik_DataTable_Array implements some of the features of the Piwik_DataTable such as queueFilter, getRowsCount.
  * 
  * @package Piwik_DataTable
  */

Modified: trunk/modules/DataTable/Filter/Sort.php
===================================================================
--- trunk/modules/DataTable/Filter/Sort.php	2008-03-22 14:46:25 UTC (rev 403)
+++ trunk/modules/DataTable/Filter/Sort.php	2008-03-23 01:09:59 UTC (rev 404)
@@ -11,7 +11,7 @@
 
 /**
  * Sort the DataTable based on the value of column $columnToSort ordered by $order.
- * 
+ * Possible to specify a natural sorting (see php.net/natsort for details)
  * @package Piwik_DataTable
  * @subpackage Piwik_DataTable_Filter 
  */

Modified: trunk/modules/DataTable/Filter.php
===================================================================
--- trunk/modules/DataTable/Filter.php	2008-03-22 14:46:25 UTC (rev 403)
+++ trunk/modules/DataTable/Filter.php	2008-03-23 01:09:59 UTC (rev 404)
@@ -12,10 +12,10 @@
 /**
  * A filter is applied instantly to a given DataTable and can 
  * - remove rows 
- * - change columns values
- * - add/remove columns or details
+ * - change columns values (lowercase the strings, truncate, etc.)
+ * - add/remove columns or details (compute percentage values, add an 'icon' detail based on the label, etc.)
  * - add/remove/edit sub DataTable associated to some rows
- * - whatever your imagination wants :)
+ * - whatever you can imagine
  * 
  * The concept is very simple: the filter is given the DataTable 
  * and can do whatever is necessary on the data (in the filter() method).

Modified: trunk/modules/DataTable/Manager.php
===================================================================
--- trunk/modules/DataTable/Manager.php	2008-03-22 14:46:25 UTC (rev 403)
+++ trunk/modules/DataTable/Manager.php	2008-03-23 01:09:59 UTC (rev 404)
@@ -11,7 +11,8 @@
 
 /**
  * The DataTable_Manager registers all the instanciated DataTable and provides an 
- * easy way to access them.
+ * easy way to access them. This is used to store all the DataTable during the archiving process.
+ * At the end of archiving, the ArchiveProcessing will read the stored datatable and record them in the DB.
  * 
  * @package Piwik_DataTable
  */
@@ -21,6 +22,11 @@
 	protected function __construct()
 	{}
 	
+	/**
+	 * Returns instance
+	 *
+	 * @return Piwik_DataTable_Manager
+	 */
 	static public function getInstance()
 	{
 		if (self::$instance == null)
@@ -30,12 +36,25 @@
 		}
 		return self::$instance;
 	}
+	/**
+	 * Array used to store the DataTable
+	 *
+	 * @var array
+	 */
+	protected $tables = array();
 	
-	protected $tables = array();
+	/**
+	 * Number of datatable currently stored in the array
+	 *
+	 * @var int
+	 */
 	protected $count = 0;
 	
 	/**
 	 * Add a DataTable to the registry
+	 * 
+	 * @param Piwik_DataTable
+	 * @return int Number of tables registered in the manager (including the one just added)
 	 */
 	public function addTable( $table )
 	{
@@ -50,6 +69,7 @@
 	 * This method will not fetch the DataTable from the DB.
 	 * 
 	 * @exception If the table can't be found
+	 * @return Piwik_DataTable The table 
 	 */
 	public function getTable( $idTable )
 	{
@@ -66,8 +86,20 @@
 	}
 	
 	/**
-	 * Delete all the registered DataTables
+	 * Returns all the dataTable registered in the manager
+	 * 
+	 * @return array of Piwik_DataTable
 	 */
+	public function getTables()
+	{
+		return $this->tables;
+	}
+	
+	/**
+	 * Delete all the registered DataTables from the manager
+	 * 
+	 * @return void
+	 */
 	public function deleteAll()
 	{
 		$this->tables = array();
@@ -75,8 +107,10 @@
 	
 	/**
 	 * Returns the number of DataTable currently registered.
+	 * 
+	 * @return int
 	 */
-	function count()
+	public function count()
 	{
 		return count($this->tables);
 	}

Modified: trunk/modules/DataTable/Renderer/Csv.php
===================================================================
--- trunk/modules/DataTable/Renderer/Csv.php	2008-03-22 14:46:25 UTC (rev 403)
+++ trunk/modules/DataTable/Renderer/Csv.php	2008-03-23 01:09:59 UTC (rev 404)
@@ -19,6 +19,8 @@
  * The default field delimiter string is a comma (,).
  * Formatting and layout are ignored.
  * 
+ * Note that CSV output doesn't handle recursive dataTable. It will output only the first parent level of the tables.
+ * 
  * @package Piwik_DataTable
  * @subpackage Piwik_DataTable_Renderer
  * 
@@ -26,11 +28,35 @@
 
 class Piwik_DataTable_Renderer_Csv extends Piwik_DataTable_Renderer
 {
+	/**
+	 * Column separator
+	 *
+	 * @var string
+	 */
 	public $separator = ',';
+	
+	/**
+	 * Line end 
+	 *
+	 * @var string
+	 */
+	public $lineEnd = "\n";
+	
+	/**
+	 * 'details' columns will be exported, prefixed by 'detail_'
+	 *
+	 * @var bool
+	 */
 	public $exportDetail = true;
+	
+	/**
+	 * idSubtable will be exported in a column called 'idsubdatatable'
+	 *
+	 * @var bool
+	 */
 	public $exportIdSubtable = true;
-	public $lineEnd = "\n";
 	
+	
 	function __construct($table = null)
 	{
 		parent::__construct($table);

Modified: trunk/modules/DataTable/Renderer/Html.php
===================================================================
--- trunk/modules/DataTable/Renderer/Html.php	2008-03-22 14:46:25 UTC (rev 403)
+++ trunk/modules/DataTable/Renderer/Html.php	2008-03-23 01:09:59 UTC (rev 404)
@@ -11,6 +11,7 @@
 
 /**
  * Simple HTML output
+ * Works with recursive DataTable (when a row can be associated with a subDataTable).
  * 
  * @package Piwik_DataTable
  * @subpackage Piwik_DataTable_Renderer

Modified: trunk/modules/DataTable/Renderer/Json.php
===================================================================
--- trunk/modules/DataTable/Renderer/Json.php	2008-03-22 14:46:25 UTC (rev 403)
+++ trunk/modules/DataTable/Renderer/Json.php	2008-03-23 01:09:59 UTC (rev 404)
@@ -11,7 +11,8 @@
 
 require_once "DataTable/Renderer/Php.php";
 /**
- * JSON export. Using the php 5.2 feature json_encode
+ * JSON export. Using the php 5.2 feature json_encode.
+ * Works with recursive DataTable (when a row can be associated with a subDataTable).
  * 
  * @package Piwik_DataTable
  * @subpackage Piwik_DataTable_Renderer

Modified: trunk/modules/DataTable/Renderer/Php.php
===================================================================
--- trunk/modules/DataTable/Renderer/Php.php	2008-03-22 14:46:25 UTC (rev 403)
+++ trunk/modules/DataTable/Renderer/Php.php	2008-03-23 01:09:59 UTC (rev 404)
@@ -10,16 +10,20 @@
  */
 
 /**
- * Returns the equivalent PHP array of the DataTable.
+ * Returns the equivalent PHP array for a given DataTable.
  * You can specify in the constructor if you want the serialized version.
  * Please note that by default it will produce a flat version of the array.
- * See the method flatRender() for details.
+ * See the method flatRender() for details. @see flatRender();
  * 
+ * Works with recursive DataTable (when a row can be associated with a subDataTable).
+ * 
  * @package Piwik_DataTable
  * @subpackage Piwik_DataTable_Renderer
  */
 class Piwik_DataTable_Renderer_Php extends Piwik_DataTable_Renderer
 {
+	protected $serialize;
+	
 	public function __construct($table = null, $serialize = true)
 	{
 		parent::__construct($table);
@@ -56,7 +60,7 @@
 	 * @return array Php array representing the 'flat' version of the datatable
 	 *
 	 */
-	public function flatRender( $dataTable = null )
+	public function flatRender( $dataTable = null, $doRenderSubTablesIfAvailable = true )
 	{
 		if(is_null($dataTable))
 		{
@@ -73,7 +77,6 @@
 				$flatArray[$keyName] = $this->flatRender($table);
 				$this->serialize = $serializeSave;
 			}
-//			var_dump($flatArray);
 		}
 		
 		// A DataTable_Simple is already flattened so no need to do some crazy stuff to convert it
@@ -87,16 +90,12 @@
 			{
 				$flatArray = current($flatArray);
 			}
-//			elseif(count($flatArray) == 0)
-//			{
-//				$flatArray = null;
-//			}
 			
 		}
 		// A normal DataTable needs to be handled specifically
 		else
 		{
-			$array = $this->renderTable($dataTable);
+			$array = $this->renderTable($dataTable, $doRenderSubTablesIfAvailable);
 			$flatArray = $this->flattenArray($array);
 		}
 		
@@ -164,8 +163,6 @@
 		return $array;
 	}
 	
-	protected $serialize;
-	
 	
 	protected function renderTable($table, $doRenderSubTablesIfAvailable = false)
 	{

Modified: trunk/modules/DataTable/Renderer/Rss.php
===================================================================
--- trunk/modules/DataTable/Renderer/Rss.php	2008-03-22 14:46:25 UTC (rev 403)
+++ trunk/modules/DataTable/Renderer/Rss.php	2008-03-23 01:09:59 UTC (rev 404)
@@ -10,7 +10,9 @@
  */
 
 /**
- * RSS Feed
+ * RSS Feed. 
+ * The RSS renderer can be used only on Piwik_DataTable_Array that are arrays of Piwik_DataTable.
+ * A RSS feed contains one dataTable per element in the Piwik_DataTable_Array.
  * 
  * @package Piwik_DataTable
  * @subpackage Piwik_DataTable_Renderer

Modified: trunk/modules/DataTable/Renderer/Xml.php
===================================================================
--- trunk/modules/DataTable/Renderer/Xml.php	2008-03-22 14:46:25 UTC (rev 403)
+++ trunk/modules/DataTable/Renderer/Xml.php	2008-03-23 01:09:59 UTC (rev 404)
@@ -11,8 +11,12 @@
 
 require_once "DataTable/Renderer/Php.php";
 /**
- * XML export
+ * XML export of a given DataTable.
+ * See the tests cases for more information about the XML format (/tests/modules/DataTable/Renderer.test.php)
+ * Or have a look at the API calls examples.
  * 
+ * Works with recursive DataTable (when a row can be associated with a subDataTable).
+ * 
  * @package Piwik_DataTable
  * @subpackage Piwik_DataTable_Renderer
  */
@@ -193,6 +197,12 @@
 			$out .= $prefixLine."\t<row>\n";
 			foreach($row as $name => $value)
 			{
+				// handle the recursive dataTable case by XML outputting the recursive table
+				if(is_array($value))
+				{
+					$value = "\n".$this->renderDataTable($value, $prefixLine."\t\t");
+					$value .= $prefixLine."\t\t"; 
+				}
 				$out .= $prefixLine."\t\t<$name>$value</$name>\n";
 			} 
 			$out .= $prefixLine."\t</row>\n";

Modified: trunk/modules/DataTable/Renderer.php
===================================================================
--- trunk/modules/DataTable/Renderer.php	2008-03-22 14:46:25 UTC (rev 403)
+++ trunk/modules/DataTable/Renderer.php	2008-03-23 01:09:59 UTC (rev 404)
@@ -12,6 +12,9 @@
 /**
  * A DataTable Renderer can produce an output given a DataTable object.
  * All new Renderers must be copied in DataTable/Renderer and added to the factory() method.
+ * To use a renderer, simply do:
+ *  $render = new Piwik_DataTable_Renderer_Xml( $myTable );
+ *  echo $render;
  * 
  * @package Piwik_DataTable
  * @subpackage Piwik_DataTable_Renderer
@@ -20,6 +23,12 @@
 {
 	protected $table;
 	
+	/**
+	 * Builds the renderer.
+	 * Works with any kind of DataTable if the renderer used handles this DataTable.
+	 *
+	 * @param Piwik_DataTable|Piwik_DataTable_Simple|Piwik_DataTable_Array $table to be rendered
+	 */
 	function __construct($table = null)
 	{
 		if(!is_null($table))
@@ -29,12 +38,15 @@
 	}
 	
 	/**
-	 * Computes the output and returns the string/binary
+	 * Computes the dataTable output and returns the string/binary
+	 * 
+	 * @return string
 	 */
 	abstract public function render();
 	
 	/**
 	 * @see render()
+	 * @return string
 	 */
 	public function __toString()
 	{
@@ -43,6 +55,8 @@
 	
 	/**
 	 * Set the DataTable to be rendered
+	 * 
+	 * @param Piwik_DataTable|Piwik_DataTable_Simple|Piwik_DataTable_Array $table to be rendered
 	 */
 	public function setTable($table)
 	{
@@ -57,7 +71,8 @@
 	/**
 	 * Returns the DataTable associated to the output format $name
 	 * 
-	 * @exception If the renderer is unknown
+	 * @throws exception If the renderer is unknown
+	 * @return Piwik_DataTable_Renderer
 	 */
 	static public function factory( $name )
 	{

Modified: trunk/modules/DataTable/Row/DataTableSummary.php
===================================================================
--- trunk/modules/DataTable/Row/DataTableSummary.php	2008-03-22 14:46:25 UTC (rev 403)
+++ trunk/modules/DataTable/Row/DataTableSummary.php	2008-03-23 01:09:59 UTC (rev 404)
@@ -15,7 +15,7 @@
  * - for each numeric column, the returned "summary" column is the sum of all the subRows
  * - for every other column, it is ignored and will not be in the "summary row"
  * 
- * @see Piwik_DataTable_Row::sumRow() for more information on the algorith
+ * @see Piwik_DataTable_Row::sumRow() for more information on the algorithm
  * 
  * @package Piwik_DataTable
  * @subpackage Piwik_DataTable_Row

Modified: trunk/modules/DataTable/Row.php
===================================================================
--- trunk/modules/DataTable/Row.php	2008-03-22 14:46:25 UTC (rev 403)
+++ trunk/modules/DataTable/Row.php	2008-03-23 01:09:59 UTC (rev 404)
@@ -10,11 +10,12 @@
  */
 
 /**
- * A DataTable is composed by rows.
- * A row is composed by 
+ * A DataTable is composed of rows.
+ * 
+ * A row is composed of:
  * - columns often at least a 'label' column containing the description 
  * 		of the row, and some numeric values ('nb_visits', etc.)
- * - details: other information never to be shown as "columns")
+ * - details: other information never to be shown as 'columns'
  * - idSubtable: a row can be linked to a SubTable
  * 
  * IMPORTANT: Make sure that the column named 'label' contains at least one non-numeric character.
@@ -27,7 +28,16 @@
  */
 class Piwik_DataTable_Row
 {
-	// Row content
+	/**
+	 * This array contains the row information:
+	 * - array indexed by self::COLUMNS contains the columns, pairs of (column names, value) 
+	 * - (optional) array indexed by self::DETAILS contains the details,  pairs of (detail names, value)
+	 * - (optional) integer indexed by self::DATATABLE_ASSOCIATED contains the ID of the Piwik_DataTable associated to this row. 
+	 *   This ID can be used to read the DataTable from the DataTable_Manager.
+	 * 
+	 * @var array
+	 * @see constructor for more information
+	 */
 	public $c = array();
 	
 	const COLUMNS = 0;
@@ -36,20 +46,20 @@
 
 
 	/**
-	 * Very efficient load of the Row structure from a well structured php array
+	 * Efficient load of the Row structure from a well structured php array
 	 * 
 	 * @param array The row array has the structure
 	 * 					array( 
 	 * 						Piwik_DataTable_Row::COLUMNS => array( 
-	 * 										0 => 1554,
-	 * 										1 => 42,
-	 * 										2 => 657,
-	 * 										3 => 155744,	
+	 * 										'label' => 'Piwik',
+	 * 										'column1' => 42,
+	 * 										'visits' => 657,
+	 * 										'time_spent' => 155744,	
 	 * 									),
 	 * 						Piwik_DataTable_Row::DETAILS => array(
 	 * 										'logo' => 'test.png'
 	 * 									),
-	 * 						Piwik_DataTable_Row::DATATABLE_ASSOCIATED => #DataTable object // numeric idDataTable
+	 * 						Piwik_DataTable_Row::DATATABLE_ASSOCIATED => #Piwik_DataTable object (but in the row only the ID will be stored)
 	 * 					)
 	 */
 	public function __construct( $row = array() )
@@ -84,10 +94,15 @@
 			unset($idSubtable);
 		}
 	}
-
+
+	/**
+	 * Applys a basic rendering to the Row and returns the output
+	 *
+	 * @return string characterizing the row. Example: - 1 ['label' => 'piwik', 'nb_uniq_visitors' => 1685, 'nb_visits' => 1861, 'nb_actions' => 2271, 'max_actions' => 13, 'sum_visit_length' => 920131, 'bounce_count' => 1599] [] [idsubtable = 1375]
+	 */
 	public function __toString()
 	{
-		$columns=array();
+		$columns = array();
 		foreach($this->getColumns() as $column => $value)
 		{
 			if(is_string($value)) $value = "'$value'";
@@ -107,12 +122,25 @@
 		return $output;
 	}
 	
+	/**
+	 * Deletes the given column 
+	 *
+	 * @param string Column name
+	 * @return bool True on success, false if the column didn't exist
+	 */
 	public function deleteColumn( $name )
 	{
+		if(!isset($this->c[self::COLUMNS][$name]))
+		{
+			return false;
+		}
 		unset($this->c[self::COLUMNS][$name]);
+		return true;
 	}
+	
 	/**
 	 * Returns the given column
+	 * 
 	 * @param string Column name
 	 * @return mixed|false The column value  
 	 */
@@ -127,6 +155,7 @@
 	
 	/**
 	 * Returns the given detail
+	 * 
 	 * @param string Detail name
 	 * @return mixed|false The detail value  
 	 */
@@ -140,9 +169,9 @@
 	}
 	
 	/**
-	 * Returns the array of columns
+	 * Returns the array containing all the columns
 	 * 
-	 * @return array array( 
+	 * @return array Example: array( 
 	 * 					'column1' 	=> VALUE,
 	 * 					'label' 	=> 'www.php.net'
 	 * 					'nb_visits' => 15894,
@@ -154,9 +183,9 @@
 	}
 	
 	/**
-	 * Returns the array of details
+	 * Returns the array containing all the details
 	 * 
-	 * @return array array( 
+	 * @return array Example: array( 
 	 * 					'logo' 	=> 'images/logo/www.google.png',
 	 * 					'url'	=> 'www.google.com'
 	 * 			)
@@ -180,8 +209,10 @@
 	/**
 	 * Sums a DataTable to this row subDataTable.
 	 * If this row doesn't have a SubDataTable yet, we create a new one.
-	 * Then we add the values of the given DataTable to this row's DataTable 
-	 * @see addDataTable() for the summing algorithm 
+	 * Then we add the values of the given DataTable to this row's DataTable.
+	 * 	 
+	 * @param Piwik_DataTable Table to sum to this row's subDatatable
+	 * @see Piwik_DataTable::addDataTable() for the algorithm used for the sum 
 	 */
 	public function sumSubtable(Piwik_DataTable $subTable)
 	{
@@ -198,32 +229,30 @@
 		
 		$thisSubTable->addDataTable($subTable);
 	}
-
 	
-	protected function checkNoSubTable()
-	{
-		if(!is_null($this->c[self::DATATABLE_ASSOCIATED]))
-		{
-			throw new Exception("Adding a subtable to the row, but it already has a subtable associated.");
-		}
-	}
 	
-	
 	/**
 	 * Set a DataTable to be associated to this row.
 	 * If the row already has a DataTable associated to it, throws an Exception.
+	 * 
+	 * @param Piwik_DataTable DataTable to associate to this row
 	 * @throws Exception 
 	 * 
 	 */
 	public function addSubtable(Piwik_DataTable $subTable)
 	{
-		$this->checkNoSubTable();
+		if(!is_null($this->c[self::DATATABLE_ASSOCIATED]))
+		{
+			throw new Exception("Adding a subtable to the row, but it already has a subtable associated.");
+		}
 		$this->c[self::DATATABLE_ASSOCIATED] = $subTable->getId();
 	}
 	
 	/**
 	 * Set a DataTable to this row. If there is already 
 	 * a DataTable associated, it is simply overwritten.
+	 * 
+	 * @param Piwik_DataTable DataTable to associate to this row
 	 */
 	public function setSubtable(Piwik_DataTable $subTable)
 	{
@@ -231,7 +260,8 @@
 	}
 	
 	/**
-	 * Set all the columns at once.
+	 * Set all the columns at once. Overwrites previously set columns.
+	 * 
 	 * @param array array( 
 	 * 					'label' 	=> 'www.php.net'
 	 * 					'nb_visits' => 15894,
@@ -243,7 +273,10 @@
 	}
 	
 	/**
-	 * Set the $value value to the column named $name
+	 * Set the value $value to the column called $name.
+	 * 
+	 * @param string $name of the column to set
+	 * @param mixed $value of the column to set
 	 */
 	public function setColumn($name, $value)
 	{
@@ -260,7 +293,10 @@
 	}
 	
 	/**
-	 * Add a new column to the row. If the column already exist, throw an exception
+	 * Add a new column to the row. If the column already exists, throws an exception
+	 * 
+	 * @param string $name of the column to add
+	 * @param mixed $value of the column to set
 	 * @throws Exception
 	 */
 	public function addColumn($name, $value)
@@ -274,7 +310,10 @@
 	
 	
 	/**
-	 * Add a new detail to the row. If the column already exist, throw an exception
+	 * Add a new detail to the row. If the column already exists, throws an exception.
+	 * 
+	 * @param string $name of the detail to add
+	 * @param mixed $value of the detail to set
 	 * @throws Exception
 	 */
 	public function addDetail($name, $value)
@@ -287,14 +326,15 @@
 	}
 	
 	/**
-	 * Add the given $row columns values to the existing row' columns values.
-	 * It will take in consideration only the int or float values of $row.
+	 * Sums the given $row columns values to the existing row' columns values.
+	 * It will sum only the int or float values of $row.
+	 * It will not sum the column 'label' even if it has a numeric value.
 	 * 
 	 * If a given column doesn't exist in $this then it is added with the value of $row.
 	 * If the column already exists in $this then we have
 	 * 		this.columns[idThisCol] += $row.columns[idThisCol]
 	 */
-	public function sumRow( $rowToSum )
+	public function sumRow( Piwik_DataTable_Row $rowToSum )
 	{
 		foreach($rowToSum->getColumns() as $name => $value)
 		{
@@ -302,7 +342,7 @@
 				&& Piwik::isNumeric($value))
 			{
 				$current = $this->getColumn($name);
-				if($current==false)
+				if($current === false)
 				{
 					$current = 0;
 				}
@@ -317,9 +357,14 @@
 	 * 
 	 * Two rows are equal 
 	 * - if they have exactly the same columns / details
-	 * - if they have a subDataTable associated and that both of them are exactly the same.
+	 * - if they have a subDataTable associated, then we check that both of them are the same.
+	 * 
+	 * @param Piwik_DataTable_Row row1 to compare
+	 * @param Piwik_DataTable_Row row2 to compare
+	 * 
+	 * @return bool
 	 */
-	static public function isEqual( $row1, $row2 )
+	static public function isEqual( Piwik_DataTable_Row $row1, Piwik_DataTable_Row $row2 )
 	{		
 		//same columns
 		$cols1 = $row1->getColumns();

Modified: trunk/modules/DataTable/Simple.php
===================================================================
--- trunk/modules/DataTable/Simple.php	2008-03-22 14:46:25 UTC (rev 403)
+++ trunk/modules/DataTable/Simple.php	2008-03-23 01:09:59 UTC (rev 404)
@@ -10,27 +10,19 @@
  */
 
 /**
- * The DataTable_Simple is used to provide a very simple way to create simple DataGrid.
+ * The DataTable_Simple is used to provide an easy way to create simple DataGrid.
+ * A DataTable_Simple actually is a DataTable with 2 columns: 'label' and 'value'.
  * 
- * A DataTable Simple basically is an array of name => value 
- * 
- * Returning a DataTable_Simple from a plugin API Call has huge advantages:
+ * It is usually best to return a DataTable_Simple instead of 
+ * a PHP array (or other custom data structure) in API methods:
  * - the generic filters can be applied automatically (offset, limit, pattern search, sort, etc.)
  * - the renderer can be applied (XML, PHP, HTML, etc.)
- * 
  * So you don't have to write specific renderer for your data, it is already available in all the formats supported natively by Piwik.
  * 
- * NB: A DataTable_Simple actually is a DataTable with 2 columns: 'label' and 'value'.
- * 
  * @package Piwik_DataTable
  */
 class Piwik_DataTable_Simple extends Piwik_DataTable
 {
-	public function __construct()
-	{
-		parent::__construct();
-	}
-
 	/**
 	 * Loads in the DataTable the array information
 	 * @param array Array containing the rows information
@@ -38,6 +30,7 @@
 	 * 			'Label row 1' => Value row 1,
 	 * 			'Label row 2' => Value row 2,
 	 * 	)
+	 * @return void
 	 */
 	function loadFromArray($array)
 	{
@@ -50,7 +43,12 @@
 		}
 	}
 	
-		
+	/**
+	 * Returns the 'value' column of the row that has a label '$label'. 
+	 *
+	 * @param string Label of the row we want the value
+	 * @return false|mixed The 'value' column of the row labelled $label
+	 */
 	function getColumn( $label )
 	{
 		$row = $this->getRowFromLabel($label);

Modified: trunk/modules/DataTable.php
===================================================================
--- trunk/modules/DataTable.php	2008-03-22 14:46:25 UTC (rev 403)
+++ trunk/modules/DataTable.php	2008-03-23 01:09:59 UTC (rev 404)
@@ -121,6 +121,8 @@
  * $XMLstring = $xmlOutput->getOutput();
  * 
  * 
+ * @see Piwik_DataTable_Row A Piwik_DataTable is composed of Piwik_DataTable_Row
+ * 
  * @package Piwik
  * @subpackage Piwik_DataTable
  * 
@@ -134,6 +136,14 @@
 	protected $indexNotUpToDate = false;
 	protected $queuedFilters = array();
 	protected $rowsCountBeforeLimitFilter = 0;
+	
+	/**
+	 * Defaults to false for performance reasons (most of the time we don't need recursive sorting so we save a looping over the dataTable)
+	 *
+	 * @var bool
+	 */
+	protected $enableRecursiveSort = false;
+	
 	const MAXIMUM_DEPTH_LEVEL_ALLOWED = 20;
 	
 	public function __construct()
@@ -145,8 +155,26 @@
 	{
 		$this->indexNotUpToDate = true;
 		usort( $this->rows, $functionCallback );
+		
+		if($this->enableRecursiveSort === true)
+		{
+			foreach($this->getRows() as $row)
+			{
+				if(($idSubtable = $row->getIdSubDataTable()) !== null)
+				{
+					$table = Piwik_DataTable_Manager::getInstance()->getTable($idSubtable);
+					$table->enableRecursiveSort();
+					$table->sort($functionCallback);
+				}
+			}
+		}
 	}
 	
+	public function enableRecursiveSort()
+	{
+		$this->enableRecursiveSort = true;
+	}
+	
 	public function getRowsCountBeforeLimitFilter()
 	{
 		$toReturn = $this->rowsCountBeforeLimitFilter;
@@ -322,6 +350,8 @@
 	
 	/**
 	 * Returns the array of Piwik_DataTable_Row
+	 * 
+	 * @return array of Piwik_DataTable_Row
 	 */
 	public function getRows()
 	{

Modified: trunk/modules/Log/APICall.php
===================================================================
--- trunk/modules/Log/APICall.php	2008-03-22 14:46:25 UTC (rev 403)
+++ trunk/modules/Log/APICall.php	2008-03-23 01:09:59 UTC (rev 404)
@@ -14,6 +14,7 @@
  * Class used to log all the API Calls information (class / method / parameters / returned value / time spent)
  * 
  * @package Piwik_Log
+ * @subpackage Piwik_Log_APICall
  */
 class Piwik_Log_APICall extends Piwik_Log
 {

Modified: trunk/modules/Log/Error.php
===================================================================
--- trunk/modules/Log/Error.php	2008-03-22 14:46:25 UTC (rev 403)
+++ trunk/modules/Log/Error.php	2008-03-23 01:09:59 UTC (rev 404)
@@ -14,6 +14,7 @@
  * Class used to log an error event.
  * 
  * @package Piwik_Log
+ * @subpackage Piwik_Log_Error
  */
 class Piwik_Log_Error extends Piwik_Log
 {

Modified: trunk/modules/Log/Exception.php
===================================================================
--- trunk/modules/Log/Exception.php	2008-03-22 14:46:25 UTC (rev 403)
+++ trunk/modules/Log/Exception.php	2008-03-23 01:09:59 UTC (rev 404)
@@ -13,8 +13,10 @@
 
 /**
  * Class used to log an exception event.
+ * Displays the exception with a user friendly error message, suggests to get support from piwik.org
  * 
  * @package Piwik_Log
+ * @subpackage Piwik_Log_Exception
  */
 class Piwik_Log_Exception extends Piwik_Log
 {

Modified: trunk/modules/Log/Message.php
===================================================================
--- trunk/modules/Log/Message.php	2008-03-22 14:46:25 UTC (rev 403)
+++ trunk/modules/Log/Message.php	2008-03-23 01:09:59 UTC (rev 404)
@@ -14,6 +14,7 @@
  * Class used to log a standard message event.
  * 
  * @package Piwik_Log
+ * @subpackage Piwik_Log_Message
  */
 class Piwik_Log_Message extends Piwik_Log
 {

Modified: trunk/modules/LogStats/Action.php
===================================================================
--- trunk/modules/LogStats/Action.php	2008-03-22 14:46:25 UTC (rev 403)
+++ trunk/modules/LogStats/Action.php	2008-03-23 01:09:59 UTC (rev 404)
@@ -16,57 +16,20 @@
  * This class is used to build the Action Name (which can be built from the URL, 
  * or can be directly specified in the JS code, etc.).
  * It also saves the Action when necessary in the DB. 
- * 
- * 
- * About the Action concept
- * ------------------------------------
+ *  
+ * About the Action concept:
  * - An action is defined by a name.
  * - The name can be specified in the JS Code in the variable 'action_name'
+ *    For example you can decide to use the javascript value document.title as an action_name
+ * - If the name is not specified, we use the URL(path+query) to build a default name.
+ *    For example for "http://piwik.org/test/my_page/test.html" 
+ *    the name would be "test/my_page/test.html"
+ * - If the name is empty we set it to default_action_name found in global.ini.php
  * - Handling UTF8 in the action name
- * PLUGIN_IDEA - An action is associated to URLs and link to the URL from the interface
- * PLUGIN_IDEA - An action hit by a visitor is associated to the HTML title of the page that triggered the action
+ * PLUGIN_IDEA - An action is associated to URLs and link to the URL from the reports (currently actions do not link to the url of the pages)
+ * PLUGIN_IDEA - An action hit by a visitor is associated to the HTML title of the page that triggered the action and this HTML title is displayed in the interface
  * 
- * + If the name is not specified, we use the URL(path+query) to build a default name.
- *   For example for "http://piwik.org/test/my_page/test.html" 
- *   the name would be "test/my_page/test.html"
  * 
- * We make sure it is clean and displayable.
- * If the name is empty we set it to a default name.
- *  
- * Specifications
- *  
- * - Download tracking
- * 
- *   * MANUAL Download tracking 
- *      download = http://piwik.org/hellokity.zip
- * 	(name = dir1/file alias name)
- *
- *   * AUTOMATIC Download tracking for a known list of file extensions. 
- *    Make a hit to the piwik.php with the parameter: 
- *      download = http://piwik.org/hellokity.zip
- *  
- *   When 'name' is not specified, 
- * 	if AUTOMATIC and if anchor not empty => name = link title anchor
- * 	else name = path+query of the URL
- *   Ex: myfiles/beta.zip
- *
- * - External link tracking
- * 
- *   * MANUAL External link tracking
- * 	 outlink = http://amazon.org/test
- * 	(name = the big partners / amazon)
- * 
- *   * AUTOMATIC External link tracking
- *      When a link is not detected as being part of the same website 
- *     AND when the url extension is not detected as being a file download
- * 	 outlink = http://amazon.org/test
- * 
- *  When 'name' is not specified, 
- * 	if AUTOMATIC and if anchor not empty => name = link title anchor
- * 	else name = URL
- *   Ex: http://amazon.org/test
- * 
- * 
  * @package Piwik_LogStats
  */
 class Piwik_LogStats_Action
@@ -84,7 +47,7 @@
 	const TYPE_OUTLINK  = 2;
 	
 	/**
-	 * @param Piwik_LogStats_Db object
+	 * @param Piwik_LogStats_Db Database object to be used
 	 */
 	function __construct( $db )
 	{
@@ -105,11 +68,14 @@
 	}
 	
 	/**
-	 * Generate the name of the action from the URL or the specified name.
-	 * See the class description for more information.
+	 * Generates the name of the action from the URL or the specified name.
+	 * Sets the name as $this->finalActionName
+	 * 
+	 * @return void
 	 */
 	private function generateInfo()
 	{
+		$actionName = '';
 		if(!empty($this->downloadUrl))
 		{
 			$this->actionType = self::TYPE_DOWNLOAD;
@@ -212,6 +178,8 @@
 	}
 	
 	/**
+	 * Sets the attribute $idAction based on $finalActionName and $actionType.
+	 * 
 	 * @see getActionId()
 	 */
 	private function loadActionId()
@@ -223,7 +191,9 @@
 		
 		$idAction = $this->db->fetch("	SELECT idaction 
 							FROM ".$this->db->prefixTable('log_action')
-						."  WHERE name = ? AND type = ?", array($name, $type) );
+						."  WHERE name = ? AND type = ?", 
+						array($name, $type) 
+					);
 		
 		// the action name has not been found, create it
 		if($idAction === false)

Modified: trunk/modules/LogStats/Config.php
===================================================================
--- trunk/modules/LogStats/Config.php	2008-03-22 14:46:25 UTC (rev 403)
+++ trunk/modules/LogStats/Config.php	2008-03-23 01:09:59 UTC (rev 404)
@@ -12,16 +12,24 @@
 /**
  * Simple class to access the configuration file
  * 
- * This is essentially a very simple version of Zend_Config that we wrote 
- * because of performance concerns. 
+ * This is essentially a simple version of Zend_Config that we wrote 
+ * because of performance reasons. 
  * The LogStats module can't afford a dependency with the Zend_Framework.
  * 
+ * It's using the php.net/parse_ini_file function to parse the configuration files.
+ * It can be used to access both user config.ini.php and piwik global.ini.php config file.
+ * 
  * @package Piwik_LogStats
  */
 class Piwik_LogStats_Config
 {
 	static private $instance = null;
 	
+	/**
+	 * Returns singleton
+	 *
+	 * @return Piwik_LogStats_Config
+	 */
 	static public function getInstance()
 	{
 		if (self::$instance == null)
@@ -32,6 +40,11 @@
 		return self::$instance;
 	}
 	
+	/**
+	 * Contains configuration files values
+	 *
+	 * @var array
+	 */
 	public $config = array();
 	
 	private function __construct()
@@ -42,6 +55,14 @@
 		$this->configGlobal = parse_ini_file($pathIniFileGlobal, true);
 	}
 	
+	/**
+	 * Magic get methods catching calls to $config->var_name
+	 * Returns the value if found in the 
+	 *
+	 * @param string $name
+	 * @return mixed The value requested, usually a string
+	 * @throws exception if the value requested not found in both files
+	 */
 	public function __get( $name )
 	{
 		if(isset($this->configUser[$name]))

Modified: trunk/modules/LogStats/Db.php
===================================================================
--- trunk/modules/LogStats/Db.php	2008-03-22 14:46:25 UTC (rev 403)
+++ trunk/modules/LogStats/Db.php	2008-03-23 01:09:59 UTC (rev 404)
@@ -11,7 +11,8 @@
 
 /**
  * Simple database PDO wrapper.
- * We can't afford to have a dependency with the Zend_Db module in the LogStats module.
+ * We can't afford to have a dependency with the Zend_Db module in LogStats.
+ * We wrote this simple class 
  * 
  * @package Piwik_LogStats
  */
@@ -29,16 +30,16 @@
 	/**
 	 * Builds the DB object
 	 */
-	public function __construct( $host, $username, $password, $dbname) 
+	public function __construct( $host, $username, $password, $dbname, $driverName = 'mysql') 
 	{
-		$this->dsn = "mysql:dbname=$dbname;host=$host";
+		$this->dsn = $driverName.":dbname=$dbname;host=$host";
 		$this->username = $username;
 		$this->password = $password;
 	}
 
 	
 	/**
-	 * Returns true if the profiler is enabled
+	 * Returns true if the SQL profiler is enabled
 	 * Only used by the unit test that tests that the profiler is off on a  production server
 	 * 
 	 * @return bool 
@@ -49,7 +50,7 @@
 	}
 	
 	/**
-	 * Enables the profiling. 
+	 * Enables the SQL profiling. 
 	 * For each query, saves in the DB the time spent on this query. 
 	 * Very useful to see the slow query under heavy load.
 	 * You can then use Piwik::printLogStatsSQLProfiling(); 
@@ -59,8 +60,9 @@
 	{
 		self::$profiling = true;
 	}
+	
 	/** 
-	 * Disables the profiling logging.
+	 * Disables the SQL profiling logging.
 	 */
 	static public function disableProfiling()
 	{
@@ -69,6 +71,8 @@
 	
 	/**
 	 * Connects to the DB
+	 * 
+	 * @throws Exception if there was an error connecting the DB
 	 */
 	public function connect() 
 	{
@@ -76,7 +80,15 @@
 			$pdoConnect = new PDO($this->dsn, $this->username, $this->password);
 			$pdoConnect->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
 			$this->connection = $pdoConnect;
+
+			// we erase the password from this object "just in case" it could be printed 
+			$this->password = '';
 		} catch (PDOException $e) {
+			
+			// we erase the password from this object "just in case" it could be printed 
+			$this->password = '';
+			
+			// we don't throw the PDO Exception directly as it may contain sensitive information
 			throw new Exception("Error connecting database: ".$e->getMessage());
 		}
 	}
@@ -97,10 +109,14 @@
 	}
 	
 	/**
-	 * Returns an array containing all the rows of a query result.
+	 * Returns an array containing all the rows of a query result, using optional bound parameters.
+	 * 
+	 * @param string Query 
+	 * @param array Parameters to bind
 	 * @see also query()
+	 * @throws Exception if an exception occured
 	 */
-	public function fetchAll( $query, $parameters )
+	public function fetchAll( $query, $parameters = array() )
 	{
 		try {
 			$sth = $this->query( $query, $parameters );
@@ -111,10 +127,15 @@
 	}
 	
 	/**
-	 * Returns the first row of a query result.
-	 * @see query()
+	 * Returns the first row of a query result, using optional bound parameters.
+	 * 
+	 * @param string Query 
+	 * @param array Parameters to bind
+	 * @see also query()
+	 * 
+	 * @throws Exception if an exception occured
 	 */
-	public function fetch( $query, $parameters )
+	public function fetch( $query, $parameters = array() )
 	{
 		try {
 			$sth = $this->query( $query, $parameters );
@@ -125,10 +146,12 @@
 	}
 	
 	/**
-	 * Executes a query with bind parameters
+	 * Executes a query, using optional bound parameters.
 	 * 
 	 * @param string Query 
 	 * @param array Parameters to bind
+	 * 
+	 * @throw Exception if an exception occured
 	 */
 	public function query($query, $parameters = array()) 
 	{
@@ -161,6 +184,7 @@
 	/**
 	 * Returns the last inserted ID in the DB
 	 * Wrapper of PDO::lastInsertId()
+	 * 
 	 * @return int
 	 */
 	public function lastInsertId()
@@ -169,7 +193,7 @@
 	}
 	
 	/**
-	 * When destroyed, log the SQL profiling information
+	 * When destroyed, if SQL profiled enabled, logs the SQL profiling information
 	 */
 	public function __destruct()
 	{

Modified: trunk/modules/LogStats/Generator.php
===================================================================
--- trunk/modules/LogStats/Generator.php	2008-03-22 14:46:25 UTC (rev 403)
+++ trunk/modules/LogStats/Generator.php	2008-03-23 01:09:59 UTC (rev 404)
@@ -13,6 +13,10 @@
  * Class used to generate fake visits. 
  * Useful to test performances, general functional testing, etc.
  * 
+ * Objective:
+ * Generate thousands of visits / actions per visitor using 
+ *  a single request to misc/generateVisits.php
+ * 
  * Requirements of the visits generator script. Fields that can be edited:
  * - url => campaigns
  * 		- newsletter
@@ -28,12 +32,11 @@
  * - action_name 
  * - HTML title
  * 
- * Objective:
- * Generate thousands of visits / actions per visitor 
  *  
  * @package Piwik_LogStats
  * 
- * 													"Le Generator, il est trop Fort!"
+ * 											"Le Generator, il est trop Fort!"
+ * 											- Random fan
  */
 
 class Piwik_LogStats_Generator

Modified: trunk/modules/ViewDataTable/Html.php
===================================================================
--- trunk/modules/ViewDataTable/Html.php	2008-03-22 14:46:25 UTC (rev 403)
+++ trunk/modules/ViewDataTable/Html.php	2008-03-23 01:09:59 UTC (rev 404)
@@ -133,8 +133,6 @@
 		return false;
 	}
 
-	
-
 	public function setSearchRecursive()
 	{
 		$this->variablesDefault['search_recursive'] = true;

Modified: trunk/modules/ViewDataTable.php
===================================================================
--- trunk/modules/ViewDataTable.php	2008-03-22 14:46:25 UTC (rev 403)
+++ trunk/modules/ViewDataTable.php	2008-03-23 01:09:59 UTC (rev 404)
@@ -29,6 +29,9 @@
 	protected $JSsortEnabled 			= true;
 	protected $showFooter				= true;
 	
+	
+	protected $recursiveDataTableLoad   = false;
+	
 	protected $currentControllerAction;
 	protected $currentControllerName;
 	
@@ -40,10 +43,7 @@
 	public $dataTable; // data table
 	
 	protected $moduleNameAndMethod;
-	
-	// do we need all the children of the datatables?
-	protected $recursiveDataTableLoad   = false;
-	
+		
 	protected $variablesDefault = array();
 	
 	protected $idSubtable = false;
@@ -216,7 +216,7 @@
 	{
 		// if we request a subDataTable the $this->currentControllerAction DIV ID is already there in the page
 		// we make the DIV ID really unique by appending the ID of the subtable requested
-		if( $this->idSubtable != false)
+		if( $this->idSubtable !== false)
 		{			
 			$uniqIdTable = 'subDataTable_' . $this->idSubtable;
 		}
@@ -314,12 +314,14 @@
 		return $javascriptVariablesToSet;
 	}
 	
-	protected function loadDataTableFromAPI( $idSubtable = false)
-	{
-		if($idSubtable === false)
-		{
-			$idSubtable = $this->idSubtable;
-		}
+	/**
+	 * Function called by the ViewDataTable objects in order to fetch data from the API.
+	 * They must set $this->moduleNameAndMethod before (using the $this->init() method).
+	 * 
+	 *
+	 */
+	protected function loadDataTableFromAPI()
+	{		
 		// we prepare the string to give to the API Request
 		// we setup the method and format variable
 		// - we request the method to call to get this specific DataTable
@@ -332,12 +334,6 @@
 			$requestString .= '&expanded=1';
 		}
 		
-		// if a subDataTable is requested we add the variable to the API request string
-		if( $idSubtable != false)
-		{
-			$requestString .= '&this->idSubtable='.$idSubtable;
-		}
-		
 		$toSetEventually = array(
 			'filter_limit',
 			'filter_sort_column',
@@ -357,15 +353,13 @@
 				$requestString .= '&'.$varToSet.'='.$value;
 			}
 		}
-//		echo $requestString;exit;
+		
 		// We finally make the request to the API
 		$request = new Piwik_API_Request($requestString);
 		
 		// and get the DataTable structure
 		$dataTable = $request->process();
 
-//		echo $dataTable;exit;
-
 		$this->dataTable = $dataTable;
 	}
 

Modified: trunk/piwik.php
===================================================================
--- trunk/piwik.php	2008-03-22 14:46:25 UTC (rev 403)
+++ trunk/piwik.php	2008-03-23 01:09:59 UTC (rev 404)
@@ -1,4 +1,4 @@
-<?php
+<?php	
 /**
  * Piwik - Open source web analytics
  * 
@@ -51,20 +51,17 @@
 
 $GLOBALS['DEBUGPIWIK'] =  false;
 
-
 if($GLOBALS['DEBUGPIWIK'] === true)
 {	
 	date_default_timezone_set(date_default_timezone_get());
-	/**
-	 * Error / exception handling functions
-	 */
 	require_once PIWIK_INCLUDE_PATH . "/modules/ErrorHandler.php";
 	require_once PIWIK_INCLUDE_PATH . "/modules/ExceptionHandler.php";
 	set_error_handler('Piwik_ErrorHandler');
 	set_exception_handler('Piwik_ExceptionHandler');
+	printDebug($_GET);
 }
+
 ob_start();
-printDebug($_GET);
 $process = new Piwik_LogStats;
 $process->main();
 ob_end_flush();

Modified: trunk/plugins/Actions/API.php
===================================================================
--- trunk/plugins/Actions/API.php	2008-03-22 14:46:25 UTC (rev 403)
+++ trunk/plugins/Actions/API.php	2008-03-23 01:09:59 UTC (rev 404)
@@ -48,7 +48,8 @@
 		
 		if($expanded)
 		{
-			$dataTable = $archive->getDataTableExpanded($name, $idSubtable);			
+			$dataTable = $archive->getDataTableExpanded($name, $idSubtable);
+			$dataTable->enableRecursiveSort();
 		}
 		else
 		{

Modified: trunk/tests/modules/DataTable/Renderer.test.php
===================================================================
--- trunk/tests/modules/DataTable/Renderer.test.php	2008-03-22 14:46:25 UTC (rev 403)
+++ trunk/tests/modules/DataTable/Renderer.test.php	2008-03-23 01:09:59 UTC (rev 404)
@@ -40,12 +40,21 @@
 	 */
 	protected function getDataTableTest()
 	{
+		$arraySubTableForRow2 = array ( 
+			array ( Piwik_DataTable_Row::COLUMNS => array( 'label' => 'sub1', 'count' => 1) ), 
+			array ( Piwik_DataTable_Row::COLUMNS => array( 'label' => 'sub2', 'count' => 2) ), 
+		);
+		$subDataTableForRow2 = new Piwik_DataTable();
+		$subDataTableForRow2->loadFromArray($arraySubTableForRow2);
+		
+		$subtable = 
 		$array = array ( 
 			array ( Piwik_DataTable_Row::COLUMNS => array( 'label' => 'Google', 'nb_uniq_visitors' => 11, 'nb_visits' => 11, 'nb_actions' => 17, 'max_actions' => '5', 'sum_visit_length' => 517, 'bounce_count' => 9), 
 						Piwik_DataTable_Row::DETAILS => array('url' => 'http://www.google.com', 'logo' => './plugins/Referers/images/searchEngines/www.google.com.png'), 
 					 ), 
 			array ( Piwik_DataTable_Row::COLUMNS => array( 'label' => 'Yahoo!', 'nb_uniq_visitors' => 15, 'nb_visits' => 151, 'nb_actions' => 147, 'max_actions' => '50', 'sum_visit_length' => 517, 'bounce_count' => 90), 
-						Piwik_DataTable_Row::DETAILS => array('url' => 'http://www.yahoo.com', 'logo' => './plugins/Referers/images/searchEngines/www.yahoo.com.png'), 
+						Piwik_DataTable_Row::DETAILS => array('url' => 'http://www.yahoo.com', 'logo' => './plugins/Referers/images/searchEngines/www.yahoo.com.png'),
+						Piwik_DataTable_Row::DATATABLE_ASSOCIATED => $subDataTableForRow2,
 					 )
 			);
 		$dataTable = new Piwik_DataTable();
@@ -116,9 +125,22 @@
 		<bounce_count>90</bounce_count>
 		<url>http://www.yahoo.com</url>
 		<logo>./plugins/Referers/images/searchEngines/www.yahoo.com.png</logo>
+		<idsubdatatable>1</idsubdatatable>
+		<subtable>
+			<row>
+				<label>sub1</label>
+				<count>1</count>
+			</row>
+			<row>
+				<label>sub2</label>
+				<count>2</count>
+			</row>
+		</subtable>
 	</row>
 </result>';
-		$this->assertEqual( $expected,$render->render());
+		$rendered = $render->render();
+		
+		$this->assertEqual( $expected,$rendered);
 	}
 
 	function test_XML_test2()
@@ -216,9 +238,11 @@
 	{
 		$dataTable = $this->getDataTableTest();
 	  	$render = new Piwik_DataTable_Renderer_Json($dataTable);
-		$expected = '[{"label":"Google","nb_uniq_visitors":11,"nb_visits":11,"nb_actions":17,"max_actions":"5","sum_visit_length":517,"bounce_count":9,"url":"http:\/\/www.google.com","logo":".\/plugins\/Referers\/images\/searchEngines\/www.google.com.png"},{"label":"Yahoo!","nb_uniq_visitors":15,"nb_visits":151,"nb_actions":147,"max_actions":"50","sum_visit_length":517,"bounce_count":90,"url":"http:\/\/www.yahoo.com","logo":".\/plugins\/Referers\/images\/searchEngines\/www.yahoo.com.png"}]';
+		$expected = '[{"label":"Google","nb_uniq_visitors":11,"nb_visits":11,"nb_actions":17,"max_actions":"5","sum_visit_length":517,"bounce_count":9,"url":"http:\/\/www.google.com","logo":".\/plugins\/Referers\/images\/searchEngines\/www.google.com.png"},{"label":"Yahoo!","nb_uniq_visitors":15,"nb_visits":151,"nb_actions":147,"max_actions":"50","sum_visit_length":517,"bounce_count":90,"url":"http:\/\/www.yahoo.com","logo":".\/plugins\/Referers\/images\/searchEngines\/www.yahoo.com.png","idsubdatatable":13,"subtable":[{"label":"sub1","count":1},{"label":"sub2","count":2}]}]';
 
-		$this->assertEqual( $expected,$render->render());
+		$rendered = $render->render();
+		
+		$this->assertEqual( $expected,$rendered);
 	}
 	function test_JSON_test2()
 	{
@@ -281,9 +305,25 @@
 					    'bounce_count' => 90,
 					    'url' => 'http://www.yahoo.com',
 					    'logo' => './plugins/Referers/images/searchEngines/www.yahoo.com.png',
+					  	'idsubdatatable' => 19,
+					    'subtable' => 
+						    array (
+						      0 => 
+						      array (
+						        'label' => 'sub1',
+						        'count' => 1,
+						      ),
+						      1 => 
+						      array (
+						        'label' => 'sub2',
+						        'count' => 2,
+						      ),
+					    ),
 					  ),
 					));
-		$this->assertEqual( $expected,$render->render());
+		$rendered = $render->render();
+//		var_export(unserialize($rendered));
+		$this->assertEqual( $expected,$rendered);
 	}
 	function test_PHP_test2()
 	{



More information about the Piwik-svn mailing list