[Piwik-svn] r160 - trunk/modules/API

svnmaster at piwik.org svnmaster at piwik.org
Mon Jan 14 04:57:14 CET 2008


Author: matt
Date: 2008-01-14 04:57:13 +0100 (Mon, 14 Jan 2008)
New Revision: 160

Modified:
   trunk/modules/API/Request.php
Log:


Modified: trunk/modules/API/Request.php
===================================================================
--- trunk/modules/API/Request.php	2008-01-14 03:00:40 UTC (rev 159)
+++ trunk/modules/API/Request.php	2008-01-14 03:57:13 UTC (rev 160)
@@ -1,10 +1,22 @@
-<?php
+<?php
+/**
+ * Piwik - Open source web analytics
+ * 
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
+ * 
+ * $Id$
+ */
+
 /**
  * An API request is the object used to make a call to the API and get the result.
  * The request has the format of a normal GET request, ie. parameter_1=X&parameter_2=Y
  * 
  * You can use this object from anywhere in piwik (inside plugins for example).
- * You can even call it outside of piwik (see 
+ * You can even call it outside of piwik  using the REST API over http
+ * or in a php script on the same server as piwik, by including piwik/index.php
+ * (see the documentation http://dev.piwik.org/trac/wiki/API)
+ * 
  * Example: 
  * $request = new Piwik_API_Request('
  * 				method=UserSettings.getWideScreen
@@ -18,12 +30,13 @@
  *	$result = $request->process();
  *  echo $result;
  * 
- * @see http://dev.piwik.org/trac/wiki/API for a complete documentation
+ * @see http://dev.piwik.org/trac/wiki/API
  * @package Piwik_API
  */
 class Piwik_API_Request
 {
 	/**
+	 * Constructs the request to the API, given the request url
 	 * 
 	 * @param string GET request that defines the API call (must at least contain a "method" parameter) 
 	 *  Example: method=UserSettings.getWideScreen&idSite=1&date=yesterday&period=week&format=xml
@@ -55,7 +68,8 @@
 	/**
 	 * Returns array( $class, $method) from the given string $class.$method
 	 * 
-	 * @return array
+	 * @return array
+	 * @throws exception if the name is invalid
 	 */
 	private function extractModuleAndMethod($parameter)
 	{
@@ -66,30 +80,27 @@
 		}
 		return $a;
 	}
+	
+	protected $outputFormatRequested;
 	
 	/**
 	 * Handles the request to the API.
 	 * It first checks that the method called (parameter 'method') is available in the module (it means that the method exists and is public)
-	 * It then reads the parameters from the request string and throws an exception if there are absent parameters.
-	 * It then calls the API Proxy which will call the method.
-	 * If the data resulted from the API call is a Piwik_DataTable then 
-	 * 		- we apply the standard filters if the parameters have been found
-	 * 		  in the URL. For example to offset,limit the Table you can add the following parameters to any API
-	 *  	  call that returns a DataTable: filter_limit=10&filter_offset=20
-	 * 		- we apply the filters that have been previously queued on the DataTable
-	 * 		- we apply the renderer that generate the DataTable in a given format (XML, PHP, HTML, JSON, etc.) 
-	 * 		  the format can be changed using the 'format' parameter in the request.
-	 *        Example: format=xml
+	 * It then reads the parameters from the request string and throws an exception if there are missing parameters.
+	 * It then calls the API Proxy which will call the requested method.
+	 * 
+	 * @see the method handleReturnedValue() for the data post process logic 
 	 * 
 	 * @return mixed The data resulting from the API call  
 	 */
 	public function process()
 	{
-		try {
-			// read the format requested for the output data
-			$outputFormatRequested = Piwik_Common::getRequestVar('format', 'xml', 'string', $this->requestToUse);
-			$outputFormatRequested = strtolower($outputFormatRequested);
+		try {
 			
+			// read the format requested for the output data
+			$this->outputFormatRequested = Piwik_Common::getRequestVar('format', 'xml', 'string', $this->requestToUse);
+			$this->outputFormatRequested = strtolower($this->outputFormatRequested);
+		
 			// read parameters
 			$moduleMethod = Piwik_Common::getRequestVar('method', null, null, $this->requestToUse);
 			
@@ -108,132 +119,181 @@
 			
 			// check method exists
 			$api->checkMethodExists($className, $method);
-			
+			
+			// get the list of parameters required by the method
 			$parameters = $api->getParametersList($className, $method);
-			
-			$finalParameters = array();
-			foreach($parameters as $name => $defaultValue)
-			{
-				try{
-					// there is a default value specified
-					if($defaultValue !== Piwik_API_Proxy::NO_DEFAULT_VALUE)
-					{
-						$requestValue = Piwik_Common::getRequestVar($name, $defaultValue, null, $this->requestToUse);
-					}
-					else
-					{
-						$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.");
-				}			
-				$finalParameters[] = $requestValue;
-			}
-			
+			
+			// load the parameters from the request URL
+			$finalParameters = $this->getRequestParametersArray( $parameters );
+			
+			// call the method 
 			$returnedValue = call_user_func_array( array( $api->$module, $method), $finalParameters );
-			
-			$toReturn = $returnedValue;
-			
-			// If the returned value is an object DataTable we
-			// apply the set of generic filters if asked in the URL
-			// and we render the DataTable according to the format specified in the URL
-			if($returnedValue instanceof Piwik_DataTable)
-			{
-				$dataTable = $returnedValue;
-				
-				$this->applyDataTableGenericFilters($dataTable);
-				
-				$dataTable->applyQueuedFilters();
-				
-				$toReturn = $this->getRenderedDataTable($dataTable);
-				
-			}
 			
-			// Case nothing returned (really nothing was 'return'ed), 
-			// => the operation was successful
-			elseif(!isset($toReturn))
-			{
-				$toReturn = $this->getStandardSuccessOutput($outputFormatRequested);
+			// post process the data
+			$toReturn = $this->handleReturnedValue( $returnedValue );
+			
+		} catch(Exception $e ) {
+			
+			// if it is not a direct API call, we are requesting the original data structure
+			// and we actually are handling this exception at the top level in the FrontController
+			if($this->outputFormatRequested == 'original')
+			{
+				throw $e;
 			}
+			$message = $e->getMessage();
 			
-			// Case an array is returned from the API call, we convert it to the requested format
-			// - if calling from inside the application (format = original)
-			//    => the data stays unchanged (ie. a standard php array or whatever data structure)
-			// - if any other format is requested, we have to convert this data structure (which we assume 
-			//   to be an array) to a DataTable in order to apply the requested DataTable_Renderer (for example XML)
-			elseif(is_array($toReturn))
-			{
-				if($outputFormatRequested == 'original')
+			// it seems that JSON doesn't like line breaks
+			$message = nl2br($message);
+			
+			$toReturn =  $this->getExceptionOutput( $message, $this->outputFormatRequested);
+			
+		}
+		
+		return $toReturn;
+	}
+	
+	/**
+	 * Returns the values of the current request
+	 *
+	 * @param array Parameters array of the method called. Contains name and default values of the required parameters
+	 * @return array Values of the given parameters
+	 * @throws exception If there is a missing parameter
+	 */
+	protected function getRequestParametersArray( $parameters )
+	{
+		$finalParameters = array();
+		foreach($parameters as $name => $defaultValue)
+		{
+			try{
+				// there is a default value specified
+				if($defaultValue !== Piwik_API_Proxy::NO_DEFAULT_VALUE)
 				{
-					// we handle the serialization. Because some php array have a very special structure that 
-					// couldn't be converted with the automatic DataTable->loadFromSimpleArray
-					// the user may want to request the original PHP data structure serialized by the API
-					// in case he has to setup serialize=1 in the URL
-					if($this->caseRendererPHPSerialize( $defaultSerialize = 0))
-					{
-						$toReturn = serialize($toReturn);
-					}
+					$requestValue = Piwik_Common::getRequestVar($name, $defaultValue, null, $this->requestToUse);
 				}
 				else
 				{
-//					var_dump($toReturn);exit;
-//					echo "$outputFormatRequested requested";
-					$dataTable = new Piwik_DataTable();
-					$dataTable->loadFromSimpleArray($toReturn);
-//					echo $dataTable;exit;
-					$toReturn = $this->getRenderedDataTable($dataTable);
-//					echo $toReturn;exit;
+					$requestValue = Piwik_Common::getRequestVar($name, null, null, $this->requestToUse);				
 				}
-			}
-			// bool // integer // float // object is serialized
-			// NB: null value is already handled by the isset() test above
-			else
+			} catch(Exception $e) {
+				throw new Exception("The required variable '$name' is not correct or has not been found in the API Request.");
+			}			
+			$finalParameters[] = $requestValue;
+		}
+		return $finalParameters;
+	}
+	
+	/**
+	 * This method post processes the data resulting from the API call.
+	 * 
+	 *
+	 * - If the data resulted from the API call is a Piwik_DataTable then 
+	 * 		- we apply the standard filters if the parameters have been found
+	 * 		  in the URL. For example to offset,limit the Table you can add the following parameters to any API
+	 *  	  call that returns a DataTable: filter_limit=10&filter_offset=20
+	 * 		- we apply the filters that have been previously queued on the DataTable
+	 * 		- we apply the renderer that generate the DataTable in a given format (XML, PHP, HTML, JSON, etc.) 
+	 * 		  the format can be changed using the 'format' parameter in the request.
+	 *        Example: format=xml
+	 * 
+	 * - If there is nothing returned (void) we display a standard success message
+	 * 
+	 * - If there is a PHP array returned, we try to convert it to a dataTable 
+	 *   It is then possible to convert this datatable to any requested format (xml/etc)
+	 * 
+	 * - If a bool is returned we convert to a string (true is displayed as 'true' false as 'false')
+	 * 
+	 * - If an integer / float is returned, we simply return it
+	 * 
+	 * @throws Exception If an object/resource is returned, if any of conversion fails, etc. 
+	 * 
+	 * @param mixed The initial returned value, before post process
+	 * @return mixed Usually a string, but can still be a PHP data structure if the format requested is 'original'
+	 */
+	protected function handleReturnedValue( $returnedValue ) 
+	{
+		$toReturn = $returnedValue;
+		
+		// If the returned value is an object DataTable we
+		// apply the set of generic filters if asked in the URL
+		// and we render the DataTable according to the format specified in the URL
+		if($returnedValue instanceof Piwik_DataTable)
+		{			
+			$this->applyDataTableGenericFilters($returnedValue);
+			
+			$returnedValue->applyQueuedFilters();
+			
+			$toReturn = $this->getRenderedDataTable($returnedValue);
+			
+		}
+		
+		// Case nothing returned (really nothing was 'return'ed), 
+		// => the operation was successful
+		elseif(!isset($toReturn))
+		{
+			$toReturn = $this->getStandardSuccessOutput($this->outputFormatRequested);
+		}
+		
+		// Case an array is returned from the API call, we convert it to the requested format
+		// - if calling from inside the application (format = original)
+		//    => the data stays unchanged (ie. a standard php array or whatever data structure)
+		// - if any other format is requested, we have to convert this data structure (which we assume 
+		//   to be an array) to a DataTable in order to apply the requested DataTable_Renderer (for example XML)
+		elseif(is_array($toReturn))
+		{
+			if($this->outputFormatRequested == 'original')
 			{
-				// original data structure requested, we return without process
-				if( $outputFormatRequested == 'original' )
+				// we handle the serialization. Because some php array have a very special structure that 
+				// couldn't be converted with the automatic DataTable->loadFromSimpleArray
+				// the user may want to request the original PHP data structure serialized by the API
+				// in case he has to setup serialize=1 in the URL
+				if($this->caseRendererPHPSerialize( $defaultSerialize = 0))
 				{
-					return $toReturn;
+					$toReturn = serialize($toReturn);
 				}
-				
-				if( $toReturn === true )
-				{
-					$toReturn = 'true';
-				}
-				elseif( $toReturn === false )
-				{
-					$toReturn = 'false';
-				}
-				elseif( is_object($toReturn)
-							|| is_resource($toReturn)
-							)
-				{
-					return $this->getExceptionOutput( ' The API cannot handle this data structure. You can get the data internally by directly using the class.', $outputFormatRequested);
-				}
-				return $this->getStandardSuccessOutput($outputFormatRequested, $message = $toReturn);
-			}
-			
-		} catch(Exception $e ) {
-			
-			// if it is not a direct API call, we are requesting the original data structure
-			// and we actually are handling this exception at the top level in the FrontController
-			if($outputFormatRequested == 'original')
-			{
-				throw $e;
 			}
-			$message = $e->getMessage();
+			else
+			{
+				$dataTable = new Piwik_DataTable();
+				$dataTable->loadFromSimpleArray($toReturn);
+				$toReturn = $this->getRenderedDataTable($dataTable);
+			}
+		}
+		// bool // integer // float // object is serialized
+		// NB: null value is already handled by the isset() test above
+		else
+		{
+			// original data structure requested, we return without process
+			if( $this->outputFormatRequested == 'original' )
+			{
+				return $toReturn;
+			}
 			
-			// it seems that JSON doesn't like line breaks
-			$message = nl2br($message);
-			
-			$toReturn =  $this->getExceptionOutput( $message, $outputFormatRequested);
-			
+			if( $toReturn === true )
+			{
+				$toReturn = 'true';
+			}
+			elseif( $toReturn === false )
+			{
+				$toReturn = 'false';
+			}
+			elseif( is_object($toReturn)
+						|| is_resource($toReturn)
+						)
+			{
+				return $this->getExceptionOutput( ' The API cannot handle this data structure. You can get the data internally by directly using the class.', $this->outputFormatRequested);
+			}
+			return $this->getStandardSuccessOutput($this->outputFormatRequested, $message = $toReturn);
 		}
-		
-		return $toReturn;
 	}
 	
-	
-	function getStandardSuccessOutput($format, $message = 'ok')
+	/**
+	 * Returns a success $message in the requested $format 
+	 *
+	 * @param string $format xml/json/php/csv
+	 * @param string $message
+	 * @return string
+	 */
+	protected function getStandardSuccessOutput($format, $message = 'ok')
 	{
 		switch($format)
 		{
@@ -269,7 +329,15 @@
 		}
 		
 		return $return;
-	}
+	}
+	
+	/**
+	 * Returns an error $message in the requested $format 
+	 *
+	 * @param string $format xml/json/php/csv
+	 * @param string $message
+	 * @return string
+	 */
 	function getExceptionOutput($message, $format)
 	{
 		switch($format)
@@ -302,7 +370,9 @@
 	}
 
 	/**
-	 * Apply the specified renderer to the DataTable
+	 * Apply the specified renderer to the DataTable
+	 * 
+	 * @param Piwik_DataTable
 	 * @return Piwik_DataTable
 	 */
 	protected function getRenderedDataTable($dataTable)
@@ -342,9 +412,14 @@
 		$toReturn = $renderer->render();
 		return $toReturn;
 	}
-	
-	
-	function caseRendererPHPSerialize($defaultSerializeValue = 1)
+	
+	/**
+	 * Returns true if the user requested to serialize the output data (&serialize=1 in the request)
+	 *
+	 * @param $defaultSerializeValue Default value in case the user hasn't specified a value
+	 * @return bool
+	 */	
+	protected function caseRendererPHPSerialize($defaultSerializeValue = 1)
 	{
 		$serialize = Piwik_Common::getRequestVar('serialize', $defaultSerializeValue, 'int', $this->requestToUse);
 		if($serialize)
@@ -356,7 +431,13 @@
 			return false;		
 		}
 	}
-	
+	
+	/**
+	 * Returns an array containing the information of the generic Piwik_DataTable_Filter 
+	 * to be applied automatically to the data resulting from the API calls.
+	 *
+	 * @return array See the code for spec
+	 */
 	public static function getGenericFiltersInformation()
 	{
 		$genericFilters = array(
@@ -388,14 +469,14 @@
 	
 	
 	/**
-	 * Applys generic filters to the DataTable object resulting from the API Call.
+	 * Apply generic filters to the DataTable object resulting from the API Call.
+	 * Disable this feature by setting the parameter disable_generic_filters to 1 in the API call request.
+	 * 
+	 * @param Piwik_DataTable
 	 * @return void
 	 */
 	protected function applyDataTableGenericFilters($dataTable)
 	{
-//		print($dataTable->getRowsCount());
-//		$filter = new Piwik_DataTable_Filter_Sort($dataTable, 2, 'desc');
-		
 		// Generic filters
 		// PatternFileName => Parameter names to match to constructor parameters
 		/*
@@ -407,11 +488,11 @@
 		$genericFilters = Piwik_API_Request::getGenericFiltersInformation();
 		
 		// if the flag disable_generic_filters is defined we skip the generic filters
-		
 		if(Piwik_Common::getRequestVar('disable_generic_filters', 'false', 'string', $this->requestToUse) != 'false')
 		{
 			return;
-		}
+		}
+		
 		foreach($genericFilters as $filterName => $parameters)
 		{
 			$filterParameters = array();



More information about the Piwik-svn mailing list