schema = $params["schema"] ?? static::SCHEMA; $this->headers = $params["headers"] ?? static::HEADERS; $this->useHeaders = $params["use_headers"] ?? static::USE_HEADERS; $rows = $params["rows"] ?? null; if (is_callable($rows)) $rows = $rows(); $this->rows = $rows; $cookFunc = $params["cook_func"] ?? null; $cookCtx = $cookArgs = null; if ($cookFunc !== null) { nur_func::ensure_func($cookFunc, $this, $cookArgs); $cookCtx = nur_func::_prepare($cookFunc); } $this->cookCtx = $cookCtx; $this->cookArgs = $cookArgs; $this->output = $params["output"] ?? static::OUTPUT; $maxMemory = $params["max_memory"] ?? null; $throwOnError = $params["throw_on_error"] ?? null; parent::__construct($maxMemory, $throwOnError); } protected ?array $schema; protected ?array $headers; protected bool $useHeaders; protected ?iterable $rows; protected ?string $output; protected ?array $cookCtx; protected ?array $cookArgs; protected function ensureHeaders(?array $row=null): void { if ($this->headers !== null || !$this->useHeaders) return; if ($this->schema === null) $headers = null; else $headers = array_keys($this->schema); if ($headers === null && $row !== null) $headers = array_keys($row); $this->headers = $headers; } protected abstract function _write(array $row): void; protected bool $wroteHeaders = false; function writeHeaders(?array $headers=null): void { if ($this->wroteHeaders) return; if ($this->useHeaders) { if ($headers !== null) $this->headers = $headers; else $this->ensureHeaders(); if ($this->headers !== null) $this->_write($this->headers); } $this->wroteHeaders = true; } protected function cookRow(?array $row): ?array { if ($this->cookCtx !== null) { $args = cl::merge([$row], $this->cookArgs); $row = nur_func::_call($this->cookCtx, $args); } if ($row !== null) { foreach ($row as &$value) { # formatter les dates if ($value instanceof DateTime) { $value = $value->format(); } elseif ($value instanceof DateTimeInterface) { $value = DateTime::with($value)->format(); } }; unset($value); } return $row; } function write(?array $row): void { $row = $this->cookRow($row); if ($row === null) return; $this->writeHeaders(array_keys($row)); $this->_write($row); } function writeAll(?iterable $rows=null): void { $unsetRows = false; if ($rows === null) { $rows = $this->rows; $unsetRows = true; } if ($rows !== null) { foreach ($rows as $row) { $this->write(cl::with($row)); } } if ($unsetRows) $this->rows = null; } abstract protected function _sendContentType(): void; protected bool $sentHeaders = false; function sendHeaders(): void { if ($this->sentHeaders) return; $this->_sendContentType(); $output = $this->output; if ($output !== null) { http::download_as(path::filename($output)); } $this->sentHeaders = true; } protected function _build(?iterable $rows=null): void { $this->writeAll($rows); $this->writeHeaders(); } abstract protected function _checkOk(): bool; protected bool $built = false, $closed = false; function build(?iterable $rows=null, bool $close=true): bool { $ok = true; if (!$this->built) { $this->_build($rows); $this->built = true; } if ($close && !$this->closed) { $ok = $this->_checkOk(); $this->closed = true; } return $ok; } function sendFile(?iterable $rows=null): int { if (!$this->built) { $this->_build($rows); $this->built = true; } if (!$this->closed) { if (!$this->_checkOk()) return 0; $this->closed = true; } $this->sendHeaders(); return $this->fpassthru(); } }