Completed
Pull Request — master (#6)
by Harry
07:18 queued 03:24
created

CsvFormatter   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 133
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Test Coverage

Coverage 100%

Importance

Changes 3
Bugs 0 Features 1
Metric Value
wmc 15
c 3
b 0
f 1
lcom 1
cbo 6
dl 0
loc 133
ccs 42
cts 42
cp 1
rs 10

7 Methods

Rating   Name   Duplication   Size   Complexity  
C __construct() 0 34 7
A format() 0 14 3
A escape() 0 4 1
A encode() 0 4 1
A getInitialBlock() 0 4 1
A getRowSeparator() 0 4 1
A getClosingBlock() 0 4 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 14
    private $initial;
46
47 14
    /**
48
     * @param CsvFormatInterface $csvFormat
49 14
     */
50 12
    public function __construct(CsvFormatInterface $csvFormat)
51 12
    {
52 12
        $this->csvFormat = $csvFormat;
53 12
54 12
        if ($this->csvFormat->getEscapeCharacter()) {
55 12
            $this->escapeChars = [
56
                $this->csvFormat->getEscapeCharacter(), // escape escape first so that it doesn't re-escape later on
57 12
                $this->csvFormat->getDelimiter(),
58 9
                "\n",
59 9
                "\r",
60
                "\t",
61 12
            ];
62
            if ($this->csvFormat->hasQuotes() && !$this->csvFormat->isDoubleQuote()) {
63 12
                $this->escapeChars[] = $this->csvFormat->getQuoteCharacter();
64 12
            }
65 12
66 12
            $this->escapeChars = array_unique($this->escapeChars);
67
68 14
            $this->replaceChars = array_map(function ($char) {
69 2
                return $this->csvFormat->getEscapeCharacter() . $char;
70 2
            }, $this->escapeChars);
71 2
        }
72
73 14
        if ($this->csvFormat->hasQuotes() && $this->csvFormat->isDoubleQuote()) {
74 14
            $this->escapeChars[] = $this->csvFormat->getQuoteCharacter();
75 14
            $this->replaceChars[] = str_repeat($this->csvFormat->getQuoteCharacter(), 2);
76 14
        }
77
78
        $this->initial = (!is_null($this->csvFormat->getBom())) ? $this->csvFormat->getBom() : '';
79
80
        $this->addProcessor(new DateTimeProcessor());
81
        $this->addProcessor(new BoolProcessor());
82
        $this->addProcessor(new ObjectToStringProcessor());
83 11
    }
84
85 11
    /**
86
     * @param array $data
87 11
     *
88 11
     * @return string
89 4
     */
90 4
    public function format(array $data)
91 11
    {
92
        $data = $this->process($data);
93 11
94
        foreach ($data as &$element) {
95 11
            if (is_null($element)) {
96
                $element = $this->csvFormat->getNullOutput();
97
            } else {
98
                $element = $this->csvFormat->getQuoteCharacter() . $this->escape($element) . $this->csvFormat->getQuoteCharacter();
99
            }
100
        }
101
102
        return $this->encode(implode($this->csvFormat->getDelimiter(), $data));
103 11
    }
104
105 11
    /**
106
     * @param string $string
107
     *
108
     * @return string
109
     */
110
    protected function escape($string)
111
    {
112
        return str_replace($this->escapeChars, $this->replaceChars, $string);
113 4
    }
114
115 4
    /**
116
     * @param string $string
117
     *
118
     * @return string
119
     */
120
    private function encode($string)
121
    {
122
        return mb_convert_encoding($string, $this->csvFormat->getEncoding());
123 4
    }
124
125 4
    /**
126
     * Return an initial block if required
127
     *
128
     * @return string
129
     */
130
    public function getInitialBlock()
131
    {
132
        return $this->initial;
133 4
    }
134
135 4
    /**
136
     * Get a separator between each row
137
     *
138
     * @return string
139
     */
140
    public function getRowSeparator()
141
    {
142
        return $this->encode($this->csvFormat->getLineTerminator());
143
    }
144
145
    /**
146
     * Return a closing block if required
147
     *
148
     * @return string
149
     */
150
    public function getClosingBlock()
151
    {
152
        return '';
153
    }
154
}
155