Completed
Push — master ( c2bd55...6b7717 )
by Todd
09:04
created

Validation   A

Complexity

Total Complexity 33

Size/Duplication

Total Lines 205
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0

Test Coverage

Coverage 52.17%

Importance

Changes 6
Bugs 0 Features 2
Metric Value
wmc 33
c 6
b 0
f 2
lcom 1
cbo 0
dl 0
loc 205
ccs 48
cts 92
cp 0.5217
rs 9.4

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A errorMessage() 0 11 3
C addError() 0 35 7
A mainMessage() 0 8 2
B status() 0 20 7
C getMessage() 0 27 7
A getErrorsFlat() 0 9 3
A isValid() 0 3 1
A fieldValid() 0 4 2
1
<?php
2
/**
3
 * @author Todd Burry <[email protected]>
4
 * @copyright 2009-2014 Vanilla Forums Inc.
5
 * @license MIT
6
 */
7
8
namespace Garden;
9
10
11
use Garden\Exception\ValidationException;
12
13
/**
14
 * An class for collecting validation errors.
15
 */
16
class Validation {
17
    /// Properties ///
18
19
    protected $errors = [];
20
21
    protected $mainMessage;
22
23
    protected $status;
24
25
    /// Methods ///
26
27
    /**
28
     * Initialize an instance of the {@link Validation} class.
29
     *
30
     * @param array $errors An array of errors.
31
     * @param string $mainMessage The main message of the error.
32
     * @param int $status The http status code of the error or 0 to build the status code from the indivdual errors.
33
     */
34 68
    public function __construct(array $errors = [], $mainMessage = '', $status = 0) {
35 68
        $this->errors = $errors;
36 68
        $this->mainMessage = $mainMessage;
37 68
        $this->status = $status;
38 68
    }
39
40
    /**
41
     * Gets the error message from an error.
42
     *
43
     * Errors are stored with either a message or a translation code.
44
     * This method will look at both to determine the full message.
45
     *
46
     * @param array $error The error array.
47
     * @return string Returns the message from the error.
48
     */
49
    public static function errorMessage(array $error) {
50
        if (isset($error['message'])) {
51
            return $error['message'];
52
        } else {
53
            $field = val('field', $error, '*');
54
            if (is_array($field)) {
55
                $field = implode(', ', $field);
56
            }
57
            return sprintft($error['code'].': %s.', $field);
58
        }
59
    }
60
61
    /**
62
     * Add an error.
63
     *
64
     * @param string $messageCode The message translation code.
65
     * If you add a message that starts with "@" then no translation will take place.
66
     * @param string|array $field The name of the field to add or an array of fields if the error applies to
67
     * more than one field.
68
     * @param int|array $options An array of additional information to add to the error entry or a numeric error code.
69
     * @return Validation Returns $this for fluent calls.
70
     */
71 42
    public function addError($messageCode, $field = '*', $options = []) {
72 42
        $error = [];
73 42
        if (substr($messageCode, 0, 1) === '@') {
74
            $error['message'] = substr($messageCode, 1);
75
        } else {
76 42
            $error['code'] = $messageCode;
77
        }
78 42
        if (is_array($field)) {
79 11
            $fieldname = array_select(['path', 'name'], $field);
80
81 11
            if ($fieldname) {
82
                // This is a full field object.
83 10
                $fieldKey = $fieldname;
84 10
                $error['field'] = $fieldKey;
85 10
            } else {
86 1
                $fieldKey = '*';
87 1
                $error['field'] = $field;
88
            }
89 11
        } else {
90 33
            $fieldKey = $field;
91 33
            if ($field !== '*') {
92 33
                $error['field'] = $field;
93 33
            }
94
        }
95
96 42
        if (is_array($options)) {
97 42
            $error += $options;
98 42
        } else if (is_int($options)) {
99 1
            $error['status'] = $options;
100 1
        }
101
102 42
        $this->errors[$fieldKey][] = $error;
103
104 42
        return $this;
105
    }
106
107
    /**
108
     * Gets the main error message for the validation.
109
     *
110
     * @param string|null $value Pass a new main message or null to get the current main message.
111
     * @return Validation|string Returns the main message or $this for fluent sets.
112
     */
113
    public function mainMessage($value = null) {
114
        if ($value !== null) {
115
            $this->mainMessage = $value;
116
            return $this;
117
        }
118
119
        return $this->mainMessage;
120
    }
121
122
    /**
123
     * Get or set the error status code.
124
     *
125
     * The status code is an http resonse code and should be of the 4xx variety.
126
     *
127
     * @param int|null $value Pass a new status code or null to get the current code.
128
     * @return Validation|int Returns the current status code or $this for fluent sets.
129
     */
130
    public function status($value = null) {
131
        if ($value !== null) {
132
            $this->status = $value;
133
            return $this;
134
        }
135
        if ($this->status) {
136
            return $this->status;
137
        }
138
139
        // There was no status so loop through the errors and look for the highest one.
140
        $maxStatus = 400;
141
        foreach ($this->errors as $field => $errors) {
142
            foreach ($errors as $error) {
143
                if (isset($error['status']) && $error['status'] > $maxStatus) {
144
                    $maxStatus = $error['status'];
145
                }
146
            }
147
        }
148
        return $maxStatus;
149
    }
150
151
    /**
152
     * Get the message for this exception.
153
     *
154
     * @return string Returns the exception message.
155
     */
156 1
    public function getMessage() {
157 1
        if ($this->mainMessage) {
158
            return $this->mainMessage;
159
        }
160
161
        // Generate the message by concatenating all of the errors together.
162 1
        $messages = [];
163 1
        foreach ($this->errors as $errors) {
164 1
            foreach ($errors as $error) {
165 1
                $field = val('field', $error, '*');
166 1
                if (is_array($field)) {
167
                    $field = implode(', ', $field);
168
                }
169
170 1
                if (isset($error['message'])) {
171
                    $message = $error['message'];
172 1
                } elseif (strpos($error['code'], '%s') === false) {
173
                    $message = sprintft($error['code'].': %s.', $field);
174
                } else {
175 1
                    $message = sprintft($error['code'], $field);
176
                }
177
178 1
                $messages[] = $message;
179 1
            }
180 1
        }
181 1
        return implode(' ', $messages);
182
    }
183
184
    /**
185
     * Gets all of the errors as a flat array.
186
     *
187
     * The errors are internally stored indexed by field. This method flattens them for final error returns.
188
     *
189
     * @return array Returns all of the errors.
190
     */
191
    public function getErrorsFlat() {
192
        $result = [];
193
        foreach ($this->errors as $errors) {
194
            foreach ($errors as $error) {
195
                $result[] = $error;
196
            }
197
        }
198
        return $result;
199
    }
200
201
    /**
202
     * Check whether or not the validation is free of errors.
203
     *
204
     * @return bool Returns true if there are no errors, false otherwise.
205
     */
206 68
    public function isValid() {
207 68
        return count($this->errors) === 0;
208
    }
209
210
    /**
211
     * Check whether or not a particular field is has errors.
212
     *
213
     * @param string $field The name of the field to check for validity.
214
     * @return bool Returns true if the field has no errors, false otherwise.
215
     */
216 33
    public function fieldValid($field) {
217 33
        $result = !isset($this->errors[$field]) || count($this->errors[$field]) === 0;
218 33
        return $result;
219
    }
220
}
221