Conditions | 29 |
Paths | 69 |
Total Lines | 122 |
Code Lines | 70 |
Lines | 35 |
Ratio | 28.69 % |
Changes | 0 |
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:
If many parameters/temporary variables are present:
1 | <?php |
||
84 | public function parseRow($line) |
||
85 | { |
||
86 | // RFC4180 - Each record is located on a separate line, delimited by a line break (CRLF) |
||
87 | // Tabular Data - The line terminator character MUST be LF or CRLF |
||
88 | $line = rtrim($line, "\r\n"); |
||
89 | |||
90 | // RFC4180 - Within the header and each record, there may be one or more fields, separated by commas. |
||
91 | // Spaces are considered part of a field and should not be ignored. |
||
92 | // The last field in the record must not be followed by a comma. |
||
93 | // - Each field may or may not be enclosed in double quotes |
||
94 | // (however some programs, such as Microsoft Excel, do not use double quotes at all). |
||
95 | // If fields are not enclosed with double quotes, then double quotes may not appear inside the fields. |
||
96 | // - Fields containing line breaks (CRLF), double quotes, and commas |
||
97 | // should be enclosed in double-quotes. |
||
98 | // - If double-quotes are used to enclose fields, |
||
99 | // then a double-quote appearing inside a field must be escaped by preceding it with another double quote. |
||
100 | $enclosed = null; |
||
101 | $fields = []; |
||
102 | $field = -1; |
||
103 | $lastCharPos = mb_strlen($line)-1; |
||
104 | for ($charPos = 0; $charPos < mb_strlen($line); $charPos++) { |
||
105 | $char = mb_substr($line, $charPos, 1); |
||
106 | if ($enclosed === null) { |
||
107 | // start of a new field |
||
108 | if ($char == $this->dialect["delimiter"]) { |
||
109 | View Code Duplication | if ( |
|
|
|||
110 | // delimiter at end of line |
||
111 | ($charPos == $lastCharPos) |
||
112 | // double delimiters |
||
113 | || ($charPos != $lastCharPos && mb_substr($line, $charPos+1, 1) == $this->dialect["delimiter"]) |
||
114 | ) { |
||
115 | $field++; |
||
116 | $fields[$field] = ""; |
||
117 | } |
||
118 | continue; |
||
119 | } else { |
||
120 | $field++; |
||
121 | $fields[$field] = ""; |
||
122 | View Code Duplication | if ($char == $this->dialect["quoteChar"]) { |
|
123 | $enclosed = true; |
||
124 | continue; |
||
125 | } else { |
||
126 | $enclosed = false; |
||
127 | $fields[$field] .= $char; |
||
128 | continue; |
||
129 | } |
||
130 | } |
||
131 | } elseif ($enclosed) { |
||
132 | // processing an enclosed field |
||
133 | if ($this->dialect["doubleQuote"] !== null && $char == $this->dialect["quoteChar"]) { |
||
134 | // encountered quote in doubleQuote mode |
||
135 | if ($charPos !== 0 && mb_substr($line, $charPos-1, 1) == $this->dialect["quoteChar"]) { |
||
136 | // previous char was also a double quote |
||
137 | // the quote was added in previous iteration, nothing to do here |
||
138 | continue; |
||
139 | } elseif ($charPos != $lastCharPos && mb_substr($line, $charPos+1, 1) == $this->dialect["quoteChar"]) { |
||
140 | // next char is a also a double quote - add a quote to the field |
||
141 | $fields[$field] .= $this->dialect["quoteChar"]; |
||
142 | continue; |
||
143 | } |
||
144 | } |
||
145 | if ($this->dialect["escapeChar"]) { |
||
146 | // handle escape chars |
||
147 | if ($char == $this->dialect["escapeChar"]) { |
||
148 | // char is the escape char, add the escaped char to the string |
||
149 | if ($charPos === $lastCharPos) { |
||
150 | throw new DataSourceException("Encountered escape char at end of line"); |
||
151 | } else { |
||
152 | $fields[$field] .= mb_substr($line, $charPos+1, 1); |
||
153 | } |
||
154 | continue; |
||
155 | } elseif ($charPos != 0 && mb_substr($line, $charPos-1, 1) == $this->dialect["escapeChar"]) { |
||
156 | // previous char was the escape string |
||
157 | // added the char in previous iteration, nothing to do here |
||
158 | continue; |
||
159 | } |
||
160 | } |
||
161 | View Code Duplication | if ($char == $this->dialect["quoteChar"]) { |
|
162 | // encountered a quote signifying the end of the enclosed field |
||
163 | $enclosed = null; |
||
164 | continue; |
||
165 | } else { |
||
166 | // character in enclosed field |
||
167 | $fields[$field] .= $char; |
||
168 | continue; |
||
169 | } |
||
170 | } else { |
||
171 | // processing a non-enclosed field |
||
172 | if ($char == $this->dialect["quoteChar"]) { |
||
173 | // non enclosed field - cannot have a quotes |
||
174 | throw new \Exception("Invalid csv file - if field is not enclosed with double quotes - then double quotes may not appear inside the field"); |
||
175 | } elseif ($char == $this->dialect["delimiter"]) { |
||
176 | // end of non-enclosed field + start of new field |
||
177 | View Code Duplication | if ( |
|
178 | // delimiter at end of line |
||
179 | ($charPos == $lastCharPos) |
||
180 | // double delimiters |
||
181 | || ($charPos != $lastCharPos && mb_substr($line, $charPos+1, 1) == $this->dialect["delimiter"]) |
||
182 | ) { |
||
183 | $field++; |
||
184 | $fields[$field] = ""; |
||
185 | } |
||
186 | $enclosed = null; |
||
187 | continue; |
||
188 | } else { |
||
189 | // character in non-enclosed field |
||
190 | $fields[$field] .= $char; |
||
191 | continue; |
||
192 | } |
||
193 | } |
||
194 | } |
||
195 | if (count($fields) > 1 && mb_strlen($fields[count($fields)-1]) == 0) { |
||
196 | throw new \Exception("Invalid csv file - line must not end with a comma"); |
||
197 | } |
||
198 | if ($this->dialect["skipInitialSpace"]) { |
||
199 | return array_map(function($field) { |
||
200 | return ltrim($field); |
||
201 | }, $fields); |
||
202 | } else { |
||
203 | return $fields; |
||
204 | } |
||
205 | } |
||
206 | } |
||
207 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.