Skip to content

Commit d3aeb51

Browse files
authored
Merge pull request #85 from otoso/master
Add BOM handling for all platforms
2 parents e3d1592 + 8e3b67f commit d3aeb51

2 files changed

Lines changed: 54 additions & 3 deletions

File tree

src/View/CsvView.php

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,13 @@ class CsvView extends View
9999
*/
100100
const EXTENSION_MBSTRING = 'mbstring';
101101

102+
/**
103+
* List of bom signs for encodings.
104+
*
105+
* @var array
106+
*/
107+
protected $bomMap;
108+
102109
/**
103110
* List of special view vars.
104111
*
@@ -135,6 +142,14 @@ public function __construct(
135142
EventManager $eventManager = null,
136143
array $viewOptions = []
137144
) {
145+
$this->bomMap = [
146+
'UTF-32BE' => chr(0x00) . chr(0x00) . chr(0xFE) . chr(0xFF),
147+
'UTF-32LE' => chr(0xFF) . chr(0xFE) . chr(0x00) . chr(0x00),
148+
'UTF-16BE' => chr(0xFE) . chr(0xFF),
149+
'UTF-16LE' => chr(0xFF) . chr(0xFE),
150+
'UTF-8' => chr(0xEF) . chr(0xBB) . chr(0xBF),
151+
];
152+
138153
parent::__construct($request, $response, $eventManager, $viewOptions);
139154

140155
if ($response && $response instanceof Response) {
@@ -388,9 +403,6 @@ protected function _generateRow($row = null)
388403
if ($fp === false) {
389404
$fp = fopen('php://temp', 'r+');
390405

391-
if ($this->viewVars['_bom']) {
392-
fwrite($fp, chr(0xEF) . chr(0xBB) . chr(0xBF));
393-
}
394406
if ($this->viewVars['_setSeparator']) {
395407
fwrite($fp, "sep=" . $this->viewVars['_delimiter'] . "\n");
396408
}
@@ -445,6 +457,24 @@ protected function _generateRow($row = null)
445457
}
446458
}
447459

460+
//bom must be added after encoding
461+
if ($this->viewVars['_bom']) {
462+
$csv = $this->getBom($this->viewVars['_csvEncoding']) . $csv;
463+
}
464+
448465
return $csv;
449466
}
467+
468+
/**
469+
* Returns the BOM for the encoding given.
470+
*
471+
* @param string $csvEncoding The encoding you want the BOM for
472+
* @return string
473+
*/
474+
protected function getBom($csvEncoding)
475+
{
476+
$csvEncoding = strtoupper($csvEncoding);
477+
478+
return isset($this->bomMap[$csvEncoding]) ? $this->bomMap[$csvEncoding] : '';
479+
}
450480
}

tests/TestCase/View/CsvViewTest.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,27 @@ public function testRenderWithoutView()
4141
$this->assertSame('text/csv', $this->response->getType());
4242
}
4343

44+
/**
45+
* testBom method
46+
*
47+
* @return void
48+
*/
49+
public function testBom()
50+
{
51+
if (!extension_loaded('mbstring')) {
52+
$this->markTestSkipped(
53+
'The mbstring extension is not available.'
54+
);
55+
}
56+
57+
$data = [['test']];
58+
$this->view->set(['data' => $data, '_serialize' => 'data', '_bom' => true, '_csvEncoding' => 'UTF-16LE']);
59+
$output = $this->view->render(false);
60+
61+
$expected = chr(0xFF) . chr(0xFE) . mb_convert_encoding('test' . PHP_EOL, 'UTF-16LE', 'UTF-8');
62+
$this->assertSame($expected, $output);
63+
}
64+
4465
/**
4566
* Test render with an array in _serialize
4667
*

0 commit comments

Comments
 (0)