CsvWriter::fill()   A
last analyzed

Complexity

Conditions 2
Paths 1

Size

Total Lines 22
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 22
ccs 13
cts 13
cp 1
rs 9.2
c 0
b 0
f 0
cc 2
eloc 14
nc 1
nop 2
crap 2
1
<?php
2
declare(strict_types = 1);
3
4
namespace Spreadsheet\Writer;
5
6
use Spreadsheet\{
7
    SpreadsheetInterface,
8
    Exception\InvalidArgumentException,
9
    SheetInterface,
10
    RowInterface,
11
    CellInterface,
12
    File\Csv,
13
    Formatter\FormatterInterface
14
};
15
use Innmind\Filesystem\{
16
    FileInterface,
17
    Directory,
18
    Stream\Stream
19
};
20
use Innmind\Immutable\MapInterface;
21
22
final class CsvWriter implements WriterInterface
23
{
24
    private $delimiter;
25
    private $withHeader;
26
    private $formatters;
27
28 8
    public function __construct(
29
        string $delimiter,
30
        bool $withHeader,
31
        MapInterface $formatters
32
    ) {
33
        if (
34 8
            empty($delimiter) ||
35 7
            (string) $formatters->keyType() !== 'string' ||
36 8
            (string) $formatters->valueType() !== FormatterInterface::class
37
        ) {
38 2
            throw new InvalidArgumentException;
39
        }
40
41 6
        $this->delimiter = $delimiter;
42 6
        $this->withHeader = $withHeader;
43 6
        $this->formatters = $formatters;
44 6
    }
45
46 5
    public function write(SpreadsheetInterface $spreadsheet): FileInterface
47
    {
48
        $directory = $spreadsheet
49 5
            ->sheets()
50 5
            ->reduce(
51 5
                new Directory($spreadsheet->name()),
52
                function(Directory $carry, string $name, SheetInterface $sheet): Directory {
53 5
                    return $carry->add($this->buildFile($sheet));
54 5
                }
55
            );
56
57 5
        if ($directory->count() === 1) {
58 4
            return $directory->get(
59 4
                $spreadsheet->sheets()->values()->first()->name().'.csv'
60
            );
61
        }
62
63 1
        return $directory;
64
    }
65
66 5
    private function buildFile(SheetInterface $sheet): FileInterface
67
    {
68 5
        $csv = tmpfile();
69
        $columns = $sheet
70 5
            ->columns()
71 5
            ->keys()
72
            ->sort(function($a, $b): bool {
73 4
                return $a > $b;
74 5
            })
75 5
            ->toPrimitive();
76 5
        $default = array_fill_keys(array_values($columns), '');
77
78 5
        if ($this->withHeader) {
79 2
            fputcsv($csv, $columns, $this->delimiter);
80
        }
81
82
        $sheet
83 5
            ->rows()
84 5
            ->values()
85
            ->sort(function(RowInterface $a, RowInterface $b): bool {
86 4
                return $a->identifier() > $b->identifier();
87 5
            })
88 5
            ->reduce(
89
                $csv,
90
                function($carry, RowInterface $row) use ($default) {
91 5
                    fputcsv(
92
                        $carry,
93 5
                        $this->fill($default, $row->cells()),
94 5
                        $this->delimiter
95
                    );
96
97 5
                    return $carry;
98 5
                }
99
            );
100
101 5
        return new Csv($sheet->name(), new Stream($csv));
102
    }
103
104 5
    private function fill(array $default, MapInterface $cells): array
105
    {
106 5
        $line = $cells->reduce(
107
            $default,
108 5
            function(array $carry, $column, CellInterface $cell): array {
109 5
                $class = get_class($cell);
110
111 5
                if ($this->formatters->contains($class)) {
112 1
                    $carry[$column] = $this
113 1
                        ->formatters
114 1
                        ->get($class)
115 1
                        ->format($cell);
116
                } else {
117 4
                    $carry[$column] = (string) $cell;
118
                }
119
120 5
                return $carry;
121 5
            }
122
        );
123
124 5
        return array_values($line);
125
    }
126
}
127