Files
grzanieplus.pl/plugins/stTaskSchedulerImportPlugin/lib/reader/stTaskSchedulerImportCsvReader.class.php
2025-03-12 17:06:23 +01:00

222 lines
4.4 KiB
PHP

<?php
class stTaskSchedulerImportCsvReader implements stTaskSchedulerImportReaderInterface
{
/**
*
* @var resource|null
*/
protected $fh = null;
/**
*
* @var null|int
*/
protected $count = null;
/**
*
* @var string
*/
protected $separator;
/**
*
* @var string
*/
protected $encoding;
/**
*
* @var string
*/
protected $enclosure;
/**
*
* @var bool
*/
protected $readHeaderFields;
/**
* @var int|null
*/
protected $dataOffset = null;
/**
* @var array|null
*/
protected $fields = null;
public function __clone()
{
if (null !== $this->fh)
{
$this->fh = clone $this->fh;
}
}
public function __construct(string $separator = ";", string $encoding = "UTF-8", $enclosure = '"', bool $readHeaderFields = true)
{
$this->separator = $separator;
$this->encoding = $encoding;
$this->enclosure = $enclosure;
$this->readHeaderFields = $readHeaderFields;
}
public function __destruct()
{
$this->close();
}
public function getFiletypeExtension(): string
{
return 'csv';
}
public function open(string $file): bool
{
$this->fh = fopen($file, "r");
return false !== $this->fh;
}
public function isValid(): bool
{
try
{
$result = $this->read(function() {});
}
catch (stTaskSchedulerImportReaderException $e)
{
$result = false;
}
$this->rewind();
return $result;
}
public function rewind(): void
{
rewind($this->fh);
}
public function count(): int
{
if (null === $this->count)
{
fseek($this->fh, 0, SEEK_END);
$this->count = $this->getOffset();
$this->rewind();
}
return $this->count;
}
public function setOffset(int $offset): void
{
fseek($this->fh, $offset);
}
public function getOffset(): int
{
return ftell($this->fh);
}
public function read(\Closure $callback): bool
{
if ($this->readHeaderFields)
{
$fields = $this->getFields();
if (!$this->getOffset() && $this->dataOffset)
{
$this->setOffset($this->dataOffset);
}
}
$data = $this->getNextLine();
if ($data && $this->readHeaderFields)
{
$data = array_slice($data, 0, count($fields));
$combinedData = array_combine($fields, $data);
if (false === $combinedData)
{
throw new stTaskSchedulerImportReaderException(sprintf("The number of header fields is not equal to the number of read data fields (fields: \"%s\", data: \"%s\")",
implode('", "', $fields),
implode('", "', $data)
));
}
$data = $combinedData;
}
if ($data)
{
if ("UTF-8" != $this->encoding)
{
$data = array_map(function($value) {
return iconv($this->encoding, "UTF-8//TRANSLIT", $value);
}, $data);
}
$callback($data);
}
return !empty($data);
}
public function close(): void
{
if ($this->fh)
{
fclose($this->fh);
$this->fh = null;
}
}
/**
* Czyta i zwraca następna linię z pliku csv
*
* @return array|null
*/
private function getNextLine(): ?array
{
$data = fgetcsv($this->fh, null, $this->separator, $this->enclosure, "\0");
return false !== $data ? array_map('trim', $data) : null;
}
/**
* Odczytuje nazwy pól
*
* @return array|null
*/
private function getFields(): ?array
{
$offset = $this->getOffset();
if (null === $this->fields)
{
if ($offset > 0)
{
$this->rewind();
}
$this->fields = $this->getNextLine();
$this->dataOffset = $this->getOffset();
if ($offset > 0)
{
$this->setOffset($offset);
}
}
return $this->fields;
}
}