Merge pull request #6973 from steadlane/fix/csv-unescaped-values

Fix for badly escaped values in CSV export
This commit is contained in:
Daniel Hensby 2018-02-08 13:45:52 +00:00 committed by GitHub
commit 2a8d365aac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 44 additions and 18 deletions

View File

@ -124,12 +124,12 @@ class GridFieldExportButton implements GridField_HTMLProvider, GridField_ActionP
* Generate export fields for CSV. * Generate export fields for CSV.
* *
* @param GridField $gridField * @param GridField $gridField
* @return array * @return string
*/ */
public function generateExportFileData($gridField) { public function generateExportFileData($gridField) {
$separator = $this->csvSeparator; $separator = $this->getCsvSeparator();
$csvColumns = $this->getExportColumnsForGridField($gridField); $csvColumns = $this->getExportColumnsForGridField($gridField);
$fileData = ''; $fileData = array();
if($this->csvHasHeader) { if($this->csvHasHeader) {
$headers = array(); $headers = array();
@ -145,8 +145,7 @@ class GridFieldExportButton implements GridField_HTMLProvider, GridField_ActionP
} }
} }
$fileData .= "\"" . implode("\"{$separator}\"", array_values($headers)) . "\""; $fileData[] = $headers;
$fileData .= "\n";
} }
//Remove GridFieldPaginator as we're going to export the entire list. //Remove GridFieldPaginator as we're going to export the entire list.
@ -190,11 +189,10 @@ class GridFieldExportButton implements GridField_HTMLProvider, GridField_ActionP
) { ) {
$value = "\t" . $value; $value = "\t" . $value;
} }
$columnData[] = '"' . str_replace('"', '""', $value) . '"'; $columnData[] = $value;
} }
$fileData .= implode($separator, $columnData); $fileData[] = $columnData;
$fileData .= "\n";
} }
if($item->hasMethod('destroy')) { if($item->hasMethod('destroy')) {
@ -202,7 +200,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, $separator);
}
rewind($csv);
return stream_get_contents($csv);
} }
/** /**

View File

@ -48,7 +48,9 @@ class GridFieldExportButtonTest extends SapphireTest {
$button->setExportColumns(array('Name' => 'My Name')); $button->setExportColumns(array('Name' => 'My Name'));
$this->assertEquals( $this->assertEquals(
"\"My Name\"\n\"Test\"\n\"Test2\"\n", '"My Name"'."\n".
'Test'."\n".
'Test2'."\n",
$button->generateExportFileData($this->gridField) $button->generateExportFileData($this->gridField)
); );
} }
@ -64,7 +66,7 @@ class GridFieldExportButtonTest extends SapphireTest {
$button->setExportColumns(array('Name' => 'My Name')); $button->setExportColumns(array('Name' => 'My Name'));
$this->assertEquals( $this->assertEquals(
"\"My Name\"\n\"\t=SUM(1, 2)\"\n\"Test\"\n\"Test2\"\n", "\"My Name\"\n\"\t=SUM(1, 2)\"\nTest\nTest2\n",
$button->generateExportFileData($this->gridField) $button->generateExportFileData($this->gridField)
); );
} }
@ -79,7 +81,9 @@ class GridFieldExportButtonTest extends SapphireTest {
)); ));
$this->assertEquals( $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) $button->generateExportFileData($this->gridField)
); );
} }
@ -92,7 +96,9 @@ class GridFieldExportButtonTest extends SapphireTest {
)); ));
$this->assertEquals( $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) $button->generateExportFileData($this->gridField)
); );
} }
@ -106,7 +112,8 @@ class GridFieldExportButtonTest extends SapphireTest {
$button->setCsvHasHeader(false); $button->setCsvHasHeader(false);
$this->assertEquals( $this->assertEquals(
"\"Test\",\"City\"\n\"Test2\",\"City2\"\n", 'Test,City'."\n".
'Test2,"Quoted ""City"" 2"'."\n",
$button->generateExportFileData($this->gridField) $button->generateExportFileData($this->gridField)
); );
} }
@ -126,8 +133,23 @@ class GridFieldExportButtonTest extends SapphireTest {
$this->gridField->setList($arrayList); $this->gridField->setList($arrayList);
$this->assertEquals( $this->assertEquals(
"\"ID\"\n\"1\"\n\"2\"\n\"3\"\n\"4\"\n\"5\"\n\"6\"\n\"7\"\n\"8\"\n" "ID\n".
."\"9\"\n\"10\"\n\"11\"\n\"12\"\n\"13\"\n\"14\"\n\"15\"\n\"16\"\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) $button->generateExportFileData($this->gridField)
); );
} }
@ -139,7 +161,7 @@ class GridFieldExportButtonTest extends SapphireTest {
)); ));
$this->assertEquals( $this->assertEquals(
"\"Rugby Team Number\"\n\"2\"\n\"0\"\n", "\"Rugby Team Number\"\n2\n0\n",
$button->generateExportFileData($this->gridField) $button->generateExportFileData($this->gridField)
); );
} }

View File

@ -5,7 +5,7 @@ GridFieldExportButtonTest_Team:
RugbyTeamNumber: 2 RugbyTeamNumber: 2
test-team-2: test-team-2:
Name: Test2 Name: Test2
City: City2 City: 'Quoted "City" 2'
RugbyTeamNumber: 0 RugbyTeamNumber: 0
GridFieldExportButtonTest_NoView: GridFieldExportButtonTest_NoView: