cutelyst 4.0.0
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-2023 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
21
23{
25
26 const QString v = value(params);
27
28 Q_D(const ValidatorBetween);
29
30 if (!v.isEmpty()) {
31 bool ok = false;
32 bool valid = false;
33
34 switch (d->type) {
35 case QMetaType::Char:
36 case QMetaType::Short:
37 case QMetaType::Int:
38 case QMetaType::Long:
39 case QMetaType::LongLong:
40 {
41 const qlonglong val = c->locale().toLongLong(v, &ok);
42 if (Q_UNLIKELY(!ok)) {
43 result.errorMessage = parsingError(c);
44 qCWarning(C_VALIDATOR).noquote().nospace()
45 << debugString(c) << " Can not parse input \"" << v
46 << "\" into an integer number";
47 } else {
48 const qlonglong min = d->extractLongLong(c, params, d->min, &ok);
49 if (Q_UNLIKELY(!ok)) {
50 result.errorMessage = validationDataError(c, -1);
51 qCWarning(C_VALIDATOR).noquote()
52 << "Invalid mininum comparison value:" << d->min;
53 } else {
54 const qlonglong max = d->extractLongLong(c, params, d->max, &ok);
55 if (Q_UNLIKELY(!ok)) {
56 result.errorMessage = validationDataError(c, 1);
57 qCWarning(C_VALIDATOR).noquote()
58 << "Invalid maximum comparison value:" << d->max;
59 } else {
60 if ((val < min) || (val > max)) {
61 result.errorMessage =
63 QVariantMap{{QStringLiteral("val"), val},
64 {QStringLiteral("min"), min},
65 {QStringLiteral("max"), max}});
66 qCDebug(C_VALIDATOR).noquote()
67 << debugString(c) << val << "is not between" << min << "and" << max;
68 } else {
69 valid = true;
70 }
71 }
72 }
73 }
74 } break;
75 case QMetaType::UChar:
76 case QMetaType::UShort:
77 case QMetaType::UInt:
78 case QMetaType::ULong:
79 case QMetaType::ULongLong:
80 {
81 const qulonglong val = v.toULongLong(&ok);
82 if (Q_UNLIKELY(!ok)) {
83 result.errorMessage = parsingError(c);
84 qCWarning(C_VALIDATOR).noquote().nospace()
85 << debugString(c) << " Can not parse input \"" << v
86 << "\" into an unsigned integer number";
87 } else {
88 const qulonglong min = d->extractULongLong(c, params, d->min, &ok);
89 if (Q_UNLIKELY(!ok)) {
90 result.errorMessage = validationDataError(c, -1);
91 qCWarning(C_VALIDATOR).noquote()
92 << debugString(c) << "Invalid mininum comparison value:" << d->min;
93 } else {
94 const qulonglong max = d->extractULongLong(c, params, d->max, &ok);
95 if (Q_UNLIKELY(!ok)) {
96 result.errorMessage = validationDataError(c, 1);
97 qCWarning(C_VALIDATOR).noquote()
98 << debugString(c) << "Invalid maximum comparison value:" << d->max;
99 } else {
100 if ((val < min) || (val > max)) {
101 result.errorMessage =
103 QVariantMap{{QStringLiteral("val"), val},
104 {QStringLiteral("min"), min},
105 {QStringLiteral("max"), max}});
106 qCDebug(C_VALIDATOR).noquote()
107 << debugString(c) << val << "is not between" << min << "and" << max;
108 } else {
109 valid = true;
110 }
111 }
112 }
113 }
114 } break;
115 case QMetaType::Float:
116 case QMetaType::Double:
117 {
118 const double val = v.toDouble(&ok);
119 if (Q_UNLIKELY(!ok)) {
120 result.errorMessage = parsingError(c);
121 qCWarning(C_VALIDATOR).noquote().nospace()
122 << debugString(c) << " Can not parse input \"" << v
123 << "\" into a floating point number";
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).noquote()
129 << debugString(c) << "Invalid mininum comparison value:" << d->min;
130 } else {
131 const double max = d->extractDouble(c, params, d->max, &ok);
132 if (Q_UNLIKELY(!ok)) {
133 result.errorMessage = validationDataError(c, 1);
134 qCWarning(C_VALIDATOR).noquote()
135 << debugString(c) << "Invalid maximum comparison value:" << d->max;
136 } else {
137 if ((val < min) || (val > max)) {
138 result.errorMessage =
140 QVariantMap{{QStringLiteral("val"), val},
141 {QStringLiteral("min"), min},
142 {QStringLiteral("max"), max}});
143 qCDebug(C_VALIDATOR).noquote()
144 << debugString(c) << val << "is not between" << min << "and" << max;
145 } else {
146 valid = true;
147 }
148 }
149 }
150 }
151 } break;
152 case QMetaType::QString:
153 {
154 const auto val = static_cast<qlonglong>(v.length());
155 const qlonglong min = d->extractLongLong(c, params, d->min, &ok);
156 if (Q_UNLIKELY(!ok)) {
157 result.errorMessage = validationDataError(c, -1);
158 qCWarning(C_VALIDATOR).noquote()
159 << debugString(c) << "Invalid mininum comparison value:" << d->min;
160 } else {
161 const qlonglong max = d->extractLongLong(c, params, d->max, &ok);
162 if (Q_UNLIKELY(!ok)) {
163 result.errorMessage = validationDataError(c, 1);
164 qCWarning(C_VALIDATOR).noquote()
165 << debugString(c) << "Invalid maximum comparison value:" << d->max;
166 } else {
167 if ((val < min) || (val > max)) {
168 result.errorMessage =
170 QVariantMap{{QStringLiteral("val"), val},
171 {QStringLiteral("min"), min},
172 {QStringLiteral("max"), max}});
173 qCDebug(C_VALIDATOR).noquote() << debugString(c) << "String length" << val
174 << "is not between" << min << "and" << max;
175 } else {
176 valid = true;
177 }
178 }
179 }
180 } break;
181 default:
182 qCWarning(C_VALIDATOR).noquote()
183 << debugString(c) << "The comparison type" << d->type << "is not supported";
184 result.errorMessage = validationDataError(c, 0);
185 break;
186 }
187
188 if (valid) {
189 if (d->type != QMetaType::QString) {
190 const QVariant _v = d->valueToNumber(c, v, d->type);
191 if (_v.isValid()) {
192 result.value = _v;
193 } else {
194 result.errorMessage = parsingError(c);
195 }
196 } else {
197 result.value.setValue(v);
198 }
199 }
200 } else {
201 defaultValue(c, &result);
202 }
203
204 return result;
205}
206
208 const QVariant &errorData) const
209{
210 QString error;
211
212 Q_D(const ValidatorBetween);
213
214 const QVariantMap map = errorData.toMap();
215 QString min, max;
216 switch (d->type) {
217 case QMetaType::Char:
218 case QMetaType::Short:
219 case QMetaType::Int:
220 case QMetaType::Long:
221 case QMetaType::LongLong:
222 case QMetaType::QString:
223 min = c->locale().toString(map.value(QStringLiteral("min")).toLongLong());
224 max = c->locale().toString(map.value(QStringLiteral("max")).toLongLong());
225 break;
226 case QMetaType::UChar:
227 case QMetaType::UShort:
228 case QMetaType::UInt:
229 case QMetaType::ULong:
230 case QMetaType::ULongLong:
231 min = c->locale().toString(map.value(QStringLiteral("min")).toULongLong());
232 max = c->locale().toString(map.value(QStringLiteral("max")).toULongLong());
233 break;
234 case QMetaType::Float:
235 case QMetaType::Double:
236 min = c->locale().toString(map.value(QStringLiteral("min")).toDouble());
237 max = c->locale().toString(map.value(QStringLiteral("max")).toDouble());
238 break;
239 default:
240 error = validationDataError(c);
241 return error;
242 }
243
244 const QString _label = label(c);
245
246 if (_label.isEmpty()) {
247 if (d->type == QMetaType::QString) {
248 error = c->translate("Cutelyst::ValidatorBetween",
249 "The text must be between %1 and %2 characters long.")
250 .arg(min, max);
251 } else {
252 error =
253 c->translate("Cutelyst::ValidatorBetween", "The value must be between %1 and %2.")
254 .arg(min, max);
255 }
256 } else {
257 if (d->type == QMetaType::QString) {
258 error = c->translate(
259 "Cutelyst::ValidatorBetween",
260 "The text in the “%1“ field must be between %2 and %3 characters long.")
261 .arg(_label, min, max);
262 } else {
263 error = c->translate("Cutelyst::ValidatorBetween",
264 "The value in the “%1” field must be between %2 and %3.")
265 .arg(_label, min, max);
266 }
267 }
268
269 return error;
270}
271
272QString ValidatorBetween::genericValidationDataError(Context *c, const QVariant &errorData) const
273{
274 QString error;
275
276 int field = errorData.toInt();
277 const QString _label = label(c);
278
279 if (field == -1) {
280 if (_label.isEmpty()) {
281 error = c->translate("Cutelyst::ValidatorBetween",
282 "The minimum comparison value is not valid.");
283 } else {
284 //: %1 will be replaced by the field label
285 error = c->translate("Cutelyst::ValidatorBetween",
286 "The minimum comparison value for the “%1” field is not valid.")
287 .arg(_label);
288 }
289 } else if (field == 0) {
290 Q_D(const ValidatorBetween);
291 if (_label.isEmpty()) {
292 error = c->translate("Cutelyst::ValidatorBetween",
293 "The comparison type with ID %1 is not supported.")
294 .arg(static_cast<int>(d->type));
295 } else {
296 //: %1 will be replaced by the type id, %2 will be replaced by the field label
297 error =
298 c->translate("Cutelyst::ValidatorBetween",
299 "The comparison type with ID %1 for the “%2” field is not supported.")
300 .arg(QString::number(static_cast<int>(d->type)), _label);
301 }
302 } else if (field == 1) {
303 if (_label.isEmpty()) {
304 error = c->translate("Cutelyst::ValidatorBetween",
305 "The maximum comparison value is not valid.");
306 } else {
307 //: %1 will be replaced by the field label
308 error = c->translate("Cutelyst::ValidatorBetween",
309 "The maximum comparison value for the “%1” field is not valid.")
310 .arg(_label);
311 }
312 }
313
314 return error;
315}
316
317QString ValidatorBetween::genericParsingError(Context *c, const QVariant &errorData) const
318{
319 QString error;
320 Q_UNUSED(errorData)
321 Q_D(const ValidatorBetween);
322
323 const QString _label = label(c);
324 if ((d->type == QMetaType::Float) || (d->type == QMetaType::Double)) {
325 if (_label.isEmpty()) {
326 error = c->translate("Cutelyst::ValidatorBetween",
327 "Failed to parse the input value into a floating point number.");
328 } else {
329 //: %1 will be replaced by the field label
330 error = c->translate("Cutelyst::ValidatorBetween",
331 "Failed to parse the input value for the “%1” field into a "
332 "floating point number.")
333 .arg(_label);
334 }
335 } else {
336 if (_label.isEmpty()) {
337 error = c->translate("Cutelyst::ValidatorBetween",
338 "Failed to parse the input value into an integer number.");
339 } else {
340 //: %1 will be replaced by the field label
341 error =
342 c->translate(
343 "Cutelyst::ValidatorBetween",
344 "Failed to parse the input value for the “%1” field into an integer number.")
345 .arg(_label);
346 }
347 }
348
349 return error;
350}
The Cutelyst Context.
Definition: context.h:38
QLocale locale() const noexcept
Definition: context.cpp:453
QString translate(const char *context, const char *sourceText, const char *disambiguation=nullptr, int n=-1) const
Definition: context.cpp:477
Checks if a value or text length is between a minimum and maximum value.
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.
Base class for all validator rules.
QString field() const noexcept
Returns the name of the field to validate.
QString label(Context *c) const
Returns the human readable field label used for generic error messages.
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
I a defValKey has been set in the constructor, this will try to get the default value from the stash ...
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.
QString debugString(Context *c) const
Returns a string that can be used for debug output if validation fails.
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.
Definition: validatorrule.h:49