Completed
Push — master ( b3a9bb...821f5b )
by Sébastien
04:08
created

CSVWriter::getData()   D

Complexity

Conditions 13
Paths 52

Size

Total Lines 92
Code Lines 44

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 48
CRAP Score 13.0343

Importance

Changes 3
Bugs 0 Features 0
Metric Value
c 3
b 0
f 0
dl 0
loc 92
ccs 48
cts 51
cp 0.9412
rs 4.9922
cc 13
eloc 44
nc 52
nop 1
crap 13.0343

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Soluble\FlexStore\Writer;
4
5
use Soluble\FlexStore\Writer\Http\SimpleHeaders;
6
use Soluble\FlexStore\Options;
7
8
class CSVWriter extends AbstractSendableWriter
9
{
10
11
    const SEPARATOR_TAB = "\t";
12
    const SEPARATOR_COMMA = ',';
13
    const SEPARATOR_SEMICOLON = ';';
14
    const SEPARATOR_NEWLINE_UNIX = "\n";
15
    const SEPARATOR_NEWLINE_WIN = "\r\n";
16
17
    /**
18
     *
19
     * @var SimpleHeaders
20
     */
21
    protected $headers;
22
23
    /**
24
     * @var array
25
     */
26
    protected $options = [
27
        'field_separator' => ";",
28
        'line_separator' => "\n",
29
        'enclosure' => '',
30
        'charset' => 'UTF-8',
31
        'escape' => '\\',
32
        // ignore charset transliteration errors
33
        'ignore_translit_error' => false
34
    ];
35
36
    /**
37
     *
38
     * @throws Exception\CharsetConversionException
39
     * @param Options $options
40
     * @return string csv encoded data
41
     */
42 8
    public function getData(Options $options = null)
43
    {
44 8
        if ($options === null) {
45
            // Take store global/default options
46 7
            $options = $this->store->getOptions();
47 7
        }
48
49
50
// TODO - TEST database connection charset !!!
51
//
52
53 8
        ini_set("default_charset", 'UTF-8');
54
55 8
        if (PHP_VERSION_ID < 50600) {
56
            iconv_set_encoding('internal_encoding', 'UTF-8');
57
        }
58
59
        /*
60
          $backup_encoding = iconv_get_encoding("internal_encoding");
61
          iconv_set_encoding("internal_encoding", "UTF-8");
62
          iconv_set_encoding("input_encoding", "UTF-8");
63
          iconv_set_encoding("output_encoding", "UTF-8");
64
          mb_internal_encoding("UTF-8");
65
         */
66
67 8
        $internal_encoding = strtoupper(ini_get('default_charset'));
68 8
        $charset = strtoupper($this->options['charset']);
69
70 8
        $csv = '';
71
72
        // Get unformatted data when using csv writer
73 8
        $options->getHydrationOptions()->disableFormatters();
74 8
        $data = $this->store->getData($options)->toArray();
75
76
77
78
79 8
        if (strtoupper($this->options['charset']) != $charset && !function_exists('iconv')) {
80
            throw new Exception\RuntimeException('CSV writer requires iconv extension');
81
        }
82
83 8
        $iconv_output_charset = $this->options['charset'];
84 8
        if ($this->options['ignore_translit_error']) {
85 1
            $iconv_output_charset .= "//TRANSLIT//IGNORE";
86 1
        }
87
88
89 8
        if (count($data) == 0) {
90 1
            $columns = $this->store->getColumnModel()->getColumns();
91 1
            $header_line = implode($this->options['field_separator'], array_keys((array) $columns));
92 1
            $csv .= $header_line . $this->options['line_separator'];
93 1
        } else {
94 7
            $header_line = implode($this->options['field_separator'], array_keys($data[0]));
95 7
            $csv .= $header_line . $this->options['line_separator'];
96
97
98 7
            foreach ($data as $row) {
99 7
                switch ($this->options['field_separator']) {
100 7
                    case self::SEPARATOR_TAB:
101 2
                        array_walk($row, [$this, 'escapeTabDelimiter']);
102 2
                        break;
103 5
                    default:
104 5
                        array_walk($row, [$this, 'escapeFieldDelimiter']);
105 7
                }
106
107 7
                array_walk($row, [$this, 'escapeLineDelimiter']);
108
109 7
                if ($this->options['enclosure'] != '') {
110 4
                    array_walk($row, [$this, 'addEnclosure']);
111 4
                }
112
113 7
                $line = implode($this->options['field_separator'], $row);
114
115
116 7
                if ($charset != $internal_encoding) {
117 5
                    $l = (string) $line;
118 5
                    if ($l != '') {
119 5
                        $l = @iconv($internal_encoding, $iconv_output_charset, $l);
120
121 5
                        if ($l === false) {
122 2
                            throw new Exception\CharsetConversionException("Cannot convert the charset to '" . $this->options['charset'] . "' from charset '$internal_encoding', value: '$line'.");
123
                        } else {
124 4
                            $line = $l;
125
                        }
126 4
                    }
127 4
                }
128
129 6
                $csv .= $line . $this->options['line_separator'];
130 6
            }
131
        }
132 7
        return $csv;
133
    }
134
135
    /**
136
     *
137
     * @param string $item
138
     * @return void
139
     */
140 7
    protected function escapeLineDelimiter(&$item)
141
    {
142 7
        $item = str_replace(self::SEPARATOR_NEWLINE_WIN, " ", $item);
143 7
        $item = str_replace(self::SEPARATOR_NEWLINE_UNIX, " ", $item);
144 7
    }
145
146
    /**
147
     *
148
     * @param string $item
149
     * @return void
150
     */
151 2
    protected function escapeTabDelimiter(&$item)
152
    {
153 2
        $item = str_replace("\t", " ", $item);
154 2
    }
155
156
    /**
157
     *
158
     * @param string $item
159
     * @return void
160
     */
161 5
    protected function escapeFieldDelimiter(&$item)
162
    {
163 5
        $item = str_replace($this->options['field_separator'], $this->options['escape'] . $this->options['field_separator'], $item);
164 5
    }
165
166
    /**
167
     *
168
     * @param string $item
169
     * @param string $key
170
     * @return void
171
     */
172 4
    protected function addEnclosure(&$item, $key)
0 ignored issues
show
Unused Code introduced by
The parameter $key is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
173
    {
174 4
        $enc = $this->options['enclosure'];
175 4
        $escape = $this->options['escape'];
176 4
        if ($escape == '') {
177 1
            $item = $enc . str_replace($enc, '', $item) . $enc;
178 1
        } else {
179 3
            $item = $enc . str_replace($enc, $escape . $enc, $item) . $enc;
180
        }
181 4
    }
182
183
    /**
184
     * Return default headers for sending store data via http
185
     * @return SimpleHeaders
186
     */
187 3
    public function getHttpHeaders()
188
    {
189 3
        if ($this->headers === null) {
190 3
            $this->headers = new SimpleHeaders();
191 3
            $this->headers->setContentType('text/csv', $this->options['charset']);
192
            //$this->headers->setContentDispositionType(SimpleHeaders::DIPOSITION_ATTACHEMENT);
193 3
        }
194 3
        return $this->headers;
195
    }
196
}
197