1<?php
2
3namespace Box\Spout\Writer\CSV;
4
5use Box\Spout\Common\Entity\Row;
6use Box\Spout\Common\Exception\IOException;
7use Box\Spout\Common\Helper\EncodingHelper;
8use Box\Spout\Writer\Common\Entity\Options;
9use Box\Spout\Writer\WriterAbstract;
10
11/**
12 * Class Writer
13 * This class provides support to write data to CSV files
14 */
15class Writer extends WriterAbstract
16{
17    /** Number of rows to write before flushing */
18    const FLUSH_THRESHOLD = 500;
19
20    /** @var string Content-Type value for the header */
21    protected static $headerContentType = 'text/csv; charset=UTF-8';
22
23    /** @var int */
24    protected $lastWrittenRowIndex = 0;
25
26    /**
27     * Sets the field delimiter for the CSV
28     *
29     * @param string $fieldDelimiter Character that delimits fields
30     * @return Writer
31     */
32    public function setFieldDelimiter($fieldDelimiter)
33    {
34        $this->optionsManager->setOption(Options::FIELD_DELIMITER, $fieldDelimiter);
35
36        return $this;
37    }
38
39    /**
40     * Sets the field enclosure for the CSV
41     *
42     * @param string $fieldEnclosure Character that enclose fields
43     * @return Writer
44     */
45    public function setFieldEnclosure($fieldEnclosure)
46    {
47        $this->optionsManager->setOption(Options::FIELD_ENCLOSURE, $fieldEnclosure);
48
49        return $this;
50    }
51
52    /**
53     * Set if a BOM has to be added to the file
54     *
55     * @param bool $shouldAddBOM
56     * @return Writer
57     */
58    public function setShouldAddBOM($shouldAddBOM)
59    {
60        $this->optionsManager->setOption(Options::SHOULD_ADD_BOM, (bool) $shouldAddBOM);
61
62        return $this;
63    }
64
65    /**
66     * Opens the CSV streamer and makes it ready to accept data.
67     *
68     * @return void
69     */
70    protected function openWriter()
71    {
72        if ($this->optionsManager->getOption(Options::SHOULD_ADD_BOM)) {
73            // Adds UTF-8 BOM for Unicode compatibility
74            $this->globalFunctionsHelper->fputs($this->filePointer, EncodingHelper::BOM_UTF8);
75        }
76    }
77
78    /**
79     * Adds a row to the currently opened writer.
80     *
81     * @param Row $row The row containing cells and styles
82     * @throws IOException If unable to write data
83     * @return void
84     */
85    protected function addRowToWriter(Row $row)
86    {
87        $fieldDelimiter = $this->optionsManager->getOption(Options::FIELD_DELIMITER);
88        $fieldEnclosure = $this->optionsManager->getOption(Options::FIELD_ENCLOSURE);
89
90        $wasWriteSuccessful = $this->globalFunctionsHelper->fputcsv($this->filePointer, $row->getCells(), $fieldDelimiter, $fieldEnclosure);
91        if ($wasWriteSuccessful === false) {
92            throw new IOException('Unable to write data');
93        }
94
95        $this->lastWrittenRowIndex++;
96        if ($this->lastWrittenRowIndex % self::FLUSH_THRESHOLD === 0) {
97            $this->globalFunctionsHelper->fflush($this->filePointer);
98        }
99    }
100
101    /**
102     * Closes the CSV streamer, preventing any additional writing.
103     * If set, sets the headers and redirects output to the browser.
104     *
105     * @return void
106     */
107    protected function closeWriter()
108    {
109        $this->lastWrittenRowIndex = 0;
110    }
111}
112