Cutelyst  3.1.0
validatorbetween.cpp
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 
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 
29 {
30 }
31 
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:
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:
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 
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:
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 
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 
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 }
The Cutelyst Context.
Definition: context.h:52
QString translate(const char *context, const char *sourceText, const char *disambiguation=nullptr, int n=-1) const
Definition: context.cpp:480
QLocale locale() const
Definition: context.cpp:456
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 occured 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:62