Completed
Push — master ( d27e1e...d6d70b )
by Hannes
01:43
created

Rule::validate()   B

Complexity

Conditions 8
Paths 60

Size

Total Lines 29

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
nc 60
nop 1
dl 0
loc 29
rs 8.2114
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types = 1);
4
5
namespace hanneskod\clean;
6
7
final class Rule implements ValidatorInterface
8
{
9
    private ?string $default;
0 ignored issues
show
Bug introduced by
This code did not parse for me. Apparently, there is an error somewhere around this line:

Syntax error, unexpected '?', expecting T_FUNCTION or T_CONST
Loading history...
10
    private ?string $errorMsg;
11
12
    /**
13
     * @var array<callable> Pre match filters
14
     */
15
    private array $pre;
16
17
    /**
18
     * @var array<callable> Post match filters
19
     */
20
    private array $post;
21
22
    /**
23
     * @var array<callable>
24
     */
25
    private array $matchers;
26
27
    /**
28
     * @param array<callable> $pre
29
     * @param array<callable> $matchers
30
     * @param array<callable> $post
31
     */
32
    public function __construct(
33
        array $pre = [],
34
        array $matchers = [],
35
        array $post = [],
36
        ?string $default = null,
37
        ?string $errorMsg = null
38
    ) {
39
        $this->pre = $pre;
40
        $this->post = $post;
41
        $this->matchers = $matchers;
42
        $this->default = $default;
43
        $this->errorMsg = $errorMsg;
44
    }
45
46
    /**
47
     * Create a new Rule with one or more pre match filters
48
     *
49
     * A filter should take a raw value and return the filtered value.
50
     */
51
    public function pre(callable ...$pre): Rule
52
    {
53
        return new static([...$this->pre, ...$pre], $this->matchers, $this->post, $this->default, $this->errorMsg);
54
    }
55
56
    /**
57
     * Create a new Rule with one or more matchers
58
     *
59
     * A matcher should take a raw value and return true if value is a match
60
     * and false if it is not.
61
     */
62
    public function match(callable ...$match): Rule
63
    {
64
        return new static($this->pre, [...$this->matchers, ...$match], $this->post, $this->default, $this->errorMsg);
65
    }
66
67
    /**
68
     * Create a new Rule with one or more post match filters
69
     *
70
     * A filter should take a raw value and return the filtered value.
71
     */
72
    public function post(callable ...$post): Rule
73
    {
74
        return new static($this->pre, $this->matchers, [...$this->post, ...$post], $this->default, $this->errorMsg);
75
    }
76
77
    /**
78
     * Create a new Rule with default value
79
     */
80
    public function def(string $default): Rule
81
    {
82
        return new static($this->pre, $this->matchers, $this->post, $default, $this->errorMsg);
83
    }
84
85
    /**
86
     * Create a new Rule with exception message
87
     *
88
     * %s is replaced with parent exception message
89
     */
90
    public function msg(string $errorMsg): Rule
91
    {
92
        return new static($this->pre, $this->matchers, $this->post, $this->default, $errorMsg);
93
    }
94
95
    public function applyTo($data): ResultInterface
96
    {
97
        try {
98
            if (is_null($data)) {
99
                if (!isset($this->default)) {
100
                    throw new Exception('value missing');
101
                }
102
103
                $data = $this->default;
104
            }
105
106
            foreach ($this->pre as $filter) {
107
                $data = $filter($data);
108
            }
109
110
            foreach ($this->matchers as $matcherId => $matcher) {
111
                if (!$matcher($data)) {
112
                    throw new Exception("matcher #$matcherId failed");
113
                }
114
            }
115
116
            foreach ($this->post as $filter) {
117
                $data = $filter($data);
118
            }
119
120
            return new Valid($data);
121
        } catch (\Exception $e) {
122
            if (isset($this->errorMsg)) {
123
                $e = new Exception(sprintf($this->errorMsg, $e->getMessage()), 0, $e);
124
            }
125
126
            return new Invalid($e);
127
        }
128
    }
129
130
    public function validate($data)
131
    {
132
        return $this->applyTo($data)->getValidData();
133
    }
134
}
135