cutelyst  3.7.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-2022 Matthias Fehring <mf@huessenbergnetz.de>
3  * SPDX-License-Identifier: BSD-3-Clause
4  */
5 
6 #include "validatorbetween_p.h"
7 
8 using namespace Cutelyst;
9 
10 ValidatorBetween::ValidatorBetween(const QString &field, QMetaType::Type type, const QVariant &min, const QVariant &max, const ValidatorMessages &messages, const QString &defValKey) :
11  ValidatorRule(*new ValidatorBetweenPrivate(field, type, min, max, messages, defValKey))
12 {
13 }
14 
16 {
17 }
18 
20 {
21  ValidatorReturnType result;
22 
23  const QString v = value(params);
24 
25  Q_D(const ValidatorBetween);
26 
27  if (!v.isEmpty()) {
28  bool ok = false;
29  bool valid = false;
30 
31  switch (d->type) {
32  case QMetaType::Char:
33  case QMetaType::Short:
34  case QMetaType::Int:
35  case QMetaType::Long:
37  {
38  const qlonglong val = c->locale().toLongLong(v, &ok);
39  if (Q_UNLIKELY(!ok)) {
40  result.errorMessage = parsingError(c);
41  qCWarning(C_VALIDATOR, "ValidatorBetween: Failed to parse value of field %s into number at %s::%s.", qPrintable(field()), qPrintable(c->controllerName()), qPrintable(c->actionName()));
42  } else {
43  const qlonglong min = d->extractLongLong(c, params, d->min, &ok);
44  if (Q_UNLIKELY(!ok)) {
45  result.errorMessage = validationDataError(c, -1);
46  qCWarning(C_VALIDATOR, "ValidatorBetween: Invalid minimum comparison value for field %s in %s::%s.", qPrintable(field()), qPrintable(c->controllerName()), qPrintable(c->actionName()));
47  } else {
48  const qlonglong max = d->extractLongLong(c, params, d->max, &ok);
49  if (Q_UNLIKELY(!ok)) {
50  result.errorMessage = validationDataError(c, 1);
51  qCWarning(C_VALIDATOR, "ValidatorBetween: Invalid maximum comparison value for field %s in %s::%s.", qPrintable(field()), qPrintable(c->controllerName()), qPrintable(c->actionName()));
52  } else {
53  if ((val < min) || (val > max)) {
54  result.errorMessage = validationError(c, QVariantMap{
55  {QStringLiteral("val"), val},
56  {QStringLiteral("min"), min},
57  {QStringLiteral("max"), max}
58  });
59  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);
60  } else {
61  valid = true;
62  }
63  }
64  }
65  }
66  }
67  break;
68  case QMetaType::UChar:
69  case QMetaType::UShort:
70  case QMetaType::UInt:
71  case QMetaType::ULong:
73  {
74  const qulonglong val = v.toULongLong(&ok);
75  if (Q_UNLIKELY(!ok)) {
76  result.errorMessage = parsingError(c);
77  qCWarning(C_VALIDATOR, "ValidatorBetween: Failed to parse value of field %s into number at %s::%s.", qPrintable(field()), qPrintable(c->controllerName()), qPrintable(c->actionName()));
78  } else {
79  const qulonglong min = d->extractULongLong(c, params, d->min, &ok);
80  if (Q_UNLIKELY(!ok)) {
81  result.errorMessage = validationDataError(c, -1);
82  qCWarning(C_VALIDATOR, "ValidatorBetween: Invalid minimum comparison value for field %s in %s::%s.", qPrintable(field()), qPrintable(c->controllerName()), qPrintable(c->actionName()));
83  } else {
84  const qulonglong max = d->extractULongLong(c, params, d->max, &ok);
85  if (Q_UNLIKELY(!ok)) {
86  result.errorMessage = validationDataError(c, 1);
87  qCWarning(C_VALIDATOR, "ValidatorBetween: Invalid maximum comparison value for field %s in %s::%s.", qPrintable(field()), qPrintable(c->controllerName()), qPrintable(c->actionName()));
88  } else {
89  if ((val < min) || (val > max)) {
90  result.errorMessage = validationError(c, QVariantMap{
91  {QStringLiteral("val"), val},
92  {QStringLiteral("min"), min},
93  {QStringLiteral("max"), max}
94  });
95  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);
96  } else {
97  valid = true;
98  }
99  }
100  }
101  }
102  }
103  break;
104  case QMetaType::Float:
105  case QMetaType::Double:
106  {
107  const double val = v.toDouble(&ok);
108  if (Q_UNLIKELY(!ok)) {
109  result.errorMessage = parsingError(c);
110  qCWarning(C_VALIDATOR, "ValidatorBetween: Failed to parse value of field %s into number at %s::%s.", qPrintable(field()), qPrintable(c->controllerName()), qPrintable(c->actionName()));
111  } else {
112  const double min = d->extractDouble(c, params, d->min, &ok);
113  if (Q_UNLIKELY(!ok)) {
114  result.errorMessage = validationDataError(c, -1);
115  qCWarning(C_VALIDATOR, "ValidatorBetween: Invalid minimum comparison value for field %s in %s::%s.", qPrintable(field()), qPrintable(c->controllerName()), qPrintable(c->actionName()));
116  } else {
117  const double max = d->extractDouble(c, params, d->max, &ok);
118  if (Q_UNLIKELY(!ok)) {
119  result.errorMessage = validationDataError(c, 1);
120  qCWarning(C_VALIDATOR, "ValidatorBetween: Invalid maximum comparison value for field %s in %s::%s.", qPrintable(field()), qPrintable(c->controllerName()), qPrintable(c->actionName()));
121  } else {
122  if ((val < min) || (val > max)) {
123  result.errorMessage = validationError(c, QVariantMap{
124  {QStringLiteral("val"), val},
125  {QStringLiteral("min"), min},
126  {QStringLiteral("max"), max}
127  });
128  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);
129  } else {
130  valid = true;
131  }
132  }
133  }
134  }
135  }
136  break;
137  case QMetaType::QString:
138  {
139  const qlonglong val = static_cast<qlonglong>(v.length());
140  const qlonglong min = d->extractLongLong(c, params, d->min, &ok);
141  if (Q_UNLIKELY(!ok)) {
142  result.errorMessage = validationDataError(c, -1);
143  qCWarning(C_VALIDATOR, "ValidatorBetween: Invalid minimum comparison value for field %s in %s::%s.", qPrintable(field()), qPrintable(c->controllerName()), qPrintable(c->actionName()));
144  } else {
145  const qlonglong max = d->extractLongLong(c, params, d->max, &ok);
146  if (Q_UNLIKELY(!ok)) {
147  result.errorMessage = validationDataError(c, 1);
148  qCWarning(C_VALIDATOR, "ValidatorBetween: Invalid maximum comparison value for field %s in %s::%s.", qPrintable(field()), qPrintable(c->controllerName()), qPrintable(c->actionName()));
149  } else {
150  if ((val < min) || (val > max)) {
151  result.errorMessage = validationError(c, QVariantMap{
152  {QStringLiteral("val"), val},
153  {QStringLiteral("min"), min},
154  {QStringLiteral("max"), max}
155  });
156  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);
157  } else {
158  valid = true;
159  }
160  }
161  }
162  }
163  break;
164  default:
165  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()));
166  result.errorMessage = validationDataError(c, 0);
167  break;
168  }
169 
170  if (valid) {
171  if (d->type != QMetaType::QString) {
172  const QVariant _v = d->valueToNumber(c, v, d->type);
173  if (_v.isValid()) {
174  result.value = _v;
175  } else {
176  result.errorMessage = parsingError(c);
177  }
178  } else {
179  result.value.setValue(v);
180  }
181  }
182  } else {
183  defaultValue(c, &result, "ValidatorBetween");
184  }
185 
186  return result;
187 }
188 
190 {
191  QString error;
192 
193  Q_D(const ValidatorBetween);
194 
195  const QVariantMap map = errorData.toMap();
196  QString min, max;
197  switch (d->type) {
198  case QMetaType::Char:
199  case QMetaType::Short:
200  case QMetaType::Int:
201  case QMetaType::Long:
202  case QMetaType::LongLong:
203  case QMetaType::QString:
204  min = c->locale().toString(map.value(QStringLiteral("min")).toLongLong());
205  max = c->locale().toString(map.value(QStringLiteral("max")).toLongLong());
206  break;
207  case QMetaType::UChar:
208  case QMetaType::UShort:
209  case QMetaType::UInt:
210  case QMetaType::ULong:
212  min = c->locale().toString(map.value(QStringLiteral("min")).toULongLong());
213  max = c->locale().toString(map.value(QStringLiteral("max")).toULongLong());
214  break;
215  case QMetaType::Float:
216  case QMetaType::Double:
217  min = c->locale().toString(map.value(QStringLiteral("min")).toDouble());
218  max = c->locale().toString(map.value(QStringLiteral("max")).toDouble());
219  break;
220  default:
221  error = validationDataError(c);
222  return error;
223  }
224 
225  const QString _label = label(c);
226 
227  if (_label.isEmpty()) {
228  if (d->type == QMetaType::QString) {
229  error = c->translate("Cutelyst::ValidatorBetween", "The text must be between %1 and %2 characters long.").arg(min, max);
230  } else {
231  error = c->translate("Cutelyst::ValidatorBetween", "The value must be between %1 and %2.").arg(min, max);
232  }
233  } else {
234  if (d->type == QMetaType::QString) {
235  error = c->translate("Cutelyst::ValidatorBetween", "The text in the “%1“ field must be between %2 and %3 characters long.").arg(_label, min, max);
236  } else {
237  error = c->translate("Cutelyst::ValidatorBetween", "The value in the “%1” field must be between %2 and %3.").arg(_label, min, max);
238  }
239  }
240 
241  return error;
242 }
243 
245 {
246  QString error;
247 
248  int field = errorData.toInt();
249  const QString _label = label(c);
250 
251  if (field == -1) {
252  if (_label.isEmpty()) {
253  error = c->translate("Cutelyst::ValidatorBetween", "The minimum comparison value is not valid.");
254  } else {
255  //: %1 will be replaced by the field label
256  error = c->translate("Cutelyst::ValidatorBetween", "The minimum comparison value for the “%1” field is not valid.").arg(_label);
257  }
258  } else if (field == 0) {
259  Q_D(const ValidatorBetween);
260  if (_label.isEmpty()) {
261  error = c->translate("Cutelyst::ValidatorBetween", "The comparison type with ID %1 is not supported.").arg(static_cast<int>(d->type));
262  } else {
263  //: %1 will be replaced by the type id, %2 will be replaced by the field label
264  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);
265  }
266  } else if (field == 1) {
267  if (_label.isEmpty()) {
268  error = c->translate("Cutelyst::ValidatorBetween", "The maximum comparison value is not valid.");
269  } else {
270  //: %1 will be replaced by the field label
271  error = c->translate("Cutelyst::ValidatorBetween", "The maximum comparison value for the “%1” field is not valid.").arg(_label);
272  }
273  }
274 
275  return error;
276 }
277 
279 {
280  QString error;
281  Q_UNUSED(errorData)
282  Q_D(const ValidatorBetween);
283 
284  const QString _label = label(c);
285  if ((d->type == QMetaType::Float) || (d->type == QMetaType::Double)) {
286  if (_label.isEmpty()) {
287  error = c->translate("Cutelyst::ValidatorBetween", "Failed to parse the input value into a floating point number.");
288  } else {
289  //: %1 will be replaced by the field label
290  error = c->translate("Cutelyst::ValidatorBetween", "Failed to parse the input value for the “%1” field into a floating point number.").arg(_label);
291  }
292  } else {
293  if (_label.isEmpty()) {
294  error = c->translate("Cutelyst::ValidatorBetween", "Failed to parse the input value into an integer number.");
295  } else {
296  //: %1 will be replaced by the field label
297  error = c->translate("Cutelyst::ValidatorBetween", "Failed to parse the input value for the “%1” field into an integer number.").arg(_label);
298  }
299  }
300 
301  return error;
302 }
The Cutelyst Context.
Definition: context.h:39
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 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 ...
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
qlonglong toLongLong(const QString &s, bool *ok) const const
QString toString(qlonglong i) const const
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
bool isEmpty() const const
int length() const const
QString number(int n, int base)
double toDouble(bool *ok) const const
qulonglong toULongLong(bool *ok, int base) const const
bool isValid() const const
void setValue(const T &value)
int toInt(bool *ok) const const
QMap< QString, QVariant > toMap() const const
Stores custom error messages and the input field label.
Contains the result of a single input parameter validation.
Definition: validatorrule.h:49