diff --git a/src/Components/Export.php b/src/Components/Export.php index 4be379b7..722e1ec6 100644 --- a/src/Components/Export.php +++ b/src/Components/Export.php @@ -23,6 +23,8 @@ * @author Petr Bugyík * * @property int $fetchLimit + * @property-write array $header + * @property-write callable $customData */ class Export extends Component implements \Nette\Application\IResponse { @@ -31,6 +33,12 @@ class Export extends Component implements \Nette\Application\IResponse /** @var int */ protected $fetchLimit = 100000; + /** @var array */ + protected $header = array(); + + /** @var callable */ + protected $customData; + /** * @param Grid $grid * @param string $label @@ -58,10 +66,14 @@ protected function printCsv() print implode(',', $row) . "\n"; }; - $header = array(); $columns = $this->grid[Column::ID]->getComponents(); - foreach ($columns as $column) { - $header[] = $escape($column->getLabel()); + + $header = array(); + $headerItems = $this->header ? $this->header : $columns; + foreach ($headerItems as $column) { + $header[] = $this->header + ? $escape($column) + : $escape($column->getLabel()); } $print($header); @@ -70,13 +82,21 @@ protected function printCsv() $iterations = ceil($datasource->getCount() / $this->fetchLimit); for ($i = 0; $i < $iterations; $i++) { $datasource->limit($i * $this->fetchLimit, $this->fetchLimit); - $data = $datasource->getData(); + $data = $this->customData + ? call_user_func_array($this->customData, [$datasource]) + : $datasource->getData(); - foreach ($data as $item) { + foreach ($data as $items) { $row = array(); + $columns = $this->customData + ? $items + : $columns; + foreach ($columns as $column) { - $row[] = $escape($column->renderExport($item)); + $row[] = $this->customData + ? $escape($column) + : $escape($column->renderExport($items)); } $print($row); @@ -103,6 +123,29 @@ public function getFetchLimit() return $this->fetchLimit; } + /** + * Sets a custom header of result CSV file (list of field names). + * @param array $header + * @return \Grido\Components\Export + */ + public function setHeader(array $header) + { + $this->header = $header; + return $this; + } + + /** + * Sets a callback to modify output data. This callback must return a list of items. (array) function($datasource) + * DEBUG? You probably need to comment lines started with $httpResponse->setHeader in Grido\Components\Export.php + * @param callable $callback + * @return \Grido\Components\Export + */ + public function setCustomData($callback) + { + $this->customData = $callback; + return $this; + } + /** * @internal */ diff --git a/tests/Components/Export.phpt b/tests/Components/Export.phpt index 5c780bf7..62512bd0 100644 --- a/tests/Components/Export.phpt +++ b/tests/Components/Export.phpt @@ -118,6 +118,46 @@ class ExportTest extends \Tester\TestCase 'Content-Disposition' => "attachment; filename=\"$label.csv\"", ), Response::$headers); } + + function testCustomData() + { + Helper::grid(function(Grid $grid) { + $grid->setModel(new ArraySource(array( + array('firstname' => 'Satu', 'surname' => 'Tukio', 'card' => 'Visa'), + array('firstname' => 'Ronald', 'surname' => 'Olivo', 'card' => 'MasterCard'), + array('firstname' => 'Feorie', 'surname' => 'Hamid', 'card' => 'MasterCard'), + array('firstname' => 'Hyiab', 'surname' => 'Haylom', 'card' => 'MasterCard'), + array('firstname' => 'Ambessa', 'surname' => 'Ali', 'card' => 'Visa'), + array('firstname' => 'Mateo', 'surname' => 'Topić', 'card' => "Příliš; žlouťoucký, \"kůň\" \n ďábelsky \tpěl 'ódy"), + ))); + + $grid->addColumnText('firstname', 'Name') + ->setSortable(); + + $grid->setExport() + ->setHeader(array('"Jméno"', "Příjmení\t", "Karta\n", 'Jméno,Příjmení')) + ->setCustomData(function(ArraySource $source) { + $data = $source->getData(); + $outData = array(); + foreach ($data as $item) { + $outData[] = [ + $item['firstname'], + $item['surname'], + $item['card'], + $item['firstname'] . ',' .$item['surname'], + ]; + } + return $outData; + }); + }); + + $params = array('do' => 'grid-export-export'); + + ob_start(); + Helper::request($params)->send(mock('\Nette\Http\IRequest'), new Response); + $output = ob_get_clean(); + Assert::same(file_get_contents(__DIR__ . '/files/Export.custom.expect'), $output); + } } run(__FILE__); diff --git a/tests/Components/files/Export.custom.expect b/tests/Components/files/Export.custom.expect new file mode 100644 index 00000000..a7a77548 --- /dev/null +++ b/tests/Components/files/Export.custom.expect @@ -0,0 +1,9 @@ +"""Jméno""","Příjmení ","Karta +","Jméno,Příjmení" +Satu,Tukio,Visa,"Satu,Tukio" +Ronald,Olivo,MasterCard,"Ronald,Olivo" +Feorie,Hamid,MasterCard,"Feorie,Hamid" +Hyiab,Haylom,MasterCard,"Hyiab,Haylom" +Ambessa,Ali,Visa,"Ambessa,Ali" +Mateo,Topić,"Příliš; žlouťoucký, ""kůň"" + ďábelsky pěl 'ódy","Mateo,Topić" diff --git a/tests/Components/files/Export.expect b/tests/Components/files/Export.expect index b8f72ea2..e3837bc1 100644 Binary files a/tests/Components/files/Export.expect and b/tests/Components/files/Export.expect differ