Skip to content

Instantly share code, notes, and snippets.

@VincentChalnot
Created June 28, 2018 15:34
Show Gist options
  • Save VincentChalnot/55de4a96bc42350d76ccea6db4e06904 to your computer and use it in GitHub Desktop.
Save VincentChalnot/55de4a96bc42350d76ccea6db4e06904 to your computer and use it in GitHub Desktop.
Forcing enclosure on Csv file writer
<?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