Completed
Push — master ( d97897...85851c )
by Harry
03:38
created

CsvFormatter::encode()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 1
crap 1
1
<?php
2
/**
3
 * This file is part of graze/data-file
4
 *
5
 * Copyright (c) 2016 Nature Delivered Ltd. <https://www.graze.com>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 *
10
 * @license https://github.com/graze/data-file/blob/master/LICENSE.md
11
 * @link    https://github.com/graze/data-file
12
 */
13
14
namespace Graze\DataFile\Format\Formatter;
15
16
use Graze\DataFile\Format\CsvFormatInterface;
17
use Graze\DataFile\Format\Processor\BoolProcessor;
18
use Graze\DataFile\Format\Processor\DateTimeProcessor;
19
use Graze\DataFile\Format\Processor\ObjectToStringProcessor;
20
use Graze\DataFile\Format\Processor\RowProcessor;
21
22
class CsvFormatter implements FormatterInterface
23
{
24
    use RowProcessor;
25
    use InvokeFormatter;
26
27
    /**
28
     * @var CsvFormatInterface
29
     */
30
    private $csvFormat;
31
32
    /**
33
     * @var string[]
34
     */
35
    private $escapeChars;
36
37
    /**
38
     * @var string[]
39
     */
40
    private $replaceChars;
41
42
    /**
43
     * @var string
44
     */
45
    private $initial;
46
47
    /**
48
     * @param CsvFormatInterface $csvFormat
49
     */
50 15
    public function __construct(CsvFormatInterface $csvFormat)
51
    {
52 15
        $this->csvFormat = $csvFormat;
53
54 15
        $this->buildReplacements();
55
56 15
        $this->initial = (!is_null($this->csvFormat->getBom())) ? $this->csvFormat->getBom() : '';
57
58 15
        $this->addProcessor(new DateTimeProcessor());
59 15
        $this->addProcessor(new BoolProcessor());
60 15
        $this->addProcessor(new ObjectToStringProcessor());
61 15
    }
62
63
    /**
64
     * Build replacements to perform for each entry
65
     */
66 15
    private function buildReplacements()
67
    {
68 15
        if ($this->csvFormat->getEscapeCharacter()) {
69 13
            $this->escapeChars = [
70 13
                $this->csvFormat->getEscapeCharacter(), // escape escape first so that it doesn't re-escape later on
71 13
                $this->csvFormat->getDelimiter(),
72 13
                "\n",
73 13
                "\r",
74 13
                "\t",
75
            ];
76 13
            if ($this->csvFormat->hasQuotes() && !$this->csvFormat->isDoubleQuote()) {
77 10
                $this->escapeChars[] = $this->csvFormat->getQuoteCharacter();
78
            }
79
80 13
            $this->escapeChars = array_unique($this->escapeChars);
81
82 13
            $this->replaceChars = array_map(function ($char) {
83 13
                return $this->csvFormat->getEscapeCharacter() . $char;
84 13
            }, $this->escapeChars);
85
        }
86
87 15
        if ($this->csvFormat->hasQuotes() && $this->csvFormat->isDoubleQuote()) {
88 2
            $this->escapeChars[] = $this->csvFormat->getQuoteCharacter();
89 2
            $this->replaceChars[] = str_repeat($this->csvFormat->getQuoteCharacter(), 2);
90
        }
91 15
    }
92
93
    /**
94
     * @param array $data
95
     *
96
     * @return string
97
     */
98 11
    public function format(array $data)
99
    {
100 11
        $data = $this->process($data);
101
102 11
        foreach ($data as &$element) {
103 11
            if (is_null($element)) {
104 4
                $element = $this->csvFormat->getNullOutput();
105
            } else {
106 11
                $element = $this->csvFormat->getQuoteCharacter() . $this->escape($element) . $this->csvFormat->getQuoteCharacter();
107
            }
108
        }
109
110 11
        return $this->encode(implode($this->csvFormat->getDelimiter(), $data));
111
    }
112
113
    /**
114
     * @param string $string
115
     *
116
     * @return string
117
     */
118 11
    protected function escape($string)
119
    {
120 11
        return str_replace($this->escapeChars, $this->replaceChars, $string);
121
    }
122
123
    /**
124
     * @param string $string
125
     *
126
     * @return string
127
     */
128 12
    private function encode($string)
129
    {
130 12
        return mb_convert_encoding($string, $this->csvFormat->getEncoding());
131
    }
132
133
    /**
134
     * Return an initial block if required
135
     *
136
     * @return string
137
     */
138 5
    public function getInitialBlock()
139
    {
140 5
        return $this->initial;
141
    }
142
143
    /**
144
     * Get a separator between each row
145
     *
146
     * @return string
147
     */
148 4
    public function getRowSeparator()
149
    {
150 4
        return $this->encode($this->csvFormat->getLineTerminator());
151
    }
152
153
    /**
154
     * Return a closing block if required
155
     *
156
     * @return string
157
     */
158 5
    public function getClosingBlock()
159
    {
160 5
        return '';
161
    }
162
}
163