Completed
Push — master ( c6ecf3...3eacba )
by stéphane
02:27
created

Regex   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 84
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 11
eloc 43
dl 0
loc 84
ccs 18
cts 18
cp 1
rs 10
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A isNumber() 0 4 1
A isProperlyQuoted() 0 3 1
B isDate() 0 16 9
1
<?php
2
3
namespace Dallgoot\Yaml;
4
5
/**
6
 * Define Regex patterns as constants
7
 *
8
 * @author  Stéphane Rebai <[email protected]>
9
 * @license Apache 2.0
10
 * @link    TODO : url to specific online doc
11
 */
12
class Regex
13
{
14
    const OCTAL_NUM = "/^(0o\d+)$/i";
15
    const HEX_NUM   = "/^(0x[\da-f]+)$/i";
16
17
    const QUOTED = "(?'quot'(?'q'['\"]).*?(?<![\\\\])(?&q))";
18
    const NUM    = "(?'num'[-+]?(?:\\d+\\.?(?:\\d*(e[+-]?\\d+)?)|(\\.(inf|nan)))\z)";
19
    const WORD   = "(?'word'[^,]+)";
20
    const RC     = "(?'rc'\\*\\w+)"; //reference call
21
    const RD     = "(?'rd'&\\w+)"; //reference definition
22
    const TAG    = "(?'tag'!!?[\\w\\/\\-]+!?)";
23
    const ALL    = "(?'all'(?:(?:(?&rd)|(?&tag)) +)?(?:(?&quot)|(?&num)|(?&rc)|(?&word)|(?&map)|(?&seq)))";
24
    const MAP    = "(?'map'\\{ *?(?'pair'((?:(?&quot)|[^:]+) *?: *(?&all)) *,? *)* *?\\})";
25
    const SEQ    = "(?'seq'\\[ *(?:(?'i'(?&all)) *,? *)* *\\])";
26
    const ALLDEF = "(?(DEFINE)".Regex::QUOTED.
27
                                Regex::NUM.
28
                                Regex::RC.
29
                                Regex::WORD.
30
                                Regex::TAG.
31
                                Regex::RD.
32
                                Regex::ALL.
33
                                Regex::MAP.
34
                                Regex::SEQ.")";
35
36
    const MAPPING  = "/".Regex::ALLDEF."^(?&map)$/";
37
    const MAPPING_VALUES = "/".Regex::ALLDEF."(?'k'(?&quot)|[^:]+) *: *(?'v'(?&all)) *,? */i";
38
39
    const SEQUENCE = "/".Regex::ALLDEF."^(?&seq)/";
40
    const SEQUENCE_VALUES = "/".Regex::ALLDEF."(?'item'(?&all)) *,? */i";
41
42
    const KEY  = '/^([\w\'"~][\w\'" \-.\/~]*[ \t]*)(?::([ \t][^\n]+)|:)$/i';
43
    const ITEM = '/^-([ \t]+(.*))?$/';
44
45
    const NODE_ACTIONS = "/(?(DEFINE)".Regex::RC.Regex::RD.Regex::TAG.")(?'action'(?&rc)|(?&rd)|(?&tag))( +(?'content'.*))?$/";
46
47
48
    /**
49
     * Determines if a valid Date format
50
     * @param string $v a string value
51
     * @return bool
52
     * @throws \Exception if any preg_match has invalid regex
53
     */
54 2
    public static function isDate(string $v):bool
55
    {
56 2
        $d         = "\\d{4}([-\\/])\\d{2}\\1\\d{2}";
57 2
        $h         = "\\d{2}(:)\\d{2}\\2\\d{2}";
58 2
        $date      = "/^$d$/"; // 2002-12-14, 2002/12/14
59 2
        $canonical = "/^$d(?:t| )$h\\.\\dz?$/im"; // 2001-12-15T02:59:43.1Z
60 2
        $spaced    = "/^$d(?:t| )$h\\.\\d{2} [-+]\\d$/im"; // 2001-12-14 21:59:43.10 -5
61 2
        $iso8601   = "/^$d(?:t| )$h\\.\\d{2}[-+]\\d{2}\\2\\d{2}/im"; // 2001-12-14t21:59:43.10-05:00
62 2
        $matchDate      = preg_match($date, $v);
63 2
        $matchCanonical = preg_match($canonical, $v);
64 2
        $matchSpaced    = preg_match($spaced, $v);
65 2
        $matchIso       = preg_match($iso8601, $v);
66 2
        if (empty($v) || is_bool($matchDate) || is_bool($matchCanonical) || is_bool($matchSpaced) || is_bool($matchIso)) {
67 1
            throw new \Exception(__METHOD__." regex ERROR");
68
        }
69 1
        return $matchDate || $matchCanonical || $matchSpaced || $matchIso;
70
    }
71
72
    /**
73
     * Determines if number.
74
     *
75
     * @param string $var A string value
76
     *
77
     * @return boolean  True if number, False otherwise.
78
     * @todo   replace regex expression with class constants, use is_numeric ?
79
     */
80 1
    public static function isNumber(string $var):bool
81
    {
82
        //TODO: https://secure.php.net/manual/en/function.is-numeric.php
83 1
        return (bool) preg_match("/^((0o\d+)|(0x[\da-f]+)|([\d.]+e[-+]\d{1,2})|([-+]?(\d*\.?\d+)))$/i", $var);
84
    }
85
86
    /**
87
     * Determines if properly quoted.
88
     *
89
     * @param string $var The variable
90
     *
91
     * @return boolean True if properly quoted, False otherwise.
92
     */
93 1
    public static function isProperlyQuoted(string $var):bool
94
    {
95 1
        return (bool) preg_match("/^(['\"]).*?(?<![\\\\])\\1$/s", trim($var));
96
    }
97
}
98