Cutelyst  3.5.0
validatorsize.cpp
1 /*
2  * SPDX-FileCopyrightText: (C) 2017-2022 Matthias Fehring <mf@huessenbergnetz.de>
3  * SPDX-License-Identifier: BSD-3-Clause
4  */
5 
6 #include "validatorsize_p.h"
7 
8 using namespace Cutelyst;
9 
10 ValidatorSize::ValidatorSize(const QString &field, QMetaType::Type type, const QVariant &size, const Cutelyst::ValidatorMessages &messages, const QString &defValKey) :
11  ValidatorRule(*new ValidatorSizePrivate(field, type, size, messages, defValKey))
12 {
13 }
14 
16 {
17 }
18 
20 {
21  ValidatorReturnType result;
22 
23  const QString v = value(params);
24 
25  if (!v.isEmpty()) {
26 
27  Q_D(const ValidatorSize);
28  bool ok = false;
29  bool valid = false;
30 
31  switch (d->type) {
32  case QMetaType::Short:
33  case QMetaType::Int:
34  case QMetaType::Long:
35  case QMetaType::LongLong:
36  {
37  const qlonglong val = c->locale().toLongLong(v, &ok);
38  if (Q_UNLIKELY(!ok)) {
39  result.errorMessage = parsingError(c);
40  qCWarning(C_VALIDATOR, "ValidatorSize: Failed to parse value of field %s into number at %s::%s.", qPrintable(field()), qPrintable(c->controllerName()), qPrintable(c->actionName()));
41  } else {
42  const qlonglong size = d->extractLongLong(c, params, d->size, &ok);
43  if (Q_UNLIKELY(!ok)) {
44  result.errorMessage = validationDataError(c, 1);
45  qCWarning(C_VALIDATOR, "ValidatorSize: Invalid comparison size for field %s in %s::%s.", qPrintable(field()), qPrintable(c->controllerName()), qPrintable(c->actionName()));
46  } else {
47  if (val != size) {
48  result.errorMessage = validationError(c, QVariantMap{
49  {QStringLiteral("val"), val},
50  {QStringLiteral("size"), size}
51  });
52  qCDebug(C_VALIDATOR, "ValidatorSize: Validation failed for field %s in %s::%s: value is not %lli.", qPrintable(field()), qPrintable(c->controllerName()), qPrintable(c->actionName()), size);
53  } else {
54  valid = true;
55  }
56  }
57  }
58  }
59  break;
60  case QMetaType::UShort:
61  case QMetaType::UInt:
62  case QMetaType::ULong:
63  case QMetaType::ULongLong:
64  {
65  const qulonglong val = v.toULongLong(&ok);
66  if (Q_UNLIKELY(!ok)) {
67  result.errorMessage = parsingError(c);
68  qCWarning(C_VALIDATOR, "ValidatorSize: Failed to parse value of field %s into number at %s::%s.", qPrintable(field()), qPrintable(c->controllerName()), qPrintable(c->actionName()));
69  } else {
70  const qulonglong size = d->extractULongLong(c, params, d->size, &ok);
71  if (Q_UNLIKELY(!ok)) {
72  result.errorMessage = validationDataError(c, 1);
73  qCWarning(C_VALIDATOR, "ValidatorSize: Invalid maximum comparison value for field %s in %s::%s.", qPrintable(field()), qPrintable(c->controllerName()), qPrintable(c->actionName()));
74  } else {
75  if (val != size) {
76  result.errorMessage = validationError(c, QVariantMap{
77  {QStringLiteral("val"), val},
78  {QStringLiteral("size"), size}
79  });
80  qCDebug(C_VALIDATOR, "ValidatorSize: Validation failed for field %s in %s::%s: value is not %llu.", qPrintable(field()), qPrintable(c->controllerName()), qPrintable(c->actionName()), size);
81  } else {
82  valid = true;
83  }
84  }
85  }
86  }
87  break;
88  case QMetaType::Float:
89  case QMetaType::Double:
90  {
91  const double val = v.toDouble(&ok);
92  if (Q_UNLIKELY(!ok)) {
93  result.errorMessage = parsingError(c);
94  qCWarning(C_VALIDATOR, "ValidatorSize: Failed to parse value of field %s into number at %s::%s.", qPrintable(field()), qPrintable(c->controllerName()), qPrintable(c->actionName()));
95  } else {
96  const double size = d->extractDouble(c, params, d->size, &ok);
97  if (Q_UNLIKELY(!ok)) {
98  result.errorMessage = validationDataError(c, 1);
99  qCWarning(C_VALIDATOR, "ValidatorSize: Invalid maximum comparison value for field %s in %s::%s.", qPrintable(field()), qPrintable(c->controllerName()), qPrintable(c->actionName()));
100  } else {
101  if (val != size) {
102  result.errorMessage = validationError(c, QVariantMap{
103  {QStringLiteral("val"), val},
104  {QStringLiteral("size"), size}
105  });
106  qCDebug(C_VALIDATOR, "ValidatorSize: Validation failed for field %s in %s::%s: value is not %f.", qPrintable(field()), qPrintable(c->controllerName()), qPrintable(c->actionName()), size);
107  } else {
108  valid = true;
109  }
110  }
111  }
112  }
113  break;
114  case QMetaType::QString:
115  {
116  const qlonglong val = static_cast<qlonglong>(v.length());
117  const qlonglong size = d->extractLongLong(c, params, d->size, &ok);
118  if (Q_UNLIKELY(!ok)) {
119  result.errorMessage = validationDataError(c, 1);
120  qCWarning(C_VALIDATOR, "ValidatorSize: Invalid maximum comparison value for field %s in %s::%s.", qPrintable(field()), qPrintable(c->controllerName()), qPrintable(c->actionName()));
121  } else {
122  if (val != size) {
123  result.errorMessage = validationError(c, QVariantMap{
124  {QStringLiteral("val"), val},
125  {QStringLiteral("size"), size}
126  });
127  qCDebug(C_VALIDATOR, "ValidatorSize: Validation failed for field %s in %s::%s: string length is not %lli.", qPrintable(field()), qPrintable(c->controllerName()), qPrintable(c->actionName()), size);
128  } else {
129  valid = true;
130  }
131  }
132  }
133  break;
134  default:
135  qCWarning(C_VALIDATOR, "ValidatorSize: 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()));
136  result.errorMessage = validationDataError(c, 0);
137  break;
138  }
139 
140  if (valid) {
141  if (d->type != QMetaType::QString) {
142  const QVariant _v = d->valueToNumber(c, v, d->type);
143  if (_v.isValid()) {
144  result.value = _v;
145  } else {
146  result.errorMessage = parsingError(c);
147  }
148  } else {
149  result.value.setValue(v);
150  }
151  }
152  } else {
153  defaultValue(c, &result, "ValidatorSize");
154  }
155 
156  return result;
157 }
158 
160 {
161  QString error;
162 
163  Q_D(const ValidatorSize);
164 
165  const QVariantMap map = errorData.toMap();
166  QString size;
167  switch (d->type) {
168  case QMetaType::Short:
169  case QMetaType::Int:
170  case QMetaType::Long:
171  case QMetaType::LongLong:
172  case QMetaType::QString:
173  size = c->locale().toString(map.value(QStringLiteral("size")).toLongLong());
174  break;
175  case QMetaType::UShort:
176  case QMetaType::UInt:
177  case QMetaType::ULong:
178  case QMetaType::ULongLong:
179  size = c->locale().toString(map.value(QStringLiteral("size")).toULongLong());
180  break;
181  case QMetaType::Float:
182  case QMetaType::Double:
183  size = c->locale().toString(map.value(QStringLiteral("size")).toDouble());
184  break;
185  default:
186  error = validationDataError(c);
187  return error;
188  }
189 
190  const QString _label = label(c);
191 
192  if (_label.isEmpty()) {
193  if (d->type == QMetaType::QString) {
194  //: %1 will be replaced by the required string size
195  error = c->translate("Cutelyst::ValidatorSize", "The text must be exactly %1 characters long.").arg(size);
196  } else {
197  //: %1 will be replaced by the required size/value
198  error = c->translate("Cutelyst::ValidatorSize", "The value must be %1.").arg(size);
199  }
200  } else {
201  if (d->type == QMetaType::QString) {
202  //: %1 will be replaced by the field label, %2 will be replaced by the required string size
203  error = c->translate("Cutelyst::ValidatorSize", "The text in the “%1“ field must be exactly %2 characters long.").arg(_label, size);
204  } else {
205  //: %1 will be replaced by the field label, %2 will be replaced by the required size/value
206  error = c->translate("Cutelyst::ValidatorSize", "The value in the “%1” field must be %2.").arg(_label, size);
207  }
208  }
209 
210  return error;
211 }
212 
214 {
215  QString error;
216 
217  int field = errorData.toInt();
218  const QString _label = label(c);
219 
220  if (field == 0) {
221  Q_D(const ValidatorSize);
222  if (_label.isEmpty()) {
223  error = c->translate("Cutelyst::ValidatorSize", "The comparison type with ID %1 is not supported.").arg(static_cast<int>(d->type));
224  } else {
225  error = c->translate("Cutelyst::ValidatorSize", "The comparison type with ID %1 for the “%2” field is not supported.").arg(QString::number(static_cast<int>(d->type)), _label);
226  }
227  } else if (field == 1) {
228  if (_label.isEmpty()) {
229  error = c->translate("Cutelyst::ValidatorSize", "The comparison value is not valid.");
230  } else {
231  //: %1 will be replaced by the field label
232  error = c->translate("Cutelyst::ValidatorSize", "The comparison value for the “%1” field is not valid.").arg(_label);
233  }
234  }
235 
236  return error;
237 }
238 
240 {
241  QString error;
242  Q_UNUSED(errorData)
243  Q_D(const ValidatorSize);
244 
245  const QString _label = label(c);
246  if ((d->type == QMetaType::Float) || (d->type == QMetaType::Double)) {
247  if (_label.isEmpty()) {
248  error = c->translate("Cutelyst::ValidatorSize", "Failed to parse the input value into a floating point number.");
249  } else {
250  //: %1 will be replaced by the field label
251  error = c->translate("Cutelyst::ValidatorSize", "Failed to parse the input value for the “%1” field into a floating point number.").arg(_label);
252  }
253  } else {
254  if (_label.isEmpty()) {
255  error = c->translate("Cutelyst::ValidatorSize", "Failed to parse the input value into an integer number.");
256  } else {
257  //: %1 will be replaced by the field label
258  error = c->translate("Cutelyst::ValidatorSize", "Failed to parse the input value for the “%1” field into an integer number.").arg(_label);
259  }
260  }
261 
262  return error;
263 }
QString genericValidationError(Context *c, const QVariant &errorData=QVariant()) const override
Returns a generic error message if validation failed.
QString parsingError(Context *c, const QVariant &errorData=QVariant()) const
Returns an error message if an error occured while parsing input.
QString validationError(Context *c, const QVariant &errorData=QVariant()) const
Returns a descriptive error message if validation failed.
QString toString(qlonglong i) const const
Stores custom error messages and the input field label.
double toDouble(bool *ok) const const
ValidatorReturnType validate(Context *c, const ParamsMultiMap &params) const override
Performs the validation and returns the result.
The field under validation must have a size matching the given value.
Definition: validatorsize.h:42
The Cutelyst Context.
Definition: context.h:38
QString number(int n, int base)
int toInt(bool *ok) const const
~ValidatorSize() override
Deconstructs the size validator.
qlonglong toLongLong(const QString &s, bool *ok) const const
bool isEmpty() const const
QString translate(const char *context, const char *sourceText, const char *disambiguation=nullptr, int n=-1) const
Definition: context.cpp:471
QString genericValidationDataError(Context *c, const QVariant &errorData) const override
Returns a generic error message for validation data errors.
QString validationDataError(Context *c, const QVariant &errorData=QVariant()) const
Returns an error message if any validation data is missing or invalid.
The Cutelyst namespace holds all public Cutelyst API.
Definition: Mainpage.dox:7
Base class for all validator rules.
qulonglong toULongLong(bool *ok, int base) const const
QLocale locale() const noexcept
Definition: context.cpp:447
QString label(Context *c) const
Returns the human readable field label used for generic error messages.
void setValue(const T &value)
QString value(const ParamsMultiMap &params) const
Returns the value of the field from the input params.
QMap< QString, QVariant > toMap() const const
int length() const const
QString field() const
Returns the name of the field to validate.
bool isValid() const const
Contains the result of a single input parameter validation.
Definition: validatorrule.h:49
ValidatorSize(const QString &field, QMetaType::Type type, const QVariant &size, const ValidatorMessages &messages=ValidatorMessages(), const QString &defValKey=QString())
Constructs a new size validator.
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
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 ...
int size() const const
QString genericParsingError(Context *c, const QVariant &errorData) const override
Returns a generic error message for input value parsing errors.