Test Failed
Push — ci ( df83b3...4cd40d )
by litefeel
02:05
created

Spyc.php (32 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
   * Spyc -- A Simple PHP YAML Class
4
   * @version 0.5.1
5
   * @author Vlad Andersen <[email protected]>
6
   * @author Chris Wanstrath <[email protected]>
7
   * @link https://github.com/mustangostang/spyc/
8
   * @copyright Copyright 2005-2006 Chris Wanstrath, 2006-2011 Vlad Andersen
9
   * @license http://www.opensource.org/licenses/mit-license.php MIT License
10
   * @package Spyc
11
   */
12
13
if (!function_exists('spyc_load')) {
14
  /**
15
   * Parses YAML to array.
16
   * @param string $string YAML string.
17
   * @return array
18
   */
19
  function spyc_load ($string) {
20
    return Spyc::YAMLLoadString($string);
21
  }
22
}
23
24
if (!function_exists('spyc_load_file')) {
25
  /**
26
   * Parses YAML to array.
27
   * @param string $file Path to YAML file.
28
   * @return array
29
   */
30
  function spyc_load_file ($file) {
31
    return Spyc::YAMLLoad($file);
32
  }
33
}
34
35
if (!function_exists('spyc_dump')) {
36
  /**
37
   * Dumps array to YAML.
38
   * @param array $data Array.
39
   * @return string
40
   */
41
  function spyc_dump ($data) {
42
    return Spyc::YAMLDump($data, false, false, true);
0 ignored issues
show
true is of type boolean, but the function expects a false|integer.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
43
  }
44
}
45
46
if (!class_exists('Spyc')) {
47
48
/**
49
   * The Simple PHP YAML Class.
50
   *
51
   * This class can be used to read a YAML file and convert its contents
52
   * into a PHP array.  It currently supports a very limited subsection of
53
   * the YAML spec.
54
   *
55
   * Usage:
56
   * <code>
57
   *   $Spyc  = new Spyc;
58
   *   $array = $Spyc->load($file);
59
   * </code>
60
   * or:
61
   * <code>
62
   *   $array = Spyc::YAMLLoad($file);
63
   * </code>
64
   * or:
65
   * <code>
66
   *   $array = spyc_load_file($file);
67
   * </code>
68
   * @package Spyc
69
   */
70
class Spyc {
71
72
  // SETTINGS
73
74
  const REMPTY = "\0\0\0\0\0";
75
76
  /**
77
   * Setting this to true will force YAMLDump to enclose any string value in
78
   * quotes.  False by default.
79
   *
80
   * @var bool
81
   */
82
  public $setting_dump_force_quotes = false;
83
84
  /**
85
   * Setting this to true will forse YAMLLoad to use syck_load function when
86
   * possible. False by default.
87
   * @var bool
88
   */
89
  public $setting_use_syck_is_possible = false;
90
91
92
93
  /**#@+
94
  * @access private
95
  * @var mixed
96
  */
97
  private $_dumpIndent;
98
  private $_dumpWordWrap;
99
  private $_containsGroupAnchor = false;
100
  private $_containsGroupAlias = false;
101
  private $path;
102
  private $result;
103
  private $LiteralPlaceHolder = '___YAML_Literal_Block___';
104
  private $SavedGroups = array();
105
  private $indent;
106
  /**
107
   * Path modifier that should be applied after adding current element.
108
   * @var array
109
   */
110
  private $delayedPath = array();
111
112
  /**#@+
113
  * @access public
114
  * @var mixed
115
  */
116
  public $_nodeId;
117
118
/**
119
 * Load a valid YAML string to Spyc.
120
 * @param string $input
121
 * @return array
122
 */
123
  public function load ($input) {
124
    return $this->__loadString($input);
125
  }
126
127
 /**
128
 * Load a valid YAML file to Spyc.
129
 * @param string $file
130
 * @return array
131
 */
132
  public function loadFile ($file) {
133
    return $this->__load($file);
134
  }
135
136
  /**
137
     * Load YAML into a PHP array statically
138
     *
139
     * The load method, when supplied with a YAML stream (string or file),
140
     * will do its best to convert YAML in a file into a PHP array.  Pretty
141
     * simple.
142
     *  Usage:
143
     *  <code>
144
     *   $array = Spyc::YAMLLoad('lucky.yaml');
145
     *   print_r($array);
146
     *  </code>
147
     * @access public
148
     * @return array
149
     * @param string $input Path of YAML file or string containing YAML
150
     */
151
  public static function YAMLLoad($input) {
152
    $Spyc = new Spyc;
153
    return $Spyc->__load($input);
154
  }
155
156
  /**
157
     * Load a string of YAML into a PHP array statically
158
     *
159
     * The load method, when supplied with a YAML string, will do its best
160
     * to convert YAML in a string into a PHP array.  Pretty simple.
161
     *
162
     * Note: use this function if you don't want files from the file system
163
     * loaded and processed as YAML.  This is of interest to people concerned
164
     * about security whose input is from a string.
165
     *
166
     *  Usage:
167
     *  <code>
168
     *   $array = Spyc::YAMLLoadString("---\n0: hello world\n");
169
     *   print_r($array);
170
     *  </code>
171
     * @access public
172
     * @return array
173
     * @param string $input String containing YAML
174
     */
175
  public static function YAMLLoadString($input) {
176
    $Spyc = new Spyc;
177
    return $Spyc->__loadString($input);
178
  }
179
180
  /**
181
     * Dump YAML from PHP array statically
182
     *
183
     * The dump method, when supplied with an array, will do its best
184
     * to convert the array into friendly YAML.  Pretty simple.  Feel free to
185
     * save the returned string as nothing.yaml and pass it around.
186
     *
187
     * Oh, and you can decide how big the indent is and what the wordwrap
188
     * for folding is.  Pretty cool -- just pass in 'false' for either if
189
     * you want to use the default.
190
     *
191
     * Indent's default is 2 spaces, wordwrap's default is 40 characters.  And
192
     * you can turn off wordwrap by passing in 0.
193
     *
194
     * @access public
195
     * @return string
196
     * @param array $array PHP array
197
     * @param int $indent Pass in false to use the default, which is 2
198
     * @param int $wordwrap Pass in 0 for no wordwrap, false for default (40)
199
     * @param int $no_opening_dashes Do not start YAML file with "---\n"
200
     */
201
  public static function YAMLDump($array, $indent = false, $wordwrap = false, $no_opening_dashes = false) {
202
    $spyc = new Spyc;
203
    return $spyc->dump($array, $indent, $wordwrap, $no_opening_dashes);
0 ignored issues
show
It seems like $no_opening_dashes defined by parameter $no_opening_dashes on line 201 can also be of type integer; however, Spyc::dump() does only seem to accept boolean, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
204
  }
205
206
207
  /**
208
     * Dump PHP array to YAML
209
     *
210
     * The dump method, when supplied with an array, will do its best
211
     * to convert the array into friendly YAML.  Pretty simple.  Feel free to
212
     * save the returned string as tasteful.yaml and pass it around.
213
     *
214
     * Oh, and you can decide how big the indent is and what the wordwrap
215
     * for folding is.  Pretty cool -- just pass in 'false' for either if
216
     * you want to use the default.
217
     *
218
     * Indent's default is 2 spaces, wordwrap's default is 40 characters.  And
219
     * you can turn off wordwrap by passing in 0.
220
     *
221
     * @access public
222
     * @return string
223
     * @param array $array PHP array
224
     * @param int $indent Pass in false to use the default, which is 2
225
     * @param int $wordwrap Pass in 0 for no wordwrap, false for default (40)
226
     */
227
  public function dump($array,$indent = false,$wordwrap = false, $no_opening_dashes = false) {
228
    // Dumps to some very clean YAML.  We'll have to add some more features
229
    // and options soon.  And better support for folding.
230
231
    // New features and options.
232
    if ($indent === false or !is_numeric($indent)) {
233
      $this->_dumpIndent = 2;
234
    } else {
235
      $this->_dumpIndent = $indent;
236
    }
237
238
    if ($wordwrap === false or !is_numeric($wordwrap)) {
239
      $this->_dumpWordWrap = 40;
240
    } else {
241
      $this->_dumpWordWrap = $wordwrap;
242
    }
243
244
    // New YAML document
245
    $string = "";
246
    if (!$no_opening_dashes) $string = "---\n";
247
248
    // Start at the base of the array and move through it.
249
    if ($array) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $array of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
250
      $array = (array)$array;
251
      $previous_key = -1;
252 View Code Duplication
      foreach ($array as $key => $value) {
0 ignored issues
show
This code seems to be duplicated across your project.

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.

Loading history...
253
        if (!isset($first_key)) $first_key = $key;
254
        $string .= $this->_yamlize($key,$value,0,$previous_key, $first_key, $array);
255
        $previous_key = $key;
256
      }
257
    }
258
    return $string;
259
  }
260
261
  /**
262
     * Attempts to convert a key / value array item to YAML
263
     * @access private
264
     * @return string
265
     * @param $key The name of the key
266
     * @param $value The value of the item
267
     * @param $indent The indent of the current node
268
     */
269
  private function _yamlize($key,$value,$indent, $previous_key = -1, $first_key = 0, $source_array = null) {
270
    if(is_object($value)) $value = (array)$value;
271
    if (is_array($value)) {
272
      if (empty ($value))
273
        return $this->_dumpNode($key, array(), $indent, $previous_key, $first_key, $source_array);
274
      // It has children.  What to do?
275
      // Make it the right kind of item
276
      $string = $this->_dumpNode($key, self::REMPTY, $indent, $previous_key, $first_key, $source_array);
277
      // Add the indent
278
      $indent += $this->_dumpIndent;
279
      // Yamlize the array
280
      $string .= $this->_yamlizeArray($value,$indent);
281
    } elseif (!is_array($value)) {
282
      // It doesn't have children.  Yip.
283
      $string = $this->_dumpNode($key, $value, $indent, $previous_key, $first_key, $source_array);
284
    }
285
    return $string;
0 ignored issues
show
The variable $string does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
286
  }
287
288
  /**
289
     * Attempts to convert an array to YAML
290
     * @access private
291
     * @return string
292
     * @param $array The array you want to convert
293
     * @param $indent The indent of the current level
294
     */
295
  private function _yamlizeArray($array,$indent) {
296
    if (is_array($array)) {
297
      $string = '';
298
      $previous_key = -1;
299 View Code Duplication
      foreach ($array as $key => $value) {
0 ignored issues
show
This code seems to be duplicated across your project.

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.

Loading history...
300
        if (!isset($first_key)) $first_key = $key;
301
        $string .= $this->_yamlize($key, $value, $indent, $previous_key, $first_key, $array);
302
        $previous_key = $key;
303
      }
304
      return $string;
305
    } else {
306
      return false;
307
    }
308
  }
309
310
  /**
311
     * Returns YAML from a key and a value
312
     * @access private
313
     * @return string
314
     * @param $key The name of the key
315
     * @param $value The value of the item
316
     * @param $indent The indent of the current node
317
     */
318
  private function _dumpNode($key, $value, $indent, $previous_key = -1, $first_key = 0, $source_array = null) {
0 ignored issues
show
The parameter $previous_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...
The parameter $first_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...
319
    // do some folding here, for blocks
320
    if (is_string ($value) && ((strpos($value,"\n") !== false || strpos($value,": ") !== false || strpos($value,"- ") !== false ||
321
      strpos($value,"*") !== false || strpos($value,"#") !== false || strpos($value,"<") !== false || strpos($value,">") !== false || strpos ($value, '%') !== false || strpos ($value, '  ') !== false ||
322
      strpos($value,"[") !== false || strpos($value,"]") !== false || strpos($value,"{") !== false || strpos($value,"}") !== false) || strpos($value,"&") !== false || strpos($value, "'") !== false || strpos($value, "!") === 0 ||
323
      substr ($value, -1, 1) == ':')
324
    ) {
325
      $value = $this->_doLiteralBlock($value,$indent);
326
    } else {
327
      $value  = $this->_doFolding($value,$indent);
328
    }
329
330
    if ($value === array()) $value = '[ ]';
331
    if ($value === "") $value = '""';
332
    if (self::isTranslationWord($value)) {
333
      $value = $this->_doLiteralBlock($value, $indent);
334
    }
335
    if (trim ($value) != $value)
336
       $value = $this->_doLiteralBlock($value,$indent);
337
338
    if (is_bool($value)) {
339
       $value = $value ? "true" : "false";
340
    }
341
342
    if ($value === null) $value = 'null';
343
    if ($value === "'" . self::REMPTY . "'") $value = null;
344
345
    $spaces = str_repeat(' ',$indent);
346
347
    //if (is_int($key) && $key - 1 == $previous_key && $first_key===0) {
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
348
    if (is_array ($source_array) && array_keys($source_array) === range(0, count($source_array) - 1)) {
349
      // It's a sequence
350
      $string = $spaces.'- '.$value."\n";
351
    } else {
352
      // if ($first_key===0)  throw new Exception('Keys are all screwy.  The first one was zero, now it\'s "'. $key .'"');
353
      // It's mapped
354
      if (strpos($key, ":") !== false || strpos($key, "#") !== false) { $key = '"' . $key . '"'; }
355
      $string = rtrim ($spaces.$key.': '.$value)."\n";
356
    }
357
    return $string;
358
  }
359
360
  /**
361
     * Creates a literal block for dumping
362
     * @access private
363
     * @return string
364
     * @param $value
365
     * @param $indent int The value of the indent
366
     */
367
  private function _doLiteralBlock($value,$indent) {
368
    if ($value === "\n") return '\n';
369 View Code Duplication
    if (strpos($value, "\n") === false && strpos($value, "'") === false) {
0 ignored issues
show
This code seems to be duplicated across your project.

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.

Loading history...
370
      return sprintf ("'%s'", $value);
371
    }
372 View Code Duplication
    if (strpos($value, "\n") === false && strpos($value, '"') === false) {
0 ignored issues
show
This code seems to be duplicated across your project.

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.

Loading history...
373
      return sprintf ('"%s"', $value);
374
    }
375
    $exploded = explode("\n",$value);
376
    $newValue = '|';
377
    if (isset($exploded[0]) && ($exploded[0] == "|" || $exploded[0] == "|-" || $exploded[0] == ">")) {
378
        $newValue = $exploded[0];
379
        unset($exploded[0]);
380
    }
381
    $indent += $this->_dumpIndent;
382
    $spaces   = str_repeat(' ',$indent);
383
    foreach ($exploded as $line) {
384
      $line = trim($line);
385
      if (strpos($line, '"') === 0 && strrpos($line, '"') == (strlen($line)-1) || strpos($line, "'") === 0 && strrpos($line, "'") == (strlen($line)-1)) {
386
        $line = substr($line, 1, -1);
387
      }
388
      $newValue .= "\n" . $spaces . ($line);
389
    }
390
    return $newValue;
391
  }
392
393
  /**
394
     * Folds a string of text, if necessary
395
     * @access private
396
     * @return string
397
     * @param $value The string you wish to fold
398
     */
399
  private function _doFolding($value,$indent) {
400
    // Don't do anything if wordwrap is set to 0
401
402
    if ($this->_dumpWordWrap !== 0 && is_string ($value) && strlen($value) > $this->_dumpWordWrap) {
403
      $indent += $this->_dumpIndent;
404
      $indent = str_repeat(' ',$indent);
405
      $wrapped = wordwrap($value,$this->_dumpWordWrap,"\n$indent");
406
      $value   = ">\n".$indent.$wrapped;
407
    } else {
408
      if ($this->setting_dump_force_quotes && is_string ($value) && $value !== self::REMPTY)
409
        $value = '"' . $value . '"';
410
      if (is_numeric($value) && is_string($value))
411
        $value = '"' . $value . '"';
412
    }
413
414
415
    return $value;
416
  }
417
418
  private function isTrueWord($value) {
419
    $words = self::getTranslations(array('true', 'on', 'yes', 'y'));
420
    return in_array($value, $words, true);
421
  }
422
423
  private function isFalseWord($value) {
424
    $words = self::getTranslations(array('false', 'off', 'no', 'n'));
425
    return in_array($value, $words, true);
426
  }
427
428
  private function isNullWord($value) {
429
    $words = self::getTranslations(array('null', '~'));
430
    return in_array($value, $words, true);
431
  }
432
433
  private function isTranslationWord($value) {
434
    return (
435
      self::isTrueWord($value)  ||
436
      self::isFalseWord($value) ||
437
      self::isNullWord($value)
438
    );
439
  }
440
441
  /**
442
     * Coerce a string into a native type
443
     * Reference: http://yaml.org/type/bool.html
444
     * TODO: Use only words from the YAML spec.
445
     * @access private
446
     * @param $value The value to coerce
447
     */
448
  private function coerceValue(&$value) {
449
    if (self::isTrueWord($value)) {
450
      $value = true;
451
    } else if (self::isFalseWord($value)) {
452
      $value = false;
453
    } else if (self::isNullWord($value)) {
454
      $value = null;
455
    }
456
  }
457
458
  /**
459
     * Given a set of words, perform the appropriate translations on them to
460
     * match the YAML 1.1 specification for type coercing.
461
     * @param $words The words to translate
462
     * @access private
463
     */
464
  private static function getTranslations(array $words) {
465
    $result = array();
466
    foreach ($words as $i) {
467
      $result = array_merge($result, array(ucfirst($i), strtoupper($i), strtolower($i)));
468
    }
469
    return $result;
470
  }
471
472
// LOADING FUNCTIONS
473
474
  private function __load($input) {
475
    $Source = $this->loadFromSource($input);
476
    return $this->loadWithSource($Source);
477
  }
478
479
  private function __loadString($input) {
480
    $Source = $this->loadFromString($input);
481
    return $this->loadWithSource($Source);
482
  }
483
484
  private function loadWithSource($Source) {
485
    if (empty ($Source)) return array();
486
    if ($this->setting_use_syck_is_possible && function_exists ('syck_load')) {
487
      $array = syck_load (implode ("\n", $Source));
488
      return is_array($array) ? $array : array();
489
    }
490
491
    $this->path = array();
492
    $this->result = array();
493
494
    $cnt = count($Source);
495
    for ($i = 0; $i < $cnt; $i++) {
496
      $line = $Source[$i];
497
498
      $this->indent = strlen($line) - strlen(ltrim($line));
499
      $tempPath = $this->getParentPathByIndent($this->indent);
500
      $line = self::stripIndent($line, $this->indent);
501
      if (self::isComment($line)) continue;
502
      if (self::isEmpty($line)) continue;
503
      $this->path = $tempPath;
504
505
      $literalBlockStyle = self::startsLiteralBlock($line);
506
      if ($literalBlockStyle) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $literalBlockStyle of type false|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
507
        $line = rtrim ($line, $literalBlockStyle . " \n");
508
        $literalBlock = '';
509
        $line .= ' '.$this->LiteralPlaceHolder;
510
        $literal_block_indent = strlen($Source[$i+1]) - strlen(ltrim($Source[$i+1]));
511
        while (++$i < $cnt && $this->literalBlockContinues($Source[$i], $this->indent)) {
512
          $literalBlock = $this->addLiteralLine($literalBlock, $Source[$i], $literalBlockStyle, $literal_block_indent);
513
        }
514
        $i--;
515
      }
516
517
      // Strip out comments
518
      if (strpos ($line, '#')) {
519
          $line = preg_replace('/\s*#([^"\']+)$/','',$line);
520
      }
521
522
      while (++$i < $cnt && self::greedilyNeedNextLine($line)) {
523
        $line = rtrim ($line, " \n\t\r") . ' ' . ltrim ($Source[$i], " \t");
524
      }
525
      $i--;
526
527
      $lineArray = $this->_parseLine($line);
528
529
      if ($literalBlockStyle)
0 ignored issues
show
Bug Best Practice introduced by
The expression $literalBlockStyle of type false|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
530
        $lineArray = $this->revertLiteralPlaceHolder ($lineArray, $literalBlock);
0 ignored issues
show
The variable $literalBlock does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
531
532
      $this->addArray($lineArray, $this->indent);
533
534
      foreach ($this->delayedPath as $indent => $delayedPath)
535
        $this->path[$indent] = $delayedPath;
536
537
      $this->delayedPath = array();
538
539
    }
540
    return $this->result;
541
  }
542
543
  private function loadFromSource ($input) {
544
    if (!empty($input) && strpos($input, "\n") === false && file_exists($input))
545
      $input = file_get_contents($input);
546
547
    return $this->loadFromString($input);
548
  }
549
550
  private function loadFromString ($input) {
551
    $lines = explode("\n",$input);
552
    foreach ($lines as $k => $_) {
553
      $lines[$k] = rtrim ($_, "\r");
554
    }
555
    return $lines;
556
  }
557
558
  /**
559
     * Parses YAML code and returns an array for a node
560
     * @access private
561
     * @return array
562
     * @param string $line A line from the YAML file
563
     */
564
  private function _parseLine($line) {
565
    if (!$line) return array();
566
    $line = trim($line);
567
    if (!$line) return array();
568
569
    $array = array();
0 ignored issues
show
$array is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
570
571
    $group = $this->nodeContainsGroup($line);
572
    if ($group) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $group of type false|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
573
      $this->addGroup($line, $group);
574
      $line = $this->stripGroup ($line, $group);
575
    }
576
577
    if ($this->startsMappedSequence($line))
578
      return $this->returnMappedSequence($line);
579
580
    if ($this->startsMappedValue($line))
581
      return $this->returnMappedValue($line);
582
583
    if ($this->isArrayElement($line))
584
     return $this->returnArrayElement($line);
585
586
    if ($this->isPlainArray($line))
587
     return $this->returnPlainArray($line);
588
589
590
    return $this->returnKeyValuePair($line);
591
592
  }
593
594
  /**
595
     * Finds the type of the passed value, returns the value as the new type.
596
     * @access private
597
     * @param string $value
598
     * @return mixed
599
     */
600
  private function _toType($value) {
601
    if ($value === '') return "";
602
    $first_character = $value[0];
603
    $last_character = substr($value, -1, 1);
604
605
    $is_quoted = false;
606
    do {
607
      if (!$value) break;
608
      if ($first_character != '"' && $first_character != "'") break;
609
      if ($last_character != '"' && $last_character != "'") break;
610
      $is_quoted = true;
611
    } while (0);
612
613
    if ($is_quoted) {
614
      $value = str_replace('\n', "\n", $value);
615
      if ($first_character == "'")
616
        return strtr(substr ($value, 1, -1), array ('\'\'' => '\'', '\\\''=> '\''));
617
      return strtr(substr ($value, 1, -1), array ('\\"' => '"', '\\\''=> '\''));
618
    }
619
620
    if (strpos($value, ' #') !== false && !$is_quoted)
621
      $value = preg_replace('/\s+#(.+)$/','',$value);
622
623
    if ($first_character == '[' && $last_character == ']') {
624
      // Take out strings sequences and mappings
625
      $innerValue = trim(substr ($value, 1, -1));
626
      if ($innerValue === '') return array();
627
      $explode = $this->_inlineEscape($innerValue);
628
      // Propagate value array
629
      $value  = array();
630
      foreach ($explode as $v) {
631
        $value[] = $this->_toType($v);
632
      }
633
      return $value;
634
    }
635
636
    if (strpos($value,': ')!==false && $first_character != '{') {
637
      $array = explode(': ',$value);
638
      $key   = trim($array[0]);
639
      array_shift($array);
640
      $value = trim(implode(': ',$array));
641
      $value = $this->_toType($value);
642
      return array($key => $value);
643
    }
644
645
    if ($first_character == '{' && $last_character == '}') {
646
      $innerValue = trim(substr ($value, 1, -1));
647
      if ($innerValue === '') return array();
648
      // Inline Mapping
649
      // Take out strings sequences and mappings
650
      $explode = $this->_inlineEscape($innerValue);
651
      // Propagate value array
652
      $array = array();
653
      foreach ($explode as $v) {
654
        $SubArr = $this->_toType($v);
655
        if (empty($SubArr)) continue;
656
        if (is_array ($SubArr)) {
657
          $array[key($SubArr)] = $SubArr[key($SubArr)]; continue;
658
        }
659
        $array[] = $SubArr;
660
      }
661
      return $array;
662
    }
663
664
    if ($value == 'null' || $value == 'NULL' || $value == 'Null' || $value == '' || $value == '~') {
665
      return null;
666
    }
667
668
    if ( is_numeric($value) && preg_match ('/^(-|)[1-9]+[0-9]*$/', $value) ){
669
      $intvalue = (int)$value;
670
      if ($intvalue != PHP_INT_MAX && $intvalue != ~PHP_INT_MAX)
671
        $value = $intvalue;
672
      return $value;
673
    }
674
675
    if (is_numeric($value) && preg_match('/^0[xX][0-9a-fA-F]+$/', $value)) {
676
      // Hexadecimal value.
677
      return hexdec($value);
678
    }
679
680
    $this->coerceValue($value);
681
682
    if (is_numeric($value)) {
683
      if ($value === '0') return 0;
684
      if (rtrim ($value, 0) === $value)
685
        $value = (float)$value;
686
      return $value;
687
    }
688
689
    return $value;
690
  }
691
692
  /**
693
     * Used in inlines to check for more inlines or quoted strings
694
     * @access private
695
     * @return array
696
     */
697
  private function _inlineEscape($inline) {
698
    // There's gotta be a cleaner way to do this...
699
    // While pure sequences seem to be nesting just fine,
700
    // pure mappings and mappings with sequences inside can't go very
701
    // deep.  This needs to be fixed.
702
703
    $seqs = array();
704
    $maps = array();
705
    $saved_strings = array();
706
    $saved_empties = array();
707
708
    // Check for empty strings
709
    $regex = '/("")|(\'\')/';
710
    if (preg_match_all($regex,$inline,$strings)) {
711
      $saved_empties = $strings[0];
712
      $inline  = preg_replace($regex,'YAMLEmpty',$inline);
713
    }
714
    unset($regex);
715
716
    // Check for strings
717
    $regex = '/(?:(")|(?:\'))((?(1)[^"]+|[^\']+))(?(1)"|\')/';
718
    if (preg_match_all($regex,$inline,$strings)) {
719
      $saved_strings = $strings[0];
720
      $inline  = preg_replace($regex,'YAMLString',$inline);
721
    }
722
    unset($regex);
723
724
    // echo $inline;
725
726
    $i = 0;
727
    do {
728
729
    // Check for sequences
730 View Code Duplication
    while (preg_match('/\[([^{}\[\]]+)\]/U',$inline,$matchseqs)) {
0 ignored issues
show
This code seems to be duplicated across your project.

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.

Loading history...
731
      $seqs[] = $matchseqs[0];
732
      $inline = preg_replace('/\[([^{}\[\]]+)\]/U', ('YAMLSeq' . (count($seqs) - 1) . 's'), $inline, 1);
733
    }
734
735
    // Check for mappings
736 View Code Duplication
    while (preg_match('/{([^\[\]{}]+)}/U',$inline,$matchmaps)) {
0 ignored issues
show
This code seems to be duplicated across your project.

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.

Loading history...
737
      $maps[] = $matchmaps[0];
738
      $inline = preg_replace('/{([^\[\]{}]+)}/U', ('YAMLMap' . (count($maps) - 1) . 's'), $inline, 1);
739
    }
740
741
    if ($i++ >= 10) break;
742
743
    } while (strpos ($inline, '[') !== false || strpos ($inline, '{') !== false);
744
745
    $explode = explode(',',$inline);
746
    $explode = array_map('trim', $explode);
747
    $stringi = 0; $i = 0;
748
749
    while (1) {
750
751
    // Re-add the sequences
752 View Code Duplication
    if (!empty($seqs)) {
0 ignored issues
show
This code seems to be duplicated across your project.

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.

Loading history...
753
      foreach ($explode as $key => $value) {
754
        if (strpos($value,'YAMLSeq') !== false) {
755
          foreach ($seqs as $seqk => $seq) {
756
            $explode[$key] = str_replace(('YAMLSeq'.$seqk.'s'),$seq,$value);
757
            $value = $explode[$key];
758
          }
759
        }
760
      }
761
    }
762
763
    // Re-add the mappings
764 View Code Duplication
    if (!empty($maps)) {
0 ignored issues
show
This code seems to be duplicated across your project.

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.

Loading history...
765
      foreach ($explode as $key => $value) {
766
        if (strpos($value,'YAMLMap') !== false) {
767
          foreach ($maps as $mapk => $map) {
768
            $explode[$key] = str_replace(('YAMLMap'.$mapk.'s'), $map, $value);
769
            $value = $explode[$key];
770
          }
771
        }
772
      }
773
    }
774
775
776
    // Re-add the strings
777
    if (!empty($saved_strings)) {
778
      foreach ($explode as $key => $value) {
779
        while (strpos($value,'YAMLString') !== false) {
780
          $explode[$key] = preg_replace('/YAMLString/',$saved_strings[$stringi],$value, 1);
781
          unset($saved_strings[$stringi]);
782
          ++$stringi;
783
          $value = $explode[$key];
784
        }
785
      }
786
    }
787
788
789
    // Re-add the empties
790
    if (!empty($saved_empties)) {
791
      foreach ($explode as $key => $value) {
792
        while (strpos($value,'YAMLEmpty') !== false) {
793
          $explode[$key] = preg_replace('/YAMLEmpty/', '', $value, 1);
794
          $value = $explode[$key];
795
        }
796
      }
797
    }
798
799
    $finished = true;
800
    foreach ($explode as $key => $value) {
801
      if (strpos($value,'YAMLSeq') !== false) {
802
        $finished = false; break;
803
      }
804
      if (strpos($value,'YAMLMap') !== false) {
805
        $finished = false; break;
806
      }
807
      if (strpos($value,'YAMLString') !== false) {
808
        $finished = false; break;
809
      }
810
      if (strpos($value,'YAMLEmpty') !== false) {
811
        $finished = false; break;
812
      }
813
    }
814
    if ($finished) break;
815
816
    $i++;
817
    if ($i > 10)
818
      break; // Prevent infinite loops.
819
    }
820
821
822
    return $explode;
823
  }
824
825
  private function literalBlockContinues ($line, $lineIndent) {
826
    if (!trim($line)) return true;
827
    if (strlen($line) - strlen(ltrim($line)) > $lineIndent) return true;
828
    return false;
829
  }
830
831
  private function referenceContentsByAlias ($alias) {
832
    do {
833
      if (!isset($this->SavedGroups[$alias])) { echo "Bad group name: $alias."; break; }
834
      $groupPath = $this->SavedGroups[$alias];
835
      $value = $this->result;
836
      foreach ($groupPath as $k) {
837
        $value = $value[$k];
838
      }
839
    } while (false);
840
    return $value;
0 ignored issues
show
The variable $value does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
841
  }
842
843
  private function addArrayInline ($array, $indent) {
844
      $CommonGroupPath = $this->path;
845
      if (empty ($array)) return false;
846
847
      foreach ($array as $k => $_) {
848
        $this->addArray(array($k => $_), $indent);
849
        $this->path = $CommonGroupPath;
850
      }
851
      return true;
852
  }
853
854
  private function addArray ($incoming_data, $incoming_indent) {
855
856
   // print_r ($incoming_data);
0 ignored issues
show
Unused Code Comprehensibility introduced by
58% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
857
858
    if (count ($incoming_data) > 1)
859
      return $this->addArrayInline ($incoming_data, $incoming_indent);
860
861
    $key = key ($incoming_data);
862
    $value = isset($incoming_data[$key]) ? $incoming_data[$key] : null;
863
    if ($key === '__!YAMLZero') $key = '0';
864
865
    if ($incoming_indent == 0 && !$this->_containsGroupAlias && !$this->_containsGroupAnchor) { // Shortcut for root-level values.
866
      if ($key || $key === '' || $key === '0') {
867
        $this->result[$key] = $value;
868
      } else {
869
        $this->result[] = $value; end ($this->result); $key = key ($this->result);
870
      }
871
      $this->path[$incoming_indent] = $key;
872
      return;
873
    }
874
875
876
877
    $history = array();
878
    // Unfolding inner array tree.
879
    $history[] = $_arr = $this->result;
880
    foreach ($this->path as $k) {
881
      $history[] = $_arr = $_arr[$k];
882
    }
883
884
    if ($this->_containsGroupAlias) {
885
      $value = $this->referenceContentsByAlias($this->_containsGroupAlias);
886
      $this->_containsGroupAlias = false;
887
    }
888
889
890
    // Adding string or numeric key to the innermost level or $this->arr.
891
    if (is_string($key) && $key == '<<') {
892
      if (!is_array ($_arr)) { $_arr = array (); }
893
894
      $_arr = array_merge ($_arr, $value);
895
    } else if ($key || $key === '' || $key === '0') {
896
      if (!is_array ($_arr))
897
        $_arr = array ($key=>$value);
898
      else
899
        $_arr[$key] = $value;
900
    } else {
901
      if (!is_array ($_arr)) { $_arr = array ($value); $key = 0; }
902
      else { $_arr[] = $value; end ($_arr); $key = key ($_arr); }
903
    }
904
905
    $reverse_path = array_reverse($this->path);
906
    $reverse_history = array_reverse ($history);
907
    $reverse_history[0] = $_arr;
908
    $cnt = count($reverse_history) - 1;
909
    for ($i = 0; $i < $cnt; $i++) {
910
      $reverse_history[$i+1][$reverse_path[$i]] = $reverse_history[$i];
911
    }
912
    $this->result = $reverse_history[$cnt];
913
914
    $this->path[$incoming_indent] = $key;
915
916
    if ($this->_containsGroupAnchor) {
917
      $this->SavedGroups[$this->_containsGroupAnchor] = $this->path;
918
      if (is_array ($value)) {
919
        $k = key ($value);
920
        if (!is_int ($k)) {
921
          $this->SavedGroups[$this->_containsGroupAnchor][$incoming_indent + 2] = $k;
922
        }
923
      }
924
      $this->_containsGroupAnchor = false;
925
    }
926
927
  }
928
929
  private static function startsLiteralBlock ($line) {
930
    $lastChar = substr (trim($line), -1);
931
    if ($lastChar != '>' && $lastChar != '|') return false;
932
    if ($lastChar == '|') return $lastChar;
933
    // HTML tags should not be counted as literal blocks.
934
    if (preg_match ('#<.*?>$#', $line)) return false;
935
    return $lastChar;
936
  }
937
938
  private static function greedilyNeedNextLine($line) {
939
    $line = trim ($line);
940
    if (!strlen($line)) return false;
941
    if (substr ($line, -1, 1) == ']') return false;
942
    if ($line[0] == '[') return true;
943
    if (preg_match ('#^[^:]+?:\s*\[#', $line)) return true;
944
    return false;
945
  }
946
947
  private function addLiteralLine ($literalBlock, $line, $literalBlockStyle, $indent = -1) {
948
    $line = self::stripIndent($line, $indent);
949
    if ($literalBlockStyle !== '|') {
950
        $line = self::stripIndent($line);
951
    }
952
    $line = rtrim ($line, "\r\n\t ") . "\n";
953
    if ($literalBlockStyle == '|') {
954
      return $literalBlock . $line;
955
    }
956
    if (strlen($line) == 0)
957
      return rtrim($literalBlock, ' ') . "\n";
958
    if ($line == "\n" && $literalBlockStyle == '>') {
959
      return rtrim ($literalBlock, " \t") . "\n";
960
    }
961
    if ($line != "\n")
962
      $line = trim ($line, "\r\n ") . " ";
963
    return $literalBlock . $line;
964
  }
965
966
   function revertLiteralPlaceHolder ($lineArray, $literalBlock) {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
967
     foreach ($lineArray as $k => $_) {
968
      if (is_array($_))
969
        $lineArray[$k] = $this->revertLiteralPlaceHolder ($_, $literalBlock);
970
      else if (substr($_, -1 * strlen ($this->LiteralPlaceHolder)) == $this->LiteralPlaceHolder)
971
	       $lineArray[$k] = rtrim ($literalBlock, " \r\n");
972
     }
973
     return $lineArray;
974
   }
975
976
  private static function stripIndent ($line, $indent = -1) {
977
    if ($indent == -1) $indent = strlen($line) - strlen(ltrim($line));
978
    return substr ($line, $indent);
979
  }
980
981
  private function getParentPathByIndent ($indent) {
982
    if ($indent == 0) return array();
983
    $linePath = $this->path;
984
    do {
985
      end($linePath); $lastIndentInParentPath = key($linePath);
986
      if ($indent <= $lastIndentInParentPath) array_pop ($linePath);
987
    } while ($indent <= $lastIndentInParentPath);
988
    return $linePath;
989
  }
990
991
992
  private function clearBiggerPathValues ($indent) {
0 ignored issues
show
This method is not used, and could be removed.
Loading history...
993
994
995
    if ($indent == 0) $this->path = array();
996
    if (empty ($this->path)) return true;
997
998
    foreach ($this->path as $k => $_) {
999
      if ($k > $indent) unset ($this->path[$k]);
1000
    }
1001
1002
    return true;
1003
  }
1004
1005
1006
  private static function isComment ($line) {
1007
    if (!$line) return false;
1008
    if ($line[0] == '#') return true;
1009
    if (trim($line, " \r\n\t") == '---') return true;
1010
    return false;
1011
  }
1012
1013
  private static function isEmpty ($line) {
1014
    return (trim ($line) === '');
1015
  }
1016
1017
1018
  private function isArrayElement ($line) {
1019
    if (!$line || !is_scalar($line)) return false;
1020
    if (substr($line, 0, 2) != '- ') return false;
1021
    if (strlen ($line) > 3)
1022
      if (substr($line,0,3) == '---') return false;
1023
1024
    return true;
1025
  }
1026
1027
  private function isHashElement ($line) {
1028
    return strpos($line, ':');
1029
  }
1030
1031
  private function isLiteral ($line) {
0 ignored issues
show
This method is not used, and could be removed.
Loading history...
1032
    if ($this->isArrayElement($line)) return false;
1033
    if ($this->isHashElement($line)) return false;
1034
    return true;
1035
  }
1036
1037
1038
  private static function unquote ($value) {
1039
    if (!$value) return $value;
1040
    if (!is_string($value)) return $value;
1041
    if ($value[0] == '\'') return trim ($value, '\'');
1042
    if ($value[0] == '"') return trim ($value, '"');
1043
    return $value;
1044
  }
1045
1046
  private function startsMappedSequence ($line) {
1047
    return (substr($line, 0, 2) == '- ' && substr ($line, -1, 1) == ':');
1048
  }
1049
1050
  private function returnMappedSequence ($line) {
1051
    $array = array();
1052
    $key         = self::unquote(trim(substr($line,1,-1)));
1053
    $array[$key] = array();
1054
    $this->delayedPath = array(strpos ($line, $key) + $this->indent => $key);
1055
    return array($array);
1056
  }
1057
1058
  private function checkKeysInValue($value) {
1059
    if (strchr('[{"\'', $value[0]) === false) {
1060
      if (strchr($value, ': ') !== false) {
1061
          throw new Exception('Too many keys: '.$value);
1062
      }
1063
    }
1064
  }
1065
1066
  private function returnMappedValue ($line) {
1067
    $this->checkKeysInValue($line);
1068
    $array = array();
1069
    $key         = self::unquote (trim(substr($line,0,-1)));
1070
    $array[$key] = '';
1071
    return $array;
1072
  }
1073
1074
  private function startsMappedValue ($line) {
1075
    return (substr ($line, -1, 1) == ':');
1076
  }
1077
1078
  private function isPlainArray ($line) {
1079
    return ($line[0] == '[' && substr ($line, -1, 1) == ']');
1080
  }
1081
1082
  private function returnPlainArray ($line) {
1083
    return $this->_toType($line);
1084
  }
1085
1086
  private function returnKeyValuePair ($line) {
1087
    $array = array();
1088
    $key = '';
0 ignored issues
show
$key is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1089
    if (strpos ($line, ': ')) {
1090
      // It's a key/value pair most likely
1091
      // If the key is in double quotes pull it out
1092
      if (($line[0] == '"' || $line[0] == "'") && preg_match('/^(["\'](.*)["\'](\s)*:)/',$line,$matches)) {
1093
        $value = trim(str_replace($matches[1],'',$line));
1094
        $key   = $matches[2];
1095
      } else {
1096
        // Do some guesswork as to the key and the value
1097
        $explode = explode(': ', $line);
1098
        $key     = trim(array_shift($explode));
1099
        $value   = trim(implode(': ', $explode));
1100
        $this->checkKeysInValue($value);
1101
      }
1102
      // Set the type of the value.  Int, string, etc
1103
      $value = $this->_toType($value);
1104
      if ($key === '0') $key = '__!YAMLZero';
1105
      $array[$key] = $value;
1106
    } else {
1107
      $array = array ($line);
1108
    }
1109
    return $array;
1110
1111
  }
1112
1113
1114
  private function returnArrayElement ($line) {
1115
     if (strlen($line) <= 1) return array(array()); // Weird %)
1116
     $array = array();
1117
     $value   = trim(substr($line,1));
1118
     $value   = $this->_toType($value);
1119
     if ($this->isArrayElement($value)) {
1120
       $value = $this->returnArrayElement($value);
1121
     }
1122
     $array[] = $value;
1123
     return $array;
1124
  }
1125
1126
1127
  private function nodeContainsGroup ($line) {
1128
    $symbolsForReference = 'A-z0-9_\-';
1129
    if (strpos($line, '&') === false && strpos($line, '*') === false) return false; // Please die fast ;-)
1130 View Code Duplication
    if ($line[0] == '&' && preg_match('/^(&['.$symbolsForReference.']+)/', $line, $matches)) return $matches[1];
0 ignored issues
show
This code seems to be duplicated across your project.

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.

Loading history...
1131 View Code Duplication
    if ($line[0] == '*' && preg_match('/^(\*['.$symbolsForReference.']+)/', $line, $matches)) return $matches[1];
0 ignored issues
show
This code seems to be duplicated across your project.

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.

Loading history...
1132
    if (preg_match('/(&['.$symbolsForReference.']+)$/', $line, $matches)) return $matches[1];
1133
    if (preg_match('/(\*['.$symbolsForReference.']+$)/', $line, $matches)) return $matches[1];
1134
    if (preg_match ('#^\s*<<\s*:\s*(\*[^\s]+).*$#', $line, $matches)) return $matches[1];
1135
    return false;
1136
1137
  }
1138
1139
  private function addGroup ($line, $group) {
0 ignored issues
show
The parameter $line 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...
1140
    if ($group[0] == '&') $this->_containsGroupAnchor = substr ($group, 1);
0 ignored issues
show
Documentation Bug introduced by
The property $_containsGroupAnchor was declared of type boolean, but substr($group, 1) is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
1141
    if ($group[0] == '*') $this->_containsGroupAlias = substr ($group, 1);
0 ignored issues
show
Documentation Bug introduced by
The property $_containsGroupAlias was declared of type boolean, but substr($group, 1) is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
1142
    //print_r ($this->path);
0 ignored issues
show
Unused Code Comprehensibility introduced by
63% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1143
  }
1144
1145
  private function stripGroup ($line, $group) {
1146
    $line = trim(str_replace($group, '', $line));
1147
    return $line;
1148
  }
1149
}
1150
}
1151
1152
// Enable use of Spyc from command line
1153
// The syntax is the following: php Spyc.php spyc.yaml
1154
1155
do {
1156
  if (PHP_SAPI != 'cli') break;
1157
  if (empty ($_SERVER['argc']) || $_SERVER['argc'] < 2) break;
1158
  if (empty ($_SERVER['PHP_SELF']) || FALSE === strpos ($_SERVER['PHP_SELF'], 'Spyc.php') ) break;
1159
  $file = $argv[1];
1160
  echo json_encode (spyc_load_file ($file));
1161
} while (0);
1162