Passed
Push — main ( e3d1bb...64bec1 )
by
unknown
31:25 queued 12s
created

CsvFormatter::setEnclosure()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 5
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * This file is part of Blitz PHP framework.
5
 *
6
 * (c) 2022 Dimitri Sitchet Tomkeu <[email protected]>
7
 *
8
 * For the full copyright and license information, please view
9
 * the LICENSE file that was distributed with this source code.
10
 */
11
12
namespace BlitzPHP\Formatter;
13
14
/**
15
 * Formateur de données en CSV
16
 *
17
 * @see http://www.metashock.de/2014/02/create-csv-file-in-memory-php/
18
 */
19
class CsvFormatter implements FormatterInterface
20
{
21
    /**
22
     * Délimiteur de champ (un seul caractère)
23
     */
24
    private string $delimiter = ',';
25
26
    /**
27
     * Encadrement du champ (un seul caractère).
28
     */
29
    private string $enclosure = '"';
30
31
    /**
32
     * {@inheritDoc}
33
     *
34
     * @return string|null Une chaine formatée en CSV
35
     */
36
    public function format($data)
37
    {
38
        // Utiliser un seuil de 1 Mo (1024 * 1024)
39 2
        $handle = fopen('php://temp/maxmemory:1048576', 'wb');
40
        if ($handle === false) {
41
            return null;
42
        }
43
44
        if (! is_array($data)) {
45
            $data = (array) $data;
46
        }
47
48
        // Vérifie s'il s'agit d'un tableau multidimensionnel
49
        if (isset($data[0]) && count($data) !== count($data, COUNT_RECURSIVE)) {
50 2
            $headings = array_keys($data[0]);
51
        } else {
52 2
            $headings = array_keys($data);
53 2
            $data     = [$data];
54
        }
55
56
        // Appliquer les en-têtes
57 2
        fputcsv($handle, $headings, $this->delimiter, $this->enclosure);
58
59
        foreach ($data as $record) {
60
            // Si l'enregistrement n'est pas un tableau, alors break.
61
            // C'est parce que le 2ème paramètre de fputcsv() doit être un tableau
62
            if (! is_array($record)) {
63
                break;
64
            }
65
66
            // Suppression de la notification "conversion de tableau en chaîne".
67
            // Gardez le "mal" @ ici.
68 2
            $record = @array_map('strval', $record);
69
70 2
            fputcsv($handle, $record, $this->delimiter, $this->enclosure);
71
        }
72
73 2
        rewind($handle);
74
75 2
        $csv = stream_get_contents($handle);
76
77 2
        fclose($handle);
78
79
        // Convertit l'encodage UTF-8 en UTF-16LE qui est pris en charge par MS Excel
80 2
        return mb_convert_encoding($csv, 'UTF-16LE', 'UTF-8');
0 ignored issues
show
Bug Best Practice introduced by
The expression return mb_convert_encodi...v, 'UTF-16LE', 'UTF-8') also could return the type array which is incompatible with the documented return type null|string.
Loading history...
81
    }
82
83
    /**
84
     * {@inheritDoc}
85
     *
86
     * @param string $data Chaine CSV
87
     *
88
     * @return array A multi-dimensional array with the outer array being the number of rows
89
     *               and the inner arrays the individual fields
90
     */
91
    public function parse(string $data): array
92
    {
93 2
        $array = [];
94 2
        $lines = explode("\n", trim($data));
95
96
        foreach ($lines as $line) {
97 2
            $array[] = str_getcsv($line, $this->delimiter, $this->enclosure);
98
        }
99
100 2
        $head = array_shift($array);
101
102
        if ($array === []) {
103 2
            return $head;
104
        }
105
106 2
        $result = [];
107
108
        foreach ($array as $values) {
109 2
            $result[] = array_combine($head, $values);
110
        }
111
112 2
        return $result;
113
    }
114
115
    /**
116
     * Recupère le délimiteur de champ
117
     */
118
    public function getDelimiter(): string
119
    {
120 2
        return $this->delimiter;
121
    }
122
123
    /**
124
     * Définit le délimiteur de champ
125
     */
126
    public function setDelimiter(string $delimiter): self
127
    {
128 2
        $this->delimiter = $delimiter[0] ?? ',';
129
130 2
        return $this;
131
    }
132
133
    /**
134
     * Recupère l'encadrement du champ (un seul caractère).
135
     */
136
    public function getEnclosure(): string
137
    {
138 2
        return $this->enclosure;
139
    }
140
141
    /**
142
     * Set définit l'encadrement du champ (un seul caractère).
143
     */
144
    public function setEnclosure(string $enclosure): self
145
    {
146 2
        $this->enclosure = $enclosure[0] ?? '"';
147
148 2
        return $this;
149
    }
150
}
151