cutelyst 3.9.1
A C++ Web Framework built on top of Qt, using the simple approach of Catalyst (Perl) framework.
validatorbetween.cpp
1/*
2 * SPDX-FileCopyrightText: (C) 2017-2022 Matthias Fehring <mf@huessenbergnetz.de>
3 * SPDX-License-Identifier: BSD-3-Clause
4 */
5
6#include "validatorbetween_p.h"
7
8using namespace Cutelyst;
9
11 QMetaType::Type type,
12 const QVariant &min,
13 const QVariant &max,
14 const ValidatorMessages &messages,
15 const QString &defValKey)
16 : ValidatorRule(*new ValidatorBetweenPrivate(field, type, min, max, messages, defValKey))
17{
18}
19
23
25{
27
28 const QString v = value(params);
29
30 Q_D(const ValidatorBetween);
31
32 if (!v.isEmpty()) {
33 bool ok = false;
34 bool valid = false;
35
36 switch (d->type) {
37 case QMetaType::Char:
38 case QMetaType::Short:
39 case QMetaType::Int:
40 case QMetaType::Long:
41 case QMetaType::LongLong:
42 {
43 const qlonglong val = c->locale().toLongLong(v, &ok);
44 if (Q_UNLIKELY(!ok)) {
45 result.errorMessage = parsingError(c);
46 qCWarning(
47 C_VALIDATOR,
48 "ValidatorBetween: Failed to parse value of field %s into number at %s::%s.",
49 qPrintable(field()),
50 qPrintable(c->controllerName()),
51 qPrintable(c->actionName()));
52 } else {
53 const qlonglong min = d->extractLongLong(c, params, d->min, &ok);
54 if (Q_UNLIKELY(!ok)) {
55 result.errorMessage = validationDataError(c, -1);
56 qCWarning(C_VALIDATOR,
57 "ValidatorBetween: Invalid minimum comparison value for field %s in "
58 "%s::%s.",
59 qPrintable(field()),
60 qPrintable(c->controllerName()),
61 qPrintable(c->actionName()));
62 } else {
63 const qlonglong max = d->extractLongLong(c, params, d->max, &ok);
64 if (Q_UNLIKELY(!ok)) {
65 result.errorMessage = validationDataError(c, 1);
66 qCWarning(C_VALIDATOR,
67 "ValidatorBetween: Invalid maximum comparison value for field %s "
68 "in %s::%s.",
69 qPrintable(field()),
70 qPrintable(c->controllerName()),
71 qPrintable(c->actionName()));
72 } else {
73 if ((val < min) || (val > max)) {
74 result.errorMessage =
76 QVariantMap{{QStringLiteral("val"), val},
77 {QStringLiteral("min"), min},
78 {QStringLiteral("max"), max}});
79 qCDebug(C_VALIDATOR,
80 "ValidatorBetween: Validation failed for field %s in %s::%s: "
81 "%lli is not between %lli and %lli.",
82 qPrintable(field()),
83 qPrintable(c->controllerName()),
84 qPrintable(c->actionName()),
85 val,
86 min,
87 max);
88 } else {
89 valid = true;
90 }
91 }
92 }
93 }
94 } break;
95 case QMetaType::UChar:
96 case QMetaType::UShort:
97 case QMetaType::UInt:
98 case QMetaType::ULong:
99 case QMetaType::ULongLong:
100 {
101 const qulonglong val = v.toULongLong(&ok);
102 if (Q_UNLIKELY(!ok)) {
103 result.errorMessage = parsingError(c);
104 qCWarning(
105 C_VALIDATOR,
106 "ValidatorBetween: Failed to parse value of field %s into number at %s::%s.",
107 qPrintable(field()),
108 qPrintable(c->controllerName()),
109 qPrintable(c->actionName()));
110 } else {
111 const qulonglong min = d->extractULongLong(c, params, d->min, &ok);
112 if (Q_UNLIKELY(!ok)) {
113 result.errorMessage = validationDataError(c, -1);
114 qCWarning(C_VALIDATOR,
115 "ValidatorBetween: Invalid minimum comparison value for field %s in "
116 "%s::%s.",
117 qPrintable(field()),
118 qPrintable(c->controllerName()),
119 qPrintable(c->actionName()));
120 } else {
121 const qulonglong max = d->extractULongLong(c, params, d->max, &ok);
122 if (Q_UNLIKELY(!ok)) {
123 result.errorMessage = validationDataError(c, 1);
124 qCWarning(C_VALIDATOR,
125 "ValidatorBetween: Invalid maximum comparison value for field %s "
126 "in %s::%s.",
127 qPrintable(field()),
128 qPrintable(c->controllerName()),
129 qPrintable(c->actionName()));
130 } else {
131 if ((val < min) || (val > max)) {
132 result.errorMessage =
134 QVariantMap{{QStringLiteral("val"), val},
135 {QStringLiteral("min"), min},
136 {QStringLiteral("max"), max}});
137 qCDebug(C_VALIDATOR,
138 "ValidatorBetween: Validation failed for field %s in %s::%s: "
139 "%llu is not between %llu and %llu.",
140 qPrintable(field()),
141 qPrintable(c->controllerName()),
142 qPrintable(c->actionName()),
143 val,
144 min,
145 max);
146 } else {
147 valid = true;
148 }
149 }
150 }
151 }
152 } break;
153 case QMetaType::Float:
154 case QMetaType::Double:
155 {
156 const double val = v.toDouble(&ok);
157 if (Q_UNLIKELY(!ok)) {
158 result.errorMessage = parsingError(c);
159 qCWarning(
160 C_VALIDATOR,
161 "ValidatorBetween: Failed to parse value of field %s into number at %s::%s.",
162 qPrintable(field()),
163 qPrintable(c->controllerName()),
164 qPrintable(c->actionName()));
165 } else {
166 const double min = d->extractDouble(c, params, d->min, &ok);
167 if (Q_UNLIKELY(!ok)) {
168 result.errorMessage = validationDataError(c, -1);
169 qCWarning(C_VALIDATOR,
170 "ValidatorBetween: Invalid minimum comparison value for field %s in "
171 "%s::%s.",
172 qPrintable(field()),
173 qPrintable(c->controllerName()),
174 qPrintable(c->actionName()));
175 } else {
176 const double max = d->extractDouble(c, params, d->max, &ok);
177 if (Q_UNLIKELY(!ok)) {
178 result.errorMessage = validationDataError(c, 1);
179 qCWarning(C_VALIDATOR,
180 "ValidatorBetween: Invalid maximum comparison value for field %s "
181 "in %s::%s.",
182 qPrintable(field()),
183 qPrintable(c->controllerName()),
184 qPrintable(c->actionName()));
185 } else {
186 if ((val < min) || (val > max)) {
187 result.errorMessage =
189 QVariantMap{{QStringLiteral("val"), val},
190 {QStringLiteral("min"), min},
191 {QStringLiteral("max"), max}});
192 qCDebug(C_VALIDATOR,
193 "ValidatorBetween: Validation failed for field %s in %s::%s: "
194 "%f is not between %f and %f.",
195 qPrintable(field()),
196 qPrintable(c->controllerName()),
197 qPrintable(c->actionName()),
198 val,
199 min,
200 max);
201 } else {
202 valid = true;
203 }
204 }
205 }
206 }
207 } break;
208 case QMetaType::QString:
209 {
210 const qlonglong val = static_cast<qlonglong>(v.length());
211 const qlonglong min = d->extractLongLong(c, params, d->min, &ok);
212 if (Q_UNLIKELY(!ok)) {
213 result.errorMessage = validationDataError(c, -1);
214 qCWarning(
215 C_VALIDATOR,
216 "ValidatorBetween: Invalid minimum comparison value for field %s in %s::%s.",
217 qPrintable(field()),
218 qPrintable(c->controllerName()),
219 qPrintable(c->actionName()));
220 } else {
221 const qlonglong max = d->extractLongLong(c, params, d->max, &ok);
222 if (Q_UNLIKELY(!ok)) {
223 result.errorMessage = validationDataError(c, 1);
224 qCWarning(C_VALIDATOR,
225 "ValidatorBetween: Invalid maximum comparison value for field %s in "
226 "%s::%s.",
227 qPrintable(field()),
228 qPrintable(c->controllerName()),
229 qPrintable(c->actionName()));
230 } else {
231 if ((val < min) || (val > max)) {
232 result.errorMessage =
234 QVariantMap{{QStringLiteral("val"), val},
235 {QStringLiteral("min"), min},
236 {QStringLiteral("max"), max}});
237 qCDebug(C_VALIDATOR,
238 "ValidatorBetween: Validation failed for field %s in %s::%s: "
239 "string length %lli is not between %lli and %lli.",
240 qPrintable(field()),
241 qPrintable(c->controllerName()),
242 qPrintable(c->actionName()),
243 val,
244 min,
245 max);
246 } else {
247 valid = true;
248 }
249 }
250 }
251 } break;
252 default:
253 qCWarning(C_VALIDATOR,
254 "ValidatorBetween: The comparison type with ID %i for field %s at %s::%s is "
255 "not supported.",
256 static_cast<int>(d->type),
257 qPrintable(field()),
258 qPrintable(c->controllerName()),
259 qPrintable(c->actionName()));
260 result.errorMessage = validationDataError(c, 0);
261 break;
262 }
263
264 if (valid) {
265 if (d->type != QMetaType::QString) {
266 const QVariant _v = d->valueToNumber(c, v, d->type);
267 if (_v.isValid()) {
268 result.value = _v;
269 } else {
270 result.errorMessage = parsingError(c);
271 }
272 } else {
273 result.value.setValue(v);
274 }
275 }
276 } else {
277 defaultValue(c, &result, "ValidatorBetween");
278 }
279
280 return result;
281}
282
284 const QVariant &errorData) const
285{
286 QString error;
287
288 Q_D(const ValidatorBetween);
289
290 const QVariantMap map = errorData.toMap();
291 QString min, max;
292 switch (d->type) {
293 case QMetaType::Char:
294 case QMetaType::Short:
295 case QMetaType::Int:
296 case QMetaType::Long:
297 case QMetaType::LongLong:
298 case QMetaType::QString:
299 min = c->locale().toString(map.value(QStringLiteral("min")).toLongLong());
300 max = c->locale().toString(map.value(QStringLiteral("max")).toLongLong());
301 break;
302 case QMetaType::UChar:
303 case QMetaType::UShort:
304 case QMetaType::UInt:
305 case QMetaType::ULong:
306 case QMetaType::ULongLong:
307 min = c->locale().toString(map.value(QStringLiteral("min")).toULongLong());
308 max = c->locale().toString(map.value(QStringLiteral("max")).toULongLong());
309 break;
310 case QMetaType::Float:
311 case QMetaType::Double:
312 min = c->locale().toString(map.value(QStringLiteral("min")).toDouble());
313 max = c->locale().toString(map.value(QStringLiteral("max")).toDouble());
314 break;
315 default:
316 error = validationDataError(c);
317 return error;
318 }
319
320 const QString _label = label(c);
321
322 if (_label.isEmpty()) {
323 if (d->type == QMetaType::QString) {
324 error = c->translate("Cutelyst::ValidatorBetween",
325 "The text must be between %1 and %2 characters long.")
326 .arg(min, max);
327 } else {
328 error =
329 c->translate("Cutelyst::ValidatorBetween", "The value must be between %1 and %2.")
330 .arg(min, max);
331 }
332 } else {
333 if (d->type == QMetaType::QString) {
334 error = c->translate(
335 "Cutelyst::ValidatorBetween",
336 "The text in the “%1“ field must be between %2 and %3 characters long.")
337 .arg(_label, min, max);
338 } else {
339 error = c->translate("Cutelyst::ValidatorBetween",
340 "The value in the “%1” field must be between %2 and %3.")
341 .arg(_label, min, max);
342 }
343 }
344
345 return error;
346}
347
348QString ValidatorBetween::genericValidationDataError(Context *c, const QVariant &errorData) const
349{
350 QString error;
351
352 int field = errorData.toInt();
353 const QString _label = label(c);
354
355 if (field == -1) {
356 if (_label.isEmpty()) {
357 error = c->translate("Cutelyst::ValidatorBetween",
358 "The minimum comparison value is not valid.");
359 } else {
360 //: %1 will be replaced by the field label
361 error = c->translate("Cutelyst::ValidatorBetween",
362 "The minimum comparison value for the “%1” field is not valid.")
363 .arg(_label);
364 }
365 } else if (field == 0) {
366 Q_D(const ValidatorBetween);
367 if (_label.isEmpty()) {
368 error = c->translate("Cutelyst::ValidatorBetween",
369 "The comparison type with ID %1 is not supported.")
370 .arg(static_cast<int>(d->type));
371 } else {
372 //: %1 will be replaced by the type id, %2 will be replaced by the field label
373 error =
374 c->translate("Cutelyst::ValidatorBetween",
375 "The comparison type with ID %1 for the “%2” field is not supported.")
376 .arg(QString::number(static_cast<int>(d->type)), _label);
377 }
378 } else if (field == 1) {
379 if (_label.isEmpty()) {
380 error = c->translate("Cutelyst::ValidatorBetween",
381 "The maximum comparison value is not valid.");
382 } else {
383 //: %1 will be replaced by the field label
384 error = c->translate("Cutelyst::ValidatorBetween",
385 "The maximum comparison value for the “%1” field is not valid.")
386 .arg(_label);
387 }
388 }
389
390 return error;
391}
392
393QString ValidatorBetween::genericParsingError(Context *c, const QVariant &errorData) const
394{
395 QString error;
396 Q_UNUSED(errorData)
397 Q_D(const ValidatorBetween);
398
399 const QString _label = label(c);
400 if ((d->type == QMetaType::Float) || (d->type == QMetaType::Double)) {
401 if (_label.isEmpty()) {
402 error = c->translate("Cutelyst::ValidatorBetween",
403 "Failed to parse the input value into a floating point number.");
404 } else {
405 //: %1 will be replaced by the field label
406 error = c->translate("Cutelyst::ValidatorBetween",
407 "Failed to parse the input value for the “%1” field into a "
408 "floating point number.")
409 .arg(_label);
410 }
411 } else {
412 if (_label.isEmpty()) {
413 error = c->translate("Cutelyst::ValidatorBetween",
414 "Failed to parse the input value into an integer number.");
415 } else {
416 //: %1 will be replaced by the field label
417 error =
418 c->translate(
419 "Cutelyst::ValidatorBetween",
420 "Failed to parse the input value for the “%1” field into an integer number.")
421 .arg(_label);
422 }
423 }
424
425 return error;
426}
The Cutelyst Context.
Definition context.h:39
QLocale locale() const noexcept
Definition context.cpp:466
QString translate(const char *context, const char *sourceText, const char *disambiguation=nullptr, int n=-1) const
Definition context.cpp:490
ValidatorBetween(const QString &field, QMetaType::Type type, const QVariant &min, const QVariant &max, const ValidatorMessages &messages=ValidatorMessages(), const QString &defValKey=QString())
Constructs a new between validator.
QString genericValidationError(Context *c, const QVariant &errorData=QVariant()) const override
Returns a generic error message.
ValidatorReturnType validate(Context *c, const ParamsMultiMap &params) const override
Performs the validation and returns the result.
~ValidatorBetween() override
Deconstructs the between validator.
QString genericParsingError(Context *c, const QVariant &errorData) const override
Returns a generic error message for input value parsing errors.
QString genericValidationDataError(Context *c, const QVariant &errorData) const override
Returns a generic error message for validation data errors.
QString label(Context *c) const
Returns the human readable field label used for generic error messages.
QString field() const
Returns the name of the field to validate.
QString parsingError(Context *c, const QVariant &errorData=QVariant()) const
Returns an error message if an error occurred while parsing input.
void defaultValue(Context *c, ValidatorReturnType *result, const char *validatorName) const
I a defValKey has been set in the constructor, this will try to get the default value from the stash ...
ValidatorRule(const QString &field, const ValidatorMessages &messages=ValidatorMessages(), const QString &defValKey=QString())
Constructs a new ValidatorRule with the given parameters.
QString value(const ParamsMultiMap &params) const
Returns the value of the field from the input params.
QString validationDataError(Context *c, const QVariant &errorData=QVariant()) const
Returns an error message if any validation data is missing or invalid.
QString validationError(Context *c, const QVariant &errorData=QVariant()) const
Returns a descriptive error message if validation failed.
The Cutelyst namespace holds all public Cutelyst API.
Definition Mainpage.dox:8
QMultiMap< QString, QString > ParamsMultiMap
Stores custom error messages and the input field label.
Contains the result of a single input parameter validation.