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(QStringView format, QCalendar cal) 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(QStringView format) const const
QString toString(QStringView format, QCalendar cal) 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
Checks if a date, time or datetime is after a comparison value.
bool isValid(int year, int month, int day)
The Cutelyst Context.
Definition: context.h:38
QString timeFormat(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
QString genericParsingError(Context *c, const QVariant &errorData=QVariant()) const override
Returns a generic error if the input value could not be parsed.
bool isValid(int h, int m, int s, int ms)
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
QString value(const ParamsMultiMap &params) const
Returns the value of the field from the input params.
bool isValid() const const
QString dateFormat(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 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(FormatType format) const const
QString arg(Args &&... args) 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 ...
void setValue(QVariant &&value)