cutelyst  3.9.1
A C++ Web Framework built on top of Qt, using the simple approach of Catalyst (Perl) framework.
validatorafter.cpp
1 /*
2  * SPDX-FileCopyrightText: (C) 2017-2022 Matthias Fehring <mf@huessenbergnetz.de>
3  * SPDX-License-Identifier: BSD-3-Clause
4  */
5 
6 #include "validatorafter_p.h"
7 
8 #include <QLocale>
9 #include <QTimeZone>
10 
11 using namespace Cutelyst;
12 
14  const QVariant &comparison,
15  const QString &timeZone,
16  const char *inputFormat,
17  const Cutelyst::ValidatorMessages &messages,
18  const QString &defValKey)
19  : ValidatorRule(
20  *new ValidatorAfterPrivate(field, comparison, timeZone, inputFormat, messages, defValKey))
21 {
22 }
23 
25 {
26 }
27 
29 {
30  ValidatorReturnType result;
31 
32  Q_D(const ValidatorAfter);
33 
34  const QString v = value(params);
35 
36  if (!v.isEmpty()) {
37 
38  const QTimeZone tz = d->extractTimeZone(c, params, d->timeZone);
39 
40  const QVariant _comp =
41  (d->comparison.userType() == QMetaType::QString)
42  ? d->extractOtherDateTime(c, params, d->comparison.toString(), tz, d->inputFormat)
43  : d->comparison;
44 
45  if (_comp.userType() == QMetaType::QDate) {
46 
47  const QDate odate = _comp.toDate();
48  if (Q_UNLIKELY(!odate.isValid())) {
49  qCWarning(
50  C_VALIDATOR,
51  "ValidatorAfter: Invalid comparison date and time for field %s at %s::%s.",
52  qPrintable(field()),
53  qPrintable(c->controllerName()),
54  qPrintable(c->actionName()));
56  } else {
57  const QDate date = d->extractDate(c, v, d->inputFormat);
58  if (Q_UNLIKELY(!date.isValid())) {
59  qCWarning(
60  C_VALIDATOR,
61  "ValidatorAfter: Can not parse input date \"%s\" for field %s at %s::%s.",
62  qPrintable(v),
63  qPrintable(field()),
64  qPrintable(c->controllerName()),
65  qPrintable(c->actionName()));
66  result.errorMessage = parsingError(c, odate);
67  } else {
68  if (Q_UNLIKELY(date <= odate)) {
69  qCDebug(C_VALIDATOR,
70  "ValidatorAfter: Validation failed at %s::%s for field %s: Input "
71  "date \"%s\" is not after \"%s\".",
72  qPrintable(c->controllerName()),
73  qPrintable(c->actionName()),
74  qPrintable(field()),
75  qPrintable(date.toString()),
76  qPrintable(odate.toString()));
77  result.errorMessage = validationError(c, odate);
78  } else {
79  result.value.setValue(date);
80  }
81  }
82  }
83 
84  } else if (_comp.userType() == QMetaType::QDateTime) {
85 
86  const QDateTime odatetime = _comp.toDateTime();
87  if (Q_UNLIKELY(!odatetime.isValid())) {
88  qCWarning(
89  C_VALIDATOR,
90  "ValidatorAfter: Invalid comparison date and time for field %s at %s::%s.",
91  qPrintable(field()),
92  qPrintable(c->controllerName()),
93  qPrintable(c->actionName()));
95  } else {
96  const QDateTime datetime = d->extractDateTime(c, v, d->inputFormat, tz);
97  if (Q_UNLIKELY(!datetime.isValid())) {
98  qCWarning(C_VALIDATOR,
99  "ValidatorAfter: Can not parse input date and time \"%s\" for field "
100  "%s at %s::%s.",
101  qPrintable(v),
102  qPrintable(field()),
103  qPrintable(c->controllerName()),
104  qPrintable(c->actionName()));
105  result.errorMessage = parsingError(c, odatetime);
106  } else {
107  if (Q_UNLIKELY(datetime <= odatetime)) {
108  qCDebug(C_VALIDATOR,
109  "ValidatorAfter: Validation failed at %s::%s for field %s: Input "
110  "date and time \"%s\" is not after \"%s\".",
111  qPrintable(c->controllerName()),
112  qPrintable(c->actionName()),
113  qPrintable(field()),
114  qPrintable(datetime.toString()),
115  qPrintable(odatetime.toString()));
116  result.errorMessage = validationError(c, odatetime);
117  } else {
118  result.value.setValue(datetime);
119  }
120  }
121  }
122 
123  } else if (_comp.userType() == QMetaType::QTime) {
124 
125  const QTime otime = _comp.toTime();
126  if (Q_UNLIKELY(!otime.isValid())) {
127  qCWarning(C_VALIDATOR,
128  "ValidatorAfter: Invalid comparison time for field %s at %s::%s.",
129  qPrintable(field()),
130  qPrintable(c->controllerName()),
131  qPrintable(c->actionName()));
132  result.errorMessage = validationDataError(c);
133  } else {
134  const QTime time = d->extractTime(c, v, d->inputFormat);
135  if (Q_UNLIKELY(!time.isValid())) {
136  qCWarning(
137  C_VALIDATOR,
138  "ValidatorAfter: Can not parse input time \"%s\" for field %s at %s::%s.",
139  qPrintable(v),
140  qPrintable(field()),
141  qPrintable(c->controllerName()),
142  qPrintable(c->actionName()));
143  result.errorMessage = parsingError(c, otime);
144  } else {
145  if (Q_UNLIKELY(time <= otime)) {
146  qCDebug(C_VALIDATOR,
147  "ValidatorAfter: Validation failed at %s::%s for field %s: Input "
148  "time \"%s\" is not after \"%s\".",
149  qPrintable(c->controllerName()),
150  qPrintable(c->actionName()),
151  qPrintable(field()),
152  qPrintable(time.toString()),
153  qPrintable(otime.toString()));
154  result.errorMessage = validationError(c, otime);
155  } else {
156  result.value.setValue(time);
157  }
158  }
159  }
160 
161  } else {
162  qCWarning(C_VALIDATOR)
163  << "ValidatorAfter: Invalid validation data for field" << field() << "at"
164  << c->controllerName() << "::" << c->actionName() << ":" << d->comparison;
165  result.errorMessage = validationDataError(c);
166  }
167  } else {
168  defaultValue(c, &result, "ValidatorAfter");
169  }
170 
171  return result;
172 }
173 
175  const QVariant &errorData) const
176 {
177  QString error;
178 
179  const QString _label = label(c);
180  if (_label.isEmpty()) {
181 
182  switch (errorData.userType()) {
183  case QMetaType::QDate:
184  error =
185  QStringLiteral("Has to be after %1.")
187  break;
189  error = QStringLiteral("Has to be after %1.")
190  .arg(errorData.toDateTime().toString(
192  break;
193  case QMetaType::QTime:
194  error =
195  QStringLiteral("Has to be after %1.")
197  break;
198  default:
199  error = validationDataError(c);
200  break;
201  }
202 
203  } else {
204 
205  switch (errorData.userType()) {
206  case QMetaType::QDate:
207  error =
208  c->translate("Cutelyst::ValidatorAfter",
209  "The date in the “%1” field must be after %2.")
210  .arg(_label,
212  break;
214  error = c->translate("Cutelyst::ValidatorAfter",
215  "The date and time in the “%1” field must be after %2.")
216  .arg(_label,
217  errorData.toDateTime().toString(
219  break;
220  case QMetaType::QTime:
221  error =
222  c->translate("Cutelyst::ValidatorAfter",
223  "The time in the “%1” field must be after %2.")
224  .arg(_label,
226  break;
227  default:
228  error = validationDataError(c);
229  break;
230  }
231  }
232 
233  return error;
234 }
235 
237 {
238  QString error;
239 
240  Q_UNUSED(errorData)
241  error =
242  c->translate("Cutelyst::ValidatorAfter",
243  "The comparison value is not a valid date and/or time, or cannot be found.");
244 
245  return error;
246 }
247 
249 {
250  QString error;
251 
252  Q_D(const ValidatorAfter);
253 
254  const QString _label = label(c);
255  if (d->inputFormat) {
256  if (_label.isEmpty()) {
257  error =
258  c->translate(
259  "Cutelyst::ValidatorAfter",
260  "Could not be parsed according to the following date and/or time format: %1")
261  .arg(c->translate(d->translationContext.data(), d->inputFormat));
262  } else {
263  error = c->translate("Cutelyst::ValidatorAfter",
264  "The value of the “%1” field could not be parsed according to the "
265  "following date and/or time format: %2")
266  .arg(_label, c->translate(d->translationContext.data(), d->inputFormat));
267  }
268  } else {
269 
270  if (_label.isEmpty()) {
271  switch (errorData.userType()) {
273  error = c->translate("Cutelyst::ValidatorAfter",
274  "Could not be parsed as date and time.");
275  break;
276  case QMetaType::QTime:
277  error = c->translate("Cutelyst::ValidatorAfter", "Could not be parsed as time.");
278  break;
279  case QMetaType::QDate:
280  error = c->translate("Cutelyst::ValidatorAfter", "Could not be parsed as date.");
281  break;
282  default:
283  error = validationDataError(c);
284  break;
285  }
286  } else {
287  switch (errorData.userType()) {
289  //: %1 will be replaced by the field label
290  error = c->translate(
291  "Cutelyst::ValidatorAfter",
292  "The value in the “%1” field could not be parsed as date and time.")
293  .arg(_label);
294  break;
295  case QMetaType::QTime:
296  //: %1 will be replaced by the field label
297  error = c->translate("Cutelyst::ValidatorAfter",
298  "The value in the “%1” field could not be parsed as time.")
299  .arg(_label);
300  break;
301  case QMetaType::QDate:
302  //: %1 will be replaced by the field label
303  error = c->translate("Cutelyst::ValidatorAfter",
304  "The value in the “%1” field could not be parsed as date.")
305  .arg(_label);
306  break;
307  default:
308  error = validationDataError(c);
309  break;
310  }
311  }
312  }
313 
314  return error;
315 }
QString genericValidationError(Context *c, const QVariant &errorData=QVariant()) const override
Returns a generic error if validation failed.
QString toString(Qt::DateFormat format) const const
QString parsingError(Context *c, const QVariant &errorData=QVariant()) const
Returns an error message if an error occurred while parsing input.
QString validationError(Context *c, const QVariant &errorData=QVariant()) const
Returns a descriptive error message if validation failed.
QString toString(Qt::DateFormat format) const const
QString toString(Qt::DateFormat format) const const
ValidatorReturnType validate(Context *c, const ParamsMultiMap &params) const override
Performs the validation and returns the result.
Stores custom error messages and the input field label.
QDateTime toDateTime() const const
QTime toTime() const const
bool isValid() const const
Checks if a date, time or datetime is after a comparison value.
The Cutelyst Context.
Definition: context.h:38
QString timeFormat(QLocale::FormatType format) const const
bool isEmpty() const const
~ValidatorAfter() override
Deconstructs the after validator.
QString translate(const char *context, const char *sourceText, const char *disambiguation=nullptr, int n=-1) const
Definition: context.cpp:490
bool isValid() const const
QString genericParsingError(Context *c, const QVariant &errorData=QVariant()) const override
Returns a generic error if the input value could not be parsed.
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.
QLocale locale() const noexcept
Definition: context.cpp:466
QString label(Context *c) const
Returns the human readable field label used for generic error messages.
ValidatorAfter(const QString &field, const QVariant &comparison, const QString &timeZone=QString(), const char *inputFormat=nullptr, const ValidatorMessages &messages=ValidatorMessages(), const QString &defValKey=QString())
Constructs a new after validator.
int userType() const const
void setValue(const T &value)
QString value(const ParamsMultiMap &params) const
Returns the value of the field from the input params.
bool isValid() const const
QString dateFormat(QLocale::FormatType format) const const
QDate toDate() const const
QString genericValidationDataError(Context *c, const QVariant &errorData=QVariant()) const override
Returns a generic error if comparison data was invalid.
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
QString field() const
Returns the name of the field to validate.
Contains the result of a single input parameter validation.
Definition: validatorrule.h:49
QString dateTimeFormat(QLocale::FormatType format) 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 ...