<?php
//vim: ts=2 sw=2
class DataFormatter {
function __construct() {
$this->fp = null;
$this->file_path = null;
$this->save_to_local = false;
$this->zip_threshold = 100; # when file's size > 100KB, gzip it
$this->row_count = 0;
$this->append_row_count = false;
}
function __destruct() {
if (!is_null($this->fp)) {
fclose($this->fp);
$this->fp = null;
}
}
public function isEmpty() {
return $this->row_count == 0;
}
public function saveToLocal($file_name) {
$this->save_to_local = $file_name;
}
public function setZipThreshold($zip_threshold) {
$this->zip_threshold = $zip_threshold;
}
public function setAppendRowCount($append) {
$this->append_row_count = $append;
}
public function writeHeader($download_file_name) {}
public function writeRow($row) {
$this->row_count += 1;
}
public function writeFooter() {}
public function done() {
if (empty($this->save_to_local) || is_null($this->file_path))
return;
$temp_file_path = $this->file_path;
if (filesize($this->file_path) >= $this->zip_threshold*1024) {
fclose($this->fp);
$this->fp = null;
$cmd = "/bin/gzip -f " . $this->file_path;
exec(escapeshellcmd($cmd))
$temp_file_path = $this->file_path . '.gz';
}
if ($this->append_row_count)
//NOTE: the column titles will be the first, here we need the number
//of data rows, so need to substract the 1 row
echo $temp_file_path . ',' . max(0, $this->row_count-1);
else
echo $temp_file_path;
return;
}
public function localFilePath($extname) {
$parts = explode(DIRECTORY_SEPARATOR, __FILE__);
array_pop($parts);
array_pop($parts);
array_push($parts, "user_data");
array_push($parts, "exported_data");
$dir = implode(DIRECTORY_SEPARATOR, $parts);
if (!file_exists($dir))
mkdir($dir, 0777, true);
$path = $dir . DIRECTORY_SEPARATOR . $this->save_to_local . $extname;
return $path;
}
protected function genDownloadFileName($basename, $extname) {
if ($basename == "1" || $basename == "true") {
$now = new DateTime("now", new DateTimeZone("UTC"));
return "data_" . $now->format("YmdHi") . $extname;
} else {
return $basename . $extname;
}
}
};
class HtmlDataFormatter extends DataFormatter {
function __construct() {
parent::__construct();
$this->is_first = true;
}
public function writeHeader($download_file_name) {
$path = null;
if (!empty($this->save_to_local))
{
$this->file_path = $this->localFilePath(".html");
$path = $this->file_path;
}
else
{
if (!empty($download_file_name))
{
header('Content-Type: text/html');
$filename = $this->genDownloadFileName($download_file_name, '.html');
header('Content-Disposition: attachment; filename="' . $filename . '"')
}
$path = 'php://output';
}
$this->fp = fopen($path, 'w');
fwrite($this->fp, '<table style="border-spacing: 5px;">');
}
public function writeRow($row) {
parent::writeRow($row);
fwrite($this->fp, '<tr>');
$col_tag = 'td';
if ($this->is_first) {
$col_tag = 'th';
$this->is_first = false;
}
foreach($row as $col) {
fwrite($this->fp, '<' . $col_tag . '>' . $col . '</' . $col_tag . '>');
}
fwrite($this->fp, '</tr>');
}
public function writeFooter() {
fwrite($this->fp, '</table>');
}
};
class JsonDataFormatter extends DataFormatter {
function __construct() {
parent::__construct();
$this->is_first = true;
$this->row_written = false;
}
public function writeHeader($download_file_name) {
$path = null;
if (!empty($this->save_to_local))
{
$this->file_path = $this->localFilePath(".json");
$path = $this->file_path;
}
else
{
if (!empty($download_file_name)) {
header('Content-Type: application/json');
$filename = $this->genDownloadFileName($download_file_name, '.json');
header('Content-Disposition: attachment; filename="' . $filename . '"')
}
$path = 'php://output';
}
$this->fp = fopen($path, 'w');
fwrite($this->fp, '{"data":{');
}
public function writeRow($row) {
parent::writeRow($row);
if ($this->is_first)
fwrite($this->fp, '"columns":');
$values = array();
foreach($row as $col) {
// if (is_string($col))
// $col = addcslashes($col,"\\\"\n\r");
$values[] = '"' . $col . '"';
}
if ($this->row_written)
fwrite($this->fp, ',');
fwrite($this->fp, '['.implode(',', $values).']');
if ($this->is_first) {
fwrite($this->fp, ',"rows":[');
$this->is_first = false;
} else {
$this->row_written = true;
}
}
public function writeFooter() {
if (!$this->isEmpty())
fwrite($this->fp, ']');
fwrite($this->fp, '}}');
}
};
class CsvDataFormatter extends DataFormatter {
public function writeHeader($download_file_name) {
$path = null;
if (!empty($this->save_to_local))
{
$this->file_path = $this->localFilePath(".csv");
$path = $this->file_path;
}
else
{
if (!empty($download_file_name)) {
header('Content-Type: text/csv');
$filename = $this->genDownloadFileName($download_file_name, '.csv');
header('Content-Disposition: attachment; filename="' . $filename . '"')
}
$path = 'php://output';
}
$this->fp = fopen($path, 'w');
}
public function writeRow($row) {
parent::writeRow($row);
fputcsv($this->fp, $row);
}
};
function build_formatter($format='html') {
if (empty($format))
$format = 'html';
if ($format == 'csv')
return new CsvDataFormatter();
elseif ($format == 'html')
return new HtmlDataFormatter();
elseif ($format == 'json')
return new JsonDataFormatter();
else
return null;
};
?>