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