Completed
Push — master ( 8096c4...8558a8 )
by ignace nyamagana
28:17 queued 13:25
created

Output   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 251
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 1

Test Coverage

Coverage 100%

Importance

Changes 28
Bugs 2 Features 0
Metric Value
wmc 21
c 28
b 2
f 0
lcom 2
cbo 1
dl 0
loc 251
ccs 87
cts 87
cp 1
rs 10

14 Methods

Rating   Name   Duplication   Size   Complexity  
A setEncodingFrom() 0 11 2
A getEncodingFrom() 0 4 1
A getOutputBOM() 0 4 1
A getInputBOM() 0 20 2
getIterator() 0 1 ?
A output() 0 11 2
A fpassthru() 0 18 4
A __toString() 0 7 1
A jsonSerialize() 0 4 1
getQueryIterator() 0 1 ?
A convertToUtf8() 0 16 2
A toHTML() 0 7 1
A toXML() 0 18 2
A setOutputBOM() 0 12 2
1
<?php
2
/**
3
* This file is part of the League.csv library
4
*
5
* @license http://opensource.org/licenses/MIT
6
* @link https://github.com/thephpleague/csv/
7
* @version 8.0.0
8
* @package League.csv
9
*
10
* For the full copyright and license information, please view the LICENSE
11
* file that was distributed with this source code.
12
*/
13
namespace League\Csv\Config;
14
15
use DomDocument;
16
use InvalidArgumentException;
17
use Iterator;
18
use League\Csv\AbstractCsv;
19
use League\Csv\Modifier\MapIterator;
20
use SplFileObject;
21
22
/**
23
 *  A trait to output CSV
24
 *
25
 * @package League.csv
26
 * @since  6.3.0
27
 *
28
 */
29
trait Output
30
{
31
    /**
32
     * Charset Encoding for the CSV
33
     *
34
     * @var string
35
     */
36
    protected $encodingFrom = 'UTF-8';
37
38
    /**
39
     * The Input file BOM character
40
     * @var string
41
     */
42
    protected $input_bom = '';
43
44
    /**
45
     * The Output file BOM character
46
     * @var string
47
     */
48
    protected $output_bom = '';
49
50
    /**
51
     * Sets the CSV encoding charset
52
     *
53
     * @param string $str
54
     *
55
     * @return static
56
     */
57 6
    public function setEncodingFrom($str)
58
    {
59 6
        $str = str_replace('_', '-', $str);
60 6
        $str = filter_var($str, FILTER_SANITIZE_STRING, ['flags' => FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_HIGH]);
61 6
        if (empty($str)) {
62 3
            throw new InvalidArgumentException('you should use a valid charset');
63
        }
64 6
        $this->encodingFrom = strtoupper($str);
65
66 6
        return $this;
67
    }
68
69
    /**
70
     * Gets the source CSV encoding charset
71
     *
72
     * @return string
73
     */
74 3
    public function getEncodingFrom()
75
    {
76 3
        return $this->encodingFrom;
77
    }
78
79
    /**
80
     * Sets the BOM sequence to prepend the CSV on output
81
     *
82
     * @param string $str The BOM sequence
83
     *
84
     * @return static
85
     */
86 9
    public function setOutputBOM($str)
87
    {
88 9
        if (empty($str)) {
89 3
            $this->output_bom = '';
90
91 3
            return $this;
92
        }
93
94 9
        $this->output_bom = (string) $str;
95
96 9
        return $this;
97
    }
98
99
    /**
100
     * Returns the BOM sequence in use on Output methods
101
     *
102
     * @return string
103
     */
104 3
    public function getOutputBOM()
105
    {
106 3
        return $this->output_bom;
107
    }
108
109
    /**
110
     * Returns the BOM sequence of the given CSV
111
     *
112
     * @return string
113
     */
114 51
    public function getInputBOM()
115
    {
116 51
        if (!$this->input_bom) {
117
            $bom = [
118 51
                AbstractCsv::BOM_UTF32_BE, AbstractCsv::BOM_UTF32_LE,
119 34
                AbstractCsv::BOM_UTF16_BE, AbstractCsv::BOM_UTF16_LE, AbstractCsv::BOM_UTF8,
120 34
            ];
121 51
            $csv = $this->getIterator();
122 51
            $csv->setFlags(SplFileObject::READ_CSV);
123 51
            $csv->rewind();
124 51
            $line = $csv->fgets();
125
            $res  = array_filter($bom, function ($sequence) use ($line) {
126 51
                return strpos($line, $sequence) === 0;
127 51
            });
128
129 51
            $this->input_bom = (string) array_shift($res);
130 34
        }
131
132 51
        return $this->input_bom;
133
    }
134
135
    /**
136
     * @inheritdoc
137
     */
138
    abstract public function getIterator();
139
140
    /**
141
     * Outputs all data on the CSV file
142
     *
143
     * @param string $filename CSV downloaded name if present adds extra headers
144
     *
145
     * @return int Returns the number of characters read from the handle
146
     *             and passed through to the output.
147
     */
148 6
    public function output($filename = null)
149
    {
150 6
        if (null !== $filename) {
151 6
            $filename = filter_var($filename, FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW);
152 6
            header('Content-Type: application/octet-stream');
153 6
            header('Content-Transfer-Encoding: binary');
154 6
            header("Content-Disposition: attachment; filename=\"$filename\"");
155 4
        }
156
157 6
        return $this->fpassthru();
158
    }
159
160
    /**
161
     * Outputs all data from the CSV
162
     *
163
     * @return int Returns the number of characters read from the handle
164
     *             and passed through to the output.
165
     */
166 18
    protected function fpassthru()
167
    {
168 18
        $bom = '';
169 18
        $input_bom = $this->getInputBOM();
170 18
        if ($this->output_bom && $input_bom != $this->output_bom) {
171 6
            $bom = $this->output_bom;
172 4
        }
173 18
        $csv = $this->getIterator();
174 18
        $csv->setFlags(SplFileObject::READ_CSV);
175 18
        $csv->rewind();
176 18
        if (!empty($bom)) {
177 6
            $csv->fseek(mb_strlen($input_bom));
178 4
        }
179 18
        echo $bom;
180 18
        $res = $csv->fpassthru();
181
182 18
        return $res + strlen($bom);
183
    }
184
185
    /**
186
     * Retrieves the CSV content
187
     *
188
     * @return string
189
     */
190 12
    public function __toString()
191
    {
192 12
        ob_start();
193 12
        $this->fpassthru();
194
195 12
        return ob_get_clean();
196
    }
197
198
    /**
199
     * @inheritdoc
200
     */
201
    public function jsonSerialize()
202
    {
203 6
        return iterator_to_array($this->convertToUtf8($this->getQueryIterator()), false);
204
    }
205 6
206
    /**
207
     * Returns the CSV Iterator
208
     *
209
     * @return Iterator
210
     */
211
    abstract protected function getQueryIterator();
212
213
    /**
214
     * Convert Csv file into UTF-8
215
     *
216
     * @param Iterator $iterator
217
     *
218
     * @return Iterator
219
     */
220
    protected function convertToUtf8(Iterator $iterator)
221
    {
222 21
        if (stripos($this->encodingFrom, 'UTF-8') !== false) {
223
            return $iterator;
224 21
        }
225 18
226
        $convertCell = function ($value) {
227
            return mb_convert_encoding($value, 'UTF-8', $this->encodingFrom);
228
        };
229 3
230 3
        $convertRow = function (array $row) use ($convertCell) {
231
            return array_map($convertCell, $row);
232
        };
233 3
234 3
        return new MapIterator($iterator, $convertRow);
235
    }
236 3
237
    /**
238
     * Returns a HTML table representation of the CSV Table
239
     *
240
     * @param string $class_attr optional classname
241
     *
242
     * @return string
243
     */
244
    public function toHTML($class_attr = 'table-csv-data')
245
    {
246 6
        $doc = $this->toXML('table', 'tr', 'td');
247
        $doc->documentElement->setAttribute('class', $class_attr);
248 6
249 6
        return $doc->saveHTML($doc->documentElement);
250
    }
251 6
252
    /**
253
     * Transforms a CSV into a XML
254
     *
255
     * @param string $root_name XML root node name
256
     * @param string $row_name  XML row node name
257
     * @param string $cell_name XML cell node name
258
     *
259
     * @return DomDocument
260
     */
261
    public function toXML($root_name = 'csv', $row_name = 'row', $cell_name = 'cell')
262
    {
263 15
        $doc = new DomDocument('1.0', 'UTF-8');
264
        $root = $doc->createElement($root_name);
265 15
        foreach ($this->convertToUtf8($this->getQueryIterator()) as $row) {
266 15
            $rowElement = $doc->createElement($row_name);
267 15
            array_walk($row, function ($value) use (&$rowElement, $doc, $cell_name) {
268 15
                $content = $doc->createTextNode($value);
269 15
                $cell = $doc->createElement($cell_name);
270 15
                $cell->appendChild($content);
271 15
                $rowElement->appendChild($cell);
272 15
            });
273 15
            $root->appendChild($rowElement);
274 15
        }
275 15
        $doc->appendChild($root);
276 15
277 10
        return $doc;
278 15
    }
279
}
280