CsvWriter   A
last analyzed

Complexity

Total Complexity 10

Size/Duplication

Total Lines 105
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 9

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 10
lcom 1
cbo 9
dl 0
loc 105
ccs 53
cts 53
cp 1
rs 10
c 0
b 0
f 0

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 17 4
A write() 0 19 2
B buildFile() 0 37 2
A fill() 0 22 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