diff --git a/src/Symfony/Component/Serializer/CHANGELOG.md b/src/Symfony/Component/Serializer/CHANGELOG.md index e3f7fb0a14610..8253276c99c7a 100644 --- a/src/Symfony/Component/Serializer/CHANGELOG.md +++ b/src/Symfony/Component/Serializer/CHANGELOG.md @@ -8,6 +8,7 @@ CHANGELOG of objects that needs data insertion in constructor * added an optional `default_constructor_arguments` option of context to specify a default data in case the object is not initializable by its constructor because of data missing +* added optional `bool $escapeFormulas = false` argument to `CsvEncoder::__construct` 4.0.0 ----- diff --git a/src/Symfony/Component/Serializer/Encoder/CsvEncoder.php b/src/Symfony/Component/Serializer/Encoder/CsvEncoder.php index 31a65d32d92d3..7ecd086d2d636 100644 --- a/src/Symfony/Component/Serializer/Encoder/CsvEncoder.php +++ b/src/Symfony/Component/Serializer/Encoder/CsvEncoder.php @@ -27,18 +27,22 @@ class CsvEncoder implements EncoderInterface, DecoderInterface const ESCAPE_CHAR_KEY = 'csv_escape_char'; const KEY_SEPARATOR_KEY = 'csv_key_separator'; const HEADERS_KEY = 'csv_headers'; + const ESCAPE_FORMULAS_KEY = 'csv_escape_formulas'; private $delimiter; private $enclosure; private $escapeChar; private $keySeparator; + private $escapeFormulas; + private $formulasStartCharacters = array('=', '-', '+', '@'); - public function __construct(string $delimiter = ',', string $enclosure = '"', string $escapeChar = '\\', string $keySeparator = '.') + public function __construct(string $delimiter = ',', string $enclosure = '"', string $escapeChar = '\\', string $keySeparator = '.', bool $escapeFormulas = false) { $this->delimiter = $delimiter; $this->enclosure = $enclosure; $this->escapeChar = $escapeChar; $this->keySeparator = $keySeparator; + $this->escapeFormulas = $escapeFormulas; } /** @@ -65,11 +69,11 @@ public function encode($data, $format, array $context = array()) } } - list($delimiter, $enclosure, $escapeChar, $keySeparator, $headers) = $this->getCsvOptions($context); + list($delimiter, $enclosure, $escapeChar, $keySeparator, $headers, $escapeFormulas) = $this->getCsvOptions($context); foreach ($data as &$value) { $flattened = array(); - $this->flatten($value, $flattened, $keySeparator); + $this->flatten($value, $flattened, $keySeparator, '', $escapeFormulas); $value = $flattened; } unset($value); @@ -172,13 +176,17 @@ public function supportsDecoding($format) /** * Flattens an array and generates keys including the path. */ - private function flatten(array $array, array &$result, string $keySeparator, string $parentKey = '') + private function flatten(array $array, array &$result, string $keySeparator, string $parentKey = '', bool $escapeFormulas = false) { foreach ($array as $key => $value) { if (is_array($value)) { - $this->flatten($value, $result, $keySeparator, $parentKey.$key.$keySeparator); + $this->flatten($value, $result, $keySeparator, $parentKey.$key.$keySeparator, $escapeFormulas); } else { - $result[$parentKey.$key] = $value; + if ($escapeFormulas && \in_array(substr($value, 0, 1), $this->formulasStartCharacters, true)) { + $result[$parentKey.$key] = "\t".$value; + } else { + $result[$parentKey.$key] = $value; + } } } } @@ -190,12 +198,13 @@ private function getCsvOptions(array $context) $escapeChar = isset($context[self::ESCAPE_CHAR_KEY]) ? $context[self::ESCAPE_CHAR_KEY] : $this->escapeChar; $keySeparator = isset($context[self::KEY_SEPARATOR_KEY]) ? $context[self::KEY_SEPARATOR_KEY] : $this->keySeparator; $headers = isset($context[self::HEADERS_KEY]) ? $context[self::HEADERS_KEY] : array(); + $escapeFormulas = isset($context[self::ESCAPE_FORMULAS_KEY]) ? $context[self::ESCAPE_FORMULAS_KEY] : $this->escapeFormulas; if (!is_array($headers)) { throw new InvalidArgumentException(sprintf('The "%s" context variable must be an array or null, given "%s".', self::HEADERS_KEY, gettype($headers))); } - return array($delimiter, $enclosure, $escapeChar, $keySeparator, $headers); + return array($delimiter, $enclosure, $escapeChar, $keySeparator, $headers, $escapeFormulas); } /** diff --git a/src/Symfony/Component/Serializer/Tests/Encoder/CsvEncoderTest.php b/src/Symfony/Component/Serializer/Tests/Encoder/CsvEncoderTest.php index a5e5c256f34ad..de5d505a7e85b 100644 --- a/src/Symfony/Component/Serializer/Tests/Encoder/CsvEncoderTest.php +++ b/src/Symfony/Component/Serializer/Tests/Encoder/CsvEncoderTest.php @@ -173,6 +173,109 @@ public function testEncodeCustomHeaders() $this->assertEquals($csv, $this->encoder->encode($value, 'csv', $context)); } + public function testEncodeFormulas() + { + $this->encoder = new CsvEncoder(',', '"', '\\', '.', true); + + $this->assertSame(<<<'CSV' +0 +" =2+3" + +CSV + , $this->encoder->encode(array('=2+3'), 'csv')); + + $this->assertSame(<<<'CSV' +0 +" -2+3" + +CSV + , $this->encoder->encode(array('-2+3'), 'csv')); + + $this->assertSame(<<<'CSV' +0 +" +2+3" + +CSV + , $this->encoder->encode(array('+2+3'), 'csv')); + + $this->assertSame(<<<'CSV' +0 +" @MyDataColumn" + +CSV + , $this->encoder->encode(array('@MyDataColumn'), 'csv')); + } + + public function testDoNotEncodeFormulas() + { + $this->assertSame(<<<'CSV' +0 +=2+3 + +CSV + , $this->encoder->encode(array('=2+3'), 'csv')); + + $this->assertSame(<<<'CSV' +0 +-2+3 + +CSV + , $this->encoder->encode(array('-2+3'), 'csv')); + + $this->assertSame(<<<'CSV' +0 ++2+3 + +CSV + , $this->encoder->encode(array('+2+3'), 'csv')); + + $this->assertSame(<<<'CSV' +0 +@MyDataColumn + +CSV + , $this->encoder->encode(array('@MyDataColumn'), 'csv')); + } + + public function testEncodeFormulasWithSettingsPassedInContext() + { + $this->assertSame(<<<'CSV' +0 +" =2+3" + +CSV + , $this->encoder->encode(array('=2+3'), 'csv', array( + CsvEncoder::ESCAPE_FORMULAS_KEY => true, + ))); + + $this->assertSame(<<<'CSV' +0 +" -2+3" + +CSV + , $this->encoder->encode(array('-2+3'), 'csv', array( + CsvEncoder::ESCAPE_FORMULAS_KEY => true, + ))); + + $this->assertSame(<<<'CSV' +0 +" +2+3" + +CSV + , $this->encoder->encode(array('+2+3'), 'csv', array( + CsvEncoder::ESCAPE_FORMULAS_KEY => true, + ))); + + $this->assertSame(<<<'CSV' +0 +" @MyDataColumn" + +CSV + , $this->encoder->encode(array('@MyDataColumn'), 'csv', array( + CsvEncoder::ESCAPE_FORMULAS_KEY => true, + ))); + } + public function testSupportsDecoding() { $this->assertTrue($this->encoder->supportsDecoding('csv')); pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy