SimpleCSV   B
last analyzed

Complexity

Total Complexity 50

Size/Duplication

Total Lines 206
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 135
c 1
b 0
f 0
dl 0
loc 206
rs 8.4
wmc 50

9 Methods

Rating   Name   Duplication   Size   Complexity  
A import() 0 3 1
A __construct() 0 4 1
A linebreak() 0 19 6
A export() 0 3 1
A enclosure() 0 17 5
B delimiter() 0 25 9
A downloadAs() 0 29 4
B fromArray() 0 32 10
C toArray() 0 60 13

How to fix   Complexity   

Complex Class

Complex classes like SimpleCSV often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use SimpleCSV, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace XoopsModules\Wgevents\Export\Simplecsv;
4
5
use XoopsModules\Wgevents;
6
7
class SimpleCSV {
8
    private $_delimiter;
9
    private $_enclosure;
10
    private $_linebreak;
11
    private $_csv = '';
12
    public static function import( $filename_or_data, $is_data = false, $delimiter = 'auto', $enclosure = 'auto', $linebreak = 'auto' ) {
13
        $csv = new static( $delimiter, $enclosure, $linebreak );
14
        return $csv->toArray( $filename_or_data, $is_data );
15
    }
16
    public static function export( $items, $delimiter = ',', $enclosure = '"', $linebreak = "\r\n") {
17
        $csv = new static( $delimiter, $enclosure, $linebreak );
18
        return $csv->fromArray( $items );
19
    }
20
    public function __construct( $delimiter = 'auto', $enclosure = 'auto', $linebreak = 'auto' ) {
21
        $this->_delimiter = $delimiter;
22
        $this->_enclosure = $enclosure;
23
        $this->_linebreak = $linebreak;
24
    }
25
    public function delimiter( $set = false ) {
26
        if ($set !== false) {
27
            return $this->_delimiter = $set;
28
        }
29
        if ($this->_delimiter === 'auto') {
30
            // detect delimiter
31
            if ( \strpos($this->_csv, $this->_enclosure . ',' ) !== false ) {
32
                $this->_delimiter = ',';
33
            } elseif (\strpos($this->_csv, $this->_enclosure."\t") !== false ) {
34
                $this->_delimiter = "\t";
35
            } elseif ( \strpos($this->_csv, $this->_enclosure . ';' ) !== false ) {
36
                $this->_delimiter = ';';
37
            } elseif ( \strpos($this->_csv, ',' ) !== false ) {
38
                $this->_delimiter = ',';
39
            } elseif (\strpos($this->_csv, "\t") !== false) {
40
                $this->_delimiter = "\t";
41
            }
42
            elseif ( \strpos($this->_csv, ';' ) !== false) {
43
                $this->_delimiter = ';';
44
            }
45
            else {
46
                $this->_delimiter = ',';
47
            }
48
        }
49
        return $this->_delimiter;
50
    }
51
    public function enclosure( $set = false ) {
52
        if ($set !== false) {
53
            return $this->_enclosure = $set;
54
        }
55
        if ($this->_enclosure === 'auto') {
56
            // detect quot
57
            if (\strpos($this->_csv, '"') !== false) {
58
                $this->_enclosure = '"';
59
            }
60
            elseif (\strpos($this->_csv, "'") !== false) {
61
                $this->_enclosure = "'";
62
            }
63
            else {
64
                $this->_enclosure = '"';
65
            }
66
        }
67
        return $this->_enclosure;
68
    }
69
    public function linebreak( $set = false ) {
70
        if ($set !== false) {
71
            return $this->_linebreak = $set;
72
        }
73
        if ($this->_linebreak === 'auto') {
74
            if (\strpos($this->_csv,"\r\n") !== false) {
75
                $this->_linebreak = "\r\n";
76
            }
77
            elseif (\strpos($this->_csv,"\n") !== false) {
78
                $this->_linebreak = "\n";
79
            }
80
            elseif (\strpos($this->_csv,"\r") !== false) {
81
                $this->_linebreak = "\r";
82
            }
83
            else {
84
                $this->_linebreak = "\r\n";
85
            }
86
        }
87
        return $this->_linebreak;
88
    }
89
    public function toArray( $filename, $is_csv_content = false ) {
90
        
91
        $this->_csv = $is_csv_content ? $filename : \file_get_contents( $filename );
92
93
        $CSV_LINEBREAK = $this->linebreak();
94
        $CSV_ENCLOSURE = $this->enclosure();
95
        $CSV_DELIMITER = $this->delimiter();
96
97
98
        $r = [];
99
        $cnt = \strlen($this->_csv); 
100
        
101
        $esc = $escesc = false; 
102
        $i = $k = $n = 0;
103
        $r[$k][$n] = '';
104
        
105
        while ($i < $cnt) { 
106
            $ch = $this->_csv[$i];
107
            $chch = ($i < $cnt-1) ? $ch.$this->_csv[$i+1] : $ch;
108
109
            if ($ch === $CSV_LINEBREAK) {
110
                if ($esc) {
111
                    $r[$k][$n] .= $ch; 
112
                } else {
113
                    $k++;
114
                    $n = 0;
115
                    $esc = $escesc = false;
116
                    $r[$k][$n] = '';
117
                }
118
            } elseif ($chch === $CSV_LINEBREAK) {
119
                if ($esc) {
120
                    $r[$k][$n] .= $chch;
121
                } else {
122
                    $k++;
123
                    $n = 0;
124
                    $esc = $escesc = false;
125
                    $r[$k][$n] = '';
126
                }
127
                $i++;
128
            } elseif ($ch === $CSV_DELIMITER) {
129
                if ($esc) { 
130
                    $r[$k][$n] .= $ch; 
131
                } else { 
132
                    $n++;
133
                    $r[$k][$n] = '';
134
                    $esc = $escesc = false; 
135
                }
136
            } elseif ( $chch === $CSV_ENCLOSURE.$CSV_ENCLOSURE && $esc ) {
137
                $r[$k][$n] .= $CSV_ENCLOSURE;
138
                $i++;
139
            } elseif ($ch === $CSV_ENCLOSURE) {
140
                
141
                $esc = !$esc;
0 ignored issues
show
introduced by
The condition $esc is always false.
Loading history...
142
                
143
            } else {
144
                $r[$k][$n] .= $ch;
145
            }
146
            $i++; 
147
        }
148
        return $r;
149
    }
150
    public function fromArray( $items ) {
151
        
152
        if (!\is_array($items)) {
153
            \trigger_error('CSV::export array required', E_USER_WARNING);
154
            return false;
155
        }
156
        
157
        $CSV_DELIMITER = $this->delimiter();
158
        $CSV_ENCLOSURE = $this->enclosure();
159
        $CSV_LINEBREAK = $this->linebreak();
160
        
161
        $result = '';
162
        foreach( $items as $i) {
163
            $line = '';
164
            
165
            foreach ($i as $v) { 
166
                if (\strpos($v, $CSV_ENCLOSURE) !== false) { 
167
                    $v = \str_replace($CSV_ENCLOSURE, $CSV_ENCLOSURE . $CSV_ENCLOSURE, $v); 
168
                }
169
170
                if ((\strpos($v, $CSV_DELIMITER) !== false) 
171
                    || (\strpos($v, $CSV_ENCLOSURE) !== false) 
172
                    || (\strpos($v, $CSV_LINEBREAK) !== false))
173
                {
174
                    $v = $CSV_ENCLOSURE . $v . $CSV_ENCLOSURE; 
175
                }
176
                $line .= $line ? $CSV_DELIMITER . $v : $v;
177
            }
178
            $result .= $result ? $CSV_LINEBREAK . $line : $line;
179
        }
180
        
181
        return $result;
182
    }
183
184
    public static function downloadAs( $items, $filename, $delimiter = ',', $enclosure = "'", $linebreak = "\r\n") {
185
        $csv = new static( $delimiter, $enclosure, $linebreak );
186
        $content = $csv->fromArray( $items );
187
188
        $fh = fopen('php://memory','wb');
189
        if (!$fh) {
0 ignored issues
show
introduced by
$fh is of type resource, thus it always evaluated to false.
Loading history...
190
            return false;
191
        }
192
193
        if ( !fwrite($fh,$content)) {
194
            fclose( $fh );
195
            return false;
196
        }
197
198
        $size = ftell($fh);
199
200
        header('Content-type: application/CSV');
201
        header('Content-Disposition: attachment; filename="'.$filename.'"');
202
        header('Last-Modified: ' . gmdate('D, d M Y H:i:s \G\M\T' , \time() ));
203
        header('Content-Length: '.$size);
204
205
        while( ob_get_level() ) {
206
            ob_end_clean();
207
        }
208
        fseek($fh,0);
209
        fpassthru( $fh );
210
211
        fclose($fh);
212
        return true;
213
    }
214
}
215