Completed
Pull Request — master (#3)
by Harry
03:17
created

CsvFormatter   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 116
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Test Coverage

Coverage 100%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 13
c 2
b 0
f 0
lcom 1
cbo 6
dl 0
loc 116
ccs 42
cts 42
cp 1
rs 10

6 Methods

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