Conditions | 71 |
Paths | 977 |
Total Lines | 246 |
Code Lines | 152 |
Lines | 12 |
Ratio | 4.88 % |
Changes | 1 | ||
Bugs | 0 | Features | 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 |
||
53 | public function parse($value, $exceptionOnInvalidType = false, $objectSupport = false, $objectForMap = false) |
||
54 | { |
||
55 | if (!preg_match('//u', $value)) { |
||
56 | throw new ParseException('The YAML value does not appear to be valid UTF-8.'); |
||
57 | } |
||
58 | $this->currentLineNb = -1; |
||
59 | $this->currentLine = ''; |
||
60 | $value = $this->cleanup($value); |
||
61 | $this->lines = explode("\n", $value); |
||
62 | |||
63 | View Code Duplication | if (function_exists('mb_internal_encoding') && ((int) ini_get('mbstring.func_overload')) & 2) { |
|
|
|||
64 | $mbEncoding = mb_internal_encoding(); |
||
65 | mb_internal_encoding('UTF-8'); |
||
66 | } |
||
67 | |||
68 | $data = array(); |
||
69 | $context = null; |
||
70 | $allowOverwrite = false; |
||
71 | while ($this->moveToNextLine()) { |
||
72 | if ($this->isCurrentLineEmpty()) { |
||
73 | continue; |
||
74 | } |
||
75 | |||
76 | // tab? |
||
77 | if ("\t" === $this->currentLine[0]) { |
||
78 | throw new ParseException('A YAML file cannot contain tabs as indentation.', $this->getRealCurrentLineNb() + 1, $this->currentLine); |
||
79 | } |
||
80 | |||
81 | $isRef = $mergeNode = false; |
||
82 | if (preg_match('#^\-((?P<leadspaces>\s+)(?P<value>.+?))?\s*$#u', $this->currentLine, $values)) { |
||
83 | if ($context && 'mapping' == $context) { |
||
84 | throw new ParseException('You cannot define a sequence item when in a mapping'); |
||
85 | } |
||
86 | $context = 'sequence'; |
||
87 | |||
88 | View Code Duplication | if (isset($values['value']) && preg_match('#^&(?P<ref>[^ ]+) *(?P<value>.*)#u', $values['value'], $matches)) { |
|
89 | $isRef = $matches['ref']; |
||
90 | $values['value'] = $matches['value']; |
||
91 | } |
||
92 | |||
93 | // array |
||
94 | if (!isset($values['value']) || '' == trim($values['value'], ' ') || 0 === strpos(ltrim($values['value'], ' '), '#')) { |
||
95 | $c = $this->getRealCurrentLineNb() + 1; |
||
96 | $parser = new self($c); |
||
97 | $parser->refs = &$this->refs; |
||
98 | $data[] = $parser->parse($this->getNextEmbedBlock(null, true), $exceptionOnInvalidType, $objectSupport, $objectForMap); |
||
99 | } else { |
||
100 | if (isset($values['leadspaces']) |
||
101 | && preg_match('#^(?P<key>'.Inline::REGEX_QUOTED_STRING.'|[^ \'"\{\[].*?) *\:(\s+(?P<value>.+?))?\s*$#u', $values['value'], $matches) |
||
102 | ) { |
||
103 | // this is a compact notation element, add to next block and parse |
||
104 | $c = $this->getRealCurrentLineNb(); |
||
105 | $parser = new self($c); |
||
106 | $parser->refs = &$this->refs; |
||
107 | |||
108 | $block = $values['value']; |
||
109 | if ($this->isNextLineIndented()) { |
||
110 | $block .= "\n".$this->getNextEmbedBlock($this->getCurrentLineIndentation() + strlen($values['leadspaces']) + 1); |
||
111 | } |
||
112 | |||
113 | $data[] = $parser->parse($block, $exceptionOnInvalidType, $objectSupport, $objectForMap); |
||
114 | } else { |
||
115 | $data[] = $this->parseValue($values['value'], $exceptionOnInvalidType, $objectSupport, $objectForMap); |
||
116 | } |
||
117 | } |
||
118 | } elseif (preg_match('#^(?P<key>'.Inline::REGEX_QUOTED_STRING.'|[^ \'"\[\{].*?) *\:(\s+(?P<value>.+?))?\s*$#u', $this->currentLine, $values) && (false === strpos($values['key'], ' #') || in_array($values['key'][0], array('"', "'")))) { |
||
119 | if ($context && 'sequence' == $context) { |
||
120 | throw new ParseException('You cannot define a mapping item when in a sequence'); |
||
121 | } |
||
122 | $context = 'mapping'; |
||
123 | |||
124 | // force correct settings |
||
125 | Inline::parse(null, $exceptionOnInvalidType, $objectSupport, $objectForMap, $this->refs); |
||
126 | try { |
||
127 | $key = Inline::parseScalar($values['key']); |
||
128 | } catch (ParseException $e) { |
||
129 | $e->setParsedLine($this->getRealCurrentLineNb() + 1); |
||
130 | $e->setSnippet($this->currentLine); |
||
131 | |||
132 | throw $e; |
||
133 | } |
||
134 | |||
135 | if ('<<' === $key) { |
||
136 | $mergeNode = true; |
||
137 | $allowOverwrite = true; |
||
138 | if (isset($values['value']) && 0 === strpos($values['value'], '*')) { |
||
139 | $refName = substr($values['value'], 1); |
||
140 | if (!array_key_exists($refName, $this->refs)) { |
||
141 | throw new ParseException(sprintf('Reference "%s" does not exist.', $refName), $this->getRealCurrentLineNb() + 1, $this->currentLine); |
||
142 | } |
||
143 | |||
144 | $refValue = $this->refs[$refName]; |
||
145 | |||
146 | if (!is_array($refValue)) { |
||
147 | throw new ParseException('YAML merge keys used with a scalar value instead of an array.', $this->getRealCurrentLineNb() + 1, $this->currentLine); |
||
148 | } |
||
149 | |||
150 | foreach ($refValue as $key => $value) { |
||
151 | if (!isset($data[$key])) { |
||
152 | $data[$key] = $value; |
||
153 | } |
||
154 | } |
||
155 | } else { |
||
156 | if (isset($values['value']) && $values['value'] !== '') { |
||
157 | $value = $values['value']; |
||
158 | } else { |
||
159 | $value = $this->getNextEmbedBlock(); |
||
160 | } |
||
161 | $c = $this->getRealCurrentLineNb() + 1; |
||
162 | $parser = new self($c); |
||
163 | $parser->refs = &$this->refs; |
||
164 | $parsed = $parser->parse($value, $exceptionOnInvalidType, $objectSupport, $objectForMap); |
||
165 | |||
166 | if (!is_array($parsed)) { |
||
167 | throw new ParseException('YAML merge keys used with a scalar value instead of an array.', $this->getRealCurrentLineNb() + 1, $this->currentLine); |
||
168 | } |
||
169 | |||
170 | if (isset($parsed[0])) { |
||
171 | // If the value associated with the merge key is a sequence, then this sequence is expected to contain mapping nodes |
||
172 | // and each of these nodes is merged in turn according to its order in the sequence. Keys in mapping nodes earlier |
||
173 | // in the sequence override keys specified in later mapping nodes. |
||
174 | foreach ($parsed as $parsedItem) { |
||
175 | if (!is_array($parsedItem)) { |
||
176 | throw new ParseException('Merge items must be arrays.', $this->getRealCurrentLineNb() + 1, $parsedItem); |
||
177 | } |
||
178 | |||
179 | foreach ($parsedItem as $key => $value) { |
||
180 | if (!isset($data[$key])) { |
||
181 | $data[$key] = $value; |
||
182 | } |
||
183 | } |
||
184 | } |
||
185 | } else { |
||
186 | // If the value associated with the key is a single mapping node, each of its key/value pairs is inserted into the |
||
187 | // current mapping, unless the key already exists in it. |
||
188 | foreach ($parsed as $key => $value) { |
||
189 | if (!isset($data[$key])) { |
||
190 | $data[$key] = $value; |
||
191 | } |
||
192 | } |
||
193 | } |
||
194 | } |
||
195 | View Code Duplication | } elseif (isset($values['value']) && preg_match('#^&(?P<ref>[^ ]+) *(?P<value>.*)#u', $values['value'], $matches)) { |
|
196 | $isRef = $matches['ref']; |
||
197 | $values['value'] = $matches['value']; |
||
198 | } |
||
199 | |||
200 | if ($mergeNode) { |
||
201 | // Merge keys |
||
202 | } elseif (!isset($values['value']) || '' == trim($values['value'], ' ') || 0 === strpos(ltrim($values['value'], ' '), '#')) { |
||
203 | // hash |
||
204 | // if next line is less indented or equal, then it means that the current value is null |
||
205 | if (!$this->isNextLineIndented() && !$this->isNextLineUnIndentedCollection()) { |
||
206 | // Spec: Keys MUST be unique; first one wins. |
||
207 | // But overwriting is allowed when a merge node is used in current block. |
||
208 | if ($allowOverwrite || !isset($data[$key])) { |
||
209 | $data[$key] = null; |
||
210 | } |
||
211 | } else { |
||
212 | $c = $this->getRealCurrentLineNb() + 1; |
||
213 | $parser = new self($c); |
||
214 | $parser->refs = &$this->refs; |
||
215 | $value = $parser->parse($this->getNextEmbedBlock(), $exceptionOnInvalidType, $objectSupport, $objectForMap); |
||
216 | // Spec: Keys MUST be unique; first one wins. |
||
217 | // But overwriting is allowed when a merge node is used in current block. |
||
218 | if ($allowOverwrite || !isset($data[$key])) { |
||
219 | $data[$key] = $value; |
||
220 | } |
||
221 | } |
||
222 | } else { |
||
223 | $value = $this->parseValue($values['value'], $exceptionOnInvalidType, $objectSupport, $objectForMap); |
||
224 | // Spec: Keys MUST be unique; first one wins. |
||
225 | // But overwriting is allowed when a merge node is used in current block. |
||
226 | if ($allowOverwrite || !isset($data[$key])) { |
||
227 | $data[$key] = $value; |
||
228 | } |
||
229 | } |
||
230 | } else { |
||
231 | // multiple documents are not supported |
||
232 | if ('---' === $this->currentLine) { |
||
233 | throw new ParseException('Multiple documents are not supported.'); |
||
234 | } |
||
235 | |||
236 | // 1-liner optionally followed by newline(s) |
||
237 | if ($this->lines[0] === trim($value)) { |
||
238 | try { |
||
239 | $value = Inline::parse($this->lines[0], $exceptionOnInvalidType, $objectSupport, $objectForMap, $this->refs); |
||
240 | } catch (ParseException $e) { |
||
241 | $e->setParsedLine($this->getRealCurrentLineNb() + 1); |
||
242 | $e->setSnippet($this->currentLine); |
||
243 | |||
244 | throw $e; |
||
245 | } |
||
246 | |||
247 | if (is_array($value)) { |
||
248 | $first = reset($value); |
||
249 | if (is_string($first) && 0 === strpos($first, '*')) { |
||
250 | $data = array(); |
||
251 | foreach ($value as $alias) { |
||
252 | $data[] = $this->refs[substr($alias, 1)]; |
||
253 | } |
||
254 | $value = $data; |
||
255 | } |
||
256 | } |
||
257 | |||
258 | if (isset($mbEncoding)) { |
||
259 | mb_internal_encoding($mbEncoding); |
||
260 | } |
||
261 | |||
262 | return $value; |
||
263 | } |
||
264 | |||
265 | switch (preg_last_error()) { |
||
266 | case PREG_INTERNAL_ERROR: |
||
267 | $error = 'Internal PCRE error.'; |
||
268 | break; |
||
269 | case PREG_BACKTRACK_LIMIT_ERROR: |
||
270 | $error = 'pcre.backtrack_limit reached.'; |
||
271 | break; |
||
272 | case PREG_RECURSION_LIMIT_ERROR: |
||
273 | $error = 'pcre.recursion_limit reached.'; |
||
274 | break; |
||
275 | case PREG_BAD_UTF8_ERROR: |
||
276 | $error = 'Malformed UTF-8 data.'; |
||
277 | break; |
||
278 | case PREG_BAD_UTF8_OFFSET_ERROR: |
||
279 | $error = 'Offset doesn\'t correspond to the begin of a valid UTF-8 code point.'; |
||
280 | break; |
||
281 | default: |
||
282 | $error = 'Unable to parse.'; |
||
283 | } |
||
284 | |||
285 | throw new ParseException($error, $this->getRealCurrentLineNb() + 1, $this->currentLine); |
||
286 | } |
||
287 | |||
288 | if ($isRef) { |
||
289 | $this->refs[$isRef] = end($data); |
||
290 | } |
||
291 | } |
||
292 | |||
293 | if (isset($mbEncoding)) { |
||
294 | mb_internal_encoding($mbEncoding); |
||
295 | } |
||
296 | |||
297 | return empty($data) ? null : $data; |
||
298 | } |
||
299 | |||
698 |
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.