Writer.php 2.08 KB
<?php

namespace Hranicka\Csv;

class Writer
{

	/** @var string */
	private $filePath;

	/** @var array */
	private $data;

	/** @var bool */
	private $hasHeaderRow;

	/** @var string */
	private $delimiter;

	/** @var string */
	private $enclosure;

	/** @var resource */
	private $handler;

	/**
	 * @param string $filePath CSV file path
	 * @param array $data
	 * @param bool $hasHeaderRow Is the first row header?
	 */
	public function __construct($filePath, array $data, $hasHeaderRow = TRUE)
	{
		$this->filePath = $filePath;
		$this->data = $data;
		$this->hasHeaderRow = $hasHeaderRow;

		$this->setup();
	}

	/**
	 * @param string $delimiter
	 * @param string $enclosure
	 * @return $this
	 */
	public function setup($delimiter = ',', $enclosure = '"')
	{
		$this->delimiter = $delimiter;
		$this->enclosure = $enclosure;

		return $this;
	}

	/**
	 * @return array
	 * @throws InvalidFileException
	 */
	public function write()
	{
		$this->openHandler();

		$line = 0;
		$keys = NULL;

		foreach ($this->data as $row) {
			$line++;

			if ($this->hasHeaderRow) {
				if ($keys === NULL) {
					$keys = array_keys($row);
					$this->writeRow($keys);
				}

				$values = array_values($row);
				if (count($keys) !== count($values)) {
					throw new InvalidFileException("Invalid columns detected on line #$line.");
				}
			}

			$this->writeRow(array_values($row));
		}

		$this->closeHandler();
	}

	private function openHandler()
	{
		$this->handler = fopen($this->filePath, 'w');
		if ($this->handler === FALSE) {
			throw new InvalidFileException('Cannot open the file.');
		}
	}

	private function closeHandler()
	{
		fclose($this->handler);
		$this->handler = NULL;
	}

	/**
	 * @param array $data
	 * @return int
	 */
	private function writeRow(array $data)
	{
		return fputcsv($this->handler, $this->convertTypes($data), $this->delimiter, $this->enclosure);
	}

	/**
	 * @param array $data
	 * @return array
	 */
	private function convertTypes(array $data)
	{
		foreach ($data as & $value) {
			if (is_array($value)) {
				$value = json_encode($value);
			}

			$value = (string)$value;
		}

		return $data;
	}

}