Test Failed
Push — master ( 41f581...fc4f20 )
by stéphane
13:19
created

Scalar::getNumber()   A

Complexity

Conditions 5
Paths 6

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 0
Metric Value
cc 5
eloc 3
nc 6
nop 1
dl 0
loc 5
ccs 0
cts 0
cp 0
crap 30
rs 9.6111
c 0
b 0
f 0
1
<?php
2
3
namespace Dallgoot\Yaml\Nodes;
4
5
use Dallgoot\Yaml\NodeFactory;
6
use Dallgoot\Yaml\TagFactory;
7
use Dallgoot\Yaml\NodeList;
8
use Dallgoot\Yaml\Builder;
9
use Dallgoot\Yaml\Regex;
10
11
/**
12
 *
13
 * @author  Stéphane Rebai <[email protected]>
14
 * @license Apache 2.0
15
 * @link    https://github.com/dallgoot/yaml
16
 */
17
class Scalar extends NodeGeneric
18 5
{
19
    public function __construct(string $nodeString, int $line)
20 5
    {
21 5
        parent::__construct($nodeString, $line);
22 5
        $value = trim($nodeString);
23 5
        if ($value !== '') {
24 5
            $hasComment = strpos($value, ' #');
25 1
            if (!is_bool($hasComment)) {
26 1
                    $realValue    = trim(substr($value, 0, $hasComment));
27 1
                    $commentValue = trim(substr($value, $hasComment));
28 1
                    $realNode = NodeFactory::get($realValue, $line);
29 1
                    $realNode->indent = null;
30 1
                    $commentNode = NodeFactory::get($commentValue, $line);
31 1
                    $commentNode->indent = null;
32 1
                    $this->add($realNode);
33
                    $this->add($commentNode);
34
            }
35 5
        }
36
    }
37 2
38
    public function build(&$parent = null)
39 2
    {
40 1
        if (!is_null($this->tag)) {
41 1
            $tagged = TagFactory::transform($this->tag, $this);
42
            if ($tagged instanceof NodeGeneric || $tagged instanceof NodeList) {
43
                return $tagged->build();
44 1
            }
45
            return $tagged;
46 1
        }
47
        return is_null($this->value) ? self::getScalar(trim($this->raw)) : $this->value->build();
48
    }
49 1
50
    public function getTargetOnLessIndent(NodeGeneric &$node):NodeGeneric
51 1
    {
52 1
        if ($node instanceof Scalar || $node instanceof Blank ) {
53
            return $this->getParent();
54 1
        } else {
55
            return $this->getParent($node->indent);
56
        }
57
    }
58 1
59
    public function getTargetOnMoreIndent(NodeGeneric &$node):NodeGeneric
60 1
    {
61
        return $this->getParent();
62
    }
63
64
65
66
    /**
67
     * Returns the correct PHP type according to the string value
68
     *
69
     * @param string $v a string value
70
     *
71
     * @return mixed The value with appropriate PHP type
72
     * @throws \Exception if it happens in Regex::isDate or Regex::isNumber
73
     * @todo implement date as DateTime Object
74
     */
75
    public static function getScalar(string $v, bool $onlyScalar = false)
76
    {
77
        /*
78
         10.3.2. Tag Resolution
79
80
The core schema tag resolution is an extension of the JSON schema tag resolution.
81
82
All nodes with the “!” non-specific tag are resolved, by the standard convention, to “tag:yaml.org,2002:seq”, “tag:yaml.org,2002:map”, or “tag:yaml.org,2002:str”, according to their kind.
83
84
Collections with the “?” non-specific tag (that is, untagged collections) are resolved to “tag:yaml.org,2002:seq” or “tag:yaml.org,2002:map” according to their kind.
85
86
Scalars with the “?” non-specific tag (that is, plain scalars) are matched with an extended list of regular expressions. However, in this case, if none of the regular expressions matches, the scalar is resolved to tag:yaml.org,2002:str (that is, considered to be a string).
87
 Regular expression       Resolved to tag
88
 null | Null | NULL | ~      tag:yaml.org,2002:null
89
 Empty      tag:yaml.org,2002:null
90
 true | True | TRUE | false | False | FALSE      tag:yaml.org,2002:bool
91
 [-+]? [0-9]+    tag:yaml.org,2002:int (Base 10)
92
 0o [0-7]+   tag:yaml.org,2002:int (Base 8)
93
 0x [0-9a-fA-F]+     tag:yaml.org,2002:int (Base 16)
94
 [-+]? ( \. [0-9]+ | [0-9]+ ( \. [0-9]* )? ) ( [eE] [-+]? [0-9]+ )?      tag:yaml.org,2002:float (Number)
95
 [-+]? ( \.inf | \.Inf | \.INF )     tag:yaml.org,2002:float (Infinity)
96
 \.nan | \.NaN | \.NAN   tag:yaml.org,2002:float (Not a number)
97
 *   tag:yaml.org,2002:str (Default)
98
 */
99
        if (Regex::isDate($v))   return Builder::$dateAsObject && !$onlyScalar ? date_create($v) : $v;
100
        if (Regex::isNumber($v)) return self::getNumber($v);
101
        $types = ['yes'   => true,
102
                  'no'    => false,
103
                  'true'  => true,
104
                  'false' => false,
105
                  'null'  => null,
106
                  '.inf'  => \INF,
107
                  '-.inf' => -\INF,
108
                  '.nan'  => \NAN
109
        ];
110
        return array_key_exists(strtolower($v), $types) ? $types[strtolower($v)] : self::replaceSequences($v);
0 ignored issues
show
Bug Best Practice introduced by
The method Dallgoot\Yaml\Nodes\Scalar::replaceSequences() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

110
        return array_key_exists(strtolower($v), $types) ? $types[strtolower($v)] : self::/** @scrutinizer ignore-call */ replaceSequences($v);
Loading history...
111
    }
112
113
    public function replaceSequences($value='')
114
    {
115
      $replaceUnicodeSeq = function ($matches) {
116
            return json_decode('"'.$matches[1].'"');
117
      };
118
      $replaceNonPrintable = function ($matches) {
119
            // var_dump($matches[1]);
120
        return $matches[1]."";
121
      };
122
// preg_match( "/[^\x{06F0}-\x{06F9}\x]+/u" , '۱۲۳۴۵۶۷۸۹۰' );
123
      return preg_replace_callback_array(
124
          [
125
              '/((?<![\\\\])\\\\x[0-9a-f]{2})/i' => $replaceUnicodeSeq,
126
              '/((?<![\\\\])\\\\u[0-9a-f]{4,})/i' => $replaceUnicodeSeq,
127
              '/(\\\\b|\\\\n|\\\\t|\\\\r)/' => $replaceNonPrintable
128
          ],
129
          $value
130
      );
131
    }
132
133
134
    /**
135
     * Returns the correct PHP type according to the string value
136
     *
137
     * @param string $v a string value
138
     *
139
     * @return int|float   The scalar value with appropriate PHP type
140
     * @todo or scientific notation matching the regular expression -? [1-9] ( \. [0-9]* [1-9] )? ( e [-+] [1-9] [0-9]* )?
141
     */
142
    private static function getNumber(string $v)
143
    {
144
        if ((bool) preg_match(Regex::OCTAL_NUM, $v)) return intval(base_convert($v, 8, 10));
145
        if ((bool) preg_match(Regex::HEX_NUM, $v))   return intval(base_convert($v, 16, 10));
146
        return is_bool(strpos($v, '.')) || substr_count($v, '.') > 1 ? intval($v) : floatval($v);
147
    }
148
149
}