From dd0c85c9cf469b7f805479f3dbd19e6dc2ea1163 Mon Sep 17 00:00:00 2001 From: JorisDebonnet Date: Mon, 27 Jul 2015 03:38:11 +0200 Subject: [PATCH] Use fputcsv in GridFieldExportButton --- forms/gridfield/GridFieldExportButton.php | 42 ++++++++++++++----- .../gridfield/GridFieldExportButtonTest.php | 34 ++++++++++++--- .../gridfield/GridFieldExportButtonTest.yml | 2 +- 3 files changed, 60 insertions(+), 18 deletions(-) diff --git a/forms/gridfield/GridFieldExportButton.php b/forms/gridfield/GridFieldExportButton.php index 150a9af3e..8e3f76f9a 100644 --- a/forms/gridfield/GridFieldExportButton.php +++ b/forms/gridfield/GridFieldExportButton.php @@ -20,6 +20,11 @@ class GridFieldExportButton implements GridField_HTMLProvider, GridField_ActionP */ protected $csvSeparator = ","; + /** + * @var string + */ + protected $csvEnclosure = '"'; + /** * @var boolean */ @@ -98,13 +103,10 @@ class GridFieldExportButton implements GridField_HTMLProvider, GridField_ActionP * @return array */ public function generateExportFileData($gridField) { - $separator = $this->csvSeparator; $csvColumns = ($this->exportColumns) ? $this->exportColumns : singleton($gridField->getModelClass())->summaryFields(); - $fileData = ''; - $columnData = array(); - $fieldItems = new ArrayList(); + $fileData = array(); if($this->csvHasHeader) { $headers = array(); @@ -115,8 +117,7 @@ class GridFieldExportButton implements GridField_HTMLProvider, GridField_ActionP $headers[] = (!is_string($columnHeader) && is_callable($columnHeader)) ? $columnSource : $columnHeader; } - $fileData .= "\"" . implode("\"{$separator}\"", array_values($headers)) . "\""; - $fileData .= "\n"; + $fileData[] = $headers; } //Remove GridFieldPaginator as we're going to export the entire list. @@ -152,12 +153,10 @@ class GridFieldExportButton implements GridField_HTMLProvider, GridField_ActionP } } - $value = str_replace(array("\r", "\n"), "\n", $value); - $columnData[] = '"' . str_replace('"', '""', $value) . '"'; + $columnData[] = $value; } - $fileData .= implode($separator, $columnData); - $fileData .= "\n"; + $fileData[] = $columnData; } if($item->hasMethod('destroy')) { @@ -165,7 +164,13 @@ class GridFieldExportButton implements GridField_HTMLProvider, GridField_ActionP } } - return $fileData; + // Convert the $fileData array into csv by capturing fputcsv's output + $csv = fopen('php://temp', 'r+'); + foreach($fileData as $line) { + fputcsv($csv, $line, $this->csvSeparator, $this->csvEnclosure); + } + rewind($csv); + return stream_get_contents($csv); } /** @@ -198,6 +203,21 @@ class GridFieldExportButton implements GridField_HTMLProvider, GridField_ActionP return $this; } + /** + * @return string + */ + public function getCsvEnclosure() { + return $this->csvEnclosure; + } + + /** + * @param string + */ + public function setCsvEnclosure($enclosure) { + $this->csvEnclosure = $enclosure; + return $this; + } + /** * @return boolean */ diff --git a/tests/forms/gridfield/GridFieldExportButtonTest.php b/tests/forms/gridfield/GridFieldExportButtonTest.php index 0de0a41ce..c7168c57b 100644 --- a/tests/forms/gridfield/GridFieldExportButtonTest.php +++ b/tests/forms/gridfield/GridFieldExportButtonTest.php @@ -48,7 +48,9 @@ class GridFieldExportButtonTest extends SapphireTest { $button->setExportColumns(array('Name' => 'My Name')); $this->assertEquals( - "\"My Name\"\n\"Test\"\n\"Test2\"\n", + '"My Name"'."\n". + 'Test'."\n". + 'Test2'."\n", $button->generateExportFileData($this->gridField) ); } @@ -63,7 +65,9 @@ class GridFieldExportButtonTest extends SapphireTest { )); $this->assertEquals( - "\"Name\",\"City\"\n\"Test\",\"City city\"\n\"Test2\",\"City2 city\"\n", + 'Name,City'."\n". + 'Test,"City city"'."\n". + 'Test2,"Quoted ""City"" 2 city"'."\n", $button->generateExportFileData($this->gridField) ); } @@ -76,7 +80,9 @@ class GridFieldExportButtonTest extends SapphireTest { )); $this->assertEquals( - "\"Name\",\"strtolower\"\n\"Test\",\"City\"\n\"Test2\",\"City2\"\n", + 'Name,strtolower'."\n". + 'Test,City'."\n". + 'Test2,"Quoted ""City"" 2"'."\n", $button->generateExportFileData($this->gridField) ); } @@ -90,7 +96,8 @@ class GridFieldExportButtonTest extends SapphireTest { $button->setCsvHasHeader(false); $this->assertEquals( - "\"Test\",\"City\"\n\"Test2\",\"City2\"\n", + 'Test,City'."\n". + 'Test2,"Quoted ""City"" 2"'."\n", $button->generateExportFileData($this->gridField) ); } @@ -110,8 +117,23 @@ class GridFieldExportButtonTest extends SapphireTest { $this->gridField->setList($arrayList); $this->assertEquals( - "\"ID\"\n\"1\"\n\"2\"\n\"3\"\n\"4\"\n\"5\"\n\"6\"\n\"7\"\n\"8\"\n" - ."\"9\"\n\"10\"\n\"11\"\n\"12\"\n\"13\"\n\"14\"\n\"15\"\n\"16\"\n", + "ID\n". + "1\n". + "2\n". + "3\n". + "4\n". + "5\n". + "6\n". + "7\n". + "8\n". + "9\n". + "10\n". + "11\n". + "12\n". + "13\n". + "14\n". + "15\n". + "16\n", $button->generateExportFileData($this->gridField) ); } diff --git a/tests/forms/gridfield/GridFieldExportButtonTest.yml b/tests/forms/gridfield/GridFieldExportButtonTest.yml index a001b4b96..59fde120f 100644 --- a/tests/forms/gridfield/GridFieldExportButtonTest.yml +++ b/tests/forms/gridfield/GridFieldExportButtonTest.yml @@ -4,7 +4,7 @@ GridFieldExportButtonTest_Team: City: City test-team-2: Name: Test2 - City: City2 + City: 'Quoted "City" 2' GridFieldExportButtonTest_NoView: item1: