<?php

/**
* @desc This report displays a overview of referrrer conversion.
*/

$reports["_CONVERSION_TRENDS"] = Array(
	"ClassName" => "ConversionTrends", 
	"Category" => "_PERFORMANCE",
	"canAggregate" => false, 
	"icon" => "images/icons/32x32/conversion_trends.png",
	"Options" => "daterangeField,profileselector,roadto,trafficsource,source,period,displaymode",
	"Filename" => "conversion_trends",
	"Distribution" => "Premium",
	"Order" => 3,
	"ReportVersion" => 1.0,
	"MinimumVersion" => 3.0,
	"EmailAlerts" => false,
	"Update" => false
);

class ConversionTrends extends Report {

	function Settings() {
		$this->DefaultDisplay = "barlinechart";
		$this->DisplayModes = "barlinechart,table";
		$this->displayReportButtons = false;
		$this->remove_outputmodes = array("all");
		$this->allowDateFormat = false;
		$this->columnDefinitions[] = array("Label" => _DATE);
		$this->columnDefinitions[] = array("Label" => _CONVERSION_RATE, "chart" => "bar");
		$this->columnDefinitions[] = array("Label" => _ROLLING_AVERAGE, "chart" => "line");
		$this->columnDefinitions[] = array("Label" => _TREND, "chart" => "line");		
		if(empty($this->displaymode)) { $this->displaymode = $this->DefaultDisplay; }
		if(empty($this->avgperiod)) { $this->avgperiod = 7; }
		$this->chartoptions = array("yAxis1label" => _CONVERSION_RATE, "yFormat" => ",.2f");
	}

	function DefineQuery() {
		global $qd, $db, $sqlst;
		
		# Define the chosen period / time unit
		if ($this->period == '_DAYS') {
			$qd = "FROM_UNIXTIME(timestamp, '%a, %m/%d/%Y')";
		} else if ($this->period == '_WEEKS') {
			$qd = "FROM_UNIXTIME(timestamp, '%x-W%v')";
		} else if ($this->period == '_MONTHS') {
			$qd = "FROM_UNIXTIME(timestamp, '%b %Y')";
		}
		
		if (!empty($this->source)) {
			# Get total unique visitors for time unit
			if ($this->sourcetype == "page") {
				$id = getID($this->source,'urls');
				$query  = "SELECT {$qd} AS timeunit, COUNT(DISTINCT visitorid) AS uvisitors FROM {$this->profile->tablename} AS a WHERE timestamp BETWEEN ". $db->quote($this->from) ." AND ". $db->quote($this->to) ." AND url='{$id}' GROUP BY timeunit ORDER BY timestamp"; 
			
			} else if ($this->sourcetype == "keyword") {
				$id = getID($this->source,'keyword'); 
				$query  = "SELECT {$qd} AS timeunit, COUNT(DISTINCT visitorid) AS uvisitors FROM {$this->profile->tablename} AS a WHERE timestamp BETWEEN ". $db->quote($this->from) ." AND ". $db->quote($this->to) ." AND keywords='{$id}' GROUP BY timeunit ORDER BY timestamp"; 
			
			} else if ($this->sourcetype == "referrer") {
				$id = getID($this->source,'referrers'); 
				$query  = "SELECT {$qd} AS timeunit, COUNT(DISTINCT visitorid) AS uvisitors FROM {$this->profile->tablename} AS a WHERE timestamp BETWEEN ". $db->quote($this->from) ." AND ". $db->quote($this->to) ." AND referrer='{$id}' GROUP BY timeunit ORDER BY timestamp"; 
			}
			# If we do not know the id of the source then return false
			if(empty($id)){ 
				return false;
			}
		} else {
			# Select the amount of unique visitors
			$query = "SELECT {$qd} AS timeunit, COUNT(DISTINCT visitorid) AS uvisitors FROM {$this->profile->tablename} WHERE timestamp BETWEEN ". $db->quote($this->from) ." AND ". $db->quote($this->to) ." GROUP BY timeunit ORDER BY timestamp";
		}		
		
		$query = subsetDataToSourceID($query);
		$this->applytrafficsource = false;
		return $query;
	}
	
	function GetReportData() {
		global $db, $qd;
		
		# Query the database with the query defined in DefineQuery function.
		$q = $this->DefineQuery();
		if(empty($q)){
			return [];
		}
		$query = $db->Execute($q);
		
		$merge = [];

		if(!empty($this->source)) {
			$this->addlabel = _SEARCH_FOR ." {$this->sourcetype}: {$this->source}";
			
			if ($this->sourcetype == "page") {
				$search_query = "url = ". getID($this->source,'urls') ." AND ";
			} else if ($this->sourcetype == "keyword") {
				$search_query = "keywords = ". getID($this->source,'keyword') ." AND ";
			} else if ($this->sourcetype == "referrer") {
				$search_query = "referrer = ". getID($this->source,'referrers') ." AND ";
			}
		} else {
			$search_query = "";
		}
		
		if (!empty($this->source)) {
			# If there is a source, we need to fetch the data set, filtered by that source, and store that data in a temporary table.
			@$db->Execute("DROP TABLE IF EXISTS {$this->profile->tablename}_temptable");
						
			$q = "SELECT visitorid, timestamp FROM {$this->profile->tablename} as a WHERE timestamp BETWEEN ". $db->quote($this->from) ." AND ". $db->quote($this->to) ." AND {$search_query} status = 200";
			$q = subsetDataToSourceID($q);

			$db->Execute("CREATE TEMPORARY TABLE {$this->profile->tablename}_temptable $q");

			# Prevent calls to multi-existing columns
			$qd = str_replace("timestamp", "c.timestamp", $qd);
			
			# Select amount of converted visitors
			$query2 = "SELECT {$qd} AS timeunit, COUNT(DISTINCT c.visitorid) AS users FROM {$this->profile->tablename}_temptable AS a, {$this->profile->tablename_conversions} AS c WHERE c.timestamp BETWEEN ". $db->quote($this->from) ." AND ". $db->quote($this->to) ." AND a.visitorid = c.visitorid  AND url = ". $db->quote(getID($this->roadto,"urls"))." AND a.timestamp < c.timestamp GROUP BY timeunit ORDER BY c.timestamp";
			
		} else {
			# Select amount of converted visitors
			$query2 = "SELECT {$qd} AS timeunit, COUNT(DISTINCT visitorid) AS users FROM {$this->profile->tablename_conversions} AS c WHERE timestamp BETWEEN ". $db->quote($this->from) ." AND ". $db->quote($this->to) ." AND url = ". $db->quote(getID($this->roadto,"urls")) ." GROUP BY timeunit ORDER BY timestamp";
			$query2 = subsetDataToSourceID($query2);
		}		
		
		$query2 = $db->Execute($query2);
		


		# Set the data array and do zero fill
		while ($data = $query->FetchRow()) {
			$merge[$data["timeunit"]][1] = $data["uvisitors"];
			$merge[$data["timeunit"]][2] = 0;
			$merge[$data["timeunit"]][3] = 0;
		}
		
		# Merge unique visitors with converted visitors, and calculate conversion rate
		while ($data = $query2->FetchRow()) {
			$merge[$data["timeunit"]][2] = $data["users"];
			if($merge[$data["timeunit"]][1] != 0) {
				$merge[$data["timeunit"]][3] = number_format((($data["users"] / $merge[$data["timeunit"]][1]) * 100), 2);
			}
		}
		
		return $merge;
	}
	
	# This function prepares the data so it can be plotted
	function ConvertData($data = []) {
		# There is no data; give a warning
		//dump($data);
		$n = count($data);
		if ($n == 0) {
			echoWarning("&nbsp;<P><h3>"._NO_DATA_FOUND_FOR." <font color=\"red\">{$this->source}</font></h3>"._NO_DATA_FOUND_TIPS."</body></html>","margin:10px;");
			return false;
		}
		
		# Start calculating trend line and rolling average
		$i = 1;
		while (list ($day, $row) = each ($data)) {
			$x[$i] = $i; # trend line for conversion rate

			$y[$i] = $row[3];

			# begin calculation
			$xy[$i] = $x[$i] * $row[3];

			$xsq[$i] = $x[$i] * $x[$i];

			$i++;
		}
		
		# $n has already been vetted to be <> 0, so we can divide by $n with impunity here
		$a_part = array_sum($xy) - ((array_sum($x) * array_sum($y)) / $n);

		# array_sum($x) isn't vetted, so we need to protect from a division by 0 here.
		$a = @($a_part / (array_sum($xsq) - (1 / $n) * (array_sum($x) * array_sum($x))));

		$b = (array_sum($y) / $n) - ($a * (array_sum($x) / $n));

		# add rolling average and plot point for trend
		reset($data);
		$ndays = count($data);
		$maxval = 0;
		$cstr = 0;
		
		$i = 0;
		while (list ($day, $row) = each ($data)) {
			while (list ($skey, $sval) = each ($row)) {
				switch ($skey) {
					# Case 3: Conversion Rate
					case 3:
						$regval[$i] = ($a * $x[($i + 1)]) + $b; # calculate every datapoint

						$cr[$i] = $sval;
						
						if ($maxval < $sval) {
							$maxval = $sval;
						}
						
						$dev = 0;
						
						if ($i < $this->avgperiod) {
							$avg = 0;
						} else {
							while ($this->avgperiod > $dev) {
								$cstr = $cstr + $cr[($i - $dev)];
								$dev++;
							}
							$avg = $cstr / $this->avgperiod;
						}
						$data[$day][4] = number_format($avg, 2);
						if ($maxval < $avg) {
							$maxval = $avg;
						}
						$cstr = 0;
					break;
				}
			}
			$i++;
		}
		
		$looptime = getmicrotime();
		
		reset($data);
		$maxval = 0;
		$i = 0;
		# Merge trend line and rolling average into stuff
		while (list ($day, $row) = each ($data)) {
			if ($maxval < $row[3]) {
				$maxval = $row[3];
			}
			if ($maxval < $row[4]) {
				$maxval = $row[4];
			}
			
			$graphdata[$i][0] = $day;
			$graphdata[$i][1] = $row[3];
			$graphdata[$i][2] = $row[4];
			
			if ($regval[($i)] < 0) {
				$graphdata[$i][3] = 0;
			} else {
				$graphdata[$i][3] = number_format($regval[($i)], 2);
			}
			$i++;
		}
		
		return $graphdata;
	}
	
	function DisplayReport() {
		

		$this->reportHeader();
		

		$this->current_plotting_graph = 1;
		
		# Fetch the basic data
		$data = $this->GetReportData();		
		
		# Convert the data to plottable data
		$data = $this->ConvertData($data);
		
		if($data == false){
			return false;
		}
		
		# If we want to view this report as a bar/line chart
		if($this->displaymode == 'barlinechart') {

			$this->MultiChart($data);
			
		} else {
			$this->sortTable = false;
			$this->displayTotalRow = false;
			$this->Table($data);
		}

		$this->current_plotting_graph = 2;
		echo "<div style='width: 100%;'>";
		$traffic_trends = new TrafficTrends();
		$traffic_trends->displayHeader = false;
		$traffic_trends->current_plotting_graph = $this->current_plotting_graph;
		$traffic_trends->DisplayReport();
		echo "</div>";
		
	}
	
	function DisplayCustomForm() {
		global $db;
		# Rolling Average Field
		echo "<div class='form-group'>";
			echo "<label for='avgperiod'>"._ROLLING_AVERAGE_PERIODS.": </label>";
			echo "<input class='form-control report_option_field' type=\"text\" size=\"2\" name=\"avgperiod\" id='avgperiod' value=". @$db->quote($this->avgperiod) . " />";
		echo "</div>";
	}
	
	function UpdateStats($from = '', $to = '',$print = 2) {
		# not using datafiles yet
		return false;		
	}
}
?>