Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
84.00% covered (warning)
84.00%
21 / 25
50.00% covered (danger)
50.00%
1 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
CsvExport
84.00% covered (warning)
84.00%
21 / 25
50.00% covered (danger)
50.00%
1 / 2
11.50
0.00% covered (danger)
0.00%
0 / 1
 streamFromSheets
81.82% covered (warning)
81.82%
18 / 22
0.00% covered (danger)
0.00%
0 / 1
10.60
 getSupportedExtensions
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2namespace Apie\Export;
3
4use Apie\Export\Concerns\FlattensValues;
5use Apie\Export\Lists\FileExtensionList;
6use Apie\Export\ValueObjects\FileExtension;
7use Nyholm\Psr7\Stream;
8use Psr\Http\Message\StreamInterface;
9use UnitEnum;
10
11class CsvExport implements ExportInterface
12{
13    use FlattensValues;
14
15    public function streamFromSheets(array $sheets, string $outputFilename = 'export.csv'): StreamInterface
16    {
17        if (count($sheets) !== 1) {
18            throw new \LogicException("I can only export one sheet with CSV!");
19        }
20        $data = reset($sheets);
21        $stream = fopen('php://temp', 'r+');
22        // Add UTF-8 BOM to help Excel detect UTF-8
23        fwrite($stream, chr(0xEF) . chr(0xBB) . chr(0xBF));
24        $outputStream = new Stream($stream);
25        foreach ($data as $row) {
26            // If row is Traversable or object, try to convert to array
27            if (is_object($row) && !$row instanceof \Stringable && !$row instanceof UnitEnum) {
28                if ($row instanceof \Traversable) {
29                    $row = iterator_to_array($row);
30                } else {
31                    // cast to array will extract properties; prefer that to avoid errors
32                    $row = (array)$row;
33                }
34            }
35            if (!is_array($row)) {
36                // single value row -> wrap
37                $row = [$row];
38            }
39
40            $converted = [];
41            foreach ($row as $cell) {
42                $cell = $this->toSingleValue($cell);
43                // fputcsv expects strings/numbers/null
44                if ($cell === null) {
45                    $converted[] = '';
46                } else {
47                    $converted[] = (string)$cell;
48                }
49            }
50            // Use fputcsv for proper escaping
51            fputcsv($stream, $converted, ',', '"');
52        }
53
54        rewind($stream);
55        return $outputStream;
56    }
57
58    public function getSupportedExtensions(): FileExtensionList
59    {
60        return new FileExtensionList([
61            new FileExtension('csv'),
62        ]);
63    }
64}