<?php

/*
	Googlyzer
	Contact: Bill Edgar (bill.edgar@oaktondata.com)
	http://www.oaktondata.com/googlyzer
	
	Copyright (c) 2011-2012, Oakton Data LLC
	All rights reserved.

	Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
	    
	    * Redistributions of source code must retain the above copyright
	      notice, this list of conditions and the following disclaimer.
	    * Redistributions in binary form must reproduce the above copyright
	      notice, this list of conditions and the following disclaimer in the
	      documentation and/or other materials provided with the distribution.
	    * Neither the name of the Oakton Data LLC nor the
	      names of its contributors may be used to endorse or promote products
	      derived from this software without specific prior written permission.

	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
	ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
	WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
	DISCLAIMED. IN NO EVENT SHALL Oakton Data LLC BE LIABLE FOR ANY
	DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
	(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
	LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
	ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
	(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
	SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
	
	This is the googlyzer_DataFeed PHP class file.
	
 */

if ( !class_exists( 'googlyzer_DataFeed' ) ) {

	/** googlyzer_DataFeed class
	 *
	 * PHP class for processing data feed from Google Analytics using curl.
	 * @author wmsedgar
	 *
	 */
	class googlyzer_DataFeed extends googlyzer_GoogleFeed {
		/* public variables */

		/* private variables */
		
		/*
		 * private methods
		 */
		
		/**
		 *
		 * helper method to load aggregates info from DOM XML source
		 *
		 * @param googlyzer_aggregateObj $aggregates
		 * @param googlyzer_AnalyticsDataObj $dataObj
		 * @return googlyzer_AnalyticsDataObj $dataObj
		 */
		private function loadAggregates( $aggregates, $dataObj ) {
			foreach ( $aggregates as $aggregatesElement ) {
				foreach ( $aggregatesElement->childNodes as $item ) {
					$name = $item->getAttribute( 'name' );
					$type = $item->getAttribute( 'type' );
					$value = $item->getAttribute( 'value' );
					$dataObj->addAggregate( array(
						'name' =>				$name,
						'type' =>				$type,
						'value' =>				$value
					) );
				}
			}
			return $dataObj;
		}
		
		/**
		 *
		 * helper method to load data source info from DOM XML source
		 *
		 * @param googlyzer_dataSourceObj $dataSources
		 * @param googlyzer_AnalyticsDataObj $dataObj
		 * @return googlyzer_AnalyticsDataObj $dataObj
		 */
		private function loadDataSources( $dataSources, $dataObj ) {
			foreach ( $dataSources as $dataSourceElement ) {
				// grab element values first
				$tableIdNode = $dataSourceElement->getElementsByTagName( 'tableId' );
				if ( $tableIdNode->length !== 0 ) {
					$tableId = $tableIdNode->item( 0 )->nodeValue;
				}
				$tableNameNode =  $dataSourceElement->getElementsByTagName( 'tableName' );
				if ( $tableNameNode->length !== 0 ) {
					$tableName = $tableNameNode->item( 0 )->nodeValue;
				}
				// loop for property items
				foreach ( $dataSourceElement->getElementsByTagName( 'property' ) as $property ) {
					$name = $property->getAttribute( 'name' );
					switch ( $name ) {
						case 'ga:profileId':
							$profileId = $property->getAttribute( 'value' );
							break;
						case 'ga:webPropertyId':
							$webPropertyId = $property->getAttribute( 'value' );
							break;
						case 'ga:accountName':
							$accountName = $property->getAttribute( 'value' );
							break;
					}
				}
				// record data source info in data object
				$dataObj->addDataSource( array(
					'accountName' =>			$accountName,
					'profileId' =>				$profileId,
					'tableId' =>				$tableId,
					'tableName' =>				$tableName,
					'webPropertyId' =>			$webPropertyId
					) );
			}
			return $dataObj;
		}
		
		/**
		 *
		 * method to grab DOM elements from XML and load into data object.
		 *
		 * @param DOMDocument $DOM
		 * @param googlyzer_AnalyticsDataObj $dataObj
		 * @return googlyzer_AnalyticsDataObj $dataObj
		 */
		private function loadDOMElements( $DOM, $dataObj ) {
			$aggregates = $dataSources = array();
			// retrieve DOM elements and load into data object
			$elementsArray = array( 'aggregates', 'containsSampleData', 'dataSource', 'endDate', 'startDate',
				'startIndex', 'totalResults' );
			foreach ( $elementsArray as $elementName ) {
				$element = $DOM->getElementsByTagName( $elementName );
				if ( $element->length != 0 ) {
					switch ( $elementName ) {
						case 'aggregates':
							// load aggregate data
							$dataObj = $this->loadAggregates( $element, $dataObj );
							break;
						case 'dataSource':
							// load data sources
							$dataObj = $this->loadDataSources( $element, $dataObj );
							break;
						default:
							$dataObj->setProperties( array( $elementName => $element->item( 0 )->nodeValue ) );
							break;
					}
				}
			}
			// return entries
			return $dataObj;
		}
		
		/**
		 * 
		 * private method for setting request options
		 * 
		 * @param array $args
		 */
		private function setRequestDefaults( $args ) {
			// set up default options array
			$defaults = array(
				'sort' =>			'',
				'filters' =>		'', // optional results filter format is ga:name operator expression - ex. ga:browser%3D~%5EFirefox
				'segment' =>		'', // optional numeric id of default or custom advanced segment - ex. segment=gaid::10
				'start_index' =>	'1', // starting index for feeds is 1, not 0
				'max_results' =>	'1000', // default maximum is 1000
				'version' =>		'2', // optional, versions are 1 or 2, used for debugging
				'prettyPrint' =>	'false' // add extra whitespace to XML to make it more readable, default is false
			);
			// loop through default keys
			foreach ( $defaults as $key => $value ) {
				// check for missing keys or empty values
				if ( !array_key_exists( $key, $args ) || empty( $args[$key] ) ) {
					// set default
					$args[$key] = $value;
				}
			}
			return $args;
		}
		
		/* 
		 * public methods
		 */
		
		public function buildPostRequest( $args ) {
			// first set defaults, if necessary
			$args = $this->setRequestDefaults( $args );
			// then extract params
			extract( $args );			
			$sort = googlyzer_Utilities::setSortOrder( $sort, $sort_column );
			$this->post_request = 
				'ids=' . urlencode( $id ) .
				'&dimensions=' . urlencode( implode( ',', $dimensions ) ) .
				'&metrics=' . urlencode( implode( ',', $metrics ) ) .
				'&sort=' . urlencode( $sort ) .
				'&filters=' . urlencode( $filters ) .
				'&segment=' . urlencode( $segment ) .
				'&start-date=' . urlencode( $start ) .
				'&end-date=' . urlencode( $end ) .
				'&start-index=' . urlencode( $start_index ) .
				'&max-results=' . urlencode( $max_results ) .
				'&v=' . urlencode( $version ) .
				'&prettyprint=' . urlencode( $prettyPrint );
		}
		
		public function handleFeed() {
			// create data object
			$dataObj = new googlyzer_AnalyticsDataObj();
			// create XML DOM
			$dataDOM = new DOMDocument();
			$dataDOM->loadXML( $this->curl_response );
			// load and process DOM elements
			$dataObj = $this->loadDOMElements( $dataDOM, $dataObj );
			// grab entries
			$dataEntries = $dataDOM->getElementsByTagName( 'entry' );
			// loop for data entries
			$entryNumber = 0;
			foreach ( $dataEntries as $entry ) {
				$dataObj->addEntry( $entryNumber );
				// record dimension names and values
				foreach( $entry->getElementsByTagName( 'dimension' ) as $dimension ) {
					$dataObj->addDimension( $dimension->getAttribute( 'name' ), $entryNumber );
					$dataObj->pushDimensionVal( $dimension->getAttribute( 'name' ), $dimension->getAttribute( 'value' ), $entryNumber );
				}
				// record metric names and values
				foreach( $entry->getElementsByTagName( 'metric' ) as $metric ) {
					$dataObj->addMetric( $metric->getAttribute( 'name' ),  $metric->getAttribute( 'type' ), $entryNumber );
					$dataObj->pushMetricVal( $metric->getAttribute( 'name' ), $metric->getAttribute( 'value' ), $entryNumber );
				}
				$entryNumber++;
			}
			return $dataObj;
		}
		
	} // end class googlyzer_DataFeed
	
} // end if class does not exist