datatable.directory codebase https://datatable.directory/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
datatable.directory/app/Tables/BaseExporter.php

158 lines
4.0 KiB

<?php
namespace App\Tables;
use App\Models\Row;
use App\Models\Table;
/**
* Table exporter base class
*/
abstract class BaseExporter
{
/**
* @var Table the table to export
*/
protected $table;
/**
* @var Column[] - parsed columns for the table
*/
protected $columns;
/**
* @var bool - true if user wants download; can e.g. change mime type to text/plain if not
*/
protected $wantDownload;
/**
* TODO export options from enabled columns, sorts, etc
*
* @param Table $table
*/
public function __construct(Table $table)
{
$this->table = $table;
$this->columns = Column::columnsFromJson($table->revision->columns);
}
protected function getHeaderComment($prefix = " ")
{
$table = $this->table;
$owner = $this->table->owner;
$s =
$prefix."Table \"$table->title\" by $owner->title\n".
$prefix."exported ".date('M n, Y \\a\\t G:i')."\n".
$prefix."\n".
$prefix."License: ". str_replace("\n", "\n$prefix", $table->license ?: 'CC0') ."\n".
$prefix."\n".
$prefix."Upstream: https://datatable.directory/$owner->handle/$table->name\n";
$s .=
$prefix."\n".
$prefix."Columns:\n";
foreach ($this->columns as $c) {
$s .= $prefix." - $c->name ... $c->title\n";
}
return $s;
}
/**
* @return string - mime type for the downloaded file
*/
protected abstract function getMimeType();
/**
* @return string - file extension for the downloaded file
*/
protected abstract function getFileExtension();
/**
* @return string - file name without extension, by default the table name
*/
protected function getFileBasename()
{
return $this->table->name;
}
/**
* Generate a response that appears as a file download to the browser
*
* @param bool $download - force download, otherwise the browser may show it in the window
*/
public function exportToBrowser($download = true)
{
$this->wantDownload = $download;
$mimeType = $this->getMimeType();
$filename = $this->getFileBasename() . '.' . $this->getFileExtension();
ob_end_clean();
// Redirect output to a client’s web browser
header("Content-Type: $mimeType; charset=utf-8");
if ($download) {
header("Content-Disposition: attachment;filename=\"$filename\"");
}
// Cache headers
header('Cache-Control: max-age=0');
// IE9
header('Cache-Control: max-age=1');
// Other IE headers
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); // Date in the past
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT'); // always modified
header('Cache-Control: cache, must-revalidate'); // HTTP/1.1
header('Pragma: no-cache'); // HTTP/1.0
$this->writeDocument();
exit;
}
/**
* Generator that produces PHP arrays for all rows, fetched from the DB in given chunks.
*
* @param int $chunkSize - size of one chunk
* @return \Generator|array[]
*/
protected function iterateRows($chunkSize = 1000)
{
$revision = $this->table->revision;
$count = $revision->rows()->count();
$start = 0;
$rq = $revision->rowsData($this->columns, false);
$columns = $this->columns;
// TODO raw query to allow selecting aggregates, column subsets, etc
if (count($columns)) $rq = $rq->sortByCol($columns[0]);
Row::disableCasts();
while ($start < $count) {
$rows = $rq->offset($start)->limit($chunkSize)->get()->toArray();
foreach ($rows as $row) {
unset($row['_row_pivot']);
yield $row;
}
$start += $chunkSize;
}
Row::enableCasts();
}
/**
* Write the document to stdout ('php://output')
*/
protected abstract function writeDocument();
}