Created
June 28, 2018 15:34
-
-
Save VincentChalnot/55de4a96bc42350d76ccea6db4e06904 to your computer and use it in GitHub Desktop.
Forcing enclosure on Csv file writer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Filesystem; | |
/** | |
* Extends the native class to add a few features such as 'force_enclosure' | |
*/ | |
class CsvFile extends \CleverAge\ProcessBundle\Filesystem\CsvFile | |
{ | |
/** @var bool */ | |
protected $forceEnclosures; | |
/** | |
* {@inheritdoc} | |
*/ | |
public function __construct( | |
$filePath, | |
$delimiter = ',', | |
$enclosure = '"', | |
$escape = '\\', | |
array $headers = null, | |
$mode = 'r', | |
$forceEnclosures = false | |
) { | |
parent::__construct($filePath, $delimiter, $enclosure, $escape, $headers, $mode); | |
$this->forceEnclosures = $forceEnclosures; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function writeRaw(array $fields) | |
{ | |
$this->assertOpened(); | |
++$this->currentLine; | |
return $this->fputcsv($this->handler, $fields, $this->delimiter, $this->enclosure, $this->escape); | |
} | |
/** | |
* Replicate php's native fputcsv to allow overrides | |
* | |
* @see http://php.net/manual/en/function.fputcsv.php#77866 | |
* | |
* @param resource $handle | |
* @param array $fields | |
* @param string $delimiter | |
* @param string $enclosure | |
* @param bool $forceEnclosures | |
* | |
* @return bool|int | |
*/ | |
protected function fputcsv( | |
&$handle, | |
array $fields = [], | |
$delimiter = ',', | |
$enclosure = '"', | |
$forceEnclosures = false | |
) { | |
$str = ''; | |
$escapeChar = '\\'; | |
/** @var string $value */ | |
foreach ($fields as $value) { | |
$value = (string) $value; // This feels sooooo wrong... | |
if ($forceEnclosures || | |
strpos($value, $delimiter) !== false || | |
strpos($value, $enclosure) !== false || | |
strpos($value, "\n") !== false || | |
strpos($value, "\r") !== false || | |
strpos($value, "\t") !== false || | |
strpos($value, ' ') !== false | |
) { | |
$str2 = $enclosure; | |
$escaped = 0; | |
$len = \strlen($value); | |
/** @noinspection ForeachInvariantsInspection We need to iterate a string */ | |
for ($i = 0; $i < $len; $i++) { | |
if ($value[$i] === $escapeChar) { | |
$escaped = 1; | |
} else { | |
if (!$escaped && $value[$i] === $enclosure) { | |
$str2 .= $enclosure; | |
} else { | |
$escaped = 0; | |
} | |
} | |
$str2 .= $value[$i]; | |
} | |
$str2 .= $enclosure; | |
$str .= $str2.$delimiter; | |
} else { | |
$str .= $value.$delimiter; | |
} | |
} | |
$str = substr($str, 0, -1); | |
$str .= "\n"; | |
return fwrite($handle, $str); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment