Executor::analyzing()   B
last analyzed

Complexity

Conditions 8
Paths 40

Size

Total Lines 39
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 21
nc 40
nop 1
dl 0
loc 39
rs 8.4444
c 0
b 0
f 0
1
<?php
2
/**
3
 * Valid builder
4
 * User: moyo
5
 * Date: 2018/6/4
6
 * Time: 3:17 PM
7
 */
8
9
namespace Carno\Validator\Valid;
10
11
use Carno\Validator\Chips\ERTrans;
12
use Respect\Validation\Validator;
13
14
class Executor
15
{
16
    use ERTrans;
17
18
    // suffix with "Type"
19
    private const C2TYPES = ['string'];
20
21
    // suffix with "Val"
22
    private const C2VALUES = ['array', 'bool', 'true', 'false', 'int', 'float', 'scalar'];
23
24
    /**
25
     * @param string $expr
26
     * @return Rule
27
     */
28
    public function analyzing(string $expr) : Rule
29
    {
30
        $field = trim(substr($expr, 0, $fwp = strpos($expr, ' ')));
31
32
        $needs = trim(substr($expr, $fwp + 1));
33
34
        if ($edp = strrpos($needs, ' (')) {
35
            $error = trim(substr($needs, $edp + 2, -1));
36
            $needs = trim(substr($needs, 0, $edp));
37
        }
38
39
        $exists = $this->rules[$field] ?? null;
40
41
        $v = $exists ? clone $exists->v() : new Validator;
42
43
        foreach (explode('|', $needs) as $want) {
44
            $params = [];
45
            if ($cdp = strpos($want, ':')) {
46
                // rule:params
47
                $rule = substr($want, 0, $cdp);
48
                $init = substr($want, $cdp + 1);
49
                // rule:[av1,av2]
50
                // rule:iv1,iv2
51
                $params = substr($init, 0, 1) == '[' ? [explode(',', trim($init, '[]'))] : explode(',', $init);
52
            } else {
53
                // rule
54
                $rule = $want;
55
            }
56
57
            if (in_array($rule, self::C2TYPES)) {
58
                $rule .= '_type';
59
            } elseif (in_array($rule, self::C2VALUES)) {
60
                $rule .= '_val';
61
            }
62
63
            $v = call_user_func_array([$v, $this->vNamed($rule)], $params);
64
        }
65
66
        return $this->rules[$field] = new Rule($field, $v, $this->vMessage($error ?? ''));
67
    }
68
69
    /**
70
     * @param string $input
71
     * @return string
72
     */
73
    private function vNamed(string $input) : string
74
    {
75
        $renamed = '';
76
77
        foreach (explode('_', $input) as $word) {
78
            $renamed .= ucfirst($word);
79
        }
80
81
        return lcfirst($renamed);
82
    }
83
84
    /**
85
     * @param string $error
86
     * @return Message
87
     */
88
    private function vMessage(string $error) : Message
89
    {
90
        if (empty($error)) {
91
            return new Message;
92
        }
93
94
        $regex = [
95
            '/^([\d]+)\|([\w\\\]+)\|(.*?)$/' => function (array $matches) {
96
                return [$matches[2], $matches[1], $matches[3]];
97
            },
98
            '/^([\w\\\]+)\|(.*?)$/' => function (array $matches) {
99
                return [$matches[1], null, $matches[2]];
100
            },
101
        ];
102
103
        foreach ($regex as $expr => $extractor) {
104
            if (preg_match($expr, $error, $matches)) {
105
                list($exception, $code, $tips) = $extractor($matches);
106
                break;
107
            }
108
        }
109
110
        return new Message($tips ?? $error, $exception ?? null, $code ?? null);
111
    }
112
}
113