[Piwik-svn] r183 - in trunk: . config libs misc modules modules/API modules/Archive modules/ArchiveProcessing modules/DataTable modules/DataTable/Renderer plugins/UsersManager/templates plugins/VisitsSummary tests/modules tests/modules/DataTable

svnmaster at piwik.org svnmaster at piwik.org
Fri Jan 18 07:28:20 CET 2008


Author: matt
Date: 2008-01-18 07:28:19 +0100 (Fri, 18 Jan 2008)
New Revision: 183

Added:
   trunk/modules/DataTable/Renderer/Rss.php
Removed:
   trunk/libs/XML/
Modified:
   trunk/TODO
   trunk/config/global.ini.php
   trunk/misc/generateVisits.php
   trunk/modules/API/Proxy.php
   trunk/modules/API/Request.php
   trunk/modules/Archive.php
   trunk/modules/Archive/Array.php
   trunk/modules/Archive/Single.php
   trunk/modules/ArchiveProcessing.php
   trunk/modules/ArchiveProcessing/Day.php
   trunk/modules/ArchiveProcessing/Period.php
   trunk/modules/DataTable/Array.php
   trunk/modules/DataTable/Renderer.php
   trunk/modules/DataTable/Renderer/Csv.php
   trunk/modules/DataTable/Renderer/Html.php
   trunk/modules/DataTable/Renderer/Php.php
   trunk/modules/DataTable/Renderer/Xml.php
   trunk/modules/Date.php
   trunk/modules/Period.php
   trunk/modules/Site.php
   trunk/plugins/UsersManager/templates/UsersManager.js
   trunk/plugins/VisitsSummary/API.php
   trunk/tests/modules/DataTable/Renderer.test.php
   trunk/tests/modules/Period.test.php
Log:
- RSS feed works!!
- not using XMLSErializer anymore. generating XML a la mano
- lots of small fixes / improvements 
- optimization on the archiving process
- cleaned Renderers and fully testing the output
- now handling date=previous10 and date=last15 for example
- last10 works for days/week/month/year
- fixed bug when adding a user
- completed visitsSummary API
- 

Modified: trunk/TODO
===================================================================
--- trunk/TODO	2008-01-17 23:51:37 UTC (rev 182)
+++ trunk/TODO	2008-01-18 06:28:19 UTC (rev 183)
@@ -17,4 +17,6 @@
 
    
 test that archive always is OFF in prod
-$GLOBALS['DEBUGPIWIK'] is false;
\ No newline at end of file
+$GLOBALS['DEBUGPIWIK'] is false;
+
+optimize getdateStart / getdateEnd in *Period

Modified: trunk/config/global.ini.php
===================================================================
--- trunk/config/global.ini.php	2008-01-17 23:51:37 UTC (rev 182)
+++ trunk/config/global.ini.php	2008-01-18 06:28:19 UTC (rev 183)
@@ -24,7 +24,6 @@
 default			= en
 
 [Plugins]
-
 enabled[] 		= Actions
 enabled[] 		= Referers
 enabled[] 		= UserSettings

Modified: trunk/misc/generateVisits.php
===================================================================
--- trunk/misc/generateVisits.php	2008-01-17 23:51:37 UTC (rev 182)
+++ trunk/misc/generateVisits.php	2008-01-18 06:28:19 UTC (rev 183)
@@ -52,7 +52,7 @@
  * Generate visits / actions for the last 31 days
  */
 
-$daysToCompute = 50;
+$daysToCompute = 10;
 
 // do NOT edit this line
 $startTime = time() - ($daysToCompute-1)*86400;

Modified: trunk/modules/API/Proxy.php
===================================================================
--- trunk/modules/API/Proxy.php	2008-01-17 23:51:37 UTC (rev 182)
+++ trunk/modules/API/Proxy.php	2008-01-18 06:28:19 UTC (rev 183)
@@ -161,7 +161,7 @@
 	 * @param methodName the method
 	 * @return string|false when not possible
 	 */
-	public function getExampleUrl($class, $methodName)
+	public function getExampleUrl($class, $methodName, $parametersToSet = array())
 	{
 		$knowExampleDefaultParametersValues = array(
 			'access' => 'view',
@@ -175,7 +175,12 @@
 
 			'period' => 'day',
 			'date' => 'today',
-		);
+		);
+		
+		foreach($parametersToSet as $name => $value)
+		{
+			$knowExampleDefaultParametersValues[$name] = $value;
+		}
 		
 		// no links for these method names
 		$doNotPrintExampleForTheseMethods = array(
@@ -244,14 +249,17 @@
 				{
 					$exampleUrl = $this->getExampleUrl($class, $methodName);
 					if($exampleUrl !== false)
-					{
+					{
+						$exampleUrlRss1 = $this->getExampleUrl($class, $methodName, array('date' => 'last10')) . $prefixUrls;
+						$exampleUrlRss2 = $this->getExampleUrl($class, $methodName, array('date' => 'last5','period' => 'week',)) . $prefixUrls;
 						$exampleUrl = $exampleUrl . $prefixUrls;
 						$str .= " [ Example in  
 									<a target=_blank href='$exampleUrl&format=xml'>XML</a>, 
-									<a target=_blank href='$exampleUrl&format=PHP'>PHP</a>, 
+									<a target=_blank href='$exampleUrl&format=PHP&prettyDisplay=true'>PHP</a>, 
 									<a target=_blank href='$exampleUrl&format=JSON'>Json</a>, 
-									<a target=_blank href='$exampleUrl&format=Csv'>Csv</a>, 
-									<a target=_blank href='$exampleUrl&format=Html'>Basic html</a>
+									<a target=_blank href='$exampleUrl&format=Csv'>Csv</a>, 
+									<a target=_blank href='$exampleUrl&format=Html'>Basic html</a>, 
+									RSS of the last <a target=_blank href='$exampleUrlRss1&format=Rss'>10 days</a>, <a target=_blank href='$exampleUrlRss2&format=Rss'>5 weeks</a>
 									]";
 					}
 					else

Modified: trunk/modules/API/Request.php
===================================================================
--- trunk/modules/API/Request.php	2008-01-17 23:51:37 UTC (rev 182)
+++ trunk/modules/API/Request.php	2008-01-18 06:28:19 UTC (rev 183)
@@ -186,7 +186,7 @@
 					$requestValue = Piwik_Common::getRequestVar($name, null, null, $this->requestToUse);				
 				}
 			} catch(Exception $e) {
-				throw new Exception("The required variable '$name' is not correct or has not been found in the API Request.");
+				throw new Exception("The required variable '$name' is not correct or has not been found in the API Request. Add the parameter '&$name=' (with a value) in the URL.");
 			}			
 			$finalParameters[] = $requestValue;
 		}

Modified: trunk/modules/Archive/Array.php
===================================================================
--- trunk/modules/Archive/Array.php	2008-01-17 23:51:37 UTC (rev 182)
+++ trunk/modules/Archive/Array.php	2008-01-18 06:28:19 UTC (rev 183)
@@ -13,20 +13,18 @@
 	{
 		$rangePeriod = new Piwik_Period_Range($strPeriod, $strDate);
 		
+		// CAREFUL this class wouldnt work as is if handling archives from multiple websites
+		// works only when managing archives from multiples dates/periods
 		foreach($rangePeriod->getSubperiods() as $subPeriod)
 		{
 			$startDate = $subPeriod->getDateStart();
-			
 			$archive = Piwik_Archive::build($oSite->getId(), $strPeriod, $startDate );
 			$archive->prepareArchive();
 		
-			$this->archives[$archive->getIdArchive()] = $archive;
-			$this->idArchives[] = $archive->getIdArchive();
-			$this->idArchiveToTimestamp[$archive->getIdArchive()] = $startDate->getTimestamp();
+			$timestamp = $archive->getTimestampStartDate();
+			$this->archives[$timestamp] = $archive;
 		}
-		
-		$this->inIdArchives = implode("",$this->idArchives);
-		uksort( $this->archives, array($this, 'sortArchiveByTimestamp') );
+		ksort( $this->archives );
 	}
 	
 
@@ -41,6 +39,14 @@
 		$table->setNameKey('date');
 		return $table;
 	}
+
+	protected function loadMetaData($table, $archive)
+	{
+		$table->metaData[$archive->getPrettyDate()] = array( 
+				'timestamp' => $archive->getTimestampStartDate(),
+				'site' => $archive->getSite(),
+			);
+	}
 	
 	/**
 	 * Returns the value of the element $name from the current archive 
@@ -60,7 +66,10 @@
 			$subTable = new Piwik_DataTable_Simple();
 			$subTable->loadFromArray( array( $numeric ) );
 			$table->addTable($subTable, $archive->getPrettyDate());
+			
+			$this->loadMetaData($table, $archive);
 		}
+		
 		return $table;
 	}
 	
@@ -85,6 +94,8 @@
 			$subTable = new Piwik_DataTable_Simple();
 			$subTable->loadFromArray( array('blob' => $blob));
 			$table->addTable($subTable, $archive->getPrettyDate());
+			
+			$this->loadMetaData($table, $archive);
 		}
 		return $table;
 	}
@@ -143,7 +154,7 @@
 		foreach($queries as $table => $aIds)
 		{
 			$inIds = implode(', ', $aIds);
-			$sql = "SELECT value, name, idarchive
+			$sql = "SELECT value, name, idarchive, UNIX_TIMESTAMP(date1) as timestamp
 									FROM $table
 									WHERE idarchive IN ( $inIds )
 										AND name IN ( $inName )";
@@ -152,25 +163,36 @@
 			
 			foreach($values as $value)
 			{
-				$idarchiveToName[$value['idarchive']][$value['name']] = $value['value'];
+				$idarchiveToName[$value['timestamp']][$value['name']] = $value['value'];
 			}			
 		}
 		
-		// we need to take the Archives in chronological order 
-		uksort( $idarchiveToName, array($this, 'sortArchiveByTimestamp') );
+		// we add empty tables so that every requested date has an entry, even if there is nothing
+		// example: <result date="2007-01-01" />
+		$emptyTable = new Piwik_DataTable_Simple;
+		foreach($this->archives as $timestamp => $archive)
+		{
+			$strDate = $this->archives[$timestamp]->getPrettyDate();
+			$contentArray[$timestamp]['table'] = clone $emptyTable;
+			$contentArray[$timestamp]['prettyDate'] = $strDate;
+		}
 		
-//		var_dump($idarchiveToName);exit;
+		foreach($idarchiveToName as $timestamp => $aNameValues)
+		{
+			$contentArray[$timestamp]['table']->loadFromArray($aNameValues);
+		}
 		
+		ksort( $contentArray );
+				
 		$tableArray = $this->getNewDataTableArray();
-		foreach($idarchiveToName as $id => $aNameValues)
+		foreach($contentArray as $timestamp => $aData)
 		{
-			$strDate = $this->archives[$id]->getPrettyDate();
+			$tableArray->addTable($aData['table'], $aData['prettyDate']);
 			
-			$table = new Piwik_DataTable_Simple;
-			$table->loadFromArray($aNameValues);
-			
-			$tableArray->addTable($table, $strDate);
+			$this->loadMetaData($tableArray, $this->archives[$timestamp]);
 		}
+		
+//		echo $tableArray;exit;
 		return $tableArray;
 	}
 
@@ -190,6 +212,8 @@
 		{
 			$subTable =  $archive->getDataTable( $name, $idSubTable ) ;
 			$table->addTable($subTable, $archive->getPrettyDate());
+			
+			$this->loadMetaData($table, $archive);
 		}
 		return $table;
 	}
@@ -211,6 +235,8 @@
 		{
 			$subTable =  $archive->getDataTableExpanded( $name, $idSubTable ) ;
 			$table->addTable($subTable, $archive->getPrettyDate());
+			
+			$this->loadMetaData($table, $archive);
 		}
 		return $table;
 	}

Modified: trunk/modules/Archive/Single.php
===================================================================
--- trunk/modules/Archive/Single.php	2008-01-17 23:51:37 UTC (rev 182)
+++ trunk/modules/Archive/Single.php	2008-01-18 06:28:19 UTC (rev 183)
@@ -13,8 +13,7 @@
 	
 	public function getPrettyDate()
 	{
-		$str = $this->period->getLabel() . " from " . $this->period->getDateStart()->toString() . " to " . $this->period->getDateEnd()->toString();
-		return $str;
+		return $this->period->getPrettyString();
 	}
 	
 	public function getIdArchive()
@@ -32,7 +31,17 @@
 		$this->period = $period;
 	}
 	
+	public function getTimestampStartDate()
+	{
+		if(!is_null($this->archiveProcessing))
+		{
+//			var_dump($this->archiveProcessing->period->getPrettyString());
+			return $this->archiveProcessing->getTimestampStartDate();
+		}
 		
+		return $this->period->getDateStart()->getTimestamp();
+	}
+		
 	/**
 	 * Prepares the archive. Gets the idarchive from the ArchiveProcessing.
 	 * 
@@ -44,24 +53,35 @@
 	{
 		if(!$this->alreadyChecked)
 		{
+			// if the END of the period is BEFORE the website creation date
+			// we already know there are no stats for this period
+			// we add one day to make sure we don't miss the day of the website creation
+			if( $this->period->getDateEnd()->addDay(2)->isEarlier( $this->site->getCreationDate() ) )
+			{
+				$this->isThereSomeVisits = false;
+				$this->alreadyChecked = true;
+				return;				
+			}
+			
+			// if the starting date is in the future we know there is no visit
+			if( $this->period->getDateStart()->subDay(1)->isLater( Piwik_Date::today() ) )
+			{
+				$this->isThereSomeVisits = false;
+				$this->alreadyChecked = true;
+				return;
+			}
+			
 			// we make sure the archive is available for the given date
 			$periodLabel = $this->period->getLabel();
 			$archiveProcessing = Piwik_ArchiveProcessing::factory($periodLabel);
 			$archiveProcessing->setSite($this->site);
 			$archiveProcessing->setPeriod($this->period);
+			
 			$IdArchive = $archiveProcessing->loadArchive();
+			$this->isThereSomeVisits = $archiveProcessing->isThereSomeVisits;
 			
 			$this->archiveProcessing = $archiveProcessing; 
-//			$isThereSomeVisits = Zend_Registry::get('db')->fetchOne(
-//					'SELECT value 
-//					FROM '.$archiveProcessing->getTableArchiveNumericName().
-//					' WHERE name = ? AND idarchive = ?', array('nb_visits',$IdArchive));
-//					
-//			if($isThereSomeVisits!==false)
-//			{
-//				$this->isThereSomeVisits = true;
-//			}
-			$this->isThereSomeVisits = $this->archiveProcessing->isThereSomeVisits;
+
 			$this->idArchive = $IdArchive;
 			$this->alreadyChecked = true;
 		}

Modified: trunk/modules/Archive.php
===================================================================
--- trunk/modules/Archive.php	2008-01-17 23:51:37 UTC (rev 182)
+++ trunk/modules/Archive.php	2008-01-18 06:28:19 UTC (rev 183)
@@ -43,6 +43,7 @@
 	const INDEX_BOUNCE_COUNT = 6;
 
 	protected $alreadyChecked = false;
+	protected $site = null;
 		
 	static protected $alreadyBuilt = array();
 	
@@ -59,7 +60,7 @@
 		$oSite = new Piwik_Site($idSite);
 			
 		if(is_string($oDate) 
-			&& ereg('last([0-9]*)', $oDate, $regs))
+			&& ereg('^(last|previous){1}([0-9]*)$', $oDate, $regs))
 		{
 			require_once 'Archive/Array.php';
 			
@@ -67,8 +68,7 @@
 			
 		}
 		else
-		{			
-		
+		{
 			if(is_string($oDate))
 			{
 				$oDate = Piwik_Date::factory($oDate);
@@ -153,17 +153,27 @@
 	 * @return Piwik_DataTable
 	 */
 	abstract public function getDataTableExpanded($name, $idSubTable = null);
-
-	/**
-	 * Set the site
-	 *
-	 * @param Piwik_Site $site
+
+	/**
+	 * Set the site
+	 *
+	 * @param Piwik_Site $site
 	 */
 	public function setSite( Piwik_Site $site )
 	{
 		$this->site = $site;
 	}
-
+	
+	/**
+	 * Get the site
+	 *
+	 * @param Piwik_Site $site
+	 */
+	public function getSite( )
+	{
+		return $this->site;
+	}
+	
 	/**
 	 * Returns the Id site associated with this archive
 	 *

Modified: trunk/modules/ArchiveProcessing/Day.php
===================================================================
--- trunk/modules/ArchiveProcessing/Day.php	2008-01-17 23:51:37 UTC (rev 182)
+++ trunk/modules/ArchiveProcessing/Day.php	2008-01-18 06:28:19 UTC (rev 183)
@@ -65,7 +65,7 @@
 		{
 			$record = new Piwik_ArchiveProcessing_Record_Numeric($name, $value);
 		}
-
+		
 		Piwik_PostEvent('ArchiveProcessing_Day.compute', $this);
 	}
 	
@@ -309,7 +309,7 @@
 		$oldRowToUpdate[Piwik_Archive::INDEX_NB_UNIQ_VISITORS]	+= $newRowToAdd[Piwik_Archive::INDEX_NB_UNIQ_VISITORS];
 		$oldRowToUpdate[Piwik_Archive::INDEX_NB_VISITS] 		+= $newRowToAdd[Piwik_Archive::INDEX_NB_VISITS];
 		$oldRowToUpdate[Piwik_Archive::INDEX_NB_ACTIONS] 		+= $newRowToAdd[Piwik_Archive::INDEX_NB_ACTIONS];
-		$oldRowToUpdate[Piwik_Archive::INDEX_MAX_ACTIONS] 		 = max($newRowToAdd[Piwik_Archive::INDEX_MAX_ACTIONS], $oldRowToUpdate[Piwik_Archive::INDEX_MAX_ACTIONS]);
+		$oldRowToUpdate[Piwik_Archive::INDEX_MAX_ACTIONS] 		 = (float)max($newRowToAdd[Piwik_Archive::INDEX_MAX_ACTIONS], $oldRowToUpdate[Piwik_Archive::INDEX_MAX_ACTIONS]);
 		$oldRowToUpdate[Piwik_Archive::INDEX_SUM_VISIT_LENGTH]	+= $newRowToAdd[Piwik_Archive::INDEX_SUM_VISIT_LENGTH];
 		$oldRowToUpdate[Piwik_Archive::INDEX_BOUNCE_COUNT] 		+= $newRowToAdd[Piwik_Archive::INDEX_BOUNCE_COUNT];
 	}

Modified: trunk/modules/ArchiveProcessing/Period.php
===================================================================
--- trunk/modules/ArchiveProcessing/Period.php	2008-01-17 23:51:37 UTC (rev 182)
+++ trunk/modules/ArchiveProcessing/Period.php	2008-01-18 06:28:19 UTC (rev 183)
@@ -215,6 +215,11 @@
 		
 		$this->isThereSomeVisits = ($record['nb_visits']->value != 0);
 		
+		if($this->isThereSomeVisits === false)
+		{
+			return;
+		}
+		
 		Piwik_PostEvent('ArchiveProcessing_Period.compute', $this);		
 	}
 }

Modified: trunk/modules/ArchiveProcessing.php
===================================================================
--- trunk/modules/ArchiveProcessing.php	2008-01-17 23:51:37 UTC (rev 182)
+++ trunk/modules/ArchiveProcessing.php	2008-01-18 06:28:19 UTC (rev 183)
@@ -37,8 +37,8 @@
 
 	protected $idArchive;
 	protected $periodId;
+	protected $timestampDateStart = null;
 	
-	
 	/**
 	 * @var Piwik_Date
 	 */
@@ -206,7 +206,8 @@
 		$this->loadArchiveProperties();
 		$this->idArchive = $this->isArchived();
 		
-		if(!$this->idArchive)
+		if($this->idArchive === false
+			|| $this->debugAlwaysArchive)
 		{
 //			Piwik::printMemoryUsage('Before loading subperiods');
 			$this->archivesSubperiods = $this->loadSubperiodsArchive();
@@ -217,6 +218,9 @@
 //			Piwik::printMemoryUsage('After compute');
 			$this->postCompute();
 //			Piwik::printMemoryUsage('After post compute');
+
+			// we execute again the isArchived that does some initialization work
+			$this->idArchive = $this->isArchived();
 			
 //			Piwik::log("New archive computed, id = {$this->idArchive}");
 		}
@@ -375,10 +379,6 @@
 	 */
 	protected function isArchived()
 	{
-		if($this->debugAlwaysArchive)
-		{
-			return false;
-		}
 //		Piwik::log("Is archive site=$idsite for period = ".$this->period->getLabel()." for date_start = $strDateStart ?");
 		$bindSQL = array(	$this->idsite, 
 								$this->strDateStart, 
@@ -392,8 +392,7 @@
 			$bindSQL[] = $this->maxTimestampArchive;
 		}
 			
-		$results = Zend_Registry::get('db')->fetchAll("
-						SELECT idarchive, value, name
+		$sqlQuery = "	SELECT idarchive, value, name, UNIX_TIMESTAMP(date1) as timestamp
 						FROM ".$this->tableArchiveNumeric."
 						WHERE idsite = ?
 							AND date1 = ?
@@ -402,9 +401,9 @@
 							AND ( (name = 'done' AND value = ".Piwik_ArchiveProcessing::DONE_OK.")
 									OR name = 'nb_visits')
 							$timeStampWhere
-						ORDER BY ts_archived DESC",
-						$bindSQL
-					);
+						ORDER BY ts_archived DESC";
+		
+		$results = Zend_Registry::get('db')->fetchAll($sqlQuery, $bindSQL );
 		// the archive exists in the table
 		if(!empty($results))
 		{
@@ -415,9 +414,11 @@
 				if($result['name'] == 'done')
 				{
 					$idarchive = $result['idarchive'];
+					$this->timestampDateStart = $result['timestamp'];
 					break;
 				}
 			}
+			
 			// let's look for the nb_visits result for this more recent archive
 			foreach($results as $result)
 			{
@@ -435,5 +436,15 @@
 			return false;
 		}
 	}
+	
+	public function getTimestampStartDate()
+	{
+		// debug
+		if(is_null($this->timestampDateStart))
+		{
+			throw new Exception("The starting date timestamp has not been set!");
+		}
+		return $this->timestampDateStart;
+	}
 }
 

Modified: trunk/modules/DataTable/Array.php
===================================================================
--- trunk/modules/DataTable/Array.php	2008-01-17 23:51:37 UTC (rev 182)
+++ trunk/modules/DataTable/Array.php	2008-01-18 06:28:19 UTC (rev 183)
@@ -28,6 +28,15 @@
 		$this->nameKey = $name;
 	}
 	
+	public $metaData = array();
+	public function setMetaData( $mixed )
+	{
+		$this->metaData[] = $mixed;
+	}
+	public function getMetaData( $mixed )
+	{
+		return $this->metaData;
+	}
 	public function queueFilter( $className, $parameters = array() )
 	{
 		foreach($this->array as $table)

Modified: trunk/modules/DataTable/Renderer/Csv.php
===================================================================
--- trunk/modules/DataTable/Renderer/Csv.php	2008-01-17 23:51:37 UTC (rev 182)
+++ trunk/modules/DataTable/Renderer/Csv.php	2008-01-18 06:28:19 UTC (rev 183)
@@ -59,21 +59,23 @@
 					$header = $returned[0];
 				}
 				$returned = array_slice($returned,1);
-				foreach($returned as &$row)
+				
+				// case empty datatable we dont print anything in the CSV export
+				// when in xml we would output <result date="2008-01-15" />
+				if(!empty($returned))
 				{
-					$row = $currentLinePrefix . $this->separator . $row;
+					foreach($returned as &$row)
+					{
+						$row = $currentLinePrefix . $this->separator . $row;
+					}
+					$str .= "\n" .  implode("\n", $returned);
 				}
-				$str .= "\n" .  implode("\n", $returned);
 			}
 //				var_dump($header);exit;
 			if(!empty($header))
 			{
 				$str = $prefixColumns . $header . $str;
 			}
-			else
-			{
-				$str = 'No data available';
-			}
 		}
 		else
 		{
@@ -184,9 +186,13 @@
 	}
 	protected function output( $str )
 	{
+		if(empty($str))
+		{
+			return 'No data available';
+		}
 		// silent fail otherwise unit tests fail
-//		@header("Content-type: application/vnd.ms-excel");
-//		@header("Content-Disposition: attachment; filename=piwik-report-export.csv");			
+		@header("Content-type: application/vnd.ms-excel");
+		@header("Content-Disposition: attachment; filename=piwik-report-export.csv");
 		return $str;
 	}
 }
\ No newline at end of file

Modified: trunk/modules/DataTable/Renderer/Html.php
===================================================================
--- trunk/modules/DataTable/Renderer/Html.php	2008-01-17 23:51:37 UTC (rev 182)
+++ trunk/modules/DataTable/Renderer/Html.php	2008-01-18 06:28:19 UTC (rev 183)
@@ -30,6 +30,29 @@
 	
 	protected function renderTable($table)
 	{
+		if($table instanceof Piwik_DataTable_Array)
+		{
+			$columnPrefixToAdd = $table->getNameKey();
+			$out = "<table border=1>";
+			foreach($table->getArray() as $date => $subtable )
+			{
+				$out .= "<tr><td><h2>$columnPrefixToAdd = $date</h2>";
+				$out .= $this->renderDataTable($subtable);
+				$out .= "</td></tr>";
+			}
+			$out .= "</table>";
+		}
+		else
+		{
+			$out = $this->renderDataTable($table);
+		}
+		
+		return $out;
+	}	
+	
+	protected function renderDataTable($table)
+	{
+	
 		if($table->getRowsCount() == 0)
 		{
 			return "<b><i>Empty table</i></b> <br>\n";
@@ -41,8 +64,8 @@
 		}
 		
 		static $depth=0;
-		$i = 1;
-		$someDetails = false;
+		$i = 1;
+		$someDetails = false;
 		$someIdSubTable = false;
 		
 		$tableStructure = array();
@@ -53,7 +76,7 @@
 		 * ROW2 = col1 | col2 (no value but appears) | col3 | details | idSubTable
 		 * 		subtable here
 		 */
-		$allColumns = array();
+		$allColumns = array();
 //		echo $table;
 		foreach($table->getRows() as $row)
 		{
@@ -69,19 +92,19 @@
 				if(is_string($value)) $value = "'$value'";
 				$details[] = "'$detail' => $value";
 			}
-			
-			if(count($details) != 0)
-			{
-				$someDetails = true;
+			
+			if(count($details) != 0)
+			{
+				$someDetails = true;
 				$details = implode("<br>", $details);
-				$tableStructure[$i]['_details'] = $details;
-			}
-			
-			$idSubtable = $row->getIdSubDataTable();
-			if(!is_null($idSubtable))
-			{
+				$tableStructure[$i]['_details'] = $details;
+			}
+			
+			$idSubtable = $row->getIdSubDataTable();
+			if(!is_null($idSubtable))
+			{
 				$someIdSubTable = true;
-				$tableStructure[$i]['_idSubtable'] = $idSubtable;
+				$tableStructure[$i]['_idSubtable'] = $idSubtable;
 			}
 			
 			if($row->getIdSubDataTable() !== null)
@@ -113,10 +136,10 @@
 		$html .= "<table border=1 width=70%>";
 		$html .= "\n<tr>";
 		foreach($allColumns as $name => $toDisplay)
-		{
-			if($toDisplay !== false)
+		{
+			if($toDisplay !== false)
 			{
-				$html .= "\n\t<td><b>$name</b></td>";
+				$html .= "\n\t<td><b>$name</b></td>";
 			}
 		}
 		$colspan = count($allColumns);
@@ -125,8 +148,8 @@
 		{
 			$html .= "\n\n<tr>";
 			foreach($allColumns as $name => $toDisplay)
-			{
-				if($toDisplay !== false)
+			{
+				if($toDisplay !== false)
 				{
 					$value = "-";
 					if(isset($row[$name]))
@@ -134,38 +157,37 @@
 						$value = $row[$name];
 					}
 					
-					$html .= "\n\t<td>$value</td>";
+					$html .= "\n\t<td>$value</td>";
 				}
 			}
 			$html .= "</tr>";
 			
 			if(isset($row['_subtable']))
-			{
+			{
 //				echo ".".$row['_subtable'];exit;
-				$html .= "<tr>
+				$html .= "<tr>
 						<td class=l{$row['_subtable']['depth']} colspan=$colspan>{$row['_subtable']['html']}</td></tr>";
 			}
 		}
 		$html .= "\n\n</table>";
-		
-		// display styles if there is a subtable displayed
-		if($someIdSubTable)
-		{
-			$styles="\n\n<style>\n";
-			for($i=0;$i<11;$i++)
-			{
-				$padding=$i*2;
-				$styles.= "\t TD.l$i { padding-left:{$padding}em; } \n";
-			}
-			$styles.="</style>\n\n";
-			if($depth == 0)
-			{
-				$html = $styles . $html;
+		
+		// display styles if there is a subtable displayed
+		if($someIdSubTable)
+		{
+			$styles="\n\n<style>\n";
+			for($i=0;$i<11;$i++)
+			{
+				$padding=$i*2;
+				$styles.= "\t TD.l$i { padding-left:{$padding}em; } \n";
 			}
-		}
-//		echo "return={".$html."}";
+			$styles.="</style>\n\n";
+			if($depth == 0)
+			{
+				$html = $styles . $html;
+			}
+		}
 		return $html;
-	}	
+	}
 }
 
 

Modified: trunk/modules/DataTable/Renderer/Php.php
===================================================================
--- trunk/modules/DataTable/Renderer/Php.php	2008-01-17 23:51:37 UTC (rev 182)
+++ trunk/modules/DataTable/Renderer/Php.php	2008-01-18 06:28:19 UTC (rev 183)
@@ -73,6 +73,7 @@
 				$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
@@ -86,6 +87,10 @@
 			{
 				$flatArray = current($flatArray);
 			}
+//			elseif(count($flatArray) == 0)
+//			{
+//				$flatArray = null;
+//			}
 			
 		}
 		// A normal DataTable needs to be handled specifically
@@ -118,7 +123,16 @@
 		{
 			$dataTable = $this->table;
 		}
-		$toReturn = $this->flatRender( $dataTable );
+		$toReturn = $this->flatRender( $dataTable );
+		
+		if( false !== Piwik_Common::getRequestVar('prettyDisplay', false) )
+		{
+			if(!is_array($toReturn))
+			{
+				$toReturn = unserialize($toReturn);
+			}
+			$toReturn =  "<pre>" . var_export($toReturn, true ) . "</pre>";
+		}
 		return $toReturn;
 	}
 	
@@ -168,6 +182,7 @@
 		{
 			$array[$row->getColumn('label')] = $row->getColumn('value');
 		}
+		
 		return $array;
 	}
 }
\ No newline at end of file

Added: trunk/modules/DataTable/Renderer/Rss.php
===================================================================
--- trunk/modules/DataTable/Renderer/Rss.php	                        (rev 0)
+++ trunk/modules/DataTable/Renderer/Rss.php	2008-01-18 06:28:19 UTC (rev 183)
@@ -0,0 +1,180 @@
+<?php
+/**
+ * Piwik - Open source web analytics
+ * 
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
+ * @version $Id: Html.php 180 2008-01-17 16:32:37Z matt $
+ * 
+ * @package Piwik_DataTable
+ */
+
+/**
+ * RSS Feed
+ * 
+ * @package Piwik_DataTable
+ * @subpackage Piwik_DataTable_Renderer
+ */
+class Piwik_DataTable_Renderer_Rss extends Piwik_DataTable_Renderer
+{
+	function __construct($table = null)
+	{
+		parent::__construct($table);
+	}
+	
+	function render()
+	{
+		return $this->renderTable($this->table);
+	}
+	
+	protected function renderTable($table)
+	{
+		if(!($table instanceof Piwik_DataTable_Array))
+		{
+			throw new Exception("RSS Feed only used on DataTable_Array");
+		}
+		
+		
+		$idSite = Piwik_Common::getRequestVar('idSite', 1);
+		$period = Piwik_Common::getRequestVar('period');
+		$currentUrl = Piwik_Url::getCurrentUrlWithoutFileName();
+		
+		$piwikUrl = $currentUrl . "?module=Home&action=index&idSite=" . $idSite . "&period=" . $period;
+		
+		$out = "";
+		foreach($table->getArray() as $date => $subtable )
+		{
+			$timestamp = $table->metaData[$date]['timestamp'];
+			$site = $table->metaData[$date]['site'];
+	
+			$pudDate = date('r', $timestamp);
+			$dateUrl = date('Y-m-d', $timestamp);
+			$thisPiwikUrl = htmlentities($piwikUrl . "&date=$dateUrl");
+			$siteName = $site->getName();
+			$title = $siteName . " on ". $date;
+			
+			$out .= "\t<item>
+		<pubDate>$pudDate</pubDate>
+		<guid>$thisPiwikUrl</guid>
+		<link>$thisPiwikUrl</link>
+		<title>$title</title>
+		<author>http://piwik.org</author>
+		<description>";	
+			
+			$out .= htmlentities( $this->renderDataTable($subtable) );
+			$out .= "</description>\n\t</item>\n";
+		}
+		
+		$header = $this->getRssHeader();
+		$footer = $this->getRssFooter();
+		
+		return $this->output( $header . $out . $footer);
+	}
+	protected function output($str)
+	{
+		@header("Content-Type: text/xml;charset=utf-8");
+		return $str;
+	}
+	protected function getRssFooter()
+	{
+		return "\t</channel>\n</rss>";
+	}
+	protected function getRssHeader()
+	{
+		$generationDate = date('r');
+		$header = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
+<rss version=\"2.0\">
+  <channel>
+    <title>piwik statistics - RSS</title>
+    <link>http://piwik.org</link>
+    <description>Piwik RSS feed</description>
+    <pubDate>$generationDate</pubDate>
+    <generator>piwik</generator>
+    <language>en</language>
+    <lastBuildDate>$generationDate</lastBuildDate>";
+    	return $header;
+	}
+	
+	protected function renderDataTable($table)
+	{
+	
+		if($table->getRowsCount() == 0)
+		{
+			return "<b><i>Empty table</i></b> <br>\n";
+		}
+		if($table instanceof Piwik_DataTable_Simple 
+			&& $table->getRowsCount() ==1)
+		{
+			$table->deleteColumn('label');
+		}
+		
+		$i = 1;		
+		$tableStructure = array();
+		
+		/*
+		 * table = array
+		 * ROW1 = col1 | col2 | col3 | details | idSubTable
+		 * ROW2 = col1 | col2 (no value but appears) | col3 | details | idSubTable
+		 * 		subtable here
+		 */
+		$allColumns = array();
+//		echo $table;
+		foreach($table->getRows() as $row)
+		{
+			foreach($row->getColumns() as $column => $value)
+			{
+				$allColumns[$column] = true;
+				$tableStructure[$i][$column] = $value;
+			}
+			$i++;
+		}
+		
+		/*
+		// to keep the same columns order as the columns labelled with strings
+		ksort($allColumns);
+		//replace the label first
+		if(isset($allColumns['label']))
+		{
+			$allColumns = array_merge(array('label'=>true),$allColumns);
+		}
+		*/
+		$html = "\n";
+		$html .= "<table border=1 width=70%>";
+		$html .= "\n<tr>";
+		foreach($allColumns as $name => $toDisplay)
+		{
+			if($toDisplay !== false)
+			{
+				$html .= "\n\t<td><b>$name</b></td>";
+			}
+		}
+		$html .= "\n</tr>";
+		$colspan = count($allColumns);
+		
+		foreach($tableStructure as $row)
+		{
+			$html .= "\n\n<tr>";
+			foreach($allColumns as $name => $toDisplay)
+			{
+				if($toDisplay !== false)
+				{
+					$value = "-";
+					if(isset($row[$name]))
+					{
+						$value = $row[$name];
+					}
+					
+					$html .= "\n\t<td>$value</td>";
+				}
+			}
+			$html .= "</tr>";
+			
+		}
+		$html .= "\n\n</table>";
+		
+		return $html;
+	}
+}
+
+
+

Modified: trunk/modules/DataTable/Renderer/Xml.php
===================================================================
--- trunk/modules/DataTable/Renderer/Xml.php	2008-01-17 23:51:37 UTC (rev 182)
+++ trunk/modules/DataTable/Renderer/Xml.php	2008-01-18 06:28:19 UTC (rev 183)
@@ -10,10 +10,8 @@
  */
 
 require_once "DataTable/Renderer/Php.php";
-require_once "XML/Serializer.php";
 /**
- * XML export. Using the excellent Pear::XML_Serializer.
- * We had to fix the PEAR library so that it works under PHP5 STRICT mode.
+ * XML export
  * 
  * @package Piwik_DataTable
  * @subpackage Piwik_DataTable_Renderer
@@ -35,26 +33,31 @@
 		$renderer = new Piwik_DataTable_Renderer_Php($table, $serialize = false);
 		
 		$array = $renderer->flatRender();
-				
+		
 		// case DataTable_Array
 		if($table instanceof Piwik_DataTable_Array)
 		{
 			return $this->renderDataTableArray($table, $array);
 		}
-		
+	
+		// integer value of ZERO is a value we want to display
+		if($array != 0 && empty($array))
+		{
+			$out = "<result />";
+			return $this->output($out);
+		}
 		if($table instanceof Piwik_DataTable_Simple)
 		{
 			if(is_array($array))
 			{
 				$out = $this->renderDataTableSimple($array);
 				$out = "<result>\n".$out."</result>";
-				return $this->output($out);
 			}
 			else
 			{
 				$out = "<result>".$array."</result>";
-				return $this->output($out);
 			}
+			return $this->output($out);
 		}
 		
 		if($table instanceof Piwik_DataTable)
@@ -80,7 +83,14 @@
 	  		$nameDescriptionAttribute = $table->getNameKey();
 	  		foreach($array as $valueAttribute => $value)
 	  		{
-	  			$xml .= "\t<result $nameDescriptionAttribute=\"$valueAttribute\">$value</result>\n";
+	  			if(!empty($value))
+	  			{
+		  			$xml .= "\t<result $nameDescriptionAttribute=\"$valueAttribute\">$value</result>\n";
+	  			}
+	  			else
+	  			{
+		  			$xml .= "\t<result $nameDescriptionAttribute=\"$valueAttribute\" />\n";	  				
+	  			}
 	  		}
 	  		$xml .= "</results>";
 	  		return $this->output($xml);
@@ -105,8 +115,19 @@
 			$nameDescriptionAttribute = $table->getNameKey();
 	  		foreach($array as $valueAttribute => $dataTableSimple)
 	  		{
-	  			$dataTableSimple = $this->renderDataTableSimple($dataTableSimple, "\t");
-	  			$xml .= "\t<result $nameDescriptionAttribute=\"$valueAttribute\">\n".$dataTableSimple."\t</result>\n";
+	  			
+	  			if(count($dataTableSimple) == 0)
+				{
+					$xml .= "\t<result $nameDescriptionAttribute=\"$valueAttribute\" />\n";
+				}
+	  			else
+	  			{
+		  			if(is_array($dataTableSimple))
+		  			{
+			  			$dataTableSimple = "\n" . $this->renderDataTableSimple($dataTableSimple, "\t") . "\t" ;
+		  			}
+		  			$xml .= "\t<result $nameDescriptionAttribute=\"$valueAttribute\">".$dataTableSimple."</result>\n";
+	  			}
 	  		}
 	  		$xml .= "</results>";
 	  		return $this->output($xml);
@@ -144,10 +165,18 @@
 			$nameDescriptionAttribute = $table->getNameKey();
 			foreach($array as $keyName => $arrayForSingleDate)
 			{
-				$out .= "\t<result $nameDescriptionAttribute=\"$keyName\">\n";
+				$dataTableOut = $this->renderDataTable( $arrayForSingleDate, "\t" );
 				
-				$out .= $this->renderDataTable( $arrayForSingleDate, "\t" );
-				$out .= "\t</result>\n";
+				if(empty($dataTableOut))
+				{
+					$out .= "\t<result $nameDescriptionAttribute=\"$keyName\" />\n";
+				}
+				else
+				{
+					$out .= "\t<result $nameDescriptionAttribute=\"$keyName\">\n";
+					$out .= $dataTableOut;
+					$out .= "\t</result>\n";
+				}
 			}
 			$out .= "</results>";
 			return $this->output($out);

Modified: trunk/modules/DataTable/Renderer.php
===================================================================
--- trunk/modules/DataTable/Renderer.php	2008-01-17 23:51:37 UTC (rev 182)
+++ trunk/modules/DataTable/Renderer.php	2008-01-18 06:28:19 UTC (rev 183)
@@ -74,7 +74,7 @@
 		}
 		else
 		{
-			throw new Exception("Renderer format '$name' not valid.");
+			throw new Exception("Renderer format '$name' not valid. Try 'xml' or 'json' or 'csv' or 'html' or 'php' or 'original' instead.");
 		}		
 	}	
 }

Modified: trunk/modules/Date.php
===================================================================
--- trunk/modules/Date.php	2008-01-17 23:51:37 UTC (rev 182)
+++ trunk/modules/Date.php	2008-01-18 06:28:19 UTC (rev 183)
@@ -27,7 +27,11 @@
 		}
 		else
 		{
-			$this->timestamp = strtotime( $date );
+			if (($timestamp = strtotime($date)) === false) 
+			{
+				throw new Exception("The date '$date' is not correct. The date format is YYYY-MM-DD or you can also use magic keywords such as 'today' or 'yesterday' or any keyword supported by the strtotime function (see http://php.net/strtotime for more information)");
+			}
+			$this->timestamp = $timestamp;
 		}
 	}
 	
@@ -36,6 +40,10 @@
 		return $this->timestamp;
 	}
 	
+	public function isLater( Piwik_Date $date)
+	{
+		return $this->getTimestamp() > $date->getTimestamp();
+	}
 	public function isEarlier(Piwik_Date $date)
 	{
 		return $this->getTimestamp() < $date->getTimestamp();

Modified: trunk/modules/Period.php
===================================================================
--- trunk/modules/Period.php	2008-01-17 23:51:37 UTC (rev 182)
+++ trunk/modules/Period.php	2008-01-18 06:28:19 UTC (rev 183)
@@ -29,6 +29,7 @@
 	protected $subperiodsProcessed = false;
 	protected $label = null;
 	
+	protected static $unknowPeriodException = "The period '%s' is not supported. Try 'day' or 'week' or 'month' or 'year'";
 	public function __construct( $date )
 	{	
 		$this->checkInputDate( $date );
@@ -55,7 +56,7 @@
 				break;
 				
 			default:
-				throw new Exception("Unknown period!");
+				throw new Exception(sprintf(self::$unknowPeriodException, $strPeriod));
 				break;
 		}
 	}
@@ -187,14 +188,7 @@
 		}
 		return true;
 	}
-	
-	public function getPrettyString()
-	{
-		$temp = $this->toString();
-		$out = $this->getLabel() . " from " . $temp[0] . " to " . end($temp);
-		return $out;
-	}
-	
+		
 	public function toString()
 	{
 		if(!$this->subperiodsProcessed)
@@ -213,6 +207,8 @@
 	{
 		return $this->date->get($part);
 	}
+	
+	abstract public function getPrettyString();
 }
 
 /**
@@ -227,6 +223,13 @@
 		$this->strDate = $strDate;
 		
 	}
+	
+	public function getPrettyString()
+	{
+		$out = "From ".$this->getDateStart()->toString() . " to " . $this->getDateEnd()->toString();
+		return $out;
+	}
+	
 	protected function removePeriod( $date, $n )
 	{
 		switch($this->strPeriod)
@@ -246,9 +249,36 @@
 			case 'year':
 				$startDate = $date->subMonth( 12 * $n );					
 			break;
+			
+			default:
+				throw new Exception(sprintf(self::$unknowPeriodException, $this->strPeriod));
+			break;
 		}
 		return $startDate;
 	}
+	
+	protected function getMaxN($lastN)
+	{	
+		switch($this->strPeriod)
+		{
+			case 'day':	
+				$lastN = min( $lastN, 5*365 );
+			break;
+			
+			case 'week':
+				$lastN = min( $lastN, 5*52 );				
+			break;
+			
+			case 'month':
+				$lastN = min( $lastN, 5*12 );			
+			break;
+			
+			case 'year':
+				$lastN = min( $lastN, 10 );					
+			break;
+		}
+		return $lastN;
+	}
 	protected function generate()
 	{
 		if($this->subperiodsProcessed)
@@ -257,21 +287,33 @@
 		}
 		$this->subperiodsProcessed = true;
 		
-		if(ereg('last([0-9]*)', $this->strDate, $regs))
+		if(ereg('(last|previous)([0-9]*)', $this->strDate, $regs))
 		{
-			$lastN = $regs[1];
+			$lastN = $regs[2];
 			
+			$lastOrPrevious = $regs[1];
+			
+			if($lastOrPrevious == 'last')
+			{
+				$endDate = Piwik_Date::today();
+			}
+			elseif($lastOrPrevious == 'previous')
+			{
+				$endDate = $this->removePeriod(Piwik_Date::today(), 1);
+			}		
+			
 			// last1 means only one result ; last2 means 2 results so we remove only 1 to the days/weeks/etc
 			$lastN--;
+			$lastN = abs($lastN);
 			
-			$endDate = Piwik_Date::today();
+			$lastN = $this->getMaxN($lastN);
+			
 			$startDate = $this->removePeriod($endDate, $lastN);
 		}
 		else
 		{
 			throw new Exception("The date $strDate seems incorrect");
 		}
-		//TODO handle previous
 		
 		$endSubperiod = Piwik_Period::factory($this->strPeriod, $endDate);
 		$this->addSubperiod($endSubperiod);
@@ -282,6 +324,7 @@
 			$subPeriod = Piwik_Period::factory($this->strPeriod, $endDate);
 			$this->addSubperiod( $subPeriod );
 		}
+//		var_dump($this->toString());exit;
 	}
 	
 	function toString()
@@ -312,7 +355,12 @@
 	{
 		parent::__construct($date);		
 	}
-			
+
+	public function getPrettyString()
+	{
+		$out = $this->getDateStart()->toString() ;
+		return $out;
+	}
 	public function isFinished()
 	{
 		$todayMidnight = Piwik_Date::today();
@@ -350,7 +398,12 @@
 	{
 		parent::__construct($date);
 	}
-	
+
+	public function getPrettyString()
+	{
+		$out = $this->getDateStart()->toString() . " to " . $this->getDateEnd()->toString();
+		return $out;
+	}
 	protected function generate()
 	{
 		if($this->subperiodsProcessed)
@@ -388,7 +441,12 @@
 	{
 		parent::__construct($date);
 	}
-	
+
+	public function getPrettyString()
+	{
+		$out = $this->getDateStart()->toString('Y-m');
+		return $out;
+	}
 	protected function generate()
 	{
 		if($this->subperiodsProcessed)
@@ -434,7 +492,12 @@
 	{
 		parent::__construct($date);
 	}
-	
+
+	public function getPrettyString()
+	{
+		$out = $this->getDateStart()->toString('Y');
+		return $out;
+	}
 	protected function generate()
 	{
 		if($this->subperiodsProcessed)

Modified: trunk/modules/Site.php
===================================================================
--- trunk/modules/Site.php	2008-01-17 23:51:37 UTC (rev 182)
+++ trunk/modules/Site.php	2008-01-18 06:28:19 UTC (rev 183)
@@ -28,6 +28,14 @@
 			self::$infoSites[$this->id] = Piwik_SitesManager_API::getSiteFromId($idsite);
 		}
 	}
+	function getName()
+	{
+		return self::$infoSites[$this->id]['name'];
+	}
+	function getMainUrl()
+	{
+		return self::$infoSites[$this->id]['main_url'];
+	}
 	
 	function getId()
 	{

Modified: trunk/plugins/UsersManager/templates/UsersManager.js
===================================================================
--- trunk/plugins/UsersManager/templates/UsersManager.js	2008-01-17 23:51:37 UTC (rev 182)
+++ trunk/plugins/UsersManager/templates/UsersManager.js	2008-01-18 06:28:19 UTC (rev 183)
@@ -198,6 +198,7 @@
 				<td><input id="useradd_password" value="password" size=10></td>\
 				<td><input id="useradd_email" value="email at domain.com" size=15></td>\
 				<td><input id="useradd_alias" value="alias" size=15></td>\
+				<td>-</td>\
 				<td><img src="plugins/UsersManager/images/ok.png" id="adduser" href="#"></td>\
 	  			<td><img src="plugins/UsersManager/images/remove.png" id="cancel"></td>\
 	 		</tr>')

Modified: trunk/plugins/VisitsSummary/API.php
===================================================================
--- trunk/plugins/VisitsSummary/API.php	2008-01-17 23:51:37 UTC (rev 182)
+++ trunk/plugins/VisitsSummary/API.php	2008-01-18 06:28:19 UTC (rev 183)
@@ -32,22 +32,50 @@
 		return self::$instance;
 	}
 	
-	public function get( $idSite, $period, $date )
+	public function get( $idSite, $period, $date, $toFetch = '' )
 	{
 		Piwik::checkUserHasViewAccess( $idSite );
 		$archive = Piwik_Archive::build($idSite, $period, $date );
-			
-		$toFetch = array( 	'max_actions',
+		
+		if(empty($toFetch))
+		{
+			$toFetch = array( 	'max_actions',
 							'nb_uniq_visitors', 
 							'nb_visits',
 							'nb_actions', 
 							'sum_visit_length',
 							'bounce_count',
 						);
+		}
+		else
+		{
+			$toFetch = array($toFetch);
+		}
 		$dataTable = $archive->getDataTableFromNumeric($toFetch);
 
 		return $dataTable;
 	}
+
+	public function getVisits( $idSite, $period, $date )
+	{
+		return $this->get( $idSite, $period, $date, 'nb_visits');
+	}
+	public function getUniqueVisitors( $idSite, $period, $date )
+	{
+		return $this->get( $idSite, $period, $date, 'nb_uniq_visitors');
+	}
+	public function getMaxActions( $idSite, $period, $date )
+	{
+		return $this->get( $idSite, $period, $date, 'max_actions');
+	}
+	public function getSumVisitsLength( $idSite, $period, $date )
+	{
+		return $this->get( $idSite, $period, $date, 'sum_visit_length');
+	}
+	public function getBounceCount( $idSite, $period, $date )
+	{
+		return $this->get( $idSite, $period, $date, 'bounce_count');
+	}
 	
 }
 

Modified: trunk/tests/modules/DataTable/Renderer.test.php
===================================================================
--- trunk/tests/modules/DataTable/Renderer.test.php	2008-01-17 23:51:37 UTC (rev 182)
+++ trunk/tests/modules/DataTable/Renderer.test.php	2008-01-18 06:28:19 UTC (rev 183)
@@ -68,6 +68,19 @@
 		$table->loadFromArray($array);
 		return $table;
 	}
+	protected function getDataTableEmpty()
+	{
+		$table = new Piwik_DataTable;
+		return $table;
+	}
+	protected function getDataTableSimpleOneZeroRowTest()
+	{
+		$array = array ( 'nb_visits' => 0 );
+		
+		$table = new Piwik_DataTable_Simple;
+		$table->loadFromArray($array);
+		return $table;
+	}
 	
 	
 	/**
@@ -128,8 +141,23 @@
 		$expected = '<result>14</result>';
 		$this->assertEqual( $expected,$render->render());
 	}
+	function test_XML_test4()
+	{
+		$dataTable = $this->getDataTableEmpty();
+	  	$render = new Piwik_DataTable_Renderer_Xml($dataTable);
+		$expected = '<result />';
+		$this->assertEqual( $expected,$render->render());
+	}
 	
+	function test_XML_test5()
+	{
+		$dataTable = $this->getDataTableSimpleOneZeroRowTest();
+	  	$render = new Piwik_DataTable_Renderer_Xml($dataTable);
+		$expected = '<result>0</result>';
+		$this->assertEqual( $expected,$render->render());
+	}
 	
+	
 	function test_CSV_test1()
 	{
 		$dataTable = $this->getDataTableTest();
@@ -162,6 +190,22 @@
 		$expected = "value\n14";
 		$this->assertEqual( $expected,$render->render());
 	}
+
+	function test_CSV_test4()
+	{
+		$dataTable = $this->getDataTableEmpty();
+	  	$render = new Piwik_DataTable_Renderer_Csv($dataTable);
+		$expected = 'No data available';
+		$this->assertEqual( $expected,$render->render());
+	}
+
+	function test_CSV_test5()
+	{
+		$dataTable = $this->getDataTableSimpleOneZeroRowTest();
+	  	$render = new Piwik_DataTable_Renderer_Csv($dataTable);
+		$expected = "value\n0";
+		$this->assertEqual( $expected,$render->render());
+	}
 	
 	function test_JSON_test1()
 	{
@@ -187,6 +231,22 @@
 		$expected = '{"value":14}';
 		$this->assertEqual( $expected,$render->render());
 	}
+
+	function test_JSON_test4()
+	{
+		$dataTable = $this->getDataTableEmpty();
+	  	$render = new Piwik_DataTable_Renderer_Json($dataTable);
+		$expected = '[]';
+		$this->assertEqual( $expected,$render->render());
+	}
+
+	function test_JSON_test5()
+	{
+		$dataTable = $this->getDataTableSimpleOneZeroRowTest();
+	  	$render = new Piwik_DataTable_Renderer_Json($dataTable);
+		$expected = '{"value":0}';
+		$this->assertEqual( $expected,$render->render());
+	}
 	
 	function test_PHP_test1()
 	{
@@ -241,10 +301,25 @@
 		$expected = serialize(14.0);
 		$this->assertEqual( $expected,$render->render());
 	}
+	function test_PHP_test4()
+	{
+		$dataTable = $this->getDataTableEmpty();
+	  	$render = new Piwik_DataTable_Renderer_Php($dataTable);
+		$expected = serialize(array());
+		$this->assertEqual( $expected,$render->render());
+	}
+	function test_PHP_test5()
+	{
+		$dataTable = $this->getDataTableSimpleOneZeroRowTest();
+	  	$render = new Piwik_DataTable_Renderer_Php($dataTable);
+		$expected = serialize(0);
+		$this->assertEqual( $expected,$render->render());
+	}
 	
 	
 	
 	
+	
 	/**
 	 * DATA OF DATATABLE_ARRAY
 	 * -------------------------
@@ -276,12 +351,14 @@
 		$table2 = new Piwik_DataTable();
 		$table2->loadFromArray($array2);
 		
+		$table3 = new Piwik_DataTable();
 		
 		
 		$table = new Piwik_DataTable_Array();
 		$table->setNameKey('testKey');
 		$table->addTable($table1, 'date1');
 		$table->addTable($table2, 'date2');
+		$table->addTable($table3, 'date3');
 		
 		return $table;
 	}
@@ -296,10 +373,13 @@
 		$table2 = new Piwik_DataTable_Simple;
 		$table2->loadFromArray($array2);
 		
+		$table3 = new Piwik_DataTable_Simple;
+		
 		$table = new Piwik_DataTable_Array();
 		$table->setNameKey('testKey');
 		$table->addTable($table1, 'row1');
 		$table->addTable($table2, 'row2');
+		$table->addTable($table3, 'row3');
 		
 		return $table;
 	}
@@ -314,10 +394,13 @@
 		$table2 = new Piwik_DataTable_Simple;
 		$table2->loadFromArray($array2);
 		
+		$table3 = new Piwik_DataTable_Simple;
+		
 		$table = new Piwik_DataTable_Array();
 		$table->setNameKey('testKey');
 		$table->addTable($table1, 'row1');
 		$table->addTable($table2, 'row2');
+		$table->addTable($table3, 'row3');
 		
 		return $table;
 	}
@@ -370,6 +453,7 @@
 			<logo>./plugins/Referers/images/searchEngines/www.yahoo.com.png1</logo>
 		</row>
 	</result>
+	<result testKey="date3" />
 </results>';
 		$this->assertEqual( $expected,$render->render());
 	}
@@ -388,6 +472,7 @@
 		<max_actions>140</max_actions>
 		<nb_uniq_visitors>570</nb_uniq_visitors>
 	</result>
+	<result testKey="row3" />
 </results>';
 		$this->assertEqual( $expected,$render->render());
 	}
@@ -398,6 +483,7 @@
 		$expected = '<results>
 	<result testKey="row1">14</result>
 	<result testKey="row2">15</result>
+	<result testKey="row3" />
 </results>';
 		$this->assertEqual( $expected,$render->render());
 	}
@@ -448,8 +534,9 @@
 				      'url' => 'http://www.yahoo.com1',
 				      'logo' => './plugins/Referers/images/searchEngines/www.yahoo.com.png1',
 				    ),
-				  ),
-				));
+				),
+				  'date3' => array (),
+				  ));		
 		$this->assertEqual( $expected,$rendered);
 	}
 	function test_PHP_Array_test2()
@@ -469,6 +556,9 @@
 			    'max_actions' => 140.0,
 			    'nb_uniq_visitors' => 570.0,
 			  ),
+			  'row3' => 
+			  array (
+			  ),
 			));
 		$this->assertEqual( $expected,$rendered);
 	}
@@ -481,6 +571,7 @@
 		$expected = serialize(array (
 				  'row1' => 14.0,
 				  'row2' => 15.0,
+				  'row3' => array(),
 				));
 		$this->assertEqual( $expected,$rendered);
 	}
@@ -492,7 +583,7 @@
 		$dataTable = $this->getDataTableArrayTest();
 	  	$render = new Piwik_DataTable_Renderer_Json($dataTable);
 	  	$rendered = $render->render();
-	  	$expected = '{"date1":[{"label":"Google","nb_unique_visitors":11,"nb_visits":11,"url":"http:\/\/www.google.com","logo":".\/plugins\/Referers\/images\/searchEngines\/www.google.com.png"},{"label":"Yahoo!","nb_unique_visitors":15,"nb_visits":151,"url":"http:\/\/www.yahoo.com","logo":".\/plugins\/Referers\/images\/searchEngines\/www.yahoo.com.png"}],"date2":[{"label":"Google1","nb_unique_visitors":110,"nb_visits":110,"url":"http:\/\/www.google.com1","logo":".\/plugins\/Referers\/images\/searchEngines\/www.google.com.png1"},{"label":"Yahoo!1","nb_unique_visitors":150,"nb_visits":1510,"url":"http:\/\/www.yahoo.com1","logo":".\/plugins\/Referers\/images\/searchEngines\/www.yahoo.com.png1"}]}';
+	  	$expected = '{"date1":[{"label":"Google","nb_unique_visitors":11,"nb_visits":11,"url":"http:\/\/www.google.com","logo":".\/plugins\/Referers\/images\/searchEngines\/www.google.com.png"},{"label":"Yahoo!","nb_unique_visitors":15,"nb_visits":151,"url":"http:\/\/www.yahoo.com","logo":".\/plugins\/Referers\/images\/searchEngines\/www.yahoo.com.png"}],"date2":[{"label":"Google1","nb_unique_visitors":110,"nb_visits":110,"url":"http:\/\/www.google.com1","logo":".\/plugins\/Referers\/images\/searchEngines\/www.google.com.png1"},{"label":"Yahoo!1","nb_unique_visitors":150,"nb_visits":1510,"url":"http:\/\/www.yahoo.com1","logo":".\/plugins\/Referers\/images\/searchEngines\/www.yahoo.com.png1"}],"date3":[]}';
 
 		$this->assertEqual( $expected,$rendered);
 	}
@@ -502,7 +593,7 @@
 	  	$render = new Piwik_DataTable_Renderer_Json($dataTable);
 	  	$rendered = $render->render();
 	  	
-		$expected = '{"row1":{"max_actions":14,"nb_uniq_visitors":57},"row2":{"max_actions":140,"nb_uniq_visitors":570}}';
+		$expected = '{"row1":{"max_actions":14,"nb_uniq_visitors":57},"row2":{"max_actions":140,"nb_uniq_visitors":570},"row3":[]}';
 
 		$this->assertEqual( $expected,$rendered);
 	}
@@ -513,7 +604,7 @@
 	  	$render = new Piwik_DataTable_Renderer_Json($dataTable);
 	  	$rendered = $render->render();
 	  	
-		$expected = '{"row1":14,"row2":15}';
+		$expected = '{"row1":14,"row2":15,"row3":[]}';
 		$this->assertEqual( $expected,$rendered);
 	}
 	

Modified: trunk/tests/modules/Period.test.php
===================================================================
--- trunk/tests/modules/Period.test.php	2008-01-17 23:51:37 UTC (rev 182)
+++ trunk/tests/modules/Period.test.php	2008-01-18 06:28:19 UTC (rev 183)
@@ -634,6 +634,24 @@
 	 	$this->assertEqual( $range->isFinished(), false);
 	 	$this->assertEqual( $range->toString(), $correct);
 	 }
+	// test range 4
+	function test_range_previous3days()
+	{
+		
+	 	$range = new Piwik_Period_Range( 'day', 'previous3' );
+	 	$yesterday = Piwik_Date::yesterday();
+	 	
+	 	$correct = array();
+	 	for($i=0;$i<3;$i++)
+	 	{
+	 		$correct[]=$yesterday->subDay($i)->toString();
+	 	}
+			
+	 	$this->assertEqual( $range->getNumberOfSubperiods(), 3);
+	 	$this->assertEqual( $range->isFinished(), true);
+	 	$this->assertEqual( $range->toString(), $correct);
+	 }
+	 
 	// test range WEEK
 	function test_range_week()
 	{
@@ -674,16 +692,37 @@
 	 	$this->assertEqual( $range->isFinished(), false);
 	 	$this->assertEqual( $range->toString(), $correct);
 	 }
+	// test range PREVIOUS MONTH
+	function test_range_previousmonth()
+	{
+		
+	 	$range = new Piwik_Period_Range( 'month', 'previous10' );
+	 	$end = Piwik_Date::today();
+	 	$end = $end->subMonth(1);
+	 	
+	 	$correct = array();
+	 	for($i=0;$i<10;$i++)
+	 	{
+	 		$date = $end->subMonth($i);
+	 		$week = new Piwik_Period_Month($date);
+	 		
+	 		$correct[]= $week->toString();
+	 	}
+			
+	 	$this->assertEqual( $range->getNumberOfSubperiods(), 10);
+	 	$this->assertEqual( $range->isFinished(), true);
+	 	$this->assertEqual( $range->toString(), $correct);
+	 }
 	 
 	// test range YEAR
 	function test_range_year()
 	{
 		
-	 	$range = new Piwik_Period_Range( 'year', 'last20' );
+	 	$range = new Piwik_Period_Range( 'year', 'last10' );
 	 	$today = Piwik_Date::today();
 	 	
 	 	$correct = array();
-	 	for($i=0;$i<20;$i++)
+	 	for($i=0;$i<10;$i++)
 	 	{
 	 		$date = $today->subMonth(12*$i);
 	 		$week = new Piwik_Period_Year($date);
@@ -691,7 +730,7 @@
 	 		$correct[]= $week->toString();
 	 	}
 	 	
-	 	$this->assertEqual( $range->getNumberOfSubperiods(), 20);
+	 	$this->assertEqual( $range->getNumberOfSubperiods(), 10);
 	 	$this->assertEqual( $range->isFinished(), false);
 	 	$this->assertEqual( $range->toString(), $correct);
 	 }



More information about the Piwik-svn mailing list