@@ -27,18 +27,22 @@ class CsvEncoder implements EncoderInterface, DecoderInterface
27
27
const ESCAPE_CHAR_KEY = 'csv_escape_char ' ;
28
28
const KEY_SEPARATOR_KEY = 'csv_key_separator ' ;
29
29
const HEADERS_KEY = 'csv_headers ' ;
30
+ const ESCAPE_FORMULAS_KEY = 'csv_escape_formulas ' ;
30
31
31
32
private $ delimiter ;
32
33
private $ enclosure ;
33
34
private $ escapeChar ;
34
35
private $ keySeparator ;
36
+ private $ escapeFormulas ;
37
+ private $ formulasStartCharacters = array ('= ' , '- ' , '+ ' , '@ ' );
35
38
36
- public function __construct (string $ delimiter = ', ' , string $ enclosure = '" ' , string $ escapeChar = '\\' , string $ keySeparator = '. ' )
39
+ public function __construct (string $ delimiter = ', ' , string $ enclosure = '" ' , string $ escapeChar = '\\' , string $ keySeparator = '. ' , $ escapeFormulas = false )
37
40
{
38
41
$ this ->delimiter = $ delimiter ;
39
42
$ this ->enclosure = $ enclosure ;
40
43
$ this ->escapeChar = $ escapeChar ;
41
44
$ this ->keySeparator = $ keySeparator ;
45
+ $ this ->escapeFormulas = $ escapeFormulas ;
42
46
}
43
47
44
48
/**
@@ -65,11 +69,11 @@ public function encode($data, $format, array $context = array())
65
69
}
66
70
}
67
71
68
- list ($ delimiter , $ enclosure , $ escapeChar , $ keySeparator , $ headers ) = $ this ->getCsvOptions ($ context );
72
+ list ($ delimiter , $ enclosure , $ escapeChar , $ keySeparator , $ headers, $ escapeFormulas ) = $ this ->getCsvOptions ($ context );
69
73
70
74
foreach ($ data as &$ value ) {
71
75
$ flattened = array ();
72
- $ this ->flatten ($ value , $ flattened , $ keySeparator );
76
+ $ this ->flatten ($ value , $ flattened , $ keySeparator, '' , $ escapeFormulas );
73
77
$ value = $ flattened ;
74
78
}
75
79
unset($ value );
@@ -172,13 +176,17 @@ public function supportsDecoding($format)
172
176
/**
173
177
* Flattens an array and generates keys including the path.
174
178
*/
175
- private function flatten (array $ array , array &$ result , string $ keySeparator , string $ parentKey = '' )
179
+ private function flatten (array $ array , array &$ result , string $ keySeparator , string $ parentKey = '' , $ escapeFormulas = false )
176
180
{
177
181
foreach ($ array as $ key => $ value ) {
178
182
if (is_array ($ value )) {
179
- $ this ->flatten ($ value , $ result , $ keySeparator , $ parentKey .$ key .$ keySeparator );
183
+ $ this ->flatten ($ value , $ result , $ keySeparator , $ parentKey .$ key .$ keySeparator, $ escapeFormulas );
180
184
} else {
181
- $ result [$ parentKey .$ key ] = $ value ;
185
+ if ($ escapeFormulas && \in_array (substr ($ value , 0 , 1 ), $ this ->formulasStartCharacters , true )) {
186
+ $ result [$ parentKey .$ key ] = "\t" .$ value ;
187
+ } else {
188
+ $ result [$ parentKey .$ key ] = $ value ;
189
+ }
182
190
}
183
191
}
184
192
}
@@ -190,12 +198,13 @@ private function getCsvOptions(array $context)
190
198
$ escapeChar = isset ($ context [self ::ESCAPE_CHAR_KEY ]) ? $ context [self ::ESCAPE_CHAR_KEY ] : $ this ->escapeChar ;
191
199
$ keySeparator = isset ($ context [self ::KEY_SEPARATOR_KEY ]) ? $ context [self ::KEY_SEPARATOR_KEY ] : $ this ->keySeparator ;
192
200
$ headers = isset ($ context [self ::HEADERS_KEY ]) ? $ context [self ::HEADERS_KEY ] : array ();
201
+ $ escapeFormulas = isset ($ context [self ::ESCAPE_FORMULAS_KEY ]) ? $ context [self ::ESCAPE_FORMULAS_KEY ] : $ this ->escapeFormulas ;
193
202
194
203
if (!is_array ($ headers )) {
195
204
throw new InvalidArgumentException (sprintf ('The "%s" context variable must be an array or null, given "%s". ' , self ::HEADERS_KEY , gettype ($ headers )));
196
205
}
197
206
198
- return array ($ delimiter , $ enclosure , $ escapeChar , $ keySeparator , $ headers );
207
+ return array ($ delimiter , $ enclosure , $ escapeChar , $ keySeparator , $ headers, $ escapeFormulas );
199
208
}
200
209
201
210
/**
0 commit comments