responsebuilder.php

来自「一款可以和GOOGLE媲美的开源统计系统,运用AJAX.功能强大. 无色提示:」· PHP 代码 · 共 417 行

PHP
417
字号
<?phpclass Piwik_API_ResponseBuilder{	private $request = null;	private $outputFormat = null;		public function __construct($request, $outputFormat)	{		$this->request = $request;		$this->outputFormat = $outputFormat;	}		/**	 * This method 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	 *        @see Piwik_DataTable::queueFilter()	 * 		- 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'	 */	public function getResponse($value)	{ 		// 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($value instanceof Piwik_DataTable			|| $value instanceof Piwik_DataTable_Array)		{			return $this->handleDataTable($value);		}				// 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)		if(is_array($value))		{			return $this->handleArray($value);		}				// when null or void is returned from the api call, we handle it as a successful operation 		if(!isset($value))		{			return $this->handleSuccess();		}				// original data structure requested, we return without process		if( $this->outputFormat == 'original' )		{			return $value;		}			if( is_object($value)				|| is_resource($value))		{			return $this->getResponseException(new Exception('The API cannot handle this data structure.'));		}				// bool // integer // float // serialized object 		return $this->handleScalar($value);	}		/**	 * Returns an error $message in the requested $format 	 *	 * @param string $message	 * @param string $format xml/json/php/csv	 * @return string	 */	public function getResponseException(Exception $e)	{		$message = htmlentities($e->getMessage(), ENT_COMPAT, "UTF-8");		switch($this->outputFormat)		{			case 'original':				throw $e;			break;			case 'xml':				@header("Content-Type: text/xml;charset=utf-8");				$return = 					"<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n" .					"<result>\n".					"\t<error message=\"".$message."\" />\n".					"</result>";			break;			case 'json':				@header( "Content-type: application/json" );				// we remove the \n from the resulting string as this is not allowed in json				$message = str_replace("\n","",$message);				$return = '{"result":"error", "message":"'.$message.'"}';			break;			case 'php':				$return = array('result' => 'error', 'message' => $message);				if($this->caseRendererPHPSerialize())				{					$return = serialize($return);				}			break;			default:				$return = 'Error: '.$message;			break;		}		return $return;	}			/**	 * 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(						'Pattern' => array(								'filter_column' 			=> array('string'), 								'filter_pattern' 			=> array('string'),						),			'PatternRecursive' => array(								'filter_column_recursive' 	=> array('string'), 								'filter_pattern_recursive' 	=> array('string'),						),			'ExcludeLowPopulation'	=> array(								'filter_excludelowpop' 		=> array('string'), 								'filter_excludelowpop_value'=> array('float'),						),			'Sort' => array(								'filter_sort_column' 		=> array('string', Piwik_Archive::INDEX_NB_VISITS),								'filter_sort_order' 		=> array('string', Zend_Registry::get('config')->General->dataTable_default_sort_order),						),			'Limit' => array(								'filter_offset' 			=> array('integer', '0'),								'filter_limit' 				=> array('integer', Zend_Registry::get('config')->General->dataTable_default_limit),						),			'ExactMatch' => array(								'filter_exact_column'		=> array('string'),								'filter_exact_pattern'		=> array('array'),						),		);				return $genericFilters;	}		/**	 * 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->request);		if($serialize)		{			return true;		}		return false;		}		/**	 * Apply the specified renderer to the DataTable	 * 	 * @param Piwik_DataTable	 * @return string	 */	protected function getRenderedDataTable($dataTable)	{		$format = Piwik_Common::getRequestVar('format', 'php', 'string', $this->request);		$format = strtolower($format);				// if asked for original dataStructure		if($format == 'original')		{			// if the original dataStructure is a simpleDataTable and has only one row, we return the value			if($dataTable instanceof Piwik_DataTable_Simple				&& $dataTable->getRowsCount() == 1)			{				return $dataTable->getRowFromId(0)->getColumn('value');			}						// by default "original" data is not serialized			if($this->caseRendererPHPSerialize( $defaultSerialize = 0))			{				$dataTable = serialize($dataTable);			}			return $dataTable;		}				$renderer = Piwik_DataTable_Renderer::factory($format);		$renderer->setTable($dataTable);				if($format == 'php')		{			$renderer->setSerialize( $this->caseRendererPHPSerialize());		}				return $renderer->render();	}			/**	 * Returns a success $message in the requested $format 	 *	 * @param string $format xml/json/php/csv	 * @param string $message	 * @return string	 */	protected function handleSuccess( $message = 'ok' )	{		switch($this->outputFormat)		{			case 'xml':				@header("Content-Type: text/xml;charset=utf-8");				$return = 					"<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n" .					"<result>\n".					"\t<success message=\"".$message."\" />\n".					"</result>";			break;			case 'json':				@header( "Content-type: application/json" );				$return = '{"result":"success", "message":"'.$message.'"}';			break;			case 'php':				$return = array('result' => 'success', 'message' => $message);				if($this->caseRendererPHPSerialize())				{					$return = serialize($return);				}			break;						case 'csv':				header("Content-type: application/vnd.ms-excel");				header("Content-Disposition: attachment; filename=piwik-report-export.csv");					$return = "message\n".$message;			break;						default:				$return = 'Success:'.$message;			break;		}		return $return;	}	protected function handleScalar($scalar)	{		if( $scalar === true )		{			$response = 'true';		}		elseif( $scalar === false )		{			$response = 'false';		}				require_once "DataTable/Simple.php";		$dataTable = new Piwik_DataTable_Simple();		$dataTable->loadFromArray( array($scalar) );		return $this->getRenderedDataTable($dataTable);	}	protected function handleDataTable($datatable)	{		if($datatable instanceof Piwik_DataTable)		{			$this->applyDataTableGenericFilters($datatable);		}		elseif($datatable instanceof Piwik_DataTable_Array)		{			$tables = $datatable->getArray();			foreach($tables as $table)			{				$this->applyDataTableGenericFilters($table);			}		}				// if the flag disable_queued_filters is defined we skip the filters that were queued		// useful in some very rare cases but better to use this than a bad hack on the data returned...		if(Piwik_Common::getRequestVar('disable_queued_filters', 'false', 'string', $this->request) == 'false')		{			$datatable->applyQueuedFilters();		}							return $this->getRenderedDataTable($datatable);	}		protected function handleArray($array)	{		if($this->outputFormat == '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 serialize($array);			}		}		else		{			$dataTable = new Piwik_DataTable();			$dataTable->loadFromSimpleArray($array);			return $this->getRenderedDataTable($dataTable);		}	}		/**	 * 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)	{		if($dataTable instanceof Piwik_DataTable_Array )		{			$tables = $dataTable->getArray();			foreach($tables as $table)			{				$this->applyDataTableGenericFilters($table);			}			return;		}				// Generic filters		// PatternFileName => Parameter names to match to constructor parameters		/*		 * Order to apply the filters:		 * 1 - Filter that remove filtered rows		 * 2 - Filter that sort the remaining rows		 * 3 - Filter that keep only a subset of the results		 */		$genericFilters = self::getGenericFiltersInformation();				// if the flag disable_generic_filters is defined we skip the generic filters		if(Piwik_Common::getRequestVar('disable_generic_filters', 'false', 'string', $this->request) != 'false')		{			return;		}				foreach($genericFilters as $filterName => $parameters)		{			$filterParameters = array();			$exceptionRaised = false;						foreach($parameters as $name => $info)			{				// parameter type to cast to				$type = $info[0];								// default value if specified, when the parameter doesn't have a value				$defaultValue = null;				if(isset($info[1]))				{					$defaultValue = $info[1];				}								try {					$value = Piwik_Common::getRequestVar($name, $defaultValue, $type, $this->request);					settype($value, $type);					$filterParameters[] = $value;				}				catch(Exception $e)				{					$exceptionRaised = true;					break;				}			}						if(!$exceptionRaised)			{								// a generic filter class name must follow this pattern				$class = "Piwik_DataTable_Filter_".$filterName;								if($filterName == 'Limit')				{					$dataTable->setRowsCountBeforeLimitFilter();				}								// build the set of parameters for the filter									$filterParameters = array_merge(array($dataTable), $filterParameters);				// make a reflection object				$reflectionObj = new ReflectionClass($class);								// use Reflection to create a new instance, using the $args				$filter = $reflectionObj->newInstanceArgs($filterParameters); 			}		}	}}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?