Initial xentral_oss_20.3.c9ffacf
This commit is contained in:
@@ -0,0 +1,147 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Components\Exporter\Csv;
|
||||
|
||||
use Iterator;
|
||||
use Xentral\Components\Exporter\Exception\InvalidResourceException;
|
||||
use Xentral\Components\Exporter\Exception\PhpExtensionMissingException;
|
||||
|
||||
final class CsvWriter
|
||||
{
|
||||
/** @var resource $handle */
|
||||
private $handle;
|
||||
|
||||
/** @var CsvConfig $config */
|
||||
private $config;
|
||||
|
||||
/**
|
||||
* @param resource $handle
|
||||
* @param CsvConfig|null $config
|
||||
*
|
||||
* @throws InvalidResourceException If resource is not writable or invalid
|
||||
* @throws PhpExtensionMissingException If mbstring is missing
|
||||
*/
|
||||
public function __construct($handle, CsvConfig $config = null)
|
||||
{
|
||||
if (!is_resource($handle)) {
|
||||
throw new InvalidResourceException('First parameter is not a valid resource.');
|
||||
}
|
||||
if (!$this->isStreamWritable($handle)) {
|
||||
throw new InvalidResourceException('Resource is not writable.');
|
||||
}
|
||||
if (!function_exists('mb_convert_encoding')) {
|
||||
throw new PhpExtensionMissingException('Required PHP extension "mbstring" is missing.');
|
||||
}
|
||||
if ($config === null) {
|
||||
$config = new CsvConfig();
|
||||
}
|
||||
|
||||
$this->config = $config;
|
||||
$this->handle = $handle;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array|Iterator $lines
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function writeLines($lines)
|
||||
{
|
||||
foreach ($lines as $line) {
|
||||
$this->writeLine($line);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $line
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function writeLine($line)
|
||||
{
|
||||
if ($this->config->isForceEnclosureEnabled()) {
|
||||
$fields = $this->encloseAllValues($line);
|
||||
fwrite(
|
||||
$this->handle,
|
||||
sprintf(
|
||||
"%s\n",
|
||||
implode($this->config->getDelimiter(), $this->convertCharset($fields))
|
||||
)
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
fputcsv(
|
||||
$this->handle,
|
||||
$this->convertCharset($line),
|
||||
$this->config->getDelimiter(),
|
||||
$this->config->getEnclosure(),
|
||||
$this->config->getEscapeChar()
|
||||
);
|
||||
}
|
||||
|
||||
/***
|
||||
* @param array $line
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function encloseAllValues($line)
|
||||
{
|
||||
$escapeChar = $this->config->getEscapeChar();
|
||||
$enclosure = $this->config->getEnclosure();
|
||||
$result = [];
|
||||
foreach ($line as $key => $value) {
|
||||
$value = str_replace($escapeChar . $enclosure, $enclosure, $value);
|
||||
$value = str_replace($enclosure, $escapeChar . $enclosure, $value);
|
||||
$result[$key] = sprintf('%1$s%2$s%1$s', $enclosure, $value);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $line
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function convertCharset($line)
|
||||
{
|
||||
if ($this->config->getSourceCharset() === $this->config->getTargetCharset()) {
|
||||
return $line; // No conversion needed
|
||||
}
|
||||
|
||||
$result = [];
|
||||
|
||||
foreach ($line as $key => $cellData) {
|
||||
$result[$key] = mb_convert_encoding(
|
||||
$cellData,
|
||||
$this->config->getTargetCharset(),
|
||||
$this->config->getSourceCharset()
|
||||
);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param resource $handle
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function isStreamWritable($handle)
|
||||
{
|
||||
$meta = stream_get_meta_data($handle);
|
||||
$currentMode = $meta['mode'];
|
||||
|
||||
$writeModes = ['r+', 'w', 'w+', 'a', 'a+', 'x', 'x+', 'c', 'c+'];
|
||||
foreach ($writeModes as $writeMode) {
|
||||
if (strpos($currentMode, $writeMode) !== false) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user