Skip to content

Commit

Permalink
Fix issue zofe#430: DataGrid crashes when exporting big result set.
Browse files Browse the repository at this point in the history
  • Loading branch information
sroutier committed May 7, 2018
1 parent 206d224 commit a5f7309
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 36 deletions.
81 changes: 49 additions & 32 deletions src/DataGrid/DataGrid.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,18 +77,15 @@ public function build($view = '')
return $this->output;
}

public function buildCSV($file = '', $timestamp = '', $sanitize = true,$del = array())
public function buildCSV($file = '', $timestamp = '', $sanitize = true, $del = array(), $directToFile = false)
{
$this->limit = null;
parent::build();

$segments = \Request::segments();

$filename = ($file != '') ? basename($file, '.csv') : end($segments);
$filename = preg_replace('/[^0-9a-z\._-]/i', '',$filename);
$filename .= ($timestamp != "") ? date($timestamp).".csv" : ".csv";

$save = (bool) strpos($file,"/");
$save = (strpos($file,"/")===false) ? false : true;

//Delimiter
$delimiter = array();
Expand All @@ -113,35 +110,17 @@ public function buildCSV($file = '', $timestamp = '', $sanitize = true,$del = ar

fputs($handle, $delimiter['enclosure'].implode($delimiter['enclosure'].$delimiter['delimiter'].$delimiter['enclosure'], $this->headers) .$delimiter['enclosure'].$delimiter['line_ending']);

foreach ($this->data as $tablerow) {
$row = new Row($tablerow);

foreach ($this->columns as $column) {

if (in_array($column->name,array("_edit")))
continue;

$cell = new Cell($column->name);
$value = str_replace('"', '""',str_replace(PHP_EOL, '', strip_tags($this->getCellValue($column, $tablerow, $sanitize))));

// Excel for Mac is pretty stupid, and will break a cell containing \r, such as user input typed on a
// old Mac.
// On the other hand, PHP will not deal with the issue for use, see for instance:
// http://stackoverflow.com/questions/12498337/php-preg-replace-replacing-line-break
// We need to normalize \r and \r\n into \n, otherwise the CSV will break on Macs
$value = preg_replace('/\r\n|\n\r|\n|\r/', "\n", $value);
$this->limit = null;
if ($save && $directToFile) {
parent::build(function ($tablerow) use ($handle, $sanitize, $delimiter) {
$this->processTableRow($tablerow, $handle, $sanitize, $delimiter);
});
} else {
parent::build();

$cell->value($value);
$row->add($cell);
foreach ($this->data as $tablerow) {
$this->processTableRow($tablerow, $handle, $sanitize, $delimiter);
}

if (count($this->row_callable)) {
foreach ($this->row_callable as $callable) {
$callable($row);
}
}

fputs($handle, $delimiter['enclosure'] . implode($delimiter['enclosure'].$delimiter['delimiter'].$delimiter['enclosure'], $row->toArray()) . $delimiter['enclosure'].$delimiter['line_ending']);
}

fclose($handle);
Expand All @@ -154,6 +133,44 @@ public function buildCSV($file = '', $timestamp = '', $sanitize = true,$del = ar
}
}

/**
* @param $tablerow
* @param $handle
* @param $sanitize
* @param $delimiter
*/
public function processTableRow($tablerow, $handle, $sanitize, $delimiter)
{
$row = new Row($tablerow);

foreach ($this->columns as $column) {

if (in_array($column->name, array("_edit")))
continue;

$cell = new Cell($column->name);
$value = str_replace('"', '""', str_replace(PHP_EOL, '', strip_tags($this->getCellValue($column, $tablerow, $sanitize))));

// Excel for Mac is pretty stupid, and will break a cell containing \r, such as user input typed on a
// old Mac.
// On the other hand, PHP will not deal with the issue for use, see for instance:
// http://stackoverflow.com/questions/12498337/php-preg-replace-replacing-line-break
// We need to normalize \r and \r\n into \n, otherwise the CSV will break on Macs
$value = preg_replace('/\r\n|\n\r|\n|\r/', "\n", $value);

$cell->value($value);
$row->add($cell);
}

if (count($this->row_callable)) {
foreach ($this->row_callable as $callable) {
$callable($row);
}
}

fputs($handle, $delimiter['enclosure'] . implode($delimiter['enclosure'] . $delimiter['delimiter'] . $delimiter['enclosure'], $row->toArray()) . $delimiter['enclosure'] . $delimiter['line_ending']);
}

protected function getCellValue($column, $tablerow, $sanitize = true)
{
//blade
Expand Down
12 changes: 8 additions & 4 deletions src/DataSet.php
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ public function paginate($items)
return $this;
}

public function build()
public function build($rowproc = null)
{
if (is_string($this->source) && strpos(" ", $this->source) === false) {
//tablename
Expand Down Expand Up @@ -204,10 +204,14 @@ public function build()
$skip++;
continue;
}
//gather the rows to render.
//gather the rows to render
else {
$rows[$cnt] = $row;
$cnt++;
if (is_callable($rowproc)) {
$rowproc($row);
} else {
$rows[$cnt] = $row;
$cnt++;
}
}
// If limit is set and we are passed it, break out of loop.
if (isset($limit) && ($cnt > $limit)) {
Expand Down

0 comments on commit a5f7309

Please sign in to comment.