1 /*
2 * Copyright (C) 2017-2018 Matthias Fehring <kontakt@buschmann23.de>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 #include "validatorbetween_p.h"
20
21 using namespace Cutelyst;
22
ValidatorBetween(const QString & field,QMetaType::Type type,const QVariant & min,const QVariant & max,const ValidatorMessages & messages,const QString & defValKey)23 ValidatorBetween::ValidatorBetween(const QString &field, QMetaType::Type type, const QVariant &min, const QVariant &max, const ValidatorMessages &messages, const QString &defValKey) :
24 ValidatorRule(*new ValidatorBetweenPrivate(field, type, min, max, messages, defValKey))
25 {
26 }
27
~ValidatorBetween()28 ValidatorBetween::~ValidatorBetween()
29 {
30 }
31
validate(Context * c,const ParamsMultiMap & params) const32 ValidatorReturnType ValidatorBetween::validate(Context *c, const ParamsMultiMap ¶ms) const
33 {
34 ValidatorReturnType result;
35
36 const QString v = value(params);
37
38 Q_D(const ValidatorBetween);
39
40 if (!v.isEmpty()) {
41 bool ok = false;
42 bool valid = false;
43
44 switch (d->type) {
45 case QMetaType::Char:
46 case QMetaType::Short:
47 case QMetaType::Int:
48 case QMetaType::Long:
49 case QMetaType::LongLong:
50 {
51 const qlonglong val = c->locale().toLongLong(v, &ok);
52 if (Q_UNLIKELY(!ok)) {
53 result.errorMessage = parsingError(c);
54 qCWarning(C_VALIDATOR, "ValidatorBetween: Failed to parse value of field %s into number at %s::%s.", qPrintable(field()), qPrintable(c->controllerName()), qPrintable(c->actionName()));
55 } else {
56 const qlonglong min = d->extractLongLong(c, params, d->min, &ok);
57 if (Q_UNLIKELY(!ok)) {
58 result.errorMessage = validationDataError(c, -1);
59 qCWarning(C_VALIDATOR, "ValidatorBetween: Invalid minimum comparison value for field %s in %s::%s.", qPrintable(field()), qPrintable(c->controllerName()), qPrintable(c->actionName()));
60 } else {
61 const qlonglong max = d->extractLongLong(c, params, d->max, &ok);
62 if (Q_UNLIKELY(!ok)) {
63 result.errorMessage = validationDataError(c, 1);
64 qCWarning(C_VALIDATOR, "ValidatorBetween: Invalid maximum comparison value for field %s in %s::%s.", qPrintable(field()), qPrintable(c->controllerName()), qPrintable(c->actionName()));
65 } else {
66 if ((val < min) || (val > max)) {
67 result.errorMessage = validationError(c, QVariantMap{
68 {QStringLiteral("val"), val},
69 {QStringLiteral("min"), min},
70 {QStringLiteral("max"), max}
71 });
72 qCDebug(C_VALIDATOR, "ValidatorBetween: Validation failed for field %s in %s::%s: %lli is not between %lli and %lli.", qPrintable(field()), qPrintable(c->controllerName()), qPrintable(c->actionName()), val, min, max);
73 } else {
74 valid = true;
75 }
76 }
77 }
78 }
79 }
80 break;
81 case QMetaType::UChar:
82 case QMetaType::UShort:
83 case QMetaType::UInt:
84 case QMetaType::ULong:
85 case QMetaType::ULongLong:
86 {
87 const qulonglong val = v.toULongLong(&ok);
88 if (Q_UNLIKELY(!ok)) {
89 result.errorMessage = parsingError(c);
90 qCWarning(C_VALIDATOR, "ValidatorBetween: Failed to parse value of field %s into number at %s::%s.", qPrintable(field()), qPrintable(c->controllerName()), qPrintable(c->actionName()));
91 } else {
92 const qulonglong min = d->extractULongLong(c, params, d->min, &ok);
93 if (Q_UNLIKELY(!ok)) {
94 result.errorMessage = validationDataError(c, -1);
95 qCWarning(C_VALIDATOR, "ValidatorBetween: Invalid minimum comparison value for field %s in %s::%s.", qPrintable(field()), qPrintable(c->controllerName()), qPrintable(c->actionName()));
96 } else {
97 const qulonglong max = d->extractULongLong(c, params, d->max, &ok);
98 if (Q_UNLIKELY(!ok)) {
99 result.errorMessage = validationDataError(c, 1);
100 qCWarning(C_VALIDATOR, "ValidatorBetween: Invalid maximum comparison value for field %s in %s::%s.", qPrintable(field()), qPrintable(c->controllerName()), qPrintable(c->actionName()));
101 } else {
102 if ((val < min) || (val > max)) {
103 result.errorMessage = validationError(c, QVariantMap{
104 {QStringLiteral("val"), val},
105 {QStringLiteral("min"), min},
106 {QStringLiteral("max"), max}
107 });
108 qCDebug(C_VALIDATOR, "ValidatorBetween: Validation failed for field %s in %s::%s: %llu is not between %llu and %llu.", qPrintable(field()), qPrintable(c->controllerName()), qPrintable(c->actionName()), val, min, max);
109 } else {
110 valid = true;
111 }
112 }
113 }
114 }
115 }
116 break;
117 case QMetaType::Float:
118 case QMetaType::Double:
119 {
120 const double val = v.toDouble(&ok);
121 if (Q_UNLIKELY(!ok)) {
122 result.errorMessage = parsingError(c);
123 qCWarning(C_VALIDATOR, "ValidatorBetween: Failed to parse value of field %s into number at %s::%s.", qPrintable(field()), qPrintable(c->controllerName()), qPrintable(c->actionName()));
124 } else {
125 const double min = d->extractDouble(c, params, d->min, &ok);
126 if (Q_UNLIKELY(!ok)) {
127 result.errorMessage = validationDataError(c, -1);
128 qCWarning(C_VALIDATOR, "ValidatorBetween: Invalid minimum comparison value for field %s in %s::%s.", qPrintable(field()), qPrintable(c->controllerName()), qPrintable(c->actionName()));
129 } else {
130 const double max = d->extractDouble(c, params, d->max, &ok);
131 if (Q_UNLIKELY(!ok)) {
132 result.errorMessage = validationDataError(c, 1);
133 qCWarning(C_VALIDATOR, "ValidatorBetween: Invalid maximum comparison value for field %s in %s::%s.", qPrintable(field()), qPrintable(c->controllerName()), qPrintable(c->actionName()));
134 } else {
135 if ((val < min) || (val > max)) {
136 result.errorMessage = validationError(c, QVariantMap{
137 {QStringLiteral("val"), val},
138 {QStringLiteral("min"), min},
139 {QStringLiteral("max"), max}
140 });
141 qCDebug(C_VALIDATOR, "ValidatorBetween: Validation failed for field %s in %s::%s: %f is not between %f and %f.", qPrintable(field()), qPrintable(c->controllerName()), qPrintable(c->actionName()), val, min, max);
142 } else {
143 valid = true;
144 }
145 }
146 }
147 }
148 }
149 break;
150 case QMetaType::QString:
151 {
152 const qlonglong val = static_cast<qlonglong>(v.length());
153 const qlonglong min = d->extractLongLong(c, params, d->min, &ok);
154 if (Q_UNLIKELY(!ok)) {
155 result.errorMessage = validationDataError(c, -1);
156 qCWarning(C_VALIDATOR, "ValidatorBetween: Invalid minimum comparison value for field %s in %s::%s.", qPrintable(field()), qPrintable(c->controllerName()), qPrintable(c->actionName()));
157 } else {
158 const qlonglong max = d->extractLongLong(c, params, d->max, &ok);
159 if (Q_UNLIKELY(!ok)) {
160 result.errorMessage = validationDataError(c, 1);
161 qCWarning(C_VALIDATOR, "ValidatorBetween: Invalid maximum comparison value for field %s in %s::%s.", qPrintable(field()), qPrintable(c->controllerName()), qPrintable(c->actionName()));
162 } else {
163 if ((val < min) || (val > max)) {
164 result.errorMessage = validationError(c, QVariantMap{
165 {QStringLiteral("val"), val},
166 {QStringLiteral("min"), min},
167 {QStringLiteral("max"), max}
168 });
169 qCDebug(C_VALIDATOR, "ValidatorBetween: Validation failed for field %s in %s::%s: string length %lli is not between %lli and %lli.", qPrintable(field()), qPrintable(c->controllerName()), qPrintable(c->actionName()), val, min, max);
170 } else {
171 valid = true;
172 }
173 }
174 }
175 }
176 break;
177 default:
178 qCWarning(C_VALIDATOR, "ValidatorBetween: The comparison type with ID %i for field %s at %s::%s is not supported.", static_cast<int>(d->type), qPrintable(field()), qPrintable(c->controllerName()), qPrintable(c->actionName()));
179 result.errorMessage = validationDataError(c, 0);
180 break;
181 }
182
183 if (valid) {
184 if (d->type != QMetaType::QString) {
185 const QVariant _v = d->valueToNumber(c, v, d->type);
186 if (_v.isValid()) {
187 result.value = _v;
188 } else {
189 result.errorMessage = parsingError(c);
190 }
191 } else {
192 result.value.setValue(v);
193 }
194 }
195 } else {
196 defaultValue(c, &result, "ValidatorBetween");
197 }
198
199 return result;
200 }
201
genericValidationError(Cutelyst::Context * c,const QVariant & errorData) const202 QString ValidatorBetween::genericValidationError(Cutelyst::Context *c, const QVariant &errorData) const
203 {
204 QString error;
205
206 Q_D(const ValidatorBetween);
207
208 const QVariantMap map = errorData.toMap();
209 QString min, max;
210 switch (d->type) {
211 case QMetaType::Char:
212 case QMetaType::Short:
213 case QMetaType::Int:
214 case QMetaType::Long:
215 case QMetaType::LongLong:
216 case QMetaType::QString:
217 min = c->locale().toString(map.value(QStringLiteral("min")).toLongLong());
218 max = c->locale().toString(map.value(QStringLiteral("max")).toLongLong());
219 break;
220 case QMetaType::UChar:
221 case QMetaType::UShort:
222 case QMetaType::UInt:
223 case QMetaType::ULong:
224 case QMetaType::ULongLong:
225 min = c->locale().toString(map.value(QStringLiteral("min")).toULongLong());
226 max = c->locale().toString(map.value(QStringLiteral("max")).toULongLong());
227 break;
228 case QMetaType::Float:
229 case QMetaType::Double:
230 min = c->locale().toString(map.value(QStringLiteral("min")).toDouble());
231 max = c->locale().toString(map.value(QStringLiteral("max")).toDouble());
232 break;
233 default:
234 error = validationDataError(c);
235 return error;
236 }
237
238 const QString _label = label(c);
239
240 if (_label.isEmpty()) {
241 if (d->type == QMetaType::QString) {
242 error = c->translate("Cutelyst::ValidatorBetween", "The text must be between %1 and %2 characters long.").arg(min, max);
243 } else {
244 error = c->translate("Cutelyst::ValidatorBetween", "The value must be between %1 and %2.").arg(min, max);
245 }
246 } else {
247 if (d->type == QMetaType::QString) {
248 error = c->translate("Cutelyst::ValidatorBetween", "The text in the “%1“ field must be between %2 and %3 characters long.").arg(_label, min, max);
249 } else {
250 error = c->translate("Cutelyst::ValidatorBetween", "The value in the “%1” field must be between %2 and %3.").arg(_label, min, max);
251 }
252 }
253
254 return error;
255 }
256
genericValidationDataError(Context * c,const QVariant & errorData) const257 QString ValidatorBetween::genericValidationDataError(Context *c, const QVariant &errorData) const
258 {
259 QString error;
260
261 int field = errorData.toInt();
262 const QString _label = label(c);
263
264 if (field == -1) {
265 if (_label.isEmpty()) {
266 error = c->translate("Cutelyst::ValidatorBetween", "The minimum comparison value is not valid.");
267 } else {
268 //: %1 will be replaced by the field label
269 error = c->translate("Cutelyst::ValidatorBetween", "The minimum comparison value for the “%1” field is not valid.").arg(_label);
270 }
271 } else if (field == 0) {
272 Q_D(const ValidatorBetween);
273 if (_label.isEmpty()) {
274 error = c->translate("Cutelyst::ValidatorBetween", "The comparison type with ID %1 is not supported.").arg(static_cast<int>(d->type));
275 } else {
276 //: %1 will be replaced by the type id, %2 will be replaced by the field label
277 error = c->translate("Cutelyst::ValidatorBetween", "The comparison type with ID %1 for the “%2” field is not supported.").arg(QString::number(static_cast<int>(d->type)), _label);
278 }
279 } else if (field == 1) {
280 if (_label.isEmpty()) {
281 error = c->translate("Cutelyst::ValidatorBetween", "The maximum comparison value is not valid.");
282 } else {
283 //: %1 will be replaced by the field label
284 error = c->translate("Cutelyst::ValidatorBetween", "The maximum comparison value for the “%1” field is not valid.").arg(_label);
285 }
286 }
287
288 return error;
289 }
290
genericParsingError(Context * c,const QVariant & errorData) const291 QString ValidatorBetween::genericParsingError(Context *c, const QVariant &errorData) const
292 {
293 QString error;
294 Q_UNUSED(errorData)
295 Q_D(const ValidatorBetween);
296
297 const QString _label = label(c);
298 if ((d->type == QMetaType::Float) || (d->type == QMetaType::Double)) {
299 if (_label.isEmpty()) {
300 error = c->translate("Cutelyst::ValidatorBetween", "Failed to parse the input value into a floating point number.");
301 } else {
302 //: %1 will be replaced by the field label
303 error = c->translate("Cutelyst::ValidatorBetween", "Failed to parse the input value for the “%1” field into a floating point number.").arg(_label);
304 }
305 } else {
306 if (_label.isEmpty()) {
307 error = c->translate("Cutelyst::ValidatorBetween", "Failed to parse the input value into an integer number.");
308 } else {
309 //: %1 will be replaced by the field label
310 error = c->translate("Cutelyst::ValidatorBetween", "Failed to parse the input value for the “%1” field into an integer number.").arg(_label);
311 }
312 }
313
314 return error;
315 }
316